SVNKit Low Level API 使用(2)
... FSRepositoryFactory.setup( ); String url = "file://localhost/rep/nodeA/"; SVNRepository repository = SVNRepositoryFactory.create( SVNURL.parseURIDecoded( url ) ); ReporterBaton reporterBaton = ...; ISVNEditor editor = ...; repository.update( -1 /*forces to use the latest revision*/ , null /*target*/ , true /*recursive*/ , reporterBaton , editor ); ...
...public class ReporterBaton implements ISVNReporterBaton { ... public void report( ISVNReporter reporter ) throws SVNException { //for the WC root reporter.setPath( "" /*path*/ , null /*lockToken*/ , 4 /*revision*/ , false /*startEmpty*/ ); ...
...reporter.setPath( "nodeB" , null , 5 , false );...
... //provide the item's lock token String lockToken = ...; reporter.setPath( "itemA2" , lockToken , 4 , false ); ...
... SVNURL url = SVNURL.parseURIDecoded( "file://localhost/rep/node2A/nodeC/nodeD/" ); //switched paths are described in this way: reporter.linkPath( url , "nodeC/nodeD" , null /*lockToken*/ , 4 /*revision*/ , false /*startEmpty*/ ); ...
... reporter.deletePath( "nodeF" ); reporter.deletePath( "nodeG" ); reporter.deletePath( "nodeL" ); ...
... reporter.setPath( "nodeH" , null , 4 , true /*startEmpty*/ ); reporter.setPath( "nodeH/nodeH2" , null , 4 , false /*startEmpty*/ ); reporter.setPath( "nodeH/itemH" , null , 5 , false /*startEmpty*/ ); ...
long rev = ...; reporter.setPath( "" , null , rev , true );
? ... //called at the end of a report reporter.finishReport( ); ... }}
... try { ... reporter.setPath( ... ); ... } catch( SVNException svne ) { reporter.abortReport( ); ... } ...
?
?Receiving changes from a server-side
Now we know that when you call an update method of an SVNRepository driver, the driver first invokes your reporter ... ISVNReporter reporter = ...; reporterBaton.report( reporter ); ...
?
... //let HEAD revision be 7 editor.targetRevision( 7 ); //gives the source revision we provided in our report editor.openRoot( 4 ); //in revision 7 properties were added for nodeB editor.openDir( "nodeB" , 5 ); editor.changeDirProperty( "prop1" , "val1" ); editor.changeDirProperty( "prop2" , "val2" ); editor.closeDir( ); ... //receiving changes for a switched node - nodeD editor.openDir( "nodeC" , 4 ); editor.openDir( "nodeC/nodeD" , 4 ); //itemD2 was added under /node2A/nodeC/nodeD/ in the repository editor.addFile( "nodeC/nodeD/itemD2" , null , -1 ); editor.applyTextDelta( "nodeC/nodeD/itemD2" , null ); editor.textDeltaChunk( "nodeC/nodeD/itemD2" , window1 ); ... editor.textDeltaEnd( "nodeC/nodeD/itemD2" ); //text checksum editor.closeFile( "nodeC/nodeD/itemD2" , checksum ); //closing nodeC/nodeD editor.closeDir( ); //closing nodeC editor.closeDir( ); ... //we are still not permitted to read /nodeA/nodeF, //this is how a server lets us know about this editor.absentDir( "nodeF" ); ...
editor.openDir( "nodeH" , 4 ); editor.addDir( "nodeH/nodeH2" , null , -1 ); //closing nodeH/nodeH2 editor.closeDir( ); editor.addDir( "nodeH/nodeH3" , null , -1 ); //closing nodeH/nodeH3 editor.closeDir( ); editor.addFile( "nodeH/itemH2" , null , -1 ); editor.applyTextDelta( "nodeH/itemH2" , null ); //sending delta windows ... editor.textDeltaEnd( "nodeH/itemH2" ); editor.closeFile( "nodeH/itemH2" , checksum ); //receiving changes for nodeH/itemH editor.openFile( "nodeH/itemH" , 5 ); editor.applyTextDelta( "nodeH/itemH" , baseChecksum ); //sending delta windows ... editor.textDeltaEnd( "nodeH/itemH" ); editor.closeFile( "nodeH/itemH" , checksum ); //closing nodeH editor.closeDir( ); ... //the lock on itemA2 was broken in the repository editor.changeFileProperty( "itemA2" , SVNProperty.LOCK_TOKEN , null ); ... //receiving a missing node - /nodeA/nodeL editor.addDir( "nodeL" , null , -1 ); ... editor.closeDir( ); ...
... //closes the WC root editor.closeDir( ); //finishes editing ediotr.closeEdit( ); ...
?
public class ExportReporterBaton implements ISVNReporterBaton { private long exportRevision; public ExportReporterBaton( long revision ){ exportRevision = revision; } public void report( ISVNReporter reporter ) throws SVNException { try { reporter.setPath( "" , null , exportRevision , true ); reporter.finishReport( ); } catch( SVNException svne ) { reporter.abortReport( ); System.out.println( "Report failed" ); } }}
public class ExportEditor implements ISVNEditor { private File myRootDirectory; private SVNDeltaProcessor myDeltaProcessor; public ExportEditor( File root ) { myRootDirectory = root; /* * Utility class that will help us to transform 'deltas' sent by the * server to the new file contents. */ myDeltaProcessor = new SVNDeltaProcessor( ); } public void targetRevision( long revision ) throws SVNException { } public void openRoot( long revision ) throws SVNException { } public void addDir( String path , String copyFromPath , long copyFromRevision ) throws SVNException { File newDir = new File( myRootDirectory , path ); if ( !newDir.exists( ) ) { if ( !newDir.mkdirs( ) ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.IO_ERROR , "error: failed to add the directory ''{0}''." , newDir ); throw new SVNException( err ); } } System.out.println( "dir added: " + path ); } public void openDir( String path , long revision ) throws SVNException { } public void changeDirProperty( String name , String value ) throws SVNException { } public void addFile( String path , String copyFromPath , long copyFromRevision ) throws SVNException { File file = new File( myRootDirectory , path ); if ( file.exists( ) ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.IO_ERROR , "error: exported file ''{0}'' already exists!" , file ); throw new SVNException( err ); } try { file.createNewFile( ); } catch ( IOException e ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.IO_ERROR , "error: cannot create new file ''{0}''" , file ); throw new SVNException( err ); } } public void openFile( String path , long revision ) throws SVNException { } public void changeFileProperty( String path , String name , String value ) throws SVNException { } public void applyTextDelta( String path , String baseChecksum ) throws SVNException { myDeltaProcessor.applyTextDelta( null , new File( myRootDirectory , path ) , false ); } public OutputStream textDeltaChunk( String path , SVNDiffWindow diffWindow ) throws SVNException { return myDeltaProcessor.textDeltaChunk( diffWindow ); } public void textDeltaEnd(String path) throws SVNException { myDeltaProcessor.textDeltaEnd( ); } public void closeFile( String path , String textChecksum ) throws SVNException { System.out.println( "file added: " + path ); } public void closeDir( ) throws SVNException { } public void deleteEntry( String path , long revision ) throws SVNException { } public void absentDir( String path ) throws SVNException { } public void absentFile( String path ) throws SVNException { } public SVNCommitInfo closeEdit( ) throws SVNException { return null; } public void abortEdit( ) throws SVNException { }}
public class Export { public static void main( String[] args ) { DAVRepositoryFactory.setup( ); SVNURL url = SVNURL.parseURIEncoded( "http://svn.svnkit.com/repos/svnkit/tags/1.3.5/doc" ); String userName = "foo"; String userPassword = "bar"; //Prepare filesystem directory (export destination). File exportDir = new File( "export" ); if ( exportDir.exists( ) ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.IO_ERROR , "Path ''{0}'' already exists" , exportDir ); throw new SVNException( err ); } exportDir.mkdirs( ); SVNRepository repository = SVNRepositoryFactory.create( url ); ISVNAuthenticationManager authManager = SVNWCUtil.createDefaultAuthenticationManager( userName, userPassword ); repository.setAuthenticationManager( authManager ); SVNNodeKind nodeKind = repository.checkPath( "" , -1 ); if ( nodeKind == SVNNodeKind.NONE ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.UNKNOWN , "No entry at URL ''{0}''" , url ); throw new SVNException( err ); } else if ( nodeKind == SVNNodeKind.FILE ) { SVNErrorMessage err = SVNErrorMessage.create( SVNErrorCode.UNKNOWN , "Entry at URL ''{0}'' is a file while directory was expected" , url ); throw new SVNException( err ); } //Get latest repository revision. We will export repository contents at this very revision. long latestRevision = repository.getLatestRevision( ); ISVNReporterBaton reporterBaton = new ExportReporterBaton( latestRevision ); ISVNEditor exportEditor = new ExportEditor( exportDir ); /* * Now ask SVNKit to perform generic 'update' operation using our reporter and editor. * * We are passing: * * - revision from which we would like to export * - null as "target" name, to perform export from the URL SVNRepository was created for, * not from some child directory. * - reporterBaton * - exportEditor. */ repository.update( latestRevision , null , true , reporterBaton , exportEditor ); System.out.println( "Exported revision: " + latestRevision ); }}
?
?
[原文:http://wiki.svnkit.com/Updating_From_A_Repository]
[实例源代码下载:http://svn.svnkit.com/repos/svnkit/tags/1.3.5/doc/examples/src/org/tmatesoft/svn/examples/repository/Export.java]