/**
* 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.server;
import com.google.common.collect.ImmutableMap;
import org.jetbrains.annotations.NotNull;
import org.testng.Assert;
import org.testng.annotations.Test;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.internal.wc.SVNFileUtil;
import org.tmatesoft.svn.core.io.ISVNEditor;
import org.tmatesoft.svn.core.io.SVNRepository;
import svnserver.SvnTestServer;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import static svnserver.SvnTestHelper.*;
/**
* Check file properties.
*
* @author Artem V. Navrotskiy <bozaro@users.noreply.github.com>
*/
public class SvnFilePropertyTest {
@NotNull
private final static Map<String, String> propsEolNative = ImmutableMap.<String, String>builder()
.put(SVNProperty.EOL_STYLE, SVNProperty.EOL_STYLE_NATIVE)
.build();
@NotNull
private final static Map<String, String> propsEolLf = ImmutableMap.<String, String>builder()
.put(SVNProperty.EOL_STYLE, SVNProperty.EOL_STYLE_LF)
.build();
@NotNull
private final static Map<String, String> propsExecutable = ImmutableMap.<String, String>builder()
.put(SVNProperty.EXECUTABLE, "*")
.put(SVNProperty.EOL_STYLE, SVNProperty.EOL_STYLE_NATIVE)
.build();
@NotNull
private final static Map<String, String> propsSymlink = ImmutableMap.<String, String>builder()
.put(SVNProperty.SPECIAL, "*")
.build();
@NotNull
private final static Map<String, String> propsAutoProps = ImmutableMap.<String, String>builder()
.put(SVNProperty.INHERITABLE_AUTO_PROPS, "*.txt = svn:eol-style=LF\n")
.build();
@NotNull
private final static Map<String, String> propsBinary = ImmutableMap.<String, String>builder()
.put(SVNProperty.MIME_TYPE, SVNFileUtil.BINARY_MIME_TYPE)
.build();
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void executable() throws Exception {
//Map<String, String> props = new HashMap<>()["key":""];
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "/non-exec.txt", "", propsEolNative);
createFile(repo, "/exec.txt", "", propsExecutable);
checkFileProp(repo, "/non-exec.txt", propsEolNative);
checkFileProp(repo, "/exec.txt", propsExecutable);
{
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.openFile("/non-exec.txt", latestRevision);
editor.changeFileProperty("/non-exec.txt", SVNProperty.EXECUTABLE, SVNPropertyValue.create("*"));
editor.closeFile("/non-exec.txt", null);
editor.openFile("/exec.txt", latestRevision);
editor.changeFileProperty("/exec.txt", SVNProperty.EXECUTABLE, null);
editor.closeFile("/exec.txt", null);
editor.closeDir();
editor.closeEdit();
}
checkFileProp(repo, "/non-exec.txt", propsExecutable);
checkFileProp(repo, "/exec.txt", propsEolNative);
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void binary() throws Exception {
//Map<String, String> props = new HashMap<>()["key":""];
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "/data.txt", "Test file", propsEolNative);
createFile(repo, "/data.dat", "Test data\0", propsBinary);
checkFileProp(repo, "/data.txt", propsEolNative);
checkFileProp(repo, "/data.dat", propsBinary);
{
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Modify files", null, false, null);
editor.openRoot(-1);
editor.openFile("/data.txt", latestRevision);
editor.changeFileProperty("/data.txt", SVNProperty.MIME_TYPE, SVNPropertyValue.create(SVNFileUtil.BINARY_MIME_TYPE));
editor.changeFileProperty("/data.txt", SVNProperty.EOL_STYLE, null);
sendDeltaAndClose(editor, "/data.txt", "Test file", "Test file\0");
editor.openFile("/data.dat", latestRevision);
editor.changeFileProperty("/data.dat", SVNProperty.MIME_TYPE, null);
editor.changeFileProperty("/data.dat", SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
sendDeltaAndClose(editor, "/data.dat", "Test data\0", "Test data");
editor.closeDir();
editor.closeEdit();
}
checkFileProp(repo, "/data.txt", propsBinary);
checkFileProp(repo, "/data.dat", propsEolNative);
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void symlink() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
final String content = "link foo/bar.txt";
createFile(repo, "/non-link", content, propsEolNative);
createFile(repo, "/link", content, propsSymlink);
checkFileProp(repo, "/non-link", propsEolNative);
checkFileProp(repo, "/link", propsSymlink);
checkFileContent(repo, "/non-link", content);
checkFileContent(repo, "/link", content);
final String content2 = "link bar/foo.txt";
{
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Change symlink property", null, false, null);
editor.openRoot(-1);
editor.openFile("/non-link", latestRevision);
editor.changeFileProperty("/non-link", SVNProperty.EOL_STYLE, null);
editor.changeFileProperty("/non-link", SVNProperty.SPECIAL, SVNPropertyValue.create("*"));
sendDeltaAndClose(editor, "/non-link", content, content2);
editor.openFile("/link", latestRevision);
editor.changeFileProperty("/link", SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
editor.changeFileProperty("/link", SVNProperty.SPECIAL, null);
sendDeltaAndClose(editor, "/link", content, content2);
editor.closeDir();
editor.closeEdit();
}
checkFileProp(repo, "/non-link", propsSymlink);
checkFileProp(repo, "/link", propsEolNative);
checkFileContent(repo, "/non-link", content2);
checkFileContent(repo, "/link", content2);
{
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Change symlink property", null, false, null);
editor.openRoot(-1);
editor.openFile("/non-link", latestRevision);
editor.changeFileProperty("/non-link", SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
editor.changeFileProperty("/non-link", SVNProperty.SPECIAL, null);
editor.closeFile("/non-link", null);
editor.openFile("/link", latestRevision);
editor.changeFileProperty("/link", SVNProperty.EOL_STYLE, null);
editor.changeFileProperty("/link", SVNProperty.SPECIAL, SVNPropertyValue.create("*"));
editor.closeFile("/link", null);
editor.closeDir();
editor.closeEdit();
}
checkFileProp(repo, "/non-link", propsEolNative);
checkFileProp(repo, "/link", propsSymlink);
checkFileContent(repo, "/non-link", content2);
checkFileContent(repo, "/link", content2);
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void symlinkBinary() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
final String content = "link foo/bar.txt";
createFile(repo, "/.gitattributes", "*.bin binary", propsEolNative);
createFile(repo, "/non-link.bin", content, propsBinary);
createFile(repo, "/link.bin", content, propsSymlink);
checkFileProp(repo, "/non-link.bin", propsBinary);
checkFileProp(repo, "/link.bin", propsSymlink);
checkFileContent(repo, "/non-link.bin", content);
checkFileContent(repo, "/link.bin", content);
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitUpdatePropertiesRoot() throws Exception {
//Map<String, String> props = new HashMap<>()["key":""];
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "/sample.txt", "", propsEolNative);
checkFileProp(repo, "/sample.txt", propsEolNative);
createFile(repo, "/.gitattributes", "*.txt\t\t\ttext eol=lf\n", propsEolNative);
// After commit .gitattributes file sample.txt must change property svn:eol-style automagically.
checkFileProp(repo, "/sample.txt", propsEolLf);
// After commit .gitattributes directory with .gitattributes must change property svn:auto-props automagically.
checkDirProp(repo, "/", propsAutoProps);
// After commit .gitattributes file sample.txt must change property svn:eol-style automagically.
{
final Set<String> changed = new HashSet<>();
repo.log(new String[]{""}, repo.getLatestRevision(), repo.getLatestRevision(), true, false, logEntry -> changed.addAll(logEntry.getChangedPaths().keySet()));
Assert.assertTrue(changed.contains("/"));
Assert.assertTrue(changed.contains("/.gitattributes"));
Assert.assertTrue(changed.contains("/sample.txt"));
Assert.assertEquals(changed.size(), 3);
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitUpdatePropertiesSubdir() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
{
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.addDir("/foo", null, -1);
// Empty file.
final String emptyFile = "/foo/.keep";
editor.addFile(emptyFile, null, -1);
editor.changeFileProperty(emptyFile, SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
sendDeltaAndClose(editor, emptyFile, null, "");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
}
createFile(repo, "/sample.txt", "", propsEolNative);
createFile(repo, "/foo/sample.txt", "", propsEolNative);
checkFileProp(repo, "/sample.txt", propsEolNative);
checkFileProp(repo, "/foo/sample.txt", propsEolNative);
createFile(repo, "/foo/.gitattributes", "*.txt\t\t\ttext eol=lf\n", propsEolNative);
// After commit .gitattributes file sample.txt must change property svn:eol-style automagically.
checkFileProp(repo, "/foo/sample.txt", propsEolLf);
checkFileProp(repo, "/sample.txt", propsEolNative);
// After commit .gitattributes directory with .gitattributes must change property svn:auto-props automagically.
checkDirProp(repo, "/foo", propsAutoProps);
// After commit .gitattributes file sample.txt must change property svn:eol-style automagically.
{
final Set<String> changed = new HashSet<>();
repo.log(new String[]{""}, repo.getLatestRevision(), repo.getLatestRevision(), true, false, logEntry -> changed.addAll(logEntry.getChangedPaths().keySet()));
Assert.assertTrue(changed.contains("/foo"));
Assert.assertTrue(changed.contains("/foo/.gitattributes"));
Assert.assertTrue(changed.contains("/foo/sample.txt"));
Assert.assertEquals(changed.size(), 3);
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitDirWithProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.addDir("/foo", null, latestRevision);
editor.changeDirProperty(SVNProperty.INHERITABLE_AUTO_PROPS, SVNPropertyValue.create("*.txt = svn:eol-style=native\n"));
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.addFile(filePath, null, -1);
editor.changeFileProperty(filePath, SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
sendDeltaAndClose(editor, filePath, null, "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitDirWithoutProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
try {
final long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.addDir("/foo", null, latestRevision);
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.addFile(filePath, null, -1);
sendDeltaAndClose(editor, filePath, null, "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
Assert.fail();
} catch (SVNException e) {
Assert.assertTrue(e.getMessage().contains(SVNProperty.INHERITABLE_AUTO_PROPS));
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitDirUpdateWithProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
{
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.addDir("/foo", null, -1);
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.addFile(filePath, null, -1);
editor.changeFileProperty(filePath, SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
sendDeltaAndClose(editor, filePath, null, "");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
}
{
long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Modify .gitattributes", null, false, null);
editor.openRoot(-1);
editor.openDir("/foo", latestRevision);
editor.changeDirProperty(SVNProperty.INHERITABLE_AUTO_PROPS, SVNPropertyValue.create("*.txt = svn:eol-style=native\n"));
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.openFile(filePath, latestRevision);
sendDeltaAndClose(editor, filePath, "", "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitDirUpdateWithoutProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
{
final ISVNEditor editor = repo.getCommitEditor("Create directory: /foo", null, false, null);
editor.openRoot(-1);
editor.addDir("/foo", null, -1);
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.addFile(filePath, null, -1);
editor.changeFileProperty(filePath, SVNProperty.EOL_STYLE, SVNPropertyValue.create(SVNProperty.EOL_STYLE_NATIVE));
sendDeltaAndClose(editor, filePath, null, "");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
}
try {
long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Modify .gitattributes", null, false, null);
editor.openRoot(-1);
editor.openDir("/foo", latestRevision);
// Empty file.
final String filePath = "/foo/.gitattributes";
editor.openFile(filePath, latestRevision);
sendDeltaAndClose(editor, filePath, "", "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeDir();
editor.closeEdit();
Assert.fail();
} catch (SVNException e) {
Assert.assertTrue(e.getMessage().contains(SVNProperty.INHERITABLE_AUTO_PROPS));
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitRootWithProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "/.gitattributes", "", propsEolNative);
{
long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Modify .gitattributes", null, false, null);
editor.openRoot(latestRevision);
editor.changeDirProperty(SVNProperty.INHERITABLE_AUTO_PROPS, SVNPropertyValue.create("*.txt = svn:eol-style=native\n"));
// Empty file.
final String filePath = "/.gitattributes";
editor.openFile(filePath, latestRevision);
sendDeltaAndClose(editor, filePath, "", "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeEdit();
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitRootWithoutProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "/.gitattributes", "", propsEolNative);
try {
long latestRevision = repo.getLatestRevision();
final ISVNEditor editor = repo.getCommitEditor("Modify .gitattributes", null, false, null);
editor.openRoot(latestRevision);
// Empty file.
final String filePath = "/.gitattributes";
editor.openFile(filePath, latestRevision);
sendDeltaAndClose(editor, filePath, "", "*.txt\t\t\ttext eol=native\n");
// Close dir
editor.closeDir();
editor.closeEdit();
Assert.fail();
} catch (SVNException e) {
Assert.assertTrue(e.getMessage().contains(SVNProperty.INHERITABLE_AUTO_PROPS));
}
}
}
/**
* Check commit .gitattributes.
*
* @throws Exception
*/
@Test
public void commitFileWithProperties() throws Exception {
try (SvnTestServer server = SvnTestServer.createEmpty()) {
final SVNRepository repo = server.openSvnRepository();
createFile(repo, "sample.txt", "", propsEolNative);
checkFileProp(repo, "/sample.txt", propsEolNative);
createFile(repo, ".gitattributes", "*.txt\t\t\ttext eol=lf\n", propsEolNative);
createFile(repo, "with-props.txt", "", propsEolLf);
try {
createFile(repo, "none-props.txt", "", null);
} catch (SVNException e) {
Assert.assertTrue(e.getMessage().contains(SVNProperty.EOL_STYLE));
}
}
}
}