From 0a5575c2fd5e26eb7cf9e9f27990ed1bb3abd81f Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 30 Sep 2019 15:58:33 +0200 Subject: [PATCH 01/14] add HgModifyCommand / implement delete method --- .../scm/repository/spi/HgModifyCommand.java | 72 +++++++++++++++++++ .../spi/HgRepositoryServiceProvider.java | 13 +++- .../spi/HgRepositoryServiceResolver.java | 10 +-- .../repository/spi/HgModifyCommandTest.java | 37 ++++++++++ 4 files changed, 126 insertions(+), 6 deletions(-) create mode 100644 scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java create mode 100644 scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java new file mode 100644 index 0000000000..df4c7f3420 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -0,0 +1,72 @@ +package sonia.scm.repository.spi; + +import com.aragost.javahg.Changeset; +import com.aragost.javahg.Repository; +import com.aragost.javahg.commands.CommitCommand; +import com.aragost.javahg.commands.PushCommand; +import com.aragost.javahg.commands.RemoveCommand; +import sonia.scm.repository.HgRepositoryHandler; +import sonia.scm.repository.util.WorkingCopy; + +import java.io.File; +import java.io.IOException; +import java.util.List; + +public class HgModifyCommand implements ModifyCommand { + + private final HgRepositoryHandler handler; + private HgCommandContext context; + private final HgWorkdirFactory workdirFactory; + + public HgModifyCommand(HgRepositoryHandler handler, HgCommandContext context, HgWorkdirFactory workdirFactory) { + this.handler = handler; + this.context = context; + this.workdirFactory = workdirFactory; + } + + @Override + public String execute(ModifyCommandRequest request) { + + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context)) { + Repository workingRepository = workingCopy.getWorkingRepository(); + request.getRequests().forEach( + partialRequest -> { + try { + partialRequest.execute(new Worker() { + @Override + public void delete(String toBeDeleted) { + RemoveCommand.on(workingRepository).execute(toBeDeleted); + } + + @Override + public void create(String toBeCreated, File file, boolean overwrite) { + + } + + @Override + public void modify(String path, File file) { + + } + + @Override + public void move(String sourcePath, String targetPath) { + + } + }); + } catch (IOException e) { + e.printStackTrace(); // TODO + } + } + ); + + CommitCommand.on(workingRepository).user(String.format("%s <%s>", request.getAuthor().getName(), request.getAuthor().getMail())).message(request.getCommitMessage()).execute(); + List execute = PushCommand.on(workingRepository).execute(); + System.out.println(execute); + return execute.get(0).getNode(); + } catch (IOException e) { + e.printStackTrace(); + return null; + } + + } +} diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index d60e888cac..79812a7f68 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -66,7 +66,8 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider Command.INCOMING, Command.OUTGOING, Command.PUSH, - Command.PULL + Command.PULL, + Command.MODIFY ); //J+ @@ -77,10 +78,11 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- HgRepositoryServiceProvider(HgRepositoryHandler handler, - HgHookManager hookManager, Repository repository) + HgHookManager hookManager, Repository repository, HgWorkdirFactory workdirFactory) { this.repository = repository; this.handler = handler; + this.workdirFactory = workdirFactory; this.repositoryDirectory = handler.getDirectory(repository.getId()); this.context = new HgCommandContext(hookManager, handler, repository, repositoryDirectory); @@ -238,6 +240,11 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider return new HgPushCommand(handler, context, repository); } + @Override + public ModifyCommand getModifyCommand() { + return new HgModifyCommand(handler, context, workdirFactory); + } + /** * Method description * @@ -287,4 +294,6 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private File repositoryDirectory; + + private final HgWorkdirFactory workdirFactory; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index d6d04ee017..7b793e1b57 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -47,15 +47,17 @@ import sonia.scm.repository.Repository; public class HgRepositoryServiceResolver implements RepositoryServiceResolver { - private HgRepositoryHandler handler; - private HgHookManager hookManager; + private final HgRepositoryHandler handler; + private final HgHookManager hookManager; + private final HgWorkdirFactory workdirFactory; @Inject public HgRepositoryServiceResolver(HgRepositoryHandler handler, - HgHookManager hookManager) + HgHookManager hookManager, HgWorkdirFactory workdirFactory) { this.handler = handler; this.hookManager = hookManager; + this.workdirFactory = workdirFactory; } @Override @@ -63,7 +65,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver HgRepositoryServiceProvider provider = null; if (HgRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { - provider = new HgRepositoryServiceProvider(handler, hookManager, repository); + provider = new HgRepositoryServiceProvider(handler, hookManager, repository, workdirFactory); } return provider; diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java new file mode 100644 index 0000000000..e612590ce2 --- /dev/null +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -0,0 +1,37 @@ +package sonia.scm.repository.spi; + +import com.google.inject.util.Providers; +import org.junit.Test; +import sonia.scm.repository.HgHookManager; +import sonia.scm.repository.Person; +import sonia.scm.repository.util.WorkdirProvider; +import sonia.scm.web.HgRepositoryEnvironmentBuilder; + +import java.io.IOException; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class HgModifyCommandTest extends AbstractHgCommandTestBase { + + @Test + public void shouldRemoveFiles() throws IOException { + HgHookManager hookManager = mock(HgHookManager.class); + when(hookManager.getChallenge()).thenReturn("CHALLENGE"); + when(hookManager.getCredentials()).thenReturn("SECRET:SECRET"); + when(hookManager.createUrl()).thenReturn("http://localhost"); + HgRepositoryEnvironmentBuilder environmentBuilder = new HgRepositoryEnvironmentBuilder(handler, hookManager); + + HgModifyCommand hgModifyCommand = new HgModifyCommand(handler, cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.DeleteFileRequest("a.txt")); + request.setCommitMessage("this is great"); + request.setAuthor(new Person("Arthur Dent", "dent@hitchhiker.com")); + + String result = hgModifyCommand.execute(request); + + assertThat(cmdContext.open().tip().getNode()).isEqualTo(result); + cmdContext.close(); + } +} From fb5617d94048ce26439972507c4e03fd8c680801 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Tue, 1 Oct 2019 14:41:56 +0200 Subject: [PATCH 02/14] implement create method for HgModifyCommand --- .../scm/repository/spi/HgModifyCommand.java | 53 ++++++++++- .../repository/spi/HgModifyCommandTest.java | 91 ++++++++++++++++++- 2 files changed, 138 insertions(+), 6 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index df4c7f3420..de39c233b4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -5,13 +5,23 @@ import com.aragost.javahg.Repository; import com.aragost.javahg.commands.CommitCommand; import com.aragost.javahg.commands.PushCommand; import com.aragost.javahg.commands.RemoveCommand; +import org.apache.commons.lang.StringUtils; +import sonia.scm.ContextEntry; import sonia.scm.repository.HgRepositoryHandler; +import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.util.WorkingCopy; import java.io.File; import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.List; +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static sonia.scm.AlreadyExistsException.alreadyExists; +import static sonia.scm.ContextEntry.ContextBuilder.entity; + public class HgModifyCommand implements ModifyCommand { private final HgRepositoryHandler handler; @@ -39,8 +49,22 @@ public class HgModifyCommand implements ModifyCommand { } @Override - public void create(String toBeCreated, File file, boolean overwrite) { - + public void create(String toBeCreated, File file, boolean overwrite) throws IOException { + Path targetFile = new File(workingRepository.getDirectory(), toBeCreated).toPath(); + if (overwrite) { + Files.move(file.toPath(), targetFile, REPLACE_EXISTING); + } else { + try { + Files.move(file.toPath(), targetFile); + } catch (FileAlreadyExistsException e) { + throw alreadyExists(createFileContext(toBeCreated)); + } + } + try { + addFileToHg(targetFile.toFile()); + } catch (Exception e) { + throwInternalRepositoryException("could not add new file to index", e); + } } @Override @@ -52,6 +76,28 @@ public class HgModifyCommand implements ModifyCommand { public void move(String sourcePath, String targetPath) { } + + private void createDirectories(Path targetFile) throws IOException { + try { + Files.createDirectories(targetFile.getParent()); + } catch (FileAlreadyExistsException e) { + throw alreadyExists(createFileContext(targetFile.toString())); + } + } + + private ContextEntry.ContextBuilder createFileContext(String path) { + ContextEntry.ContextBuilder contextBuilder = entity("file", path); + if (!StringUtils.isEmpty(request.getBranch())) { + contextBuilder.in("branch", request.getBranch()); + } + contextBuilder.in(context.getScmRepository()); + return contextBuilder; + } + + private void addFileToHg(File file) { + workingRepository.workingCopy().add(file.getAbsolutePath()); + } + }); } catch (IOException e) { e.printStackTrace(); // TODO @@ -67,6 +113,9 @@ public class HgModifyCommand implements ModifyCommand { e.printStackTrace(); return null; } + } + private String throwInternalRepositoryException(String message, Exception e) { + throw new InternalRepositoryException(context.getScmRepository(), message, e); } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java index e612590ce2..d808b9e454 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -1,12 +1,19 @@ package sonia.scm.repository.spi; import com.google.inject.util.Providers; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import sonia.scm.AlreadyExistsException; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.Person; import sonia.scm.repository.util.WorkdirProvider; import sonia.scm.web.HgRepositoryEnvironmentBuilder; +import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; import static org.assertj.core.api.Assertions.assertThat; @@ -15,15 +22,28 @@ import static org.mockito.Mockito.when; public class HgModifyCommandTest extends AbstractHgCommandTestBase { - @Test - public void shouldRemoveFiles() throws IOException { + private HgModifyCommand hgModifyCommand; + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @Before + public void initHgModifyCommand() { HgHookManager hookManager = mock(HgHookManager.class); when(hookManager.getChallenge()).thenReturn("CHALLENGE"); when(hookManager.getCredentials()).thenReturn("SECRET:SECRET"); when(hookManager.createUrl()).thenReturn("http://localhost"); HgRepositoryEnvironmentBuilder environmentBuilder = new HgRepositoryEnvironmentBuilder(handler, hookManager); + hgModifyCommand = new HgModifyCommand(handler, cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); + } - HgModifyCommand hgModifyCommand = new HgModifyCommand(handler, cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); + @After + public void closeRepository() throws IOException { + cmdContext.close(); + } + + @Test + public void shouldRemoveFiles() { ModifyCommandRequest request = new ModifyCommandRequest(); request.addRequest(new ModifyCommandRequest.DeleteFileRequest("a.txt")); request.setCommitMessage("this is great"); @@ -32,6 +52,69 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { String result = hgModifyCommand.execute(request); assertThat(cmdContext.open().tip().getNode()).isEqualTo(result); - cmdContext.close(); + } + + @Test + public void shouldCreateFilesWithoutOverwrite() throws IOException { + + File testFile = temporaryFolder.newFile("Answer.txt"); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request.setCommitMessage("I found the answer"); + request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + String changeSet = hgModifyCommand.execute(request); + + assertThat(cmdContext.open().tip().getNode()).isEqualTo(changeSet); + assertThat(cmdContext.open().tip().getAddedFiles().size()).isEqualTo(1); + } + + @Test + public void shouldOverwriteExistingFiles() throws IOException { + + File testFile = temporaryFolder.newFile("Answer.txt"); + new FileOutputStream(testFile).write(21); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request.setCommitMessage("I found the answer"); + request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + hgModifyCommand.execute(request); + + new FileOutputStream(testFile).write(42); + ModifyCommandRequest request2 = new ModifyCommandRequest(); + request2.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, true)); + request2.setCommitMessage(" Now i really found the answer"); + request2.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + String changeSet2 = hgModifyCommand.execute(request2); + + assertThat(cmdContext.open().tip().getNode()).isEqualTo(changeSet2); + assertThat(cmdContext.open().tip().getModifiedFiles().size()).isEqualTo(1); + assertThat(cmdContext.open().tip().getModifiedFiles().get(0)).isEqualTo(testFile.getName()); + } + + @Test(expected = AlreadyExistsException.class) + public void shouldThrowFileAlreadyExistsException() throws IOException { + + File testFile = temporaryFolder.newFile("Answer.txt"); + new FileOutputStream(testFile).write(21); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request.setCommitMessage("I found the answer"); + request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + hgModifyCommand.execute(request); + + new FileOutputStream(testFile).write(42); + ModifyCommandRequest request2 = new ModifyCommandRequest(); + request2.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request2.setCommitMessage(" Now i really found the answer"); + request2.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + hgModifyCommand.execute(request2); } } From 75346c925e20bd34ea63fb769c08cd945d94d62f Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 2 Oct 2019 10:00:57 +0200 Subject: [PATCH 03/14] implement Modify Command --- .../scm/repository/spi/HgModifyCommand.java | 28 ++++--- .../repository/spi/HgModifyCommandTest.java | 79 +++++++++++++++---- 2 files changed, 83 insertions(+), 24 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index de39c233b4..a0795b337d 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -3,6 +3,7 @@ package sonia.scm.repository.spi; import com.aragost.javahg.Changeset; import com.aragost.javahg.Repository; import com.aragost.javahg.commands.CommitCommand; +import com.aragost.javahg.commands.ExecutionException; import com.aragost.javahg.commands.PushCommand; import com.aragost.javahg.commands.RemoveCommand; import org.apache.commons.lang.StringUtils; @@ -21,6 +22,7 @@ import java.util.List; import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; import static sonia.scm.AlreadyExistsException.alreadyExists; import static sonia.scm.ContextEntry.ContextBuilder.entity; +import static sonia.scm.NotFoundException.notFound; public class HgModifyCommand implements ModifyCommand { @@ -51,6 +53,7 @@ public class HgModifyCommand implements ModifyCommand { @Override public void create(String toBeCreated, File file, boolean overwrite) throws IOException { Path targetFile = new File(workingRepository.getDirectory(), toBeCreated).toPath(); + createDirectories(targetFile); if (overwrite) { Files.move(file.toPath(), targetFile, REPLACE_EXISTING); } else { @@ -62,19 +65,28 @@ public class HgModifyCommand implements ModifyCommand { } try { addFileToHg(targetFile.toFile()); - } catch (Exception e) { + } catch (ExecutionException e) { throwInternalRepositoryException("could not add new file to index", e); } } @Override - public void modify(String path, File file) { - + public void modify(String path, File file) throws IOException { + Path targetFile = new File(workingRepository.getDirectory(), path).toPath(); + createDirectories(targetFile); + if (!targetFile.toFile().exists()) { + throw notFound(createFileContext(path)); + } + Files.move(file.toPath(), targetFile, REPLACE_EXISTING); + try { + addFileToHg(targetFile.toFile()); + } catch (ExecutionException e) { + throwInternalRepositoryException("could not modify existing file", e); + } } @Override public void move(String sourcePath, String targetPath) { - } private void createDirectories(Path targetFile) throws IOException { @@ -97,20 +109,18 @@ public class HgModifyCommand implements ModifyCommand { private void addFileToHg(File file) { workingRepository.workingCopy().add(file.getAbsolutePath()); } - }); } catch (IOException e) { - e.printStackTrace(); // TODO + throwInternalRepositoryException("could not execute command on repository", e); } } ); CommitCommand.on(workingRepository).user(String.format("%s <%s>", request.getAuthor().getName(), request.getAuthor().getMail())).message(request.getCommitMessage()).execute(); List execute = PushCommand.on(workingRepository).execute(); - System.out.println(execute); return execute.get(0).getNode(); - } catch (IOException e) { - e.printStackTrace(); + } catch (IOException | ExecutionException e) { + throwInternalRepositoryException("could not execute command on repository", e); return null; } } diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java index d808b9e454..b8ce787937 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import sonia.scm.AlreadyExistsException; +import sonia.scm.NotFoundException; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.Person; import sonia.scm.repository.util.WorkdirProvider; @@ -56,8 +57,7 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { @Test public void shouldCreateFilesWithoutOverwrite() throws IOException { - - File testFile = temporaryFolder.newFile("Answer.txt"); + File testFile = temporaryFolder.newFile(); ModifyCommandRequest request = new ModifyCommandRequest(); request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); @@ -72,20 +72,11 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { @Test public void shouldOverwriteExistingFiles() throws IOException { - - File testFile = temporaryFolder.newFile("Answer.txt"); - new FileOutputStream(testFile).write(21); - - ModifyCommandRequest request = new ModifyCommandRequest(); - request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); - request.setCommitMessage("I found the answer"); - request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); - - hgModifyCommand.execute(request); + File testFile = temporaryFolder.newFile(); new FileOutputStream(testFile).write(42); ModifyCommandRequest request2 = new ModifyCommandRequest(); - request2.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, true)); + request2.addRequest(new ModifyCommandRequest.CreateFileRequest("a.txt", testFile, true)); request2.setCommitMessage(" Now i really found the answer"); request2.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); @@ -93,13 +84,13 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { assertThat(cmdContext.open().tip().getNode()).isEqualTo(changeSet2); assertThat(cmdContext.open().tip().getModifiedFiles().size()).isEqualTo(1); - assertThat(cmdContext.open().tip().getModifiedFiles().get(0)).isEqualTo(testFile.getName()); + assertThat(cmdContext.open().tip().getModifiedFiles().get(0)).isEqualTo("a.txt"); } @Test(expected = AlreadyExistsException.class) public void shouldThrowFileAlreadyExistsException() throws IOException { - File testFile = temporaryFolder.newFile("Answer.txt"); + File testFile = temporaryFolder.newFile(); new FileOutputStream(testFile).write(21); ModifyCommandRequest request = new ModifyCommandRequest(); @@ -117,4 +108,62 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { hgModifyCommand.execute(request2); } + + @Test + public void shouldModifyExistingFile() throws IOException { + File testFile = temporaryFolder.newFile("a.txt"); + + new FileOutputStream(testFile).write(42); + ModifyCommandRequest request2 = new ModifyCommandRequest(); + request2.addRequest(new ModifyCommandRequest.ModifyFileRequest("a.txt", testFile)); + request2.setCommitMessage(" Now i really found the answer"); + request2.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + String changeSet2 = hgModifyCommand.execute(request2); + + assertThat(cmdContext.open().tip().getNode()).isEqualTo(changeSet2); + assertThat(cmdContext.open().tip().getModifiedFiles().size()).isEqualTo(1); + assertThat(cmdContext.open().tip().getModifiedFiles().get(0)).isEqualTo(testFile.getName()); + } + + @Test(expected = NotFoundException.class) + public void shouldThrowNotFoundExceptionIfFileDoesNotExist() throws IOException { + File testFile = temporaryFolder.newFile("Answer.txt"); + + new FileOutputStream(testFile).write(42); + ModifyCommandRequest request2 = new ModifyCommandRequest(); + request2.addRequest(new ModifyCommandRequest.ModifyFileRequest("Answer.txt", testFile)); + request2.setCommitMessage(" Now i really found the answer"); + request2.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + + hgModifyCommand.execute(request2); + } + + @Test(expected = NullPointerException.class) + public void shouldThrowNPEIfAuthorIsMissing() throws IOException { + File testFile = temporaryFolder.newFile(); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request.setCommitMessage("I found the answer"); + hgModifyCommand.execute(request); + } + + @Test(expected = NullPointerException.class) + public void shouldThrowNPEIfCommitMessageIsMissing() throws IOException { + File testFile = temporaryFolder.newFile(); + + ModifyCommandRequest request = new ModifyCommandRequest(); + request.addRequest(new ModifyCommandRequest.CreateFileRequest("Answer.txt", testFile, false)); + request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + hgModifyCommand.execute(request); + } + + @Test(expected = IndexOutOfBoundsException.class) + public void shouldThrowIndexOutOfBoundExceptionIfRequestIsMissing() throws IOException { + ModifyCommandRequest request = new ModifyCommandRequest(); + request.setCommitMessage("I found the answer"); + request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); + hgModifyCommand.execute(request); + } } From 6417ab57e8a9e59ac5db7459c61fb71b123c45bf Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 2 Oct 2019 10:43:35 +0200 Subject: [PATCH 04/14] remove unnecessary handler from HgModifyCommand / move NoChangesMadeException to scm-core --- .../java/sonia/scm/NoChangesMadeException.java | 18 ++++++++++++++++++ .../scm/repository/spi/GitModifyCommand.java | 17 +++-------------- .../scm/repository/spi/HgModifyCommand.java | 11 ++++++----- .../spi/HgRepositoryServiceProvider.java | 2 +- .../repository/spi/HgModifyCommandTest.java | 12 +++++------- 5 files changed, 33 insertions(+), 27 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/NoChangesMadeException.java diff --git a/scm-core/src/main/java/sonia/scm/NoChangesMadeException.java b/scm-core/src/main/java/sonia/scm/NoChangesMadeException.java new file mode 100644 index 0000000000..9bf0363398 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/NoChangesMadeException.java @@ -0,0 +1,18 @@ +package sonia.scm; + +import sonia.scm.repository.Repository; + +public class NoChangesMadeException extends BadRequestException { + public NoChangesMadeException(Repository repository, String branch) { + super(ContextEntry.ContextBuilder.entity(repository).build(), "no changes detected to branch " + branch); + } + + public NoChangesMadeException(Repository repository) { + super(ContextEntry.ContextBuilder.entity(repository).build(), "no changes detected"); + } + + @Override + public String getCode() { + return "40RaYIeeR1"; + } +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java index 0f7c9296a7..5f2af87d2a 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java @@ -6,9 +6,9 @@ import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.lib.Constants; import org.eclipse.jgit.lib.Ref; import org.eclipse.jgit.revwalk.RevCommit; -import sonia.scm.BadRequestException; import sonia.scm.ConcurrentModificationException; import sonia.scm.ContextEntry; +import sonia.scm.NoChangesMadeException; import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.Repository; @@ -68,10 +68,10 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman for (ModifyCommandRequest.PartialRequest r : request.getRequests()) { r.execute(this); } - failIfNotChanged(NoChangesMadeException::new); + failIfNotChanged(() -> new NoChangesMadeException(repository, ModifyWorker.this.request.getBranch())); Optional revCommit = doCommit(request.getCommitMessage(), request.getAuthor()); push(); - return revCommit.orElseThrow(NoChangesMadeException::new).name(); + return revCommit.orElseThrow(() -> new NoChangesMadeException(repository, ModifyWorker.this.request.getBranch())).name(); } @Override @@ -156,17 +156,6 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman public void move(String sourcePath, String targetPath) { } - - private class NoChangesMadeException extends BadRequestException { - public NoChangesMadeException() { - super(ContextEntry.ContextBuilder.entity(context.getRepository()).build(), "no changes detected to branch " + ModifyWorker.this.request.getBranch()); - } - - @Override - public String getCode() { - return "40RaYIeeR1"; - } - } } private String throwInternalRepositoryException(String message, Exception e) { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index a0795b337d..4d5e77681e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -6,9 +6,10 @@ import com.aragost.javahg.commands.CommitCommand; import com.aragost.javahg.commands.ExecutionException; import com.aragost.javahg.commands.PushCommand; import com.aragost.javahg.commands.RemoveCommand; +import com.aragost.javahg.commands.StatusCommand; import org.apache.commons.lang.StringUtils; import sonia.scm.ContextEntry; -import sonia.scm.repository.HgRepositoryHandler; +import sonia.scm.NoChangesMadeException; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.util.WorkingCopy; @@ -26,12 +27,10 @@ import static sonia.scm.NotFoundException.notFound; public class HgModifyCommand implements ModifyCommand { - private final HgRepositoryHandler handler; private HgCommandContext context; private final HgWorkdirFactory workdirFactory; - public HgModifyCommand(HgRepositoryHandler handler, HgCommandContext context, HgWorkdirFactory workdirFactory) { - this.handler = handler; + public HgModifyCommand(HgCommandContext context, HgWorkdirFactory workdirFactory) { this.context = context; this.workdirFactory = workdirFactory; } @@ -115,7 +114,9 @@ public class HgModifyCommand implements ModifyCommand { } } ); - + if (StatusCommand.on(workingRepository).lines().isEmpty()) { + throw new NoChangesMadeException(context.getScmRepository()); + } CommitCommand.on(workingRepository).user(String.format("%s <%s>", request.getAuthor().getName(), request.getAuthor().getMail())).message(request.getCommitMessage()).execute(); List execute = PushCommand.on(workingRepository).execute(); return execute.get(0).getNode(); diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 79812a7f68..7cd4c3602b 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -242,7 +242,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider @Override public ModifyCommand getModifyCommand() { - return new HgModifyCommand(handler, context, workdirFactory); + return new HgModifyCommand(context, workdirFactory); } /** diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java index b8ce787937..124c96bd26 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -7,6 +7,7 @@ import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import sonia.scm.AlreadyExistsException; +import sonia.scm.NoChangesMadeException; import sonia.scm.NotFoundException; import sonia.scm.repository.HgHookManager; import sonia.scm.repository.Person; @@ -35,7 +36,7 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { when(hookManager.getCredentials()).thenReturn("SECRET:SECRET"); when(hookManager.createUrl()).thenReturn("http://localhost"); HgRepositoryEnvironmentBuilder environmentBuilder = new HgRepositoryEnvironmentBuilder(handler, hookManager); - hgModifyCommand = new HgModifyCommand(handler, cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); + hgModifyCommand = new HgModifyCommand(cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); } @After @@ -159,11 +160,8 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { hgModifyCommand.execute(request); } - @Test(expected = IndexOutOfBoundsException.class) - public void shouldThrowIndexOutOfBoundExceptionIfRequestIsMissing() throws IOException { - ModifyCommandRequest request = new ModifyCommandRequest(); - request.setCommitMessage("I found the answer"); - request.setAuthor(new Person("Trillian Astra", "trillian@hitchhiker.com")); - hgModifyCommand.execute(request); + @Test(expected = NoChangesMadeException.class) + public void shouldThrowNoChangesMadeExceptionIfEmptyLocalChangesetAfterRequest() { + hgModifyCommand.execute(new ModifyCommandRequest()); } } From d1f7362ab110e8d69cabf7a0567de627db0d33a3 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Wed, 2 Oct 2019 11:34:42 +0200 Subject: [PATCH 05/14] set author from subject if not available in request for MergeCommandBuilder and ModifyCommandBuilder --- .../repository/api/MergeCommandBuilder.java | 2 ++ .../repository/api/ModifyCommandBuilder.java | 2 ++ .../sonia/scm/repository/util/AuthorUtil.java | 31 +++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java diff --git a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java index 8fcfc937e5..0a2267e888 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/MergeCommandBuilder.java @@ -4,6 +4,7 @@ import com.google.common.base.Preconditions; import sonia.scm.repository.Person; import sonia.scm.repository.spi.MergeCommand; import sonia.scm.repository.spi.MergeCommandRequest; +import sonia.scm.repository.util.AuthorUtil; /** * Use this {@link MergeCommandBuilder} to merge two branches of a repository ({@link #executeMerge()}) or to check if @@ -126,6 +127,7 @@ public class MergeCommandBuilder { * @return The result of the merge. */ public MergeCommandResult executeMerge() { + AuthorUtil.setAuthorIfNotAvailable(request); Preconditions.checkArgument(request.isValid(), "revision to merge and target revision is required"); return mergeCommand.merge(request); } diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java index 1eed0697cb..87d868c04a 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java @@ -9,6 +9,7 @@ import org.slf4j.LoggerFactory; import sonia.scm.repository.Person; import sonia.scm.repository.spi.ModifyCommand; import sonia.scm.repository.spi.ModifyCommandRequest; +import sonia.scm.repository.util.AuthorUtil; import sonia.scm.repository.util.WorkdirProvider; import sonia.scm.util.IOUtil; @@ -110,6 +111,7 @@ public class ModifyCommandBuilder { * @return The revision of the new commit. */ public String execute() { + AuthorUtil.setAuthorIfNotAvailable(request); try { Preconditions.checkArgument(request.isValid(), "commit message, branch and at least one request are required"); return command.execute(request); diff --git a/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java b/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java new file mode 100644 index 0000000000..263bba8ddb --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java @@ -0,0 +1,31 @@ +package sonia.scm.repository.util; + +import org.apache.shiro.SecurityUtils; +import org.apache.shiro.subject.Subject; +import sonia.scm.repository.Person; +import sonia.scm.repository.spi.MergeCommandRequest; +import sonia.scm.repository.spi.ModifyCommandRequest; +import sonia.scm.user.User; + +public class AuthorUtil { + + public static void setAuthorIfNotAvailable(ModifyCommandRequest request) { + if (request.getAuthor() == null) { + request.setAuthor(createAuthorFromSubject()); + } + } + + public static void setAuthorIfNotAvailable(MergeCommandRequest request) { + if (request.getAuthor() == null) { + request.setAuthor(createAuthorFromSubject()); + } + } + + private static Person createAuthorFromSubject() { + Subject subject = SecurityUtils.getSubject(); + User user = subject.getPrincipals().oneByType(User.class); + String name = user.getDisplayName(); + String email = user.getMail(); + return new Person(name, email); + } +} From a40410d1ae51264efab0fa27489f3867e83119a4 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 7 Oct 2019 11:10:37 +0200 Subject: [PATCH 06/14] fix hg modify command after factory changes --- .../src/main/java/sonia/scm/repository/spi/HgModifyCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index 4d5e77681e..7f9df4f60b 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -38,7 +38,7 @@ public class HgModifyCommand implements ModifyCommand { @Override public String execute(ModifyCommandRequest request) { - try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context)) { + try (WorkingCopy workingCopy = workdirFactory.createWorkingCopy(context, request.getBranch())) { Repository workingRepository = workingCopy.getWorkingRepository(); request.getRequests().forEach( partialRequest -> { From 120416c4d62a67af3e989b1175f68df2f214048b Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 7 Oct 2019 13:49:43 +0200 Subject: [PATCH 07/14] pull modify changes from working copy to central repository so that mercurial hooks gets triggered --- .../scm/repository/spi/HgModifyCommand.java | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index 7f9df4f60b..eaec861335 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -4,7 +4,7 @@ import com.aragost.javahg.Changeset; import com.aragost.javahg.Repository; import com.aragost.javahg.commands.CommitCommand; import com.aragost.javahg.commands.ExecutionException; -import com.aragost.javahg.commands.PushCommand; +import com.aragost.javahg.commands.PullCommand; import com.aragost.javahg.commands.RemoveCommand; import com.aragost.javahg.commands.StatusCommand; import org.apache.commons.lang.StringUtils; @@ -118,14 +118,26 @@ public class HgModifyCommand implements ModifyCommand { throw new NoChangesMadeException(context.getScmRepository()); } CommitCommand.on(workingRepository).user(String.format("%s <%s>", request.getAuthor().getName(), request.getAuthor().getMail())).message(request.getCommitMessage()).execute(); - List execute = PushCommand.on(workingRepository).execute(); + List execute = pullModifyChangesToCentralRepository(request, workingCopy); return execute.get(0).getNode(); - } catch (IOException | ExecutionException e) { + } catch (ExecutionException e) { throwInternalRepositoryException("could not execute command on repository", e); return null; } } + private List pullModifyChangesToCentralRepository(ModifyCommandRequest request, WorkingCopy workingCopy) { + try { + com.aragost.javahg.commands.PullCommand pullCommand = PullCommand.on(workingCopy.getCentralRepository()); + workdirFactory.configure(pullCommand); + return pullCommand.execute(workingCopy.getDirectory().getAbsolutePath()); + } catch (Exception e) { + throw new IntegrateChangesFromWorkdirException(context.getScmRepository(), + String.format("Could not pull modify changes from working copy to central repository", request.getBranch()), + e); + } + } + private String throwInternalRepositoryException(String message, Exception e) { throw new InternalRepositoryException(context.getScmRepository(), message, e); } From cb6f1bfa2203e790a1ebf77633d7923350e32f42 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 7 Oct 2019 14:59:46 +0200 Subject: [PATCH 08/14] remove unused move-method from ModifyCommand / create interface for CommandRequests with Author --- .../repository/api/ModifyCommandBuilder.java | 11 ---------- .../repository/spi/MergeCommandRequest.java | 3 ++- .../scm/repository/spi/ModifyCommand.java | 2 -- .../repository/spi/ModifyCommandRequest.java | 18 ++--------------- .../sonia/scm/repository/util/AuthorUtil.java | 16 +++++++-------- .../api/ModifyCommandBuilderTest.java | 10 ---------- .../scm/repository/spi/GitModifyCommand.java | 5 ----- .../scm/repository/spi/HgModifyCommand.java | 4 ---- .../repository/spi/HgModifyCommandTest.java | 17 +++++++++------- .../api/v2/resources/MergeResourceTest.java | 20 +++++++++++++++++++ 10 files changed, 41 insertions(+), 65 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java index 87d868c04a..05c1babe03 100644 --- a/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java +++ b/scm-core/src/main/java/sonia/scm/repository/api/ModifyCommandBuilder.java @@ -95,17 +95,6 @@ public class ModifyCommandBuilder { return this; } - /** - * Move an existing file. - * @param sourcePath The path and the name of the file that should be moved. - * @param targetPath The new path and name the file should be moved to. - * @return This builder instance. - */ - public ModifyCommandBuilder moveFile(String sourcePath, String targetPath) { - request.addRequest(new ModifyCommandRequest.MoveFileRequest(sourcePath, targetPath)); - return this; - } - /** * Apply the changes and create a new commit with the given message and author. * @return The revision of the new commit. diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommandRequest.java index 45dfc0b2b7..223cf8c49e 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/MergeCommandRequest.java @@ -5,10 +5,11 @@ import com.google.common.base.Objects; import com.google.common.base.Strings; import sonia.scm.Validateable; import sonia.scm.repository.Person; +import sonia.scm.repository.util.AuthorUtil.CommandWithAuthor; import java.io.Serializable; -public class MergeCommandRequest implements Validateable, Resetable, Serializable, Cloneable { +public class MergeCommandRequest implements Validateable, Resetable, Serializable, Cloneable, CommandWithAuthor { private static final long serialVersionUID = -2650236557922431528L; diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommand.java b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommand.java index b3ba882040..1bc64e0e08 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommand.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommand.java @@ -13,7 +13,5 @@ public interface ModifyCommand { void create(String toBeCreated, File file, boolean overwrite) throws IOException; void modify(String path, File file) throws IOException; - - void move(String sourcePath, String targetPath); } } diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java index d61e17c785..43814f8729 100644 --- a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyCommandRequest.java @@ -5,6 +5,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sonia.scm.Validateable; import sonia.scm.repository.Person; +import sonia.scm.repository.util.AuthorUtil.CommandWithAuthor; import sonia.scm.util.IOUtil; import java.io.File; @@ -13,7 +14,7 @@ import java.util.ArrayList; import java.util.Collections; import java.util.List; -public class ModifyCommandRequest implements Resetable, Validateable { +public class ModifyCommandRequest implements Resetable, Validateable, CommandWithAuthor { private static final Logger LOG = LoggerFactory.getLogger(ModifyCommandRequest.class); @@ -94,21 +95,6 @@ public class ModifyCommandRequest implements Resetable, Validateable { } } - public static class MoveFileRequest implements PartialRequest { - private final String sourcePath; - private final String targetPath; - - public MoveFileRequest(String sourcePath, String targetPath) { - this.sourcePath = sourcePath; - this.targetPath = targetPath; - } - - @Override - public void execute(ModifyCommand.Worker worker) { - worker.move(sourcePath, targetPath); - } - } - private abstract static class ContentModificationRequest implements PartialRequest { private final File content; diff --git a/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java b/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java index 263bba8ddb..5735889c3c 100644 --- a/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java +++ b/scm-core/src/main/java/sonia/scm/repository/util/AuthorUtil.java @@ -3,19 +3,11 @@ package sonia.scm.repository.util; import org.apache.shiro.SecurityUtils; import org.apache.shiro.subject.Subject; import sonia.scm.repository.Person; -import sonia.scm.repository.spi.MergeCommandRequest; -import sonia.scm.repository.spi.ModifyCommandRequest; import sonia.scm.user.User; public class AuthorUtil { - public static void setAuthorIfNotAvailable(ModifyCommandRequest request) { - if (request.getAuthor() == null) { - request.setAuthor(createAuthorFromSubject()); - } - } - - public static void setAuthorIfNotAvailable(MergeCommandRequest request) { + public static void setAuthorIfNotAvailable(CommandWithAuthor request) { if (request.getAuthor() == null) { request.setAuthor(createAuthorFromSubject()); } @@ -28,4 +20,10 @@ public class AuthorUtil { String email = user.getMail(); return new Person(name, email); } + + public interface CommandWithAuthor { + Person getAuthor(); + + void setAuthor(Person person); + } } diff --git a/scm-core/src/test/java/sonia/scm/repository/api/ModifyCommandBuilderTest.java b/scm-core/src/test/java/sonia/scm/repository/api/ModifyCommandBuilderTest.java index db9a247d65..6e46841cd2 100644 --- a/scm-core/src/test/java/sonia/scm/repository/api/ModifyCommandBuilderTest.java +++ b/scm-core/src/test/java/sonia/scm/repository/api/ModifyCommandBuilderTest.java @@ -1,7 +1,6 @@ package sonia.scm.repository.api; import com.google.common.io.ByteSource; -import com.sun.org.apache.xpath.internal.operations.Bool; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -85,15 +84,6 @@ class ModifyCommandBuilderTest { verify(worker).delete("toBeDeleted"); } - @Test - void shouldExecuteMove() throws IOException { - initCommand() - .moveFile("source", "target") - .execute(); - - verify(worker).move("source", "target"); - } - @Test void shouldExecuteCreateWithByteSourceContent() throws IOException { ArgumentCaptor nameCaptor = ArgumentCaptor.forClass(String.class); diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java index de70b2766c..10cc45631f 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java @@ -143,11 +143,6 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman contextBuilder.in(context.getRepository()); return contextBuilder; } - - @Override - public void move(String sourcePath, String targetPath) { - - } } private String throwInternalRepositoryException(String message, Exception e) { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index eaec861335..ee9fa002d4 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -84,10 +84,6 @@ public class HgModifyCommand implements ModifyCommand { } } - @Override - public void move(String sourcePath, String targetPath) { - } - private void createDirectories(Path targetFile) throws IOException { try { Files.createDirectories(targetFile.getParent()); diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java index 124c96bd26..f85f6a2e40 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -10,6 +10,7 @@ import sonia.scm.AlreadyExistsException; import sonia.scm.NoChangesMadeException; import sonia.scm.NotFoundException; import sonia.scm.repository.HgHookManager; +import sonia.scm.repository.HgTestUtil; import sonia.scm.repository.Person; import sonia.scm.repository.util.WorkdirProvider; import sonia.scm.web.HgRepositoryEnvironmentBuilder; @@ -19,8 +20,6 @@ import java.io.FileOutputStream; import java.io.IOException; import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.when; public class HgModifyCommandTest extends AbstractHgCommandTestBase { @@ -31,12 +30,16 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { @Before public void initHgModifyCommand() { - HgHookManager hookManager = mock(HgHookManager.class); - when(hookManager.getChallenge()).thenReturn("CHALLENGE"); - when(hookManager.getCredentials()).thenReturn("SECRET:SECRET"); - when(hookManager.createUrl()).thenReturn("http://localhost"); + HgHookManager hookManager = HgTestUtil.createHookManager(); HgRepositoryEnvironmentBuilder environmentBuilder = new HgRepositoryEnvironmentBuilder(handler, hookManager); - hgModifyCommand = new HgModifyCommand(cmdContext, new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider())); + SimpleHgWorkdirFactory workdirFactory = new SimpleHgWorkdirFactory(Providers.of(environmentBuilder), new WorkdirProvider()) { + @Override + public void configure(com.aragost.javahg.commands.PullCommand pullCommand) { + // we do not want to configure http hooks in this unit test + } + }; + hgModifyCommand = new HgModifyCommand(cmdContext, workdirFactory + ); } @After diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java index b9e720fc71..7181912cfe 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java @@ -3,6 +3,7 @@ package sonia.scm.api.v2.resources; import com.github.sdorra.shiro.SubjectAware; import com.google.common.io.Resources; import com.google.inject.util.Providers; +import org.apache.shiro.subject.PrincipalCollection; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.ThreadContext; import org.jboss.resteasy.core.Dispatcher; @@ -24,6 +25,7 @@ import sonia.scm.repository.api.MergeDryRunCommandResult; import sonia.scm.repository.api.RepositoryService; import sonia.scm.repository.api.RepositoryServiceFactory; import sonia.scm.repository.spi.MergeCommand; +import sonia.scm.user.User; import sonia.scm.web.VndMediaType; import java.net.URL; @@ -32,6 +34,7 @@ import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; import static sonia.scm.repository.RepositoryTestData.createHeartOfGold; @@ -105,6 +108,10 @@ public class MergeResourceTest extends RepositoryTestBase { @Test void shouldHandleSuccessfulMerge() throws Exception { when(mergeCommand.merge(any())).thenReturn(MergeCommandResult.success()); + User user = createDummyUser("dummy"); + PrincipalCollection collection = mock(PrincipalCollection.class); + when(subject.getPrincipals()).thenReturn(collection); + when(collection.oneByType(User.class)).thenReturn(user); URL url = Resources.getResource("sonia/scm/api/v2/mergeCommand.json"); byte[] mergeCommandJson = Resources.toByteArray(url); @@ -122,6 +129,10 @@ public class MergeResourceTest extends RepositoryTestBase { @Test void shouldHandleFailedMerge() throws Exception { when(mergeCommand.merge(any())).thenReturn(MergeCommandResult.failure(asList("file1", "file2"))); + User user = createDummyUser("dummy"); + PrincipalCollection collection = mock(PrincipalCollection.class); + when(subject.getPrincipals()).thenReturn(collection); + when(collection.oneByType(User.class)).thenReturn(user); URL url = Resources.getResource("sonia/scm/api/v2/mergeCommand.json"); byte[] mergeCommandJson = Resources.toByteArray(url); @@ -189,5 +200,14 @@ public class MergeResourceTest extends RepositoryTestBase { assertThat(response.getStatus()).isEqualTo(204); } + + private User createDummyUser(String name) { + User user = new User(); + user.setName(name); + user.setType("xml"); + user.setPassword("secret"); + user.setCreationDate(System.currentTimeMillis()); + return user; + } } } From 285084aed1339068b25693b54c3dc15327e8f6e9 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Mon, 7 Oct 2019 16:51:46 +0200 Subject: [PATCH 09/14] remove closeRepository after unit tests since its already closed by abstractTestBase --- .../java/sonia/scm/repository/spi/HgModifyCommandTest.java | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java index f85f6a2e40..862d2ab2ed 100644 --- a/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java +++ b/scm-plugins/scm-hg-plugin/src/test/java/sonia/scm/repository/spi/HgModifyCommandTest.java @@ -1,7 +1,6 @@ package sonia.scm.repository.spi; import com.google.inject.util.Providers; -import org.junit.After; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -42,11 +41,6 @@ public class HgModifyCommandTest extends AbstractHgCommandTestBase { ); } - @After - public void closeRepository() throws IOException { - cmdContext.close(); - } - @Test public void shouldRemoveFiles() { ModifyCommandRequest request = new ModifyCommandRequest(); From 76c7821ed2d86ab7d0476cdef47243b9f93c449f Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Tue, 8 Oct 2019 11:58:13 +0200 Subject: [PATCH 10/14] Reduce code redundancy --- .../repository/spi/ModifyWorkerHelper.java | 88 +++++++++++++++++++ .../scm/repository/spi/GitModifyCommand.java | 81 ++++------------- .../scm/repository/spi/HgModifyCommand.java | 67 ++++---------- .../spi/HgRepositoryServiceProvider.java | 2 +- 4 files changed, 123 insertions(+), 115 deletions(-) create mode 100644 scm-core/src/main/java/sonia/scm/repository/spi/ModifyWorkerHelper.java diff --git a/scm-core/src/main/java/sonia/scm/repository/spi/ModifyWorkerHelper.java b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyWorkerHelper.java new file mode 100644 index 0000000000..a1ff6b0eb3 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/repository/spi/ModifyWorkerHelper.java @@ -0,0 +1,88 @@ +package sonia.scm.repository.spi; + +import org.apache.commons.lang.StringUtils; +import sonia.scm.ContextEntry; +import sonia.scm.repository.Repository; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileAlreadyExistsException; +import java.nio.file.Files; +import java.nio.file.NoSuchFileException; +import java.nio.file.Path; + +import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; +import static sonia.scm.AlreadyExistsException.alreadyExists; +import static sonia.scm.ContextEntry.ContextBuilder.entity; +import static sonia.scm.NotFoundException.notFound; + +/** + * This "interface" is not really intended to be used as an interface but rather as + * a base class to reduce code redundancy in Worker instances. + */ +public interface ModifyWorkerHelper extends ModifyCommand.Worker { + + @Override + default void delete(String toBeDeleted) throws IOException { + Path fileToBeDeleted = new File(getWorkDir(), toBeDeleted).toPath(); + try { + Files.delete(fileToBeDeleted); + } catch (NoSuchFileException e) { + throw notFound(createFileContext(toBeDeleted)); + } + doScmDelete(toBeDeleted); + } + + void doScmDelete(String toBeDeleted); + + @Override + default void create(String toBeCreated, File file, boolean overwrite) throws IOException { + Path targetFile = new File(getWorkDir(), toBeCreated).toPath(); + createDirectories(targetFile); + if (overwrite) { + Files.move(file.toPath(), targetFile, REPLACE_EXISTING); + } else { + try { + Files.move(file.toPath(), targetFile); + } catch (FileAlreadyExistsException e) { + throw alreadyExists(createFileContext(toBeCreated)); + } + } + addFileToScm(toBeCreated, targetFile); + } + + default void modify(String path, File file) throws IOException { + Path targetFile = new File(getWorkDir(), path).toPath(); + createDirectories(targetFile); + if (!targetFile.toFile().exists()) { + throw notFound(createFileContext(path)); + } + Files.move(file.toPath(), targetFile, REPLACE_EXISTING); + addFileToScm(path, targetFile); + } + + void addFileToScm(String name, Path file); + + default ContextEntry.ContextBuilder createFileContext(String path) { + ContextEntry.ContextBuilder contextBuilder = entity("file", path); + if (!StringUtils.isEmpty(getBranch())) { + contextBuilder.in("branch", getBranch()); + } + contextBuilder.in(getRepository()); + return contextBuilder; + } + + default void createDirectories(Path targetFile) throws IOException { + try { + Files.createDirectories(targetFile.getParent()); + } catch (FileAlreadyExistsException e) { + throw alreadyExists(createFileContext(targetFile.toString())); + } + } + + File getWorkDir(); + + Repository getRepository(); + + String getBranch(); +} diff --git a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java index 10cc45631f..da7f0150f5 100644 --- a/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java +++ b/scm-plugins/scm-git-plugin/src/main/java/sonia/scm/repository/spi/GitModifyCommand.java @@ -5,7 +5,6 @@ import org.eclipse.jgit.api.Git; import org.eclipse.jgit.api.errors.GitAPIException; import org.eclipse.jgit.revwalk.RevCommit; import sonia.scm.ConcurrentModificationException; -import sonia.scm.ContextEntry; import sonia.scm.NoChangesMadeException; import sonia.scm.repository.GitWorkdirFactory; import sonia.scm.repository.InternalRepositoryException; @@ -13,17 +12,9 @@ import sonia.scm.repository.Repository; import java.io.File; import java.io.IOException; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.Files; -import java.nio.file.NoSuchFileException; import java.nio.file.Path; import java.util.Optional; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static sonia.scm.AlreadyExistsException.alreadyExists; -import static sonia.scm.ContextEntry.ContextBuilder.entity; -import static sonia.scm.NotFoundException.notFound; - public class GitModifyCommand extends AbstractGitCommand implements ModifyCommand { private final GitWorkdirFactory workdirFactory; @@ -38,7 +29,7 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman return inClone(clone -> new ModifyWorker(clone, request), workdirFactory, request.getBranch()); } - private class ModifyWorker extends GitCloneWorker implements Worker { + private class ModifyWorker extends GitCloneWorker implements ModifyWorkerHelper { private final File workDir; private final ModifyCommandRequest request; @@ -67,35 +58,9 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman } @Override - public void create(String toBeCreated, File file, boolean overwrite) throws IOException { - Path targetFile = new File(workDir, toBeCreated).toPath(); - createDirectories(targetFile); - if (overwrite) { - Files.move(file.toPath(), targetFile, REPLACE_EXISTING); - } else { - try { - Files.move(file.toPath(), targetFile); - } catch (FileAlreadyExistsException e) { - throw alreadyExists(createFileContext(toBeCreated)); - } - } + public void addFileToScm(String name, Path file) { try { - addFileToGit(toBeCreated); - } catch (GitAPIException e) { - throwInternalRepositoryException("could not add new file to index", e); - } - } - - @Override - public void modify(String path, File file) throws IOException { - Path targetFile = new File(workDir, path).toPath(); - createDirectories(targetFile); - if (!targetFile.toFile().exists()) { - throw notFound(createFileContext(path)); - } - Files.move(file.toPath(), targetFile, REPLACE_EXISTING); - try { - addFileToGit(path); + addFileToGit(name); } catch (GitAPIException e) { throwInternalRepositoryException("could not add new file to index", e); } @@ -106,13 +71,7 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman } @Override - public void delete(String toBeDeleted) throws IOException { - Path fileToBeDeleted = new File(workDir, toBeDeleted).toPath(); - try { - Files.delete(fileToBeDeleted); - } catch (NoSuchFileException e) { - throw notFound(createFileContext(toBeDeleted)); - } + public void doScmDelete(String toBeDeleted) { try { getClone().rm().addFilepattern(removeStartingPathSeparators(toBeDeleted)).call(); } catch (GitAPIException e) { @@ -120,29 +79,27 @@ public class GitModifyCommand extends AbstractGitCommand implements ModifyComman } } + @Override + public File getWorkDir() { + return workDir; + } + + @Override + public Repository getRepository() { + return repository; + } + + @Override + public String getBranch() { + return request.getBranch(); + } + private String removeStartingPathSeparators(String path) { while (path.startsWith(File.separator)) { path = path.substring(1); } return path; } - - private void createDirectories(Path targetFile) throws IOException { - try { - Files.createDirectories(targetFile.getParent()); - } catch (FileAlreadyExistsException e) { - throw alreadyExists(createFileContext(targetFile.toString())); - } - } - - private ContextEntry.ContextBuilder createFileContext(String path) { - ContextEntry.ContextBuilder contextBuilder = entity("file", path); - if (!StringUtils.isEmpty(request.getBranch())) { - contextBuilder.in("branch", request.getBranch()); - } - contextBuilder.in(context.getRepository()); - return contextBuilder; - } } private String throwInternalRepositoryException(String message, Exception e) { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index ee9fa002d4..cd0a649b6e 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -7,24 +7,15 @@ import com.aragost.javahg.commands.ExecutionException; import com.aragost.javahg.commands.PullCommand; import com.aragost.javahg.commands.RemoveCommand; import com.aragost.javahg.commands.StatusCommand; -import org.apache.commons.lang.StringUtils; -import sonia.scm.ContextEntry; import sonia.scm.NoChangesMadeException; import sonia.scm.repository.InternalRepositoryException; import sonia.scm.repository.util.WorkingCopy; import java.io.File; import java.io.IOException; -import java.nio.file.FileAlreadyExistsException; -import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; -import static sonia.scm.AlreadyExistsException.alreadyExists; -import static sonia.scm.ContextEntry.ContextBuilder.entity; -import static sonia.scm.NotFoundException.notFound; - public class HgModifyCommand implements ModifyCommand { private HgCommandContext context; @@ -43,62 +34,34 @@ public class HgModifyCommand implements ModifyCommand { request.getRequests().forEach( partialRequest -> { try { - partialRequest.execute(new Worker() { - @Override - public void delete(String toBeDeleted) { - RemoveCommand.on(workingRepository).execute(toBeDeleted); - } + partialRequest.execute(new ModifyWorkerHelper() { @Override - public void create(String toBeCreated, File file, boolean overwrite) throws IOException { - Path targetFile = new File(workingRepository.getDirectory(), toBeCreated).toPath(); - createDirectories(targetFile); - if (overwrite) { - Files.move(file.toPath(), targetFile, REPLACE_EXISTING); - } else { - try { - Files.move(file.toPath(), targetFile); - } catch (FileAlreadyExistsException e) { - throw alreadyExists(createFileContext(toBeCreated)); - } - } + public void addFileToScm(String name, Path file) { try { - addFileToHg(targetFile.toFile()); + addFileToHg(file.toFile()); } catch (ExecutionException e) { throwInternalRepositoryException("could not add new file to index", e); } } @Override - public void modify(String path, File file) throws IOException { - Path targetFile = new File(workingRepository.getDirectory(), path).toPath(); - createDirectories(targetFile); - if (!targetFile.toFile().exists()) { - throw notFound(createFileContext(path)); - } - Files.move(file.toPath(), targetFile, REPLACE_EXISTING); - try { - addFileToHg(targetFile.toFile()); - } catch (ExecutionException e) { - throwInternalRepositoryException("could not modify existing file", e); - } + public void doScmDelete(String toBeDeleted) { + RemoveCommand.on(workingRepository).execute(toBeDeleted); } - private void createDirectories(Path targetFile) throws IOException { - try { - Files.createDirectories(targetFile.getParent()); - } catch (FileAlreadyExistsException e) { - throw alreadyExists(createFileContext(targetFile.toString())); - } + @Override + public sonia.scm.repository.Repository getRepository() { + return context.getScmRepository(); } - private ContextEntry.ContextBuilder createFileContext(String path) { - ContextEntry.ContextBuilder contextBuilder = entity("file", path); - if (!StringUtils.isEmpty(request.getBranch())) { - contextBuilder.in("branch", request.getBranch()); - } - contextBuilder.in(context.getScmRepository()); - return contextBuilder; + @Override + public String getBranch() { + return request.getBranch(); + } + + public File getWorkDir() { + return workingRepository.getDirectory(); } private void addFileToHg(File file) { diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 7cd4c3602b..832c9aead3 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -242,7 +242,7 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider @Override public ModifyCommand getModifyCommand() { - return new HgModifyCommand(context, workdirFactory); + return new HgModifyCommand(context, handler.getWorkdirFactory()); } /** From c97c11f904b31b7e795875ff5ce2b1403679532b Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Tue, 8 Oct 2019 14:10:00 +0200 Subject: [PATCH 11/14] fix fileview command since it was using a deprecated api which is no longer available in newer mercurial versions (<= 4.7) --- .../src/main/resources/sonia/scm/hg/ext/fileview.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py index c123660a83..faa4591e6f 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py @@ -34,7 +34,7 @@ Prints date, size and last message of files. """ from collections import defaultdict -from mercurial import cmdutil,util +from mercurial import scmutil cmdtable = {} @@ -273,7 +273,7 @@ class File_Viewer: ('t', 'transport', False, 'format the output for command server'), ]) def fileview(ui, repo, **opts): - revCtx = repo[opts["revision"]] + revCtx = scmutil.revsingle(repo, opts["revision"]) subrepos = {} if not opts["disableSubRepositoryDetection"]: subrepos = collect_sub_repositories(revCtx) From 416eccacc895c76bced8d786f7833f23b006d723 Mon Sep 17 00:00:00 2001 From: Eduard Heimbuch Date: Tue, 8 Oct 2019 15:46:56 +0200 Subject: [PATCH 12/14] small fixes --- .../scm/repository/spi/HgModifyCommand.java | 2 +- .../spi/HgRepositoryServiceProvider.java | 5 +---- .../spi/HgRepositoryServiceResolver.java | 6 ++--- .../api/v2/resources/MergeResourceTest.java | 22 ++++++------------- 4 files changed, 11 insertions(+), 24 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java index cd0a649b6e..0294b6902b 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgModifyCommand.java @@ -92,7 +92,7 @@ public class HgModifyCommand implements ModifyCommand { return pullCommand.execute(workingCopy.getDirectory().getAbsolutePath()); } catch (Exception e) { throw new IntegrateChangesFromWorkdirException(context.getScmRepository(), - String.format("Could not pull modify changes from working copy to central repository", request.getBranch()), + String.format("Could not pull modify changes from working copy to central repository for branch %s", request.getBranch()), e); } } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java index 832c9aead3..c80699add8 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceProvider.java @@ -78,11 +78,10 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider //~--- constructors --------------------------------------------------------- HgRepositoryServiceProvider(HgRepositoryHandler handler, - HgHookManager hookManager, Repository repository, HgWorkdirFactory workdirFactory) + HgHookManager hookManager, Repository repository) { this.repository = repository; this.handler = handler; - this.workdirFactory = workdirFactory; this.repositoryDirectory = handler.getDirectory(repository.getId()); this.context = new HgCommandContext(hookManager, handler, repository, repositoryDirectory); @@ -294,6 +293,4 @@ public class HgRepositoryServiceProvider extends RepositoryServiceProvider /** Field description */ private File repositoryDirectory; - - private final HgWorkdirFactory workdirFactory; } diff --git a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java index 7b793e1b57..7519cb564d 100644 --- a/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java +++ b/scm-plugins/scm-hg-plugin/src/main/java/sonia/scm/repository/spi/HgRepositoryServiceResolver.java @@ -49,15 +49,13 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver private final HgRepositoryHandler handler; private final HgHookManager hookManager; - private final HgWorkdirFactory workdirFactory; @Inject public HgRepositoryServiceResolver(HgRepositoryHandler handler, - HgHookManager hookManager, HgWorkdirFactory workdirFactory) + HgHookManager hookManager) { this.handler = handler; this.hookManager = hookManager; - this.workdirFactory = workdirFactory; } @Override @@ -65,7 +63,7 @@ public class HgRepositoryServiceResolver implements RepositoryServiceResolver HgRepositoryServiceProvider provider = null; if (HgRepositoryHandler.TYPE_NAME.equalsIgnoreCase(repository.getType())) { - provider = new HgRepositoryServiceProvider(handler, hookManager, repository, workdirFactory); + provider = new HgRepositoryServiceProvider(handler, hookManager, repository); } return provider; diff --git a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java index 7181912cfe..202b2d20f1 100644 --- a/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java +++ b/scm-webapp/src/test/java/sonia/scm/api/v2/resources/MergeResourceTest.java @@ -108,10 +108,7 @@ public class MergeResourceTest extends RepositoryTestBase { @Test void shouldHandleSuccessfulMerge() throws Exception { when(mergeCommand.merge(any())).thenReturn(MergeCommandResult.success()); - User user = createDummyUser("dummy"); - PrincipalCollection collection = mock(PrincipalCollection.class); - when(subject.getPrincipals()).thenReturn(collection); - when(collection.oneByType(User.class)).thenReturn(user); + mockUser(); URL url = Resources.getResource("sonia/scm/api/v2/mergeCommand.json"); byte[] mergeCommandJson = Resources.toByteArray(url); @@ -129,10 +126,7 @@ public class MergeResourceTest extends RepositoryTestBase { @Test void shouldHandleFailedMerge() throws Exception { when(mergeCommand.merge(any())).thenReturn(MergeCommandResult.failure(asList("file1", "file2"))); - User user = createDummyUser("dummy"); - PrincipalCollection collection = mock(PrincipalCollection.class); - when(subject.getPrincipals()).thenReturn(collection); - when(collection.oneByType(User.class)).thenReturn(user); + mockUser(); URL url = Resources.getResource("sonia/scm/api/v2/mergeCommand.json"); byte[] mergeCommandJson = Resources.toByteArray(url); @@ -201,13 +195,11 @@ public class MergeResourceTest extends RepositoryTestBase { assertThat(response.getStatus()).isEqualTo(204); } - private User createDummyUser(String name) { - User user = new User(); - user.setName(name); - user.setType("xml"); - user.setPassword("secret"); - user.setCreationDate(System.currentTimeMillis()); - return user; + + private void mockUser() { + PrincipalCollection collection = mock(PrincipalCollection.class); + when(subject.getPrincipals()).thenReturn(collection); + when(collection.oneByType(User.class)).thenReturn(new User("dummy")); } } } From 1595d31074f9f523208471140c545db05114aa2a Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Tue, 8 Oct 2019 15:50:04 +0200 Subject: [PATCH 13/14] fix indentation --- .../src/main/resources/sonia/scm/hg/ext/fileview.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py index faa4591e6f..1871200389 100644 --- a/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py +++ b/scm-plugins/scm-hg-plugin/src/main/resources/sonia/scm/hg/ext/fileview.py @@ -1,8 +1,8 @@ # # Copyright (c) 2010, Sebastian Sdorra -# All rights reserved. +# aLL rights reserved. # -# Redistribution and use in source and binary forms, with or without +# rEDistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions are met: # # 1. Redistributions of source code must retain the above copyright notice, @@ -122,7 +122,7 @@ class File_Object: return result class File_Walker: - + def __init__(self, sub_repositories, visitor): self.visitor = visitor self.sub_repositories = sub_repositories @@ -273,7 +273,7 @@ class File_Viewer: ('t', 'transport', False, 'format the output for command server'), ]) def fileview(ui, repo, **opts): - revCtx = scmutil.revsingle(repo, opts["revision"]) + revCtx = scmutil.revsingle(repo, opts["revision"]) subrepos = {} if not opts["disableSubRepositoryDetection"]: subrepos = collect_sub_repositories(revCtx) From 01cb18ada84803e5aa6ec6bcd8bc455bdd7a37fd Mon Sep 17 00:00:00 2001 From: Rene Pfeuffer Date: Wed, 9 Oct 2019 09:39:10 +0000 Subject: [PATCH 14/14] Close branch feature/editor_plugin_hg