我正在使用 SVNKit 从我们的存储库中获取文件的内容。我想更改代码中的内容并将更改提交回来,而无需先签出文件。我已经在网上搜索过,只找到了需要签出本地文件系统的解决方案。
有谁知道这样做的方法?
我和 TMate Software 的人谈过,看来这确实是可能的。他们解释的方式,是的,您可以使用本地文件并使用新内容生成校验和并将其发送到 Subversion,但是(如果有的话)这只会帮助 Subversion 验证您在本地副本中是否拥有正确和最新的. 归根结底,Subversion 无论如何都会做自己的差异和增量。
因此,如果您没有本地副本,您只需创建一个校验和,就好像文件是新文件一样。这是从我的较大项目中提取的粗略代码。请注意SVNDirEntry
,如果您已经知道文件是否存在,则不需要提前检查;我在这里提供它是为了解释。
SVNDirEntry dirEntry = svnRepository.info(filePath, -1);
ISVNEditor editor = svnRepository.getCommitEditor("example modification", null, true, null);
editor.openRoot(-1);
if(dirEntry.getKind() == SVNNodeKind.NONE)
{
editor.addFile(filePath, null, -1);
}
else
{
editor.openFile(filePath, -1);
}
editor.applyTextDelta(filePath, null);
final SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
final String checksum = deltaGenerator.sendDelta(filePath, inputStream, editor, true);
editor.closeFile(filePath, checksum);
editor.closeDir(); //close the root
editor.closeEdit();
不要忘记,在获得提交编辑器之后,将所有内容打包到closeEdit()
一个try...catch
块中,以便在出现问题时可以中止编辑。
我已经尝试过了,它使用 SVNKIt 1.3.7(例如来自 Maven)通过了我的所有测试:
<repositories>
<repository>
<id>svnkit-repository</id>
<name>SVNKit Repository</name>
<url>http://maven.tmatesoft.com/content/repositories/releases/</url>
</repository>
</repositories>
...
<dependency>
<groupId>org.tmatesoft.svnkit</groupId>
<artifactId>svnkit</artifactId>
<version>1.3.7</version>
</dependency>
我刚试过。您可以获得要修改的文件的字节数。更改内存中的内容。最后,检查代码。这是狙击:
byte[] in = checkOutPom(project+"/"+ destinationPathQualifier + tag+ "/pom.xml");
BufferedReader bin = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(in)));
MyPomHandler h = new MyPomHandler(); //replaces strings in the file
ByteArrayOutputStream os = new ByteArrayOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(
os));
h.replace(bin, writer, "1.0.0-SNAPSHOT", tag);
ISVNEditor editor = getRepository().getCommitEditor(
"Patching POM with tag:"+tag, null);
modifyFile(editor, project + "/" + destinationPathQualifier + tag, project + "/" + destinationPathQualifier + tag+"/pom.xml",in, os.toByteArray());
==================================================== =
public byte[] checkOutPom(String filename)
throws SVNException {
SVNProperties fileProperties = new SVNProperties();
ByteArrayOutputStream baos = new ByteArrayOutputStream();
getRepository().getFile(filename, -1, fileProperties, baos);
return baos.toByteArray();
}
====================================================
来自 svnkit 示例代码:
public SVNCommitInfo modifyFile(ISVNEditor editor, String dirPath,
String filePath, byte[] oldData, byte[] newData)
throws SVNException {
editor.openRoot(-1);
editor.openDir(dirPath, -1);
editor.openFile(filePath, -1);
editor.applyTextDelta(filePath, null);
SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator();
String checksum = deltaGenerator.sendDelta(filePath,
new ByteArrayInputStream(oldData), 0, new ByteArrayInputStream(
newData), editor, true);
editor.closeFile(filePath, checksum);
editor.closeDir();
editor.closeDir();
return editor.closeEdit();
}
真的没有办法。从根本上说,SVN 工作在 checkout-edit-commit 模型上。可能有一些应用程序会将其隐藏起来,但它们仍会执行结帐,例如在幕后的临时目录。
理论上这应该是可行的,但实际上使用 SVNKit 似乎是不可能的。
据我所知,所有签入操作都直接或间接基于org.tmatesoft.svn.core.wc.SVNCommitItem,并且此类在其构造函数中需要一个工作副本文件路径。
您也许可以覆盖此类并尝试实现您自己的不需要工作副本的版本,但我没有详细检查过。