JavaSVN Articles
 Overview   Articles   JavaSVN API   Library Usage Examples   Mailing Lists   Home 

Intro

This section will introduce some articles on several parts of the JavaSVN API that give an extra description which can not be found in the Javadoc for the JavaSVN API classes. As needed this section will be enriched in future by including new articles covering frequently asked questions and misunderstandings that developers may have in using the API .



Table of Contents

1. How an update-related operation is performed using low-level API (org.tmatesoft.svn.core.io package)
1.1. How to use ISVNReporter
1.2. How to use ISVNEditor

1. How an update-related operation is performed using low-level API (org.tmatesoft.svn.core.io package)

1.1. How to use ISVNReporter

When SVNRepository.update(..) is called ISVNReporterBaton.report(..) is invoked to make reports (with the help of ISVNReporter) of the working files/directories state. For example, if the scope is to update existing local copies to some definite revision (that is passed to SVNRepository.update) ISVNReporterBaton.report(..) should describe to the server revisions of all the copies if their revisions differ from the update target revision. Suppose you have got the following tree you have somewhen checked out from a repository:

  /(4)
  /dirA(5)/
          /dirB(6)/
                  /file1.txt(6)
          /dirC(4)/
                  /file2.txt(5)
          /file3.txt(7)

Numbers in brackets correspond to revisions. Well, you see that the root directory has the revision number=4, dirA - 5, dirB - 6 and so on. When you call SVNRepository.update to bring the root directory up to date say to revision 8 you should describe the revisions of all the entries top-down for each directory (starting with the root):

public void report(ISVNReporter reporter) throws SVNException {

	//for the root directory
	reporter.setPath("", null, 4, false);
	
	//for "/dirA"
	reporter.setPath("/dirA", null, 5, false);
	
	//for "/dirA/dirB"
	reporter.setPath("/dirA/dirB", null, 6, false);
		
	//for "/dirA/dirB/file1.txt"
	reporter.setPath("/dirA/dirB/file1.txt", null, 6, false);

	//for "/dirA/dirC"
	reporter.setPath("/dirA/dirC", null, 4, false);
    
	....//and so on for all entries which revisions differ from 8

	/* always called at the end of the report - when the state of the 
	 * entire tree is described.
	 */
	reporter.finishReport();
}

Several significant moments:

1.2. How to use ISVNEditor

When ISVNReporterBaton has finished his work and the server knows everything of the user's working copy (dirs and files) state it sends to the client commands as well as data (file/dir properties and file delta) to bring his copy up to date. These commands are translated into calls to ISVNEditor methods.

Suppose there's the following working copy tree which is being updated recursively (starting with the directory the update was initiated on and moving deep down) to 8th revision:

    /(5)
    /dirA(5)/
            /file1.txt(5)
            /file2.txt(5)
Assume that only file1.txt is out of date and must be updated. The server sends commands to update the file which are translated into series of calls to ISVNEditor methods. Here is the scheme of this process (an implementor himself doesn't make these calls, his aim is only to provide an ISVNEditor implementation; the following is only an illustration describing how the JavaSVN library invokes ISVNEditor methods):
     //sets the target revision the copy is being updated to.
     editor.targetRevision(revision);

     /* processing starts with the parent directory the update was
      * run for - "/"; now modifications can be applied to the opened 
      * directory.
      */
     editor.openRoot(revision);

     //changing root directory properties
     editor.changeDirProperty(propertyName1, propertyValue1);
     editor.changeDirProperty(propertyName2, propertyValue2);
    
     .....................................
    
     //opens "/dirA".
     editor.openDir("/dirA", revision);

     /* now modifications can be applied to the opened directory. 
      * For example, changing its properties.
      * Also all further calls like editor.openFile(..), 
      * editor.addFile(..) or editor.openDir(..), editor.addDir(..) 
      * are relative to the currently opened directory.
      */
     editor.changeDirProperty(propertyName1, propertyValue1);
     editor.changeDirProperty(propertyName2, propertyValue2);

     .....................................

     //opens file "file1.txt" to modify it
     editor.openFile("/dirA/file1.txt", revision);
 		
     //changing properties of "file1.txt"
     editor.changeFileProperty(propertyName1, propertyValue1);
     editor.changeFileProperty(propertyName2, propertyValue2);
     
     .....................................

     /* file contents are out of date - the server sends delta
      * (the difference between the local BASE-revision copy and 
      * the file in the repository).
      * baseChecksum is provided by the server to make certain of 
      * the delta will be applied correctly - the client should 
      * compare it with his own one evaluated upon the contents of 
      * the file at the BASE revision - that is the state of the file 
      * it had just after the previous update (or checkout). If both 
      * checksums match each other - it's ok, the delta can be applied 
      * correctly, if don't - may be the local file is
      * corrupted, that's an error.
      */
     editor.applyTextDelta(baseChecksum);

     /* well, if the previous step was ok, the next step is to receive 
      * the delta itself. ISVNEditor.textDeltaChunk(..) receives 
      * an SVNDiffWindow - this is an object which contains instructions 
      * on how the delta (the entire delta or a part of it when the delta 
      * is too big) must be applied. If the delta is too big 
      * ISVNEditor.textDeltaChunk(..) is called several times to pass all 
      * parts of the delta; in this case all passed diffWindows should be 
      * accumulated and associated with their OutputStreams (each call to 
      * ISVNEditor.textDeltaChunk(..) returns an OutputStream as a storage 
      * where delta is written).
      */
     OutputStream os = editor.textDeltaChunk(diffWindow);
 
     /* the following is called when all the delta is received.
      * that is where it's applied to a local file; in this illustration
      * "file1.txt" is modified.
      */
     editor.textDeltaEnd();
 		
     /* the final point of the file modification: once again the server 
      * sends a checksum to control if the resultant file ("file1.txt") 
      * was modified correctly; the client repeats the operation of 
      * comparing the got checksum with the own one evaluated upon the 
      * resultant file contents.
      */ 
     editor.closeFile(textChecksum);

     //closes the directory  - "/dirA"
     editor.closeDir();
 
     //closes the root directory - "/"
     editor.closeDir();

     /* editing ends with a call to ISVNEditor.closeEdit() which returns
      * the commit information (SVNCommitInfo) - what revision the copy is
      * updated to, who is the author of the changes, when the changes were
      * committed.
      */   
     SVNCommitInfo commitInfo = editor.closeEdit();
 

That is how an update runs in common words. The described scheme is analogous for the case when more than one file is out of date (what is more actual in reality), the local copy tree is processed (by an ISVNEditor) top-down for each directory and file that must be updated.

Well, the case of a checkout is a little bit different. ISVNEditor.openDir(..) and ISVNEditor.openFile(..) are not called, instead ISVNEditor.addDir(..), ISVNEditor.addFile(..) are called for each directory and file to be checked out. This is a principal model of how ISVNEditor methods are invoked during a checkout (suppose we are checking out some node tree from a repository what will lead us to the previous illustrartion when the local copy already exists):

     //sets the target revision of the copy being checked out.
     editor.targetRevision(revision);

     /* ISVNEditor.openRoot is not called;
      * setting root directory properties.
      */
     editor.changeDirProperty(propertyName, propertyValue);

     /* adds "/dirA". copyDirFromPath & copyFromRevision - are irrelevant 
      * in an update editor.
      * If you want to have a compatibility with the native Subversion 
      * command line client in the case of a checkout (not simply an export) 
      * an implementation of this method should create an administrative 
      * area (.svn directory) for the directory being added ("/dirA").
      */ 
     editor.addDir("/dirA", copyDirFromPath, CopyFromRevision);

     /* setting the directory properties - they may be stored in the 
      * previously created .svn directory (SVN command line client 
      * compatibility).
      * Also all further calls like editor.addFile(..)/editor.addDir(..)
      * are relative to the added directory.
      */
     editor.changeDirProperty(propertyName1, propertyValue1);
     editor.changeDirProperty(propertyName2, propertyValue2);

     .....................................

     /* adds file "file1.txt". copyFileFromPath & copyFromRevision - are 
      * irrelevant in an update editor.
      */
     editor.addFile("/dirA/file1.txt", copyFileFromPath, CopyFromRevision);

     /* setting properties of "file1.txt". May be saved in .svn 
      * directory (for compatibility with the native SVN command 
      * line client).
      */
     editor.changeFileProperty(propertyName1, propertyValue1);
     editor.changeFileProperty(propertyName2, propertyValue2);
     
     .....................................

     /* if the file is empty  - only ISVNEditor.applyTextDelta(..) 
      * and ISVNEditor.textDeltaEnd(..) are called. Otherwise 
      * ISVNEditor.textDeltaChunk(..) is also invoked.
      * baseChecksum is irrelevant for a checkout.
      */
     editor.applyTextDelta(baseChecksum);

     //writing file contents (delta is contents in this case).
     OutputStream os1 = editor.textDeltaChunk(diffWindow1);

     //if "file1.txt" is too big...
     OutputStream os2 = editor.textDeltaChunk(diffWindow2);

     .....................................

     //all contents are received, "file1.txt" can be created
     editor.textDeltaEnd();

     /* the final point of the file modification: once again the 
      * server sends a checksum to control if the resultant file 
      * ("file1.txt") was transmitted and constructed correctly; 
      * the client compares the got checksum with the own one 
      * evaluated upon the resultant file contents.
      * It may be this method implementation where a copy of the 
      * file ("file1.txt") - the BASE revision file copy - is 
      * stored in .svn directory (for compatibility with the 
      * native SVN command line client).
      */ 
     editor.closeFile(textChecksum);

     /* again if you want to have a compatibility with the native 
      * SVN command line client each entry (wheteher it's a file 
      * or a directory) that is added should be reflected in its 
      * parent's administrative directory - .svn
      */

     //adds file "file2.txt".  
     editor.addFile("/dirA/file2.txt", copyFileFromPath, CopyFromRevision);

     ............................................//so on

     //closes the directory  - "/dirA"
     editor.closeDir();

     //closes the root directory - "/"
     editor.closeDir();

     SVNCommitInfo commitInfo = editor.closeEdit();


* * *


If you have any questions regarding JavaSVN, would like to report a bug or contribute a patch, please write to support@tmatesoft.com