`

使用SVNkit删除版本库的文件

    博客分类:
  • SVN
阅读更多

源网址:http://wiki.svnkit.com/Committing_To_A_Repository

Editing Operation: commiting to a repository

The low-level layer provides for an ability tobuildandchangetree-like hierarchies in a repository giving adeveloper an abstracteditor. With such an editor you make edits to a repository manually (i.e. explicitly in yourcode): you add new nodes (directories) and items (files) under those nodes, change or delete existing ones identifyingthem (refering to them) by their paths in a repository. Now we are going to show this model in details.

 

Using the ISVNEditor Interface

ISVNEditoris the interface for editingoperations, for committing changes to a repository in particular.ISVNEditoris also used to receive and applychanges from a repository during an update but this is the scope ofthe next example.

Imagine that we have got the following tree structure in our repository:

Tree21.png

And we want to change it to something like this:

Tree22.png

In other words we want to:

  • delete/nodeB/itemB1

  • change contents of/nodeB/nodeC/itemC1

  • add/nodeB/nodeC/itemC2with some versioned properties attached to it

  • add/nodeB/nodeD

Now we'll discuss how to do these changes using a commit editor. We'll assume that we are working with a localrepository. First of all we should obtain such an editor to carry out our plans. We create anSVNRepositorydriverbounded to the node/nodeB(since all our planned changes will be performed under this node):

 

切换行号显示
   1     ...
   2     FSRepositoryFactory.setup( );
   3     String url = "file:///C:/path/to/repos/nodeB/";
   4 
   5     SVNRepository repository = SVNRepositoryFactory.create( SVNURL.parseURIDecoded( url ) );
   6     ...

Here we don't use an authentication manager - a session user name will be used as an author of a commit. Getting acommit editor:

 

切换行号显示
   1     ...
   2     String logMessage = "log message";
   3     ISVNEditor editor = repository.getCommitEditor( logMessage , null /*locks*/ , true /*keepLocks*/ , null /*mediator*/ );
   4     ...

Now when we have got an editor we can not call any reposiotory access methods of ourSVNRepositorydriver till wecall the editor'scloseEdit()method. The following code snippet demonstrates how to prepare our planned changes in a single transaction. Main stepsof the editing a repository tree process are numbered to the left of the code:

 

切换行号显示
   1     ...
   2     //provide your local revision of nodeB
   3 1   long r = ...;
   4     editor.openRoot( r );
   5 
   6     //provide your local revision of itemB1
   7 2   r = ...;
   8     editor.deleteEntry( "itemB1" , r );
   9 
  10     //provide your local revision of nodeC
  11 3   r = ...;
  12     editor.openDir( "nodeC" , r );
  13 
  14     //provide your local revision of itemC1
  15 4   r = ...;
  16     editor.openFile( "nodeC/itemC1" , r );

Now about applying text delta - text changes (only differences) made locally toitemC1. A base checksum is used tobe sure that both client's base item and repository's one (of the same revision) have got the same contents whatprevents from committing if a client's item is corrupted since calculated differences won't be applied correctly in thiscase:

 

切换行号显示
   1     
   2     String baseChecksum = ...;
   3     editor.applyTextDelta( "nodeC/itemC1" , baseChecksum );

Use a delta generator to calculate differences between base and working versions of the item. The generator producesdifferences or delta as a sequence ofdiff windowsof fixed size. It means that applying one such a window against item contents gives you not larger than N bytes of theoutput text. A default size of a window is 100K bytes.

 

切换行号显示
   1     InputStream baseData = ...;
   2     InputStream workingData = ...;
   3 
   4     //100Kb-window generator
   5     SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator( );
   6     String checksum = deltaGenerator.sendDelta( "nodeC/itemC1" , baseData , 0 , workingData , editor , true );

The delta generator passes each produced diff window to the editor calling itstextDeltaChunk()method:

 

切换行号显示
   1     editor.textDeltaChunk( "nodeC/itemC1" , window );

When the generator is finished it calls the editor'stextDeltaEnd()method:

 

切换行号显示
   1     editor.textDeltaEnd( "nodeC/itemC1" );

sendDelta()method returns the checksum for the working version of the item contents. This checksum may be used to verify that thedelta is applied correctly on the repository side. If contents of the local working item and the one in the repository donot match, checksums are likely to be different, too:

 

切换行号显示
   1     editor.closeFile( "nodeC/itemC1" , checksum );
   2     
   3 5   //the second and the third parameters are the path and revision respectively 
   4     //of the item's ancestor if the item is being added with history
   5     editor.addFile( "nodeC/itemC2" , null , -1 );
   6 
   7     baseChecksum = ...;
   8     editor.applyTextDelta( "nodeC/itemC2" , baseChecksum );
   9 
  10     baseData = ...;
  11     workingData = ...;
  12     checksum = deltaGenerator.sendDelta( "nodeC/itemC2" , baseData , 0 , workingData , editor , true );
  13     editor.closeFile( "nodeC/itemC2" , checksum );
  14     
  15 6   editor.changeFileProperty( "nodeC/itemC2" , "propName1" , "propValue1" );
  16     editor.changeFileProperty( "nodeC/itemC2" , "propName2" , "propValue2" );
  17     ...
  18     
  19     //we are finished with changes under nodeC, so closing nodeC
  20     editor.closeDir( );
  21 
  22 7   //now we are under nodeB again
  23     editor.addDir( "nodeD" , null , -1 );
  24     
  25     //close nodeD
  26     editor.closeDir( );
  27 
  28     //close root - nodeB
  29     editor.closeDir( );

In the step 5 we are adding a new item, not copying an existing one. But if we need to make a copy of an existing item we should provide the copy source absolute path and the revision of the copy source path as the second and third arguments of theeditor.addFile()method respectively. If you would like only to copy an item(file) without changes, you don't need to apply any delta -Subversionwill take care of making a copy on the server side.

In regard to addition of a directory - parameters are like inaddFile(). We are not copying a directory, just addinga new one without history.

As you see every opened/added directory (including the root one) as well as every opened/added file must be closed withthe editor. The final point - closing our editor what results in committing the transaction tree into the repository:

 

切换行号显示
   1     SVNCommitInfo info = editor.closeEdit();

If transaction succeeds and this call makes our changes immutable in the repository, the editor returns anSVNCommitInfoobject containing informationabout a new revision. However at any call to the editor it can throw an exception which means that something has wentwrong. When we've got an exception from the editor we should abort it to purge the transaction like this:

 

切换行号显示
   1     try {
   2         ...
   3         editor.addFile( "nodeC/itemC2" , null , -1 );
   4     } catch( SVNException svne ) {
   5         editor.abortEdit( );
   6     }

After we have closed the editor we may go on using ourSVNRepositorydriver. The following diagram illustrates ourchanges step by step. Numbers in the diagram correspond to numbers of our steps inthe code:

Tree23.png

Notes:

  • withISVNEditoryou edit your repository in a hierarchical way traversing a necessary subtree; that is if your driver is bound to/aand you are going to change/a/b/c/d, you can not just opendwithout moving down in the tree to the node/a/b/c, you have to open the root (/a), then open/a/b, and then/a/b/c, after what you open/a/b/c/d.

  • for all versioned data which is present on your local machine, you have to keep local revision numbers somehow, so that when you try to change an item, a repository server can check whether your local item is out of date or not.
  • you don't have to apply text deltas immediately after you have opened a file; you may first open all necessary files in the way described above, then close all directories (including the root one) remaining opened in a way inverse to the one you opened them, then apply deltas to opened files and finally close files; you can not change directory properties after you've closed target directories.
  • In repository edition operations you'll never need to use the following methods of a commit editor (they are irrelevant in commits, but relevant in updates):

 

Example On Using ISVNEditor In A Commit Operation

In the following example we'll continue discussing application ofISVNEditorin low-level commit operations.We will perform some simple commits in the following order:

  • add a directory with a file to a repository,
  • modify the added file,
  • copy the whole added directory within a repository,
  • delete both the original and copied directories.

For each of these four commit operations we'll write separate functions:

1. Addition:

 

切换行号显示
   1     private static SVNCommitInfo addDir( ISVNEditor editor , String dirPath , String filePath , byte[] data ) throws SVNException {
   2         editor.openRoot( -1 );
   3 
   4         editor.addDir( dirPath , null , -1 );
   5 
   6         editor.addFile( filePath , null , -1 );
   7 
   8         editor.applyTextDelta( filePath , null );
   9 
  10         SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator( );
  11         String checksum = deltaGenerator.sendDelta( filePath , new ByteArrayInputStream( data ) , editor , true );
  12 
  13         editor.closeFile(filePath, checksum);
  14 
  15         //Closes dirPath.
  16         editor.closeDir();
  17 
  18         //Closes the root directory.
  19         editor.closeDir();
  20 
  21         return editor.closeEdit();
  22     }

2. File modification:

 

切换行号显示
   1     private static SVNCommitInfo modifyFile( ISVNEditor editor , String dirPath , String filePath , byte[] oldData , byte[] newData ) throws SVNException {
   2         editor.openRoot( -1 );
   3 
   4         editor.openDir( dirPath , -1 );
   5 
   6         editor.openFile( filePath , -1 );
   7         
   8         editor.applyTextDelta( filePath , null );
   9         
  10         SVNDeltaGenerator deltaGenerator = new SVNDeltaGenerator( );
  11         String checksum = deltaGenerator.sendDelta( filePath , new ByteArrayInputStream( oldData ) , 0 , new ByteArrayInputStream( newData ) , editor , true );
  12 
  13         //Closes filePath.
  14         editor.closeFile( filePath , checksum );
  15 
  16         // Closes dirPath.
  17         editor.closeDir( );
  18 
  19         //Closes the root directory.
  20         editor.closeDir( );
  21 
  22         return editor.closeEdit( );
  23     }

Here we use invalid revision numbers (-1) for simplifying the example since they will work for us, and that's all weneed now. Of course, in real systems they'd better be real (valid) revision numbers. The same is regarding a base checksum.

3. Directory copying:

 

切换行号显示
   1     private static SVNCommitInfo copyDir( ISVNEditor editor , String srcDirPath , String dstDirPath , long revision ) throws SVNException {
   2         editor.openRoot( -1 );
   3         
   4         editor.addDir( dstDirPath , srcDirPath , revision );
   5 
   6         //Closes dstDirPath.
   7         editor.closeDir( );
   8 
   9         //Closes the root directory.
  10         editor.closeDir( );
  11 
  12         return editor.closeEdit( );
  13     }

4. Directory deletion:

 

切换行号显示
   1     private static SVNCommitInfo deleteDir( ISVNEditor editor , String dirPath ) throws SVNException {
   2         editor.openRoot( -1 );
   3 
   4         editor.deleteEntry( dirPath , -1 );
   5 
   6         //Closes the root directory.
   7         editor.closeDir( );
   8 
   9         return editor.closeEdit( );
  10     }

Now when we've got these functions we are ready to start:

 

切换行号显示
   1 public class Commit {
   2 
   3     public static void main( String[] args ) {
   4 
   5         FSRepositoryFactory.setup( );
   6         SVNURL url = SVNURL.parseURIDecoded( "file:///localhost/testRepos" );
   7         String userName = "foo";
   8         String userPassword = "bar";
   9         
  10         byte[] contents = "This is a new file".getBytes( );
  11         byte[] modifiedContents = "This is the same file but modified a little.".getBytes( );
  12 
  13         SVNRepository repository = SVNRepositoryFactory.create( url );
  14 
  15         ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager( userName, userPassword );
  16         repository.setAuthenticationManager( authManager );
  17 
  18         SVNNodeKind nodeKind = repository.checkPath( "" , -1 );
  19 
  20         if ( nodeKind == SVNNodeKind.NONE ) {
  21             System.out.println( "No entry at URL " + url );
  22             System.exit( 1 );
  23         } else if ( nodeKind == SVNNodeKind.FILE ) {
  24             System.out.println( "Entry at URL " + url + " is a file while directory was expected" );
  25             System.exit( 1 );
  26         }
  27         
  28         //Get exact value of the latest (HEAD) revision.
  29         long latestRevision = repository.getLatestRevision( );
  30         System.out.println( "Repository latest revision (before committing): " + latestRevision );
  31         
  32         ISVNEditor editor = repository.getCommitEditor( "directory and file added" , null );
  33         
  34         try {
  35             SVNCommitInfo commitInfo = addDir( editor , "test" , "test/file.txt" , contents );
  36             System.out.println( "The directory was added: " + commitInfo );
  37         } catch ( SVNException svne ) {
  38             editor.abortEdit( );
  39             throw svne;
  40         }
  41         
  42         editor = repository.getCommitEditor( "file contents changed" , null );
  43         try {
  44             commitInfo = modifyFile( editor , "test" , "test/file.txt" , contents , modifiedContents );
  45             System.out.println( "The file was changed: " + commitInfo );
  46         } catch ( SVNException svne ) {
  47             editor.abortEdit( );
  48             throw svne;
  49         }
  50 
  51         //converts a relative path to an absolute one
  52         String absoluteSrcPath = repository.getRepositoryPath( "test" );
  53         long srcRevision = repository.getLatestRevision( );
  54 
  55         editor = repository.getCommitEditor( "directory copied" , null );        
  56         try {
  57             commitInfo = copyDir( editor , absoluteSrcPath , "test2" , srcRevision );
  58             System.out.println( "The directory was copied: " + commitInfo );
  59         } catch ( SVNException svne ) {
  60             editor.abortEdit( );
  61             throw svne;
  62         }
  63 
  64         
  65         //Delete directory "test".
  66         editor = repository.getCommitEditor( "directory deleted" , null );
  67         try {
  68             commitInfo = deleteDir( editor , "test" );
  69             System.out.println( "The directory was deleted: " + commitInfo );
  70         } catch ( SVNException svne ) {
  71             editor.abortEdit( );
  72             throw svne;
  73         }
  74 
  75         //Delete directory "test2".
  76         editor = repository.getCommitEditor( "copied directory deleted" , null );
  77         try {
  78             commitInfo = deleteDir( editor , "test2" );
  79             System.out.println( "The copied directory was deleted: " + commitInfo );
  80         } catch ( SVNException svne ) {
  81             editor.abortEdit( );
  82             throw svne;
  83         }
  84         
  85         latestRevision = repository.getLatestRevision( );
  86         System.out.println( "Repository latest revision (after committing): " + latestRevision );
  87         ...
  88     }
  89     ...
  90 }

That's what you'll see if you run the program:

 

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

 


Download theexample program source code.

分享到:
评论

相关推荐

    SVNkit的Jar包 和实例代码

    通过SVNkit提供的API,你可以创建新的版本库,克隆现有的版本库到本地,对文件和目录进行添加、修改、删除,然后将这些更改提交到版本库。此外,还可以执行版本间的差异比较、分支和合并操作,以及回滚到特定版本等...

    SVNKit实例 + jar包 + SVNKit API

    4. **添加文件到仓库**:调用`SVNWCUtil.createDefaultOptions`配置选项,然后使用`SVNCommitClient.doAdd`方法将本地文件添加到版本库。 5. **提交更改**:使用`SVNCommitClient`的`doCommit`方法将本地修改提交到...

    svnkit-demo.rar

    这个项目可能包含了演示如何对比不同版本号的文件、管理版本库以及获取相关信息并将其格式化为 JSON 的代码。 SVN(Subversion)是一个开源的版本控制系统,用于跟踪和管理软件项目的源代码和其他文件的变更。...

    svnkit帮助文档API

    - 创建、删除、重命名和移动文件及目录:SVNKit提供了丰富的API来管理版本库中的文件和目录结构。 - 属性管理:可以设置、获取和删除文件或目录的属性,这些属性在Subversion中是元数据,可以用来存储额外信息。 ...

    svnkit插件开发包 支持Java开发svn一键打包

    这个压缩包提供的"svnkit-1.10.6"是SVNKit的一个版本,包含了支持Java开发的SVN插件所需的jar文件。 一、SVNKit基础 SVNKit提供了丰富的API,覆盖了SVN的大多数功能,包括但不限于创建、检查、更新、提交、合并、...

    SVNKit开发的Demo

    SVNKit是一款强大的Java库,...通过这个Demo,开发者可以学习到如何在Java项目中有效地使用SVNKit库,提升版本控制的自动化水平,增强团队协作效率。同时,这也为理解Subversion的工作机制提供了一个直观的实践平台。

    svnkit的demo

    - **删除(Delete)**:`delete()`方法用于从版本库中移除文件或目录。 - **合并(Merge)**:通过`merge()`方法可以将两个不同分支的更改合并到一个工作副本中。 4. **差异与冲突**:SVNKit提供了查看文件差异和...

    SVNKit开发指南

    6. **浏览版本库操作范例**:使用SVNLogClient查看版本库的日志信息。 7. **显示文件内容操作范例**:借助SVNWCClient显示版本库中文件的内容。 #### 七、参考资源 - **SVN官方文档**:提供了关于Subversion的全面...

    SVNKIT Java

    7. **版本库操作**:创建、删除版本库,以及对版本库的其他管理操作可以通过`SVNAdmin`类完成,但请注意,这些操作通常需要管理员权限。 **SVNKit文档** 提供的"SVNKit开发指南.doc"应该包含了更详细的使用教程和...

    SVNKit开发手册

    SVNKit是一种Java库,它提供了对Subversion版本控制系统的完整接口,允许开发者在Java应用程序中集成Subversion功能。SVNKit开发手册为想要学习SVN二次开发的程序员提供了全面的指南,涵盖了SVNKit的主要组件与用法...

    svnkit 1.7.5

    标题"svnkit 1.7.5"指的是SVNKit的一个特定版本——1.7.5,这是该库的一个稳定版本,意味着它经过了充分的测试,适合在生产环境中使用。 在描述中提到的"当前最新的稳定版:1.7.5",这表明在发布时,1.7.5是SVNKit...

    java调用SVNKit示例

    Java调用SVNKit是为了在Java程序中...总结来说,这个Java示例展示了如何使用SVNKit库在Java程序中进行基本的SVN操作,如登录验证和查询目录条目。开发者可以根据这些基础,扩展实现其他SVN功能,如提交、更新、删除等。

    SVNKit-tmatesoft 1.10.0

    在Java应用程序中,如果需要与Subversion仓库进行交互,比如提取日志(log)信息,通常需要引入相应的库文件。"SVNKit-tmatesoft 1.10.0"就是这样一个关键组件。这个压缩包包含了实现这些功能所需的jar文件,它们...

    SVNKit学习——使用低级别的API(ISVNEditor接口)直接操作Repository的目录和文件(五) - 鱼我所欲也

    `ISVNEditor`接口是SVNKit的核心组件之一,它定义了一系列方法来表示一个版本库编辑操作的完整生命周期。这些方法包括开始和结束编辑,创建和删除目录,以及添加和修改文件。在使用`ISVNEditor`时,通常需要实现该...

    svnkit1.3.5完整包

    SVNKit 1.3.5 是一个针对Subversion(简称SVN)版本控制系统实现的全功能Java库,同时也提供了一个命令行客户端。这个库允许开发者在Java应用程序中集成SVN的功能,比如版本控制、代码合并、冲突解决等。SVNKit ...

    Web文件系统源码-支持版本管理,权限管理

    SVNKit是一个Java库,它实现了Apache Subversion协议,使得开发者可以在Java环境中直接进行版本控制操作。 4. **权限管理**:权限管理是确保数据安全的重要手段。系统可能使用了角色基础的访问控制(RBAC)模型,为...

    nidify-Subversion使用手冊

    4. 删除文件:使用`svn delete`或`svn rm`命令删除文件并标记为已删除。 5. 提交更改:使用`svn commit -m "提交信息"`命令将更改保存到版本库。 6. 更新工作拷贝:使用`svn update`命令获取版本库的最新更改。 三...

    SVN配置管理及工具使用

    - 使用`svn import`命令将现有项目导入到版本库中,这会将项目文件及其结构添加到SVN控制下。 4. **检出(Checkout)项目**: - 使用`svn checkout`命令从版本库获取项目副本,这是开发人员开始工作的起点。 5. ...

    DocSys文件管理系统设计1

    13. **svnKit**和**JGit**:分别用于SVN和GIT版本控制,实现文件版本管理。 14. **openOffice/Aspose**:用于处理和转换Office文件。 文件并发访问控制是DocSys设计的关键点。在传统文件系统中,通过块位图、文件...

Global site tag (gtag.js) - Google Analytics