/**
* This file is part of git-as-svn. It is subject to the license terms
* in the LICENSE file found in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/gpl-2.0.html. No part of git-as-svn,
* including this file, may be copied, modified, propagated, or distributed
* except according to the terms contained in the LICENSE file.
*/
package svnserver;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.testng.Assert;
import org.tmatesoft.svn.core.*;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.diff.SVNDeltaGenerator;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Helper to testing svn repository.
*
* @author Artem V. Navrotskiy <bozaro@users.noreply.github.com>
*/
public final class SvnTestHelper {
@NotNull
private static final byte[] emptyBytes = {};
private SvnTestHelper() {
}
public static void checkFileProp(@NotNull SVNRepository repo, @NotNull String filePath, @Nullable Map<String, String> expected) throws SVNException {
SVNProperties props = new SVNProperties();
repo.getFile(filePath, repo.getLatestRevision(), props, null);
checkProp(props, expected);
}
public static void checkDirProp(@NotNull SVNRepository repo, @NotNull String filePath, @Nullable Map<String, String> expected) throws SVNException {
SVNProperties props = new SVNProperties();
repo.getDir(filePath, repo.getLatestRevision(), props, new ArrayList<>());
checkProp(props, expected);
}
private static void checkProp(@NotNull SVNProperties props, @Nullable Map<String, String> expected) {
final Map<String, String> check = new HashMap<>();
if (expected != null) {
check.putAll(expected);
}
for (Map.Entry<String, SVNPropertyValue> entry : props.asMap().entrySet()) {
if (entry.getKey().startsWith(SVNProperty.SVN_ENTRY_PREFIX)) continue;
Assert.assertEquals(entry.getValue().getString(), check.remove(entry.getKey()));
}
Assert.assertTrue(check.isEmpty());
}
@NotNull
public static SVNCommitInfo createFile(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull String content, @Nullable Map<String, String> props) throws SVNException, IOException {
return createFile(repo, filePath, content.getBytes(StandardCharsets.UTF_8), props);
}
@NotNull
public static SVNCommitInfo createFile(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull byte[] content, @Nullable Map<String, String> props) throws SVNException, IOException {
final ISVNEditor editor = repo.getCommitEditor("Create file: " + filePath, null, false, null);
editor.openRoot(-1);
int index = 0;
int depth = 1;
while (true) {
index = filePath.indexOf('/', index + 1);
if (index < 0) {
break;
}
editor.openDir(filePath.substring(0, index), -1);
depth++;
}
editor.addFile(filePath, null, -1);
if (props != null) {
for (Map.Entry<String, String> entry : props.entrySet()) {
editor.changeFileProperty(filePath, entry.getKey(), SVNPropertyValue.create(entry.getValue()));
}
}
sendDeltaAndClose(editor, filePath, null, content);
for (int i = 0; i < depth; ++i) {
editor.closeDir();
}
return editor.closeEdit();
}
@NotNull
public static SVNCommitInfo deleteFile(@NotNull SVNRepository repo, @NotNull String filePath) throws SVNException, IOException {
long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Delete file: " + filePath, null, false, null);
editor.openRoot(-1);
int index = 0;
int depth = 1;
while (true) {
index = filePath.indexOf('/', index + 1);
if (index < 0) {
break;
}
editor.openDir(filePath.substring(0, index), -1);
depth++;
}
editor.deleteEntry(filePath, latestRevision);
for (int i = 0; i < depth; ++i) {
editor.closeDir();
}
return editor.closeEdit();
}
@NotNull
public static SVNCommitInfo modifyFile(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull String newData, long fileRev) throws SVNException, IOException {
return modifyFile(repo, filePath, newData.getBytes(StandardCharsets.UTF_8), fileRev);
}
@NotNull
public static SVNCommitInfo modifyFile(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull byte[] newData, long fileRev) throws SVNException, IOException {
final ByteArrayOutputStream oldData = new ByteArrayOutputStream();
repo.getFile(filePath, fileRev, null, oldData);
final ISVNEditor editor = repo.getCommitEditor("Modify file: " + filePath, null, false, null);
editor.openRoot(-1);
int index = 0;
int depth = 1;
while (true) {
index = filePath.indexOf('/', index + 1);
if (index < 0) {
break;
}
editor.openDir(filePath.substring(0, index), -1);
depth++;
}
editor.openFile(filePath, fileRev);
sendDeltaAndClose(editor, filePath, oldData.toByteArray(), newData);
for (int i = 0; i < depth; ++i) {
editor.closeDir();
}
return editor.closeEdit();
}
public static void sendDeltaAndClose(@NotNull ISVNEditor editor, @NotNull String filePath, @Nullable String oldData, @Nullable String newData) throws SVNException, IOException {
sendDeltaAndClose(editor, filePath, oldData == null ? null : oldData.getBytes(StandardCharsets.UTF_8), newData == null ? null : newData.getBytes(StandardCharsets.UTF_8));
}
public static void sendDeltaAndClose(@NotNull ISVNEditor editor, @NotNull String filePath, @Nullable byte[] oldData, @Nullable byte[] newData) throws SVNException, IOException {
try (
ByteArrayInputStream oldStream = new ByteArrayInputStream(oldData == null ? emptyBytes : oldData);
ByteArrayInputStream newStream = new ByteArrayInputStream(newData == null ? emptyBytes : newData)
) {
editor.applyTextDelta(filePath, null);
SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
String checksum = deltaGenerator.sendDelta(filePath, oldStream, 0, newStream, editor, true);
editor.closeFile(filePath, checksum);
}
}
public static void checkFileContent(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull String content) throws IOException, SVNException {
try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
repo.getFile(filePath, repo.getLatestRevision(), null, stream);
Assert.assertEquals(new String(stream.toByteArray(), StandardCharsets.UTF_8), content);
}
}
public static void checkFileContent(@NotNull SVNRepository repo, @NotNull String filePath, @NotNull byte[] content) throws IOException, SVNException {
try (ByteArrayOutputStream stream = new ByteArrayOutputStream()) {
repo.getFile(filePath, repo.getLatestRevision(), null, stream);
Assert.assertEquals(stream.toByteArray(), content);
}
}
}