|
The only pure Java Subversion library in the world!
|
|
Using ISVNReporter/ISVNEditor in update-related operations
The following article shortly describes the mechanism of an update-related operation (update, check out, switch, etc.) in terms
of the SVNKit low-level API (org.tmatesoft.svn.core.io package). The article is rather dedicated to using
ISVNReporter/ISVNEditor interfaces which are the key 'figures' in those operations.
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 items to some
definite revision (that is passed to SVNRepository.update(..) )
ISVNReporterBaton.report(..) should describe to the server revisions of all the
items (files, directories) 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):
import org.tmatesoft.svn.core.io.ISVNReporterBaton ;
import org.tmatesoft.svn.core.io.ISVNReporter ;
public class MyReporterBaton implements ISVNReporterBaton {
public void report(ISVNReporter reporter) throws SVNException {
reporter.setPath("", null, 4, false);
reporter.setPath("/dirA", null, 5, false);
reporter.setPath("/dirA/dirB", null, 6, false);
reporter.setPath("/dirA/dirB/file1.txt", null, 6, false);
reporter.setPath("/dirA/dirC", null, 4, false);
....
reporter.finishReport();
}
}
Several significant moments:
-
if some file(s) was(were) locked then you should provide the lock-token for
that file(s) as the 2nd parameter of
ISVNReporter.setPath(..) . For example:
/(4)
/file.txt(7, locked)
file.txt is at the 7th revision and was locked.
reporter.setPath("/file.txt", lockToken, 7, false);
Even though the revision of the locked file is the same as the target update
revision ISVNReporter.setPath(..) is called for such file anyway.
-
The last parameter of
ISVNReporter.setPath(..) - boolean flag startEmpty - must be
true for a checkout. Also it's set to true for those directories
that were not successfully updated at a previous time due to errors (if such situation had a place). So, startEmpty = true
means the directory is still empty. In other cases it must be false.
-
If a user's local item (file/directory) is updated against a URL different from that
it was checked out from (being switched in other words), then instead of calling
reporter.setPath(..) you should
call:
import org.tmatesoft.svn.core.SVNURL ;
...
reporter.linkPath(newRepositoryLocation, path,
lockToken, revision,
false);
newRepositoryLocation is an SVNURL instance which is the new parent root
(meaning path is relative to this root since this moment).
That's the only difference between just an update and a switch.
-
If an item was scheduled for deletion or if it's a missing directory (that was
accidentally deleted) then you should call:
reporter.deletePath(path);
-
At the end of the report call
ISVNReporter.finishReport() that denotes the end
of the report.
-
One more important moment: if during a report an exception occured - the report
failed - call
ISVNReporter.abortReport() that properly finishes the report in a
case of a fault.
How to use ISVNEditor
When ISVNReporterBaton has finished his work and the server knows everything
of the user's local versioned items (dirs and files) state it sends to the client commands as
well as data (file/dir properties and file delta) to bring client's items up to date.
These commands are translated into calls to ISVNEditor methods.
Suppose there's the following local 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 to SVNRepository.update(..) method; the following is rather an illustration describing how the SVNKit
library invokes ISVNEditor methods):
editor.targetRevision(revision);
editor.openRoot(revision);
editor.changeDirProperty(propertyName1, propertyValue1);
editor.changeDirProperty(propertyName2, propertyValue2);
.....................................
editor.openDir("/dirA", revision);
editor.changeDirProperty(propertyName1, propertyValue1);
editor.changeDirProperty(propertyName2, propertyValue2);
.....................................
editor.openFile("/dirA/file1.txt", revision);
editor.changeFileProperty("/dirA/file1.txt", propertyName1, propertyValue1);
editor.changeFileProperty("/dirA/file1.txt", propertyName2, propertyValue2);
.....................................
editor.applyTextDelta("/dirA/file1.txt", baseChecksum);
OutputStream os = editor.textDeltaChunk("/dirA/file1.txt", diffWindow);
editor.textDeltaEnd("/dirA/file1.txt");
editor.closeFile("/dirA/file1.txt", textChecksum);
editor.closeDir();
editor.closeDir();
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):
editor.targetRevision(revision);
editor.changeDirProperty(propertyName, propertyValue);
editor.addDir("/dirA", copyDirFromPath, CopyFromRevision);
editor.changeDirProperty(propertyName1, propertyValue1);
editor.changeDirProperty(propertyName2, propertyValue2);
.....................................
editor.addFile("/dirA/file1.txt", copyFileFromPath, CopyFromRevision);
editor.changeFileProperty("/dirA/file1.txt", propertyName1, propertyValue1);
editor.changeFileProperty("/dirA/file1.txt", propertyName2, propertyValue2);
.....................................
editor.applyTextDelta("/dirA/file1.txt", baseChecksum);
OutputStream os1 = editor.textDeltaChunk("/dirA/file1.txt", diffWindow1);
OutputStream os2 = editor.textDeltaChunk("/dirA/file1.txt", diffWindow2);
.....................................
editor.textDeltaEnd("/dirA/file1.txt");
editor.closeFile("/dirA/file1.txt", textChecksum);
editor.addFile("/dirA/file2.txt", copyFileFromPath, CopyFromRevision);
............................................
editor.closeDir();
editor.closeDir();
SVNCommitInfo commitInfo = editor.closeEdit();
If you have any questions regarding SVNKit, would like to report a bug or contribute a patch, please write to
support@svnkit.com
|