【问题标题】:Getting all Revisions with SVNKit使用 SVNKit 获取所有版本
【发布时间】:2014-05-14 05:30:33
【问题描述】:

我目前正在尝试获取所有 SVN 修订版,然后依次检查它们并对其进行处理。

svn checkout http://hamcrest.googlecode.com/svn/trunk/ hamcrest-read-only

(使用 SVN 1.8.8)我得到了代码(我只是以 hamcrest 为例)。

得到它后,我正在尝试执行以下操作:

    FSRepositoryFactory.setup();
    SVNURL localRepo = FSRepositoryFactory.createLocalRepository(f, true,
            true);
    System.out.println("Repo: " + localRepo);
    SVNRepository repo = FSRepositoryFactory.create(localRepo);

    log.info("Revisions: " + repo.getLatestRevision() + " Path: "
            + f.getAbsolutePath());
    List<SVNLogEntry> col = (List<SVNLogEntry>) repo.log(
            new String[] { "" }, null, 0, repo.getLatestRevision(), true,
            true);

    for (Object o : col) {
        System.out.println("O: " + o + " " + o.getClass());
    }

    System.out.println("Col: " + col.getClass());

不幸的是,这会创建一个空存储库,并删除其中的所有内容。这对应于 FSRepositoryFactory.create 的文档。

所以我搜索了另一种打开现有存储库的方法,并找到了SVNURL localRepo = SVNURL.fromFile(f);。不幸的是,这会产生错误:

Exception in thread "main" org.tmatesoft.svn.core.SVNException: svn: E180001: Unable to open an ra_local session to URL
svn: E180001: Unable to open repository 'file:///home/reichelt/workspace/hamcrest/hamcrest-read-only'
svn: E180001: Unable to open repository 'file:///home/reichelt/workspace/hamcrest/hamcrest-read-only'
at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:64)
at org.tmatesoft.svn.core.internal.wc.SVNErrorManager.error(SVNErrorManager.java:51)
at org.tmatesoft.svn.core.internal.io.fs.FSRepository.openRepository(FSRepository.java:796)
at org.tmatesoft.svn.core.internal.io.fs.FSRepository.getLatestRevision(FSRepository.java:121)
at de.performanzanalysator.vcs.SVNUtils.getVersions(SVNUtils.java:70)
at de.performanzanalysator.vcs.SVNUtils.main(SVNUtils.java:90)

有谁知道有办法用 SVNKit 打开现有的、已经下载的存储库吗? SVNWCClient 似乎是对的,但我找不到任何方法可以使用 SVNWCClient 打开存储库。

我使用的是 SVNKit 1.8.5。

【问题讨论】:

  • 您确定file:///home/.. 是有效回购的有效路径吗?
  • 是的,如果我执行 cd /home/.. (通常这是一条较长的路径,没有 '..'),我会进入一个可以执行例如 svn log 的目录,所以看起来就像它是一个有效的回购一样。
  • /home/.. 与根文件夹/ 相同,而您的结帐命令将hamcrest-read-only 指定为结帐目标。您应该重新检查签出 repo 的位置,并将正确的位置传递给 Java 代码。而且,如果你真的设法在 *nix 系统上结帐到/,你会遇到各种各样的问题。
  • 真正的路径是/home/reichelt/workspace/hamcrest/hamcrest-read-only,是正确的路径,包含一个.svn文件。我只想缩短线程以提高可读性,因此写了/home/..,但这不是真正的路径。对不起,我应该在开头写/home/XX或真实路径。
  • SVNKit 的版本是什么,用于签出 repo 的 svn 客户端的版本是什么?

标签: java svn svnkit


【解决方案1】:

问题中提到的异常发生是因为 SVNRepository 类希望用于存储库,但它用于处理工作副本。

SVN 的服务器端部分称为存储库,客户端部分称为工作副本。 svn checkout 命令用于从(通常是远程)存储库创建(通常是本地)工作副本。工作副本仅包含一个修订,因此某些操作(例如日志)将需要访问远程存储库。

SvnOperationFactory 类提供了一个 API 来针对工作副本和存储库执行所有“通用”SVN 任务。它可用于获取完整的更改日志,但请记住,即使日志操作是针对本地工作副本启动的,它也会联系存储库。

File workingCopyLocation = new File( ... );

SvnOperationFactory operationFactory = new SvnOperationFactory();
SvnLog logOperation = operationFactory.createLog();
logOperation.setSingleTarget(
        SvnTarget.fromFile( workingCopyLocation )
);
logOperation.setRevisionRanges( Collections.singleton(
        SvnRevisionRange.create(
                SVNRevision.create( 1 ),
                SVNRevision.HEAD
        )
) );
Collection<SVNLogEntry> logEntries = logOperation.run( null );
System.out.println( "logEntries = " + logEntries );

您可以使用相同的代码直接从存储库获取更改日志,而无需通过将setSingleTarget 初始化更改为指向远程存储库来检查工作副本:

String repoLocation = "http://hamcrest.googlecode.com/svn/trunk";
logOperation.setSingleTarget(
        SvnTarget.fromURL(
                SVNURL.parseURIEncoded( repoLocation )
        )
);

从 SVNKit 1.7 开始,SvnOperationFactory 是使用 SVNKit 的首选方式。 SVNKit 仍然包含 SVNClientManager,它提供了类似的功能,但被认为已过时。

SVNRepository 类及其子类旨在与存储库交互,如果您正在编写创建、配置或提供 SVN 存储库的软件,这将非常有用。例如,您可以使用该 API 直接从存储库获取更改日志,但除非您正在编写一些执行其他与存储库相关的任务的服务器端软件,否则您应该使用 SvnOperationFactory 方法。

String repoLocation = "http://hamcrest.googlecode.com/svn/trunk";

// DAV allows access via http and https protocols
// use FSRepositoryFactory to access local repositories
// use SVNRepositoryFactory to access remote repositories via svn protocol
DAVRepositoryFactory.setup();
SVNRepository repository = DAVRepositoryFactory.create(
        SVNURL.parseURIEncoded( repoLocation )
);

repository.log(
        new String[]{ },
        0, -1,
        false, false,
        new ISVNLogEntryHandler()
        {
            @Override
            public void handleLogEntry( SVNLogEntry logEntry )
            {
                System.out.println( "logEntry = " + logEntry );
            }
        }
);

【讨论】:

  • 谢谢,我真的误解了工作副本和存储库的概念,因为在 git 中这个术语的使用略有不同......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-11
  • 2015-12-02
  • 1970-01-01
相关资源
最近更新 更多