Introduce new API for modifications

New modifications includes list of 'renames'. Therefore we introduce
a new base class Modification.
This commit is contained in:
René Pfeuffer
2020-05-14 13:20:56 +02:00
parent 76354aa839
commit 35ffc5c4e2
18 changed files with 326 additions and 127 deletions

View File

@@ -0,0 +1,94 @@
/*
* MIT License
*
* Copyright (c) 2020-present Cloudogu GmbH and Contributors
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository;
import lombok.AllArgsConstructor;
import lombok.Getter;
import java.io.Serializable;
public interface Modification extends EffectedPath, Serializable {
@Getter
@AllArgsConstructor
class Added implements Modification {
private final String path;
@Override
public String getEffectedPath() {
return path;
}
}
@Getter
@AllArgsConstructor
class Removed implements Modification {
private final String path;
@Override
public String getEffectedPath() {
return path;
}
}
@Getter
@AllArgsConstructor
class Modified implements Modification {
private final String path;
@Override
public String getEffectedPath() {
return path;
}
}
@Getter
@AllArgsConstructor
class Renamed implements Modification {
private final String oldPath;
private final String newPath;
@Override
public String getEffectedPath() {
return newPath;
}
}
@Getter
@AllArgsConstructor
class Copied implements Modification {
private final String sourcePath;
private final String targetPath;
@Override
public String getEffectedPath() {
return targetPath;
}
}
}
interface EffectedPath {
String getEffectedPath();
}

View File

@@ -24,71 +24,74 @@
package sonia.scm.repository;
import com.google.common.collect.Lists;
import com.google.common.collect.ImmutableList;
import lombok.Builder;
import lombok.EqualsAndHashCode;
import lombok.Setter;
import lombok.Getter;
import lombok.ToString;
import java.io.Serializable;
import java.util.Collection;
import java.util.List;
import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
@EqualsAndHashCode
@ToString
@Setter
@Getter
public class Modifications implements Serializable {
private static final long serialVersionUID = -8902033326668658140L;
private String revision;
/**
* lists of changed files
*/
private List<String> added;
private List<String> modified;
private List<String> removed;
private final String revision;
private final Collection<Modification> modifications;
public Modifications() {
public Modifications(String revision, Modification... modifications) {
this(revision, asList(modifications));
}
public Modifications(List<String> added) {
this(added, null, null);
public Modifications(String revision, Collection<Modification> modifications) {
this.revision = revision;
this.modifications = ImmutableList.copyOf(modifications);
}
public Modifications(List<String> added, List<String> modified) {
this(added, modified, null);
public List<String> getEffectedPaths() {
return modifications.stream().map(Modification::getEffectedPath).collect(toList());
}
public Modifications(List<String> added, List<String> modified, List<String> removed) {
this.added = added;
this.modified = modified;
this.removed = removed;
public List<Modification.Added> getAdded() {
return modifications.stream()
.filter(m -> m instanceof Modification.Added)
.map(m -> (Modification.Added) m)
.collect(toList());
}
public List<String> getAdded() {
if (added == null) {
added = Lists.newArrayList();
}
return added;
public List<Modification.Removed> getRemoved() {
return modifications.stream()
.filter(m -> m instanceof Modification.Removed)
.map(m -> (Modification.Removed) m)
.collect(toList());
}
public List<String> getModified() {
if (modified == null) {
modified = Lists.newArrayList();
}
return modified;
public List<Modification.Modified> getModified() {
return modifications.stream()
.filter(m -> m instanceof Modification.Modified)
.map(m -> (Modification.Modified) m)
.collect(toList());
}
public List<String> getRemoved() {
if (removed == null) {
removed = Lists.newArrayList();
}
return removed;
public List<Modification.Renamed> getRenamed() {
return modifications.stream()
.filter(m -> m instanceof Modification.Renamed)
.map(m -> (Modification.Renamed) m)
.collect(toList());
}
public String getRevision() {
return revision;
public List<Modification.Copied> getCopied() {
return modifications.stream()
.filter(m -> m instanceof Modification.Copied)
.map(m -> (Modification.Copied) m)
.collect(toList());
}
}

View File

@@ -113,17 +113,23 @@ final class Differ implements AutoCloseable {
}
private Diff diff(Repository repository) throws IOException {
List<DiffEntry> entries = scanWithRename(repository, pathFilter, treeWalk);
return new Diff(commit, entries);
}
static List<DiffEntry> scanWithRename(Repository repository, PathFilter pathFilter, TreeWalk treeWalk) throws IOException {
List<DiffEntry> entries;
try (DiffFormatter diffFormatter = new DiffFormatter(null)) {
diffFormatter.setRepository(repository);
diffFormatter.setDetectRenames(true);
if (pathFilter != null) {
diffFormatter.setPathFilter(pathFilter);
}
List<DiffEntry> entries = diffFormatter.scan(
entries = diffFormatter.scan(
treeWalk.getTree(0, AbstractTreeIterator.class),
treeWalk.getTree(1, AbstractTreeIterator.class));
return new Diff(commit, entries);
}
return entries;
}
@Override

View File

@@ -34,10 +34,13 @@ import org.eclipse.jgit.treewalk.EmptyTreeIterator;
import org.eclipse.jgit.treewalk.TreeWalk;
import sonia.scm.repository.GitUtil;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Modifications;
import java.io.IOException;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
@@ -72,15 +75,14 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
treeWalk.addTree(new EmptyTreeIterator());
}
treeWalk.addTree(commit.getTree());
List<DiffEntry> entries = DiffEntry.scan(treeWalk);
Modifications modifications = new Modifications();
List<DiffEntry> entries = Differ.scanWithRename(context.open(), null, treeWalk);
Collection<Modification> modifications = new ArrayList<>();
for (DiffEntry e : entries) {
if (!e.getOldId().equals(e.getNewId())) {
appendModification(modifications, e);
if (!e.getOldId().equals(e.getNewId()) || !e.getOldPath().equals(e.getNewPath())) {
modifications.add(asModification(e));
}
}
modifications.setRevision(revision);
return modifications;
return new Modifications(revision, modifications);
}
@Override
@@ -111,16 +113,19 @@ public class GitModificationsCommand extends AbstractGitCommand implements Modif
return getModifications(request.getRevision());
}
private void appendModification(Modifications modifications, DiffEntry entry) throws UnsupportedModificationTypeException {
private Modification asModification(DiffEntry entry) throws UnsupportedModificationTypeException {
DiffEntry.ChangeType type = entry.getChangeType();
if (type == DiffEntry.ChangeType.ADD) {
modifications.getAdded().add(entry.getNewPath());
} else if (type == DiffEntry.ChangeType.MODIFY) {
modifications.getModified().add(entry.getNewPath());
} else if (type == DiffEntry.ChangeType.DELETE) {
modifications.getRemoved().add(entry.getOldPath());
} else {
throw new UnsupportedModificationTypeException(entity(repository), MessageFormat.format("The modification type: {0} is not supported.", type));
switch (type) {
case ADD:
return new Modification.Added(entry.getNewPath());
case MODIFY:
return new Modification.Modified(entry.getNewPath());
case DELETE:
return new Modification.Removed(entry.getOldPath());
case RENAME:
return new Modification.Renamed(entry.getOldPath(), entry.getNewPath());
default:
throw new UnsupportedModificationTypeException(entity(repository), MessageFormat.format("The modification type: {0} is not supported.", type));
}
}
}

View File

@@ -39,11 +39,11 @@ import java.io.File;
import java.io.IOException;
import static java.nio.charset.Charset.defaultCharset;
import static org.assertj.core.api.Assertions.assertThat;
import static org.hamcrest.Matchers.contains;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.when;
@@ -188,7 +188,9 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
assertTrue("removed list should be empty", modifications.getRemoved().isEmpty());
assertFalse("added list should not be empty", modifications.getAdded().isEmpty());
assertEquals(2, modifications.getAdded().size());
assertThat(modifications.getAdded(), contains("a.txt", "b.txt"));
assertThat(modifications.getAdded())
.extracting("path")
.containsExactly("a.txt", "b.txt");
}
@Test
@@ -198,14 +200,14 @@ public class GitLogCommandTest extends AbstractGitCommandTestBase
GitLogCommand command = createCommand();
Changeset c = command.getChangeset("435df2f061add3589cb3", request);
Assertions.assertThat(c.getBranches()).containsOnly("master");
assertThat(c.getBranches()).containsOnly("master");
}
@Test
public void shouldNotReturnCommitFromDifferentBranch() {
when(request.getBranch()).thenReturn("master");
Changeset changeset = createCommand().getChangeset("3f76a12f08a6ba0dc988c68b7f0b2cd190efc3c4", request);
Assertions.assertThat(changeset).isNull();
assertThat(changeset).isNull();
}
@Test

View File

@@ -40,6 +40,7 @@ import org.junit.jupiter.api.Assertions;
import sonia.scm.NoChangesMadeException;
import sonia.scm.NotFoundException;
import sonia.scm.repository.GitWorkdirFactory;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Person;
import sonia.scm.repository.api.MergeCommandResult;
import sonia.scm.repository.api.MergeStrategy;
@@ -318,7 +319,7 @@ public class GitMergeCommandTest extends AbstractGitCommandTestBase {
assertThat(message).isEqualTo("squash three commits");
GitModificationsCommand modificationsCommand = new GitModificationsCommand(createContext());
List<String> changes = modificationsCommand.getModifications("master").getAdded();
List<Modification.Added> changes = modificationsCommand.getModifications("master").getAdded();
assertThat(changes.size()).isEqualTo(3);
}

View File

@@ -86,6 +86,25 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase {
assertModifications.accept(outgoingModificationsCommand.getModifications(revision));
}
@Test
public void shouldReadRenamedFiles() throws Exception {
String originalFile = "a.txt";
write(outgoing, outgoingDirectory, originalFile, "bal bla");
commit(outgoing, "add file");
write(outgoing, outgoingDirectory, "b.txt", "bal bla");
File file = new File(outgoingDirectory, originalFile);
file.delete();
outgoing.rm().addFilepattern(originalFile).call();
RevCommit modifiedFileCommit = commit(outgoing, "rename file");
String revision = modifiedFileCommit.getName();
Consumer<Modifications> assertModifications = assertRenamedFiles("b.txt");
assertModifications.accept(outgoingModificationsCommand.getModifications(revision));
pushOutgoingAndPullIncoming();
assertModifications.accept(incomingModificationsCommand.getModifications(revision));
}
void pushOutgoingAndPullIncoming() throws IOException {
GitPushCommand cmd = new GitPushCommand(handler, new GitContext(outgoingDirectory, outgoingRepository, null));
PushCommandRequest request = new PushCommandRequest();
@@ -102,31 +121,62 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase {
assertThat(modifications).isNotNull();
assertThat(modifications.getAdded())
.as("added files modifications")
.hasSize(0);
.asList()
.isEmpty();
assertThat(modifications.getModified())
.as("modified files modifications")
.hasSize(0);
.asList()
.isEmpty();
assertThat(modifications.getRemoved())
.as("removed files modifications")
.asList()
.hasSize(1)
.extracting("path")
.containsOnly(fileName);
};
}
Consumer<Modifications> assertRenamedFiles(String fileName) {
return (modifications) -> {
assertThat(modifications).isNotNull();
assertThat(modifications.getAdded())
.as("added files modifications")
.asList()
.isEmpty();
assertThat(modifications.getModified())
.as("modified files modifications")
.asList()
.isEmpty();
assertThat(modifications.getRemoved())
.as("removed files modifications")
.asList()
.isEmpty();
assertThat(modifications.getRenamed())
.as("renamed files modifications")
.asList()
.hasSize(1)
.extracting("newPath")
.containsOnly(fileName);
};
}
Consumer<Modifications> assertModifiedFiles(String file) {
return (modifications) -> {
assertThat(modifications).isNotNull();
assertThat(modifications.getAdded())
.as("added files modifications")
.hasSize(0);
.asList()
.isEmpty();
assertThat(modifications.getModified())
.as("modified files modifications")
.asList()
.extracting("path")
.hasSize(1)
.containsOnly(file);
assertThat(modifications.getRemoved())
.as("removed files modifications")
.hasSize(0);
.asList()
.isEmpty();
};
}
@@ -135,14 +185,18 @@ public class GitModificationsCommandTest extends AbstractRemoteCommandTestBase {
assertThat(modifications).isNotNull();
assertThat(modifications.getAdded())
.as("added files modifications")
.asList()
.hasSize(1)
.extracting("path")
.containsOnly(file);
assertThat(modifications.getModified())
.as("modified files modifications")
.hasSize(0);
.asList()
.isEmpty();
assertThat(modifications.getRemoved())
.as("removed files modifications")
.hasSize(0);
.asList()
.isEmpty();
};
}
}

View File

@@ -24,9 +24,12 @@
package sonia.scm.repository.spi;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.spi.javahg.HgLogChangesetCommand;
import java.util.Collection;
public class HgModificationsCommand extends AbstractCommand implements ModificationsCommand {
HgModificationsCommand(HgCommandContext context) {
@@ -38,9 +41,8 @@ public class HgModificationsCommand extends AbstractCommand implements Modificat
public Modifications getModifications(String revision) {
com.aragost.javahg.Repository repository = open();
HgLogChangesetCommand hgLogChangesetCommand = HgLogChangesetCommand.on(repository, getContext().getConfig());
Modifications modifications = hgLogChangesetCommand.rev(revision).extractModifications();
modifications.setRevision(revision);
return modifications;
Collection<Modification> modifications = hgLogChangesetCommand.rev(revision).extractModifications();
return new Modifications(revision, modifications);
}
@Override

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository.spi.javahg;
//~--- non-JDK imports --------------------------------------------------------
@@ -36,10 +36,13 @@ import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Lists;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.Person;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
//~--- JDK imports ------------------------------------------------------------
@@ -251,7 +254,7 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
return changeset;
}
protected Modifications readModificationsFromStream(HgInputStream in) {
protected Collection<Modification> readModificationsFromStream(HgInputStream in) {
try {
boolean found = in.find(CHANGESET_PATTERN);
if (found) {
@@ -265,16 +268,16 @@ public abstract class AbstractChangesetCommand extends AbstractCommand
return null;
}
private Modifications extractModifications(HgInputStream in) throws IOException {
Modifications modifications = new Modifications();
private Collection<Modification> extractModifications(HgInputStream in) throws IOException {
Collection<Modification> modifications = new ArrayList<>();
String line = in.textUpTo('\n');
while (line.length() > 0) {
if (line.startsWith("a ")) {
modifications.getAdded().add(line.substring(2));
modifications.add(new Modification.Added(line.substring(2)));
} else if (line.startsWith("m ")) {
modifications.getModified().add(line.substring(2));
modifications.add(new Modification.Modified(line.substring(2)));
} else if (line.startsWith("d ")) {
modifications.getRemoved().add(line.substring(2));
modifications.add(new Modification.Removed(line.substring(2)));
}
line = in.textUpTo('\n');
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository.spi.javahg;
import com.aragost.javahg.Repository;
@@ -31,9 +31,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sonia.scm.repository.Changeset;
import sonia.scm.repository.HgConfig;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.Modification;
import java.io.IOException;
import java.util.Collection;
import java.util.List;
/**
@@ -64,7 +65,7 @@ public class HgLogChangesetCommand extends AbstractChangesetCommand {
return readListFromStream(getHgInputStream(files, CHANGESET_EAGER_STYLE_PATH));
}
public Modifications extractModifications(String... files) {
public Collection<Modification> extractModifications(String... files) {
HgInputStream hgInputStream = getHgInputStream(files, CHANGESET_EAGER_STYLE_PATH);
try {
return readModificationsFromStream(hgInputStream);

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository.spi;
//~--- non-JDK imports --------------------------------------------------------
@@ -33,11 +33,10 @@ import sonia.scm.repository.Modifications;
import java.io.IOException;
import static org.hamcrest.Matchers.contains;
import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
//~--- JDK imports ------------------------------------------------------------
@@ -162,7 +161,9 @@ public class HgLogCommandTest extends AbstractHgCommandTestBase
assertTrue("removed list should be empty", modifications.getRemoved().isEmpty());
assertFalse("added list should not be empty", modifications.getAdded().isEmpty());
assertEquals(2, modifications.getAdded().size());
assertThat(modifications.getAdded(), contains("a.txt", "b.txt"));
assertThat(modifications.getAdded())
.extracting("path")
.containsExactly("a.txt", "b.txt");
}
@Test

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository.spi;
import com.aragost.javahg.Changeset;
@@ -96,6 +96,7 @@ public class HgModificationsCommandTest extends IncomingOutgoingTestBase {
assertThat(modifications.getRemoved())
.as("removed files modifications")
.hasSize(1)
.extracting("path")
.containsOnly(fileName);
};
}
@@ -110,6 +111,7 @@ public class HgModificationsCommandTest extends IncomingOutgoingTestBase {
assertThat(modifications.getModified())
.as("modified files modifications")
.hasSize(1)
.extracting("path")
.containsOnly(file);
assertThat(modifications.getRemoved())
.as("removed files modifications")
@@ -123,6 +125,7 @@ public class HgModificationsCommandTest extends IncomingOutgoingTestBase {
assertThat(modifications.getAdded())
.as("added files modifications")
.hasSize(1)
.extracting("path")
.containsOnly(addedFile);
assertThat(modifications.getModified())
.as("modified files modifications")

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.repository;
//~--- non-JDK imports --------------------------------------------------------
@@ -49,7 +49,11 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;
import static java.util.Collections.emptyList;
import static java.util.Optional.empty;
import static sonia.scm.ContextEntry.ContextBuilder.entity;
import static sonia.scm.NotFoundException.notFound;
@@ -116,30 +120,23 @@ public final class SvnUtil
public static Modifications createModifications(SVNLogEntry entry, String revision) {
Modifications modifications = new Modifications();
modifications.setRevision(revision);
Map<String, SVNLogEntryPath> changeMap = entry.getChangedPaths();
List<Modification> modificationList;
if (Util.isNotEmpty(changeMap)) {
for (SVNLogEntryPath e : changeMap.values()) {
appendModification(modifications, e.getType(), e.getPath());
}
modificationList = changeMap.values().stream()
.map(e -> asModification(e.getType(), e.getPath()))
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toList());
} else {
modificationList = emptyList();
}
return modifications;
return new Modifications(revision, modificationList);
}
/**
* Method description
*
*
* @param modifications
* @param type
* @param path
*/
public static void appendModification(Modifications modifications, char type,
String path)
{
public static Optional<Modification> asModification(char type, String path) {
if (path.startsWith("/"))
{
path = path.substring(1);
@@ -148,23 +145,18 @@ public final class SvnUtil
switch (type)
{
case SVNLogEntryPath.TYPE_ADDED :
modifications.getAdded().add(path);
break;
return Optional.of(new Modification.Added(path));
case SVNLogEntryPath.TYPE_DELETED :
modifications.getRemoved().add(path);
break;
return Optional.of(new Modification.Removed(path));
case TYPE_UPDATED :
case SVNLogEntryPath.TYPE_MODIFIED :
modifications.getModified().add(path);
break;
return Optional.of(new Modification.Modified(path));
default :
logger.debug("unknown modification type {}", type);
return empty();
}
}

View File

@@ -31,10 +31,12 @@ import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.wc.SVNClientManager;
import org.tmatesoft.svn.core.wc.admin.SVNLookClient;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.SvnUtil;
import sonia.scm.util.Util;
import java.util.ArrayList;
import java.util.Collection;
@Slf4j
@@ -78,12 +80,12 @@ public class SvnModificationsCommand extends AbstractSvnCommand implements Modif
private Modifications getModificationsFromTransaction(String transaction) throws SVNException {
log.debug("get svn modifications from transaction: {}", transaction);
final Modifications modifications = new Modifications();
SVNLookClient client = SVNClientManager.newInstance().getLookClient();
Collection<Modification> modificationList = new ArrayList<>();
client.doGetChanged(context.getDirectory(), transaction,
e -> SvnUtil.appendModification(modifications, e.getType(), e.getPath()), true);
e -> SvnUtil.asModification(e.getType(), e.getPath()).ifPresent(modificationList::add), true);
return modifications;
return new Modifications(null, modificationList);
}
@Override

View File

@@ -143,8 +143,8 @@ public class SvnLogCommandTest extends AbstractSvnCommandTestBase
assertEquals(1, modifications.getModified().size());
assertEquals(1, modifications.getRemoved().size());
assertTrue("added list should be empty", modifications.getAdded().isEmpty());
assertEquals("a.txt", modifications.getModified().get(0));
assertEquals("b.txt", modifications.getRemoved().get(0));
assertEquals("a.txt", modifications.getModified().get(0).getPath());
assertEquals("b.txt", modifications.getRemoved().get(0).getPath());
}
@Test

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.HalRepresentation;
@@ -54,10 +54,21 @@ public class ModificationsDto extends HalRepresentation {
*/
private List<String> removed;
/**
* Mapping of renamed files
*/
private List<RenamedDto> renamed;
@Override
@SuppressWarnings("squid:S1185") // We want to have this method available in this package
protected HalRepresentation add(Links links) {
return super.add(links);
}
@Getter
@Setter
public static class RenamedDto {
private String oldPath;
private String newPath;
}
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import de.otto.edison.hal.Links;
@@ -30,6 +30,7 @@ import org.mapstruct.Context;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.MappingTarget;
import sonia.scm.repository.Modification;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.Repository;
@@ -52,4 +53,18 @@ public abstract class ModificationsToDtoMapper {
.self(resourceLinks.modifications().self(repository.getNamespace(), repository.getName(), target.getRevision()));
target.add(linksBuilder.build());
}
String map(Modification.Added added) {
return added.getPath();
}
String map(Modification.Removed removed) {
return removed.getPath();
}
String map(Modification.Modified modified) {
return modified.getPath();
}
abstract ModificationsDto.RenamedDto map(Modification.Renamed renamed);
}

View File

@@ -21,7 +21,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*/
package sonia.scm.api.v2.resources;
import com.google.inject.util.Providers;
@@ -30,7 +30,6 @@ import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.SubjectThreadState;
import org.apache.shiro.util.ThreadContext;
import org.apache.shiro.util.ThreadState;
import org.assertj.core.util.Lists;
import org.jboss.resteasy.mock.MockHttpRequest;
import org.jboss.resteasy.mock.MockHttpResponse;
import org.junit.After;
@@ -41,6 +40,9 @@ import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import sonia.scm.repository.InternalRepositoryException;
import sonia.scm.repository.Modification.Added;
import sonia.scm.repository.Modification.Modified;
import sonia.scm.repository.Modification.Removed;
import sonia.scm.repository.Modifications;
import sonia.scm.repository.NamespaceAndName;
import sonia.scm.repository.Repository;
@@ -141,7 +143,6 @@ public class ModificationsResourceTest extends RepositoryTestBase {
@Test
public void shouldGetModifications() throws Exception {
Modifications modifications = new Modifications();
String revision = "revision";
String addedFile_1 = "a.txt";
String addedFile_2 = "b.txt";
@@ -149,10 +150,13 @@ public class ModificationsResourceTest extends RepositoryTestBase {
String modifiedFile_2 = "c.txt";
String removedFile_1 = "e.txt";
String removedFile_2 = "f.txt";
modifications.setRevision(revision);
modifications.setAdded(Lists.newArrayList(addedFile_1, addedFile_2));
modifications.setModified(Lists.newArrayList(modifiedFile_1, modifiedFile_2));
modifications.setRemoved(Lists.newArrayList(removedFile_1, removedFile_2));
Modifications modifications = new Modifications(revision,
new Added(addedFile_1),
new Added(addedFile_2),
new Modified(modifiedFile_1),
new Modified(modifiedFile_2),
new Removed(removedFile_1),
new Removed(removedFile_2));
when(modificationsCommandBuilder.getModifications()).thenReturn(modifications);
when(modificationsCommandBuilder.revision(eq(revision))).thenReturn(modificationsCommandBuilder);