|
The only pure Java Subversion library in the world!
|
|
Using ISVNEditor in commit operations
Brief instructions how to commit changes using ISVNEditor :
- Get a commit editor (
ISVNCommitEditor ) calling a getCommitEditor() method of
your SVNRepository driver.
- Prepare a commit transaction: traverse your tree of versioned directories/files making reports by calling
methods of your commit editor.
- Close the editor by calling its
closeEdit() method. Having been
closed the editor can no longer be used.
In preparing a commit transaction you may add, copy or delete directories/files, change
file/directory properties, change file contents. Read the details below to get to know
how to perform the listed steps on getting and using ISVNEditor .
SVNRepository - the provider of commit editors
First of all, your program creates an SVNRepository driver for a particular protocol to use for working with a Subversion
repository. Let's suppose you would like to access a repository via the custom svn protocol.
In this case you must initialize the library for accessing the repository via svn:// :
import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl;
...
SVNRepositoryFactoryImpl.setup();
Then create an instance of an SVNRepository driver for the repository location that you want to be
the ROOT directory ("path/to/rootDir") for all commit processing:
...
import org.tmatesoft.svn.core.io.SVNRepository;
import org.tmatesoft.svn.core.io.SVNRepositoryFactory;
import org.tmatesoft.svn.core.SVNURL;
import org.tmatesoft.svn.core.SVNException;
...
String url = "svn://localhost/path/to/repos/path/to/rootDir";
SVNRepository repository = null;
try {
repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
} catch (SVNException svne) {
...
}
The next step (yet before getting a commit editor) - you should have an
implementation of ISVNWorkspaceMediator . This mediator is used for temporary file
delta storage allocations. For example, you can implement a mediator that will store
delta data in temporary files or, as an alternate, in a buffer, like this one:
...
import org.tmatesoft.svn.core.io.ISVNWorkspaceMediator;
...
public class CommitMediator implements ISVNWorkspaceMediator {
private Map myTmpStorages = new HashMap();
public String getWorkspaceProperty(String path, String name)
throws SVNException {
return null;
}
public void setWorkspaceProperty(String path, String name, String value)
throws SVNException {
}
public OutputStream createTemporaryLocation(String path, Object id)
throws IOException {
ByteArrayOutputStream tempStorageOS = new ByteArrayOutputStream();
myTmpStorages.put(id, tempStorageOS);
return tempStorageOS;
}
public InputStream getTemporaryLocation(Object id) throws IOException {
return new ByteArrayInputStream(
((ByteArrayOutputStream)myTmpStorages.get(id)).toByteArray());
}
public long getLength(Object id) throws IOException {
ByteArrayOutputStream
tempStorageOS = (ByteArrayOutputStream)myTmpStorages.get(id);
if (tempStorageOS != null) {
return tempStorageOS.size();
}
return 0;
}
public void deleteTemporaryLocation(Object id) {
myTmpStorages.remove(id);
}
}
Well, now when you've got a mediator you can ask you SVNRepository driver for a commit
editor:
...
import org.tmatesoft.svn.core.io.ISVNEditor;
...
String logMessage = "your commit log message";
try {
editor =
repository.getCommitEditor(logMessage, new CommitMediator());
} catch (SVNException svne) {
...
}
The above method receives only your log message and mediator and returns an editor. However when working
with Subversion 1.2 and higher you should rather use another getCommitEditor() method,
which in addition receives lock-tokens presenting on locked paths and a boolean flag that
dictates whether those paths should be unlocked or not after the commit succeeds:
String logMessage = "your commit log message";
Map locks;
...
String path;
String lockToken;
...
locks.put(path, lockToken);
...
boolean keepLocks = true;
try {
editor =
repository.getCommitEditor(logMessage, locks, keepLocks,
new CommitMediator());
} catch (SVNException svne) {
...
}
If there're no locked paths you can simply pass null instead
of locks and set keepLocks to false.
It's just the same as using the first version of the getCommitEditor() method.
Calling methods of ISVNEditor
Let's imagine we've got the following tree of versioned files and directories:
/
/dirA(root)/
/dirB(added)/
/file1.txt(added)
/dirC/
/file2.txt(modified)
/dirD(modified properties)/
/file3.txt(deleted)
Suppose we are to commit '/dirA' recursively. On the above layout
of the versioned tree you can see that 'dirA/dirB' with its child entry
'dirA/dirB/file1.txt' are scheduled for addition,
'dirA/dirC/file2.txt' has got local edits, 'dirD' has got changes
in properties and at last 'dirA/file3.txt'
is scheduled for deletion (of course, deleted files may have been already removed from
the filesystem, although with JavaSVN you are able only to schedule a file for deletion
but not delete it from the filesystem). Let's commit changes that are found in '/dirA' .
1. Create an SVNRepository driver for '/dirA' :
String url = "svn://host/path/to/repos/path/to/dirA";
...
repository = SVNRepositoryFactory.create(SVNURL.parseURIEncoded(url));
2. Then get a commit editor as described above.
editor =
repository.getCommitEditor(logMessage, new CommitMediator());
3. Calls to methods of your commit editor will be accumulated and translated to commands
that will be sent to the server. So, at first open the root (i.e. 'dirA' ):
editor.openRoot(-1);
4. Adding 'dirA/dirB' with 'dirA/dirB/file1.txt' :
editor.addDir("dirB", null, -1);
editor.addFile("dirB/file1.txt", null, -1);
editor.applyTextDelta("dirB/file1.txt", null);
long deltaLength;
...
SVNDiffWindow diffWindow = SVNDiffWindowBuilder
.createReplacementDiffWindow(deltaLength);
OutputStream os = editor.textDeltaChunk("dirB/file1.txt", diffWindow);
...
editor.textDeltaEnd("dirB/file1.txt");
editor.closeFile("dirB/file1.txt", null);
editor.closeDir();
If the delta is too big and you can not send it as one portion for some reasons,
you can divide it into several parts and repeat calls to those editor's delta-related
methods for each separate part of the delta.
As for the files already presenting in the repository, you can use the SVNFileUtil
class (from org.tmatesoft.svn.core.internal.wc) for computing an MD5 checksum of the BASE
file.
5. Modifying "dirC/file2.txt" :
editor.openDir("dirC", -1);
long wcRev;
...
editor.openFile("dirC/file2.txt", wcRev);
String baseChecksum;
...
editor.applyTextDelta("dirC/file2.txt", baseChecksum);
long deltaLength;
...
All the rest is just similar to the previous examlpe for adding a file except one thing -
compounding delta applying instructions. SVNAllDeltaGenerator is used for newly added files
as well as for binary ones (this class uses SVNDiffWindowBuilder ). SVNSequenceDeltaGenerator is used for
text files already being under version control.
...
import org.tmatesoft.svn.core.io.auth.SVNRAFileData;
import org.tmatesoft.svn.core.io.auth.SVNSequenceDeltaGenerator;
...
SVNSequenceDeltaGenerator deltaGenerator;
...
File base = new File("path/to/base");
File working = new File("path/to/working");
SVNRAFileData baseFile = new SVNRAFileData(base, true);
SVNRAFileData workingFile = new SVNRAFileData(working, true);
SVNDiffWindow diffWindow = deltaGenerator.generateDiffWindow(
"dirC/file2.txt", editor, workingFile, baseFile);
6. Changing properties of 'dirA/dirD' :
editor.openDir("dirD", dirWorkingRev);
String propName;
String propValue;
...
editor.changeDirProperty(propName, propValue);
editor.closeDir();
7. Deleting 'dirA/file3.txt' :
editor.deleteEntry("file3.txt", fileWorkingRev);
8. Finishing the editor's reports (this will finalize the commit):
editor.closeDir();
editor.closeEdit();
Yet some notes:
- if you would like to commit a copy of a file/directory you should
provide a copy ancestor and its revision to commit editor's
addDir() /addFile() methods.
- if you catch an exception from an editor's method you should abort the previous
reports calling the editor's
abortEdit() method.
If you have any questions regarding JavaSVN, would like to report a bug or contribute a patch, please write to
support@tmatesoft.com
|