package net.oni2.svnaccess; import static java.lang.System.err; import java.io.File; import java.util.Vector; import org.tmatesoft.svn.core.SVNDepth; import org.tmatesoft.svn.core.SVNDirEntry; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNURL; import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; import org.tmatesoft.svn.core.wc.SVNClientManager; import org.tmatesoft.svn.core.wc.SVNInfo; import org.tmatesoft.svn.core.wc.SVNRevision; import org.tmatesoft.svn.core.wc.SVNWCUtil; /** * SVN handling * * @author Christian Illy */ public class SVN { SVNClientManager svnCManager = null; /** * Constructor */ public SVN() { // For using over http:// and https:// DAVRepositoryFactory.setup(); // For using over svn:// and svn+xxx:// SVNRepositoryFactoryImpl.setup(); // For using over file:/// FSRepositoryFactory.setup(); svnCManager = SVNClientManager.newInstance(SVNWCUtil .createDefaultOptions(true)); } /** * Constructor with init values * * @param username * Username * @param password * Password */ public SVN(String username, String password) { // For using over http:// and https:// DAVRepositoryFactory.setup(); // For using over svn:// and svn+xxx:// SVNRepositoryFactoryImpl.setup(); // For using over file:/// FSRepositoryFactory.setup(); svnCManager = SVNClientManager.newInstance( SVNWCUtil.createDefaultOptions(true), username, password); } /** * Checkout/update a repository to a local path * * @param reposUrl * Repository URL * @param wcDir * Local path * @param listener * The listener for the status events * @return True if successful * @throws Exception * if missing parameters or something went wrong */ public boolean updateWC(String reposUrl, File wcDir, SVNUpdateListener listener) throws Exception { SVNURL repos = SVNURL.parseURIEncoded(reposUrl); if (wcDir.exists()) { int rev = pathIsWCof(repos, wcDir); if (rev < 0) throw new Exception( "Destination path exists but is not a Working Copy of the SVN"); return update(repos, wcDir, rev, listener); } else { return checkout(repos, wcDir, listener); } } /** * Checks if the SVN contains newer revisions than the local working copy * * @param reposUrl * URL of repository to check for newer revisions * @param wcDir * Local working copy path to compare against * @return -1: No local working copy yet
* 0: Revisions are equal
* 1: SVN contains newer revisions * @throws Exception * If destination is not a WC of the given repository */ public int checkSVN(String reposUrl, File wcDir) throws Exception { SVNURL repos = SVNURL.parseURIEncoded(reposUrl); if (wcDir.exists()) { int localRev = pathIsWCof(repos, wcDir); if (localRev < 0) throw new Exception( "Destination path exists but is not a Working Copy of the SVN"); int remoteRev = getRemoteHeadRevision(repos); if (remoteRev > localRev) return 1; else return 0; } else { return -1; } } private int getRemoteHeadRevision(SVNURL reposUrl) { try { SVNInfo info = svnCManager.getWCClient().doInfo(reposUrl, SVNRevision.HEAD, SVNRevision.HEAD); return (int) info.getRevision().getNumber(); } catch (SVNException e) { e.printStackTrace(); } return -1; } private int pathIsWCof(SVNURL reposUrl, File wcDir) { if (wcDir.exists()) { try { SVNInfo info = svnCManager.getWCClient().doInfo(wcDir, SVNRevision.WORKING); if (info.getURL().equals(reposUrl)) return (int) info.getRevision().getNumber(); } catch (SVNException e) { err.println("Error while getting information of working copy for the location '" + reposUrl + "': " + e.getMessage()); } } return -1; } private Vector getUpdatedFilesInRepository(SVNURL reposUrl, int fromRev) { Vector list = new Vector(); try { svnCManager.getLogClient().doLog(reposUrl, new String[] { reposUrl.getPath() }, SVNRevision.HEAD, SVNRevision.create(fromRev + 1), SVNRevision.HEAD, true, true, 0, new LogEntryHandler(list, reposUrl.getPath())); } catch (Exception e) { if (e.getMessage().startsWith("svn: No such revision ")) return null; err.println("Error while getting the list of updated files of the location '" + reposUrl + "': " + e.getMessage()); e.printStackTrace(); } return list; } private boolean update(SVNURL reposUrl, File wcDir, int fromRev, SVNUpdateListener listener) throws Exception { Vector updatedFiles = getUpdatedFilesInRepository(reposUrl, fromRev); if (updatedFiles == null) return true; svnCManager.getUpdateClient().setEventHandler( new UpdateEventHandler(updatedFiles, listener)); try { svnCManager.getUpdateClient().doUpdate(wcDir, SVNRevision.HEAD, SVNDepth.INFINITY, true, true); return true; } catch (Exception e) { err.println("Error while updating the working copy for the location '" + reposUrl + "': " + e.getMessage()); } return false; } private Vector getFilesInRepository(SVNURL reposUrl) throws Exception { Vector list = new Vector(); try { svnCManager.getLogClient().doList(reposUrl, SVNRevision.HEAD, SVNRevision.HEAD, false, SVNDepth.INFINITY, SVNDirEntry.DIRENT_ALL, new DirEntryHandler(list)); } catch (Exception e) { err.println("Error while getting the list of files of the location '" + reposUrl + "': " + e.getMessage()); } return list; } private boolean checkout(SVNURL reposUrl, File wcDir, SVNUpdateListener listener) throws Exception { Vector newFiles = getFilesInRepository(reposUrl); svnCManager.getUpdateClient().setEventHandler( new UpdateEventHandler(newFiles, listener)); boolean result = false; try { wcDir.mkdirs(); svnCManager.getUpdateClient() .doCheckout(reposUrl, wcDir, SVNRevision.HEAD, SVNRevision.HEAD, SVNDepth.INFINITY, true); result = true; } catch (Exception e) { err.println("Error while checking out a working copy for the location '" + reposUrl + "': " + e.getMessage()); } return result; } }