首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 软件管理 > CVS SVN >

SVNKit Low Level API 应用(1)

2013-07-04 
SVNKit Low Level API 使用(1)编辑操作:提交到存储库  Low Level API提供一个抽象的编辑器(editor),给开发

SVNKit Low Level API 使用(1)

编辑操作:提交到存储库

  Low Level API提供一个抽象的编辑器(editor),给开发人员以构建和改变存储库(repository)中树的层次的能力。有了这样的编辑器,你可以手动(即在你的代码中明确)编辑存储库:在这些节点下添加新节点(目录)和条目(文件),根据路径更改或删除仓库。接下来我们详细介绍这些操作。

  

?

使用ISVNEditor接口

  ISVNEditor是用于编辑操作的接口,尤其是提交更改到存储库。ISVNEditor也用来接收和应用存储库的更新,但这属于下一个例子的范畴。

试想一下,我们已经在我们的资料库中得到了以下的树结构:

?

SVNKit Low Level API 应用(1)

?

我们要将它改变成以下这个结构:

?

SVNKit Low Level API 应用(1)

?

换句话说,我们要:

...FSRepositoryFactory.setup();String url = "file:///C:/path/to/repos/nodeB/";SVNRepository repository = SVNRepositoryFactory.create(SVNURL.parseURIDecoded( url ));...

...String logMessage = "log message";ISVNEditor editor = repository.getCommitEditor( logMessage , null /*locks*/ , true /*keepLocks*/ , null /*mediator*/ );...

... //provide your local revision of nodeB1 long r = ...; editor.openRoot( r ); //provide your local revision of itemB12 r = ...; editor.deleteEntry( "itemB1" , r ); //provide your local revision of nodeC3 r = ...; editor.openDir( "nodeC" , r ); //provide your local revision of itemC14 r = ...; editor.openFile( "nodeC/itemC1" , r );

String baseChecksum = ...;editor.applyTextDelta( "nodeC/itemC1" , baseChecksum );

?

?

InputStream baseData = ...;InputStream workingData = ...;//100Kb-window generatorSVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator( );String checksum = deltaGenerator.sendDelta( "nodeC/itemC1" , baseData , 0 , workingData , editor , true );

?

editor.textDeltaChunk( "nodeC/itemC1" , window );
?当成器通完成后,它调用编辑器的textDeltaEnd()方法:
editor.textDeltaEnd( "nodeC/itemC1" );
?sendDelta()方法返回工作版本条目的checksum。此checksum可用于验证更改被正确应用到了资源库侧。如果本地的工作条目和内资源库中的不匹配,checksum可能是不同的:
    editor.closeFile( "nodeC/itemC1" , checksum );    5   //the second and the third parameters are the path and revision respectively     //of the item's ancestor if the item is being added with history    editor.addFile( "nodeC/itemC2" , null , -1 );    baseChecksum = ...;    editor.applyTextDelta( "nodeC/itemC2" , baseChecksum );    baseData = ...;    workingData = ...;    checksum = deltaGenerator.sendDelta( "nodeC/itemC2" , baseData , 0 , workingData , editor , true );    editor.closeFile( "nodeC/itemC2" , checksum );    6   editor.changeFileProperty( "nodeC/itemC2" , "propName1" , "propValue1" );    editor.changeFileProperty( "nodeC/itemC2" , "propName2" , "propValue2" );    ...        //we are finished with changes under nodeC, so closing nodeC    editor.closeDir( );7   //now we are under nodeB again    editor.addDir( "nodeD" , null , -1 );        //close nodeD    editor.closeDir( );    //close root - nodeB    editor.closeDir( );
?在步骤5中,我们添加了一个新的条目,而不是不复制现有的条目。但是,如果我们需要做一个现有条目的副本,我们应该提供复制源的绝对路径和版本分别作为editor.addFile()方法的第二个和第三个参数。如果您只想复制(文件)不做更改,你不需要为了增加一个目录,ddFile()中其他的参数犹如以上所列,我们不是复制一个目录,只是增加一个没有历史的新目录。正如你看到的每一个打开/添加目录(包括根),以及每一个打开/添加文件操作,都必须关闭编辑器。最后一点,关闭编辑器会引发资源库提交事务:
SVNCommitInfo info = editor.closeEdit();
?如果事务成功,这个调用使得我们改变存储库中的内容。编辑器返回SVNCommitInfo对象,其中包含了新的版本信息。然而,该操作可能抛出一个异常,这意味着什么地方出错了。当我们捕获了这样一个异常,我们按照以下的方式来终止事务:
try {    ...    editor.addFile( "nodeC/itemC2" , null , -1 );} catch( SVNException svne ) {    editor.abortEdit( );}
?当我们关闭了编辑器后,我们可能会继续使用我们的SVNRepository驱动。下图说明了我们一步一步的改变,图中的数字对应了我们在代码中的步骤:SVNKit Low Level API 应用(1)?附注:?? 通过ISVNEditor进行编辑时,可能会以分层的方式遍历一个必要的子树。如果你的驱动绑定到/a,而你要改变/a?? 所有目前在本地机器上的版本数据,你必须?? 您不必在打开了一个文件时,立即?? 在操作存储库版本的提交编辑器时,你永远不需要调用以方法(他们与提交无关,但与更新有关):

private static SVNCommitInfo addDir( ISVNEditor editor , String dirPath , String filePath , byte[] data ) throws SVNException { editor.openRoot( -1 ); editor.addDir( dirPath , null , -1 ); editor.addFile( filePath , null , -1 ); editor.applyTextDelta( filePath , null ); SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator( ); String checksum = deltaGenerator.sendDelta( filePath , new ByteArrayInputStream( data ) , editor , true ); editor.closeFile(filePath, checksum); //Closes dirPath. editor.closeDir(); //Closes the root directory. editor.closeDir(); return editor.closeEdit(); }

?

?

2、文件修改:

    private static 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 );        //Closes filePath.        editor.closeFile( filePath , checksum );        // Closes dirPath.        editor.closeDir( );        //Closes the root directory.        editor.closeDir( );        return editor.closeEdit( );    }

?

?

在这里,我们使用无效的版本号(-1),以简化的例子,这样也是可行的。而这也是我们现在需要的。当然,在实际系统中,他们最好是真实的(有效)版本号。对于checksum也是如此。

?

3、目录复制:

?

    private static SVNCommitInfo copyDir( ISVNEditor editor , String srcDirPath , String dstDirPath , long revision ) throws SVNException {        editor.openRoot( -1 );                editor.addDir( dstDirPath , srcDirPath , revision );        //Closes dstDirPath.        editor.closeDir( );        //Closes the root directory.        editor.closeDir( );        return editor.closeEdit( );    }

?

private static SVNCommitInfo deleteDir( ISVNEditor editor , String dirPath ) throws SVNException { editor.openRoot( -1 ); editor.deleteEntry( dirPath , -1 ); //Closes the root directory. editor.closeDir( ); return editor.closeEdit( ); }

public class Commit { public static void main( String[] args ) { FSRepositoryFactory.setup( ); SVNURL url = SVNURL.parseURIDecoded( "file:///localhost/testRepos" ); String userName = "foo"; String userPassword = "bar"; byte[] contents = "This is a new file".getBytes( ); byte[] modifiedContents = "This is the same file but modified a little.".getBytes( ); SVNRepository repository = SVNRepositoryFactory.create( url ); ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager( userName, userPassword ); repository.setAuthenticationManager( authManager ); SVNNodeKind nodeKind = repository.checkPath( "" , -1 ); if ( nodeKind == SVNNodeKind.NONE ) { System.out.println( "No entry at URL " + url ); System.exit( 1 ); } else if ( nodeKind == SVNNodeKind.FILE ) { System.out.println( "Entry at URL " + url + " is a file while directory was expected" ); System.exit( 1 ); } //Get exact value of the latest (HEAD) revision. long latestRevision = repository.getLatestRevision( ); System.out.println( "Repository latest revision (before committing): " + latestRevision ); ISVNEditor editor = repository.getCommitEditor( "directory and file added" , null ); try { SVNCommitInfo commitInfo = addDir( editor , "test" , "test/file.txt" , contents ); System.out.println( "The directory was added: " + commitInfo ); } catch ( SVNException svne ) { editor.abortEdit( ); throw svne; } editor = repository.getCommitEditor( "file contents changed" , null ); try { commitInfo = modifyFile( editor , "test" , "test/file.txt" , contents , modifiedContents ); System.out.println( "The file was changed: " + commitInfo ); } catch ( SVNException svne ) { editor.abortEdit( ); throw svne; } //converts a relative path to an absolute one String absoluteSrcPath = repository.getRepositoryPath( "test" ); long srcRevision = repository.getLatestRevision( ); editor = repository.getCommitEditor( "directory copied" , null ); try { commitInfo = copyDir( editor , absoluteSrcPath , "test2" , srcRevision ); System.out.println( "The directory was copied: " + commitInfo ); } catch ( SVNException svne ) { editor.abortEdit( ); throw svne; } //Delete directory "test". editor = repository.getCommitEditor( "directory deleted" , null ); try { commitInfo = deleteDir( editor , "test" ); System.out.println( "The directory was deleted: " + commitInfo ); } catch ( SVNException svne ) { editor.abortEdit( ); throw svne; } //Delete directory "test2". editor = repository.getCommitEditor( "copied directory deleted" , null ); try { commitInfo = deleteDir( editor , "test2" ); System.out.println( "The copied directory was deleted: " + commitInfo ); } catch ( SVNException svne ) { editor.abortEdit( ); throw svne; } latestRevision = repository.getLatestRevision( ); System.out.println( "Repository latest revision (after committing): " + latestRevision ); ... } ...}

Repository latest revision (before committing): 0The directory was added: r1 by 'foo' at Tue Jun 27 15:46:59 NOVST 2006The file was changed: r2 by 'foo' at Tue Jun 27 15:46:59 NOVST 2006The directory was copied: r3 by 'foo' at Tue Jun 27 15:46:59 NOVST 2006The directory was deleted: r4 by 'foo' at Tue Jun 27 15:46:59 NOVST 2006The copied directory was deleted: r5 by 'foo' at Tue Jun 27 15:47:00 NOVST 2006Repository latest revision (after committing): 5

?

下载示例源码:?example program source code

?

?

热点排行