[Buix-commits] r392 - in trunk/lutinvcs: lutinvcs-api/src/main/java/org/codelutin/vcs/util lutinvcs-provider-cvs/src/main/java/org/codelutin/vcs/impl/cvs lutinvcs-provider-mock/src/main/java/org/codelutin/vcs/impl/mock lutinvcs-provider-svn/src/main/java/org/codelutin/vcs lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn lutinvcs-provider-svn/src/test/java/org/codelutin/vcs/impl/svn
Author: tchemit Date: 2008-04-06 10:11:00 +0000 (Sun, 06 Apr 2008) New Revision: 392 Added: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNEventLoggerHandler.java Removed: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNHelper.java Modified: trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSConnexion.java trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSHandler.java trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSProvider.java trunk/lutinvcs/lutinvcs-provider-cvs/src/main/java/org/codelutin/vcs/impl/cvs/CVSConnexion.java trunk/lutinvcs/lutinvcs-provider-mock/src/main/java/org/codelutin/vcs/impl/mock/MockConnexion.java trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/SVNProvider.java trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNConnexion.java trunk/lutinvcs/lutinvcs-provider-svn/src/test/java/org/codelutin/vcs/impl/svn/FindTypeRepoTest.java Log: remove SVNHelper (logic for connexion should be only in SVNConnexion) but for convience we put it in SVNProvider Modified: trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSConnexion.java =================================================================== --- trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSConnexion.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSConnexion.java 2008-04-06 10:11:00 UTC (rev 392) @@ -39,7 +39,6 @@ /** @author chemit */ public abstract class AbstractVCSConnexion<H extends VCSHandler> implements VCSConnexion<H> { - /** to use log facility, just put in your code: log.info(\"...\"); */ static protected final Log log = LogFactory.getLog(AbstractVCSConnexion.class); protected File localRoot; Modified: trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSHandler.java =================================================================== --- trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSHandler.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSHandler.java 2008-04-06 10:11:00 UTC (rev 392) @@ -42,7 +42,6 @@ */ public abstract class AbstractVCSHandler<C extends VCSConnexion> implements VCSHandler<C> { - /** to use log facility, just put in your code: log.info(\"...\"); */ static protected final Log log = LogFactory.getLog(AbstractVCSHandler.class); public static final String LOCAL_SEP = File.separator; Modified: trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSProvider.java =================================================================== --- trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSProvider.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-api/src/main/java/org/codelutin/vcs/util/AbstractVCSProvider.java 2008-04-06 10:11:00 UTC (rev 392) @@ -20,6 +20,8 @@ import org.codelutin.vcs.VCSHandler; import org.codelutin.vcs.VCSProvider; import org.codelutin.vcs.type.VCSConnexionMode; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; /** * base implementation of provider. @@ -28,6 +30,8 @@ */ public class AbstractVCSProvider<C extends VCSConnexion, H extends VCSHandler<C>> implements VCSProvider<C, H> { + static protected final Log log = LogFactory.getLog(AbstractVCSProvider.class); + /** name of ne provider */ protected final String name; @@ -67,7 +71,10 @@ } try { connexion = connexionImpl.getConstructor(VCSConnexionMode.class, handlerImpl).newInstance(mode, handler); + + // always init connexion from his config connexion.init(config); + return connexion; } catch (Exception e) { throw new RuntimeException(_("lutinvcs.error.provider.init.connexion", connexionImpl, this, e.getCause())); Modified: trunk/lutinvcs/lutinvcs-provider-cvs/src/main/java/org/codelutin/vcs/impl/cvs/CVSConnexion.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-cvs/src/main/java/org/codelutin/vcs/impl/cvs/CVSConnexion.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-cvs/src/main/java/org/codelutin/vcs/impl/cvs/CVSConnexion.java 2008-04-06 10:11:00 UTC (rev 392) @@ -16,6 +16,7 @@ import org.codelutin.vcs.VCSConnexionConfig; import org.codelutin.vcs.VCSException; +import org.codelutin.vcs.type.VCSConnectionState; import org.codelutin.vcs.type.VCSConnexionMode; import org.codelutin.vcs.util.AbstractVCSConnexion; import org.netbeans.lib.cvsclient.CVSRoot; @@ -35,6 +36,7 @@ public void init(VCSConnexionConfig config) { //TODO this.config = config; + this.state = VCSConnectionState.INIT; } public void testConnection() throws VCSException { Modified: trunk/lutinvcs/lutinvcs-provider-mock/src/main/java/org/codelutin/vcs/impl/mock/MockConnexion.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-mock/src/main/java/org/codelutin/vcs/impl/mock/MockConnexion.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-mock/src/main/java/org/codelutin/vcs/impl/mock/MockConnexion.java 2008-04-06 10:11:00 UTC (rev 392) @@ -28,8 +28,8 @@ } public void init(VCSConnexionConfig config) { + this.config = config; state = VCSConnectionState.INIT; - this.config = config; } public void testConnection() throws VCSException { Modified: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/SVNProvider.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/SVNProvider.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/SVNProvider.java 2008-04-06 10:11:00 UTC (rev 392) @@ -16,11 +16,23 @@ import org.codelutin.vcs.impl.svn.SVNConnexion; import org.codelutin.vcs.impl.svn.SVNHandler; +import org.codelutin.vcs.type.VCSTypeRepo; +import org.codelutin.vcs.util.AbstractVCSHandler; import org.codelutin.vcs.util.AbstractVCSProvider; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNNodeKind; +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.io.SVNRepository; +import org.tmatesoft.svn.core.wc.ISVNOptions; +import org.tmatesoft.svn.core.wc.SVNClientManager; +import org.tmatesoft.svn.core.wc.SVNRevision; +import org.tmatesoft.svn.core.wc.SVNWCUtil; +import java.util.Arrays; + /** * SVN Provider * @@ -28,17 +40,195 @@ */ public class SVNProvider extends AbstractVCSProvider<SVNConnexion, SVNHandler> { + private static boolean libraryInit; + public SVNProvider() { super("SVN", SVNHandler.class, SVNConnexion.class); - // For using over http:// and https:// + setupLibrary(); + } + + /** + * Test if a anonymous svn connection can be openned. + * + * @param url the svn url to test + * @return <code>true</code> if connection is ok,<code>false</code> otherwise. + * @throws org.codelutin.vcs.VCSException if could not compute the SVNURL + */ + public boolean testAnonymousConnection(String url) throws VCSException { + boolean result = true; + + SVNRepository repository = getAnonymousConnection(url); + try { + repository.testConnection(); + } catch (SVNException e) { + result = false; + } finally { + if (repository != null) { + try { + repository.closeSession(); + } catch (Exception e) { + log.warn(e); + } + } + } + return result; + } + + /** + * Test if a anonymous svn connection can be openned. + * + * @param url the svn url to test + * @param username user name + * @param privateKeyFilePath the file to used as protected key file + * @param passphrase passphrase to use + * @return <code>true</code> if connection is ok,<code>false</code> otherwise. + * @throws org.codelutin.vcs.VCSException if could not compute the SVNURL + */ + public static boolean testSSHConnection(String url, String username, String privateKeyFilePath, char[] passphrase) throws VCSException { + boolean result = true; + + SVNRepository repository = getSSHConnection(url, username, privateKeyFilePath, passphrase); + try { + repository.testConnection(); + } catch (SVNException e) { + result = false; + } finally { + if (repository != null) { + try { + repository.closeSession(); + } catch (Exception e) { + log.warn(e); + } + } + } + return result; + } + + public static SVNRepository getAnonymousConnection(String url) throws VCSException { + + SVNURL testRepositoryURL; + try { + testRepositoryURL = SVNURL.parseURIEncoded(url); + } catch (SVNException e) { + throw new VCSException(e); + } + SVNRepository repository; + try { + ISVNOptions options = SVNWCUtil.createDefaultOptions(true); + SVNClientManager manager = SVNClientManager.newInstance(options, "anonymous", "anonymous"); + repository = manager.createRepository(testRepositoryURL, false); + repository.testConnection(); + return repository; + } catch (SVNException e) { + throw new VCSException(e); + } + } + + public static SVNRepository getSSHConnection(String url, String username, String privateKeyFilePath, char[] passphrase) throws VCSException { + + setupLibrary(); + + SVNURL testRepositoryURL; + try { + testRepositoryURL = SVNURL.parseURIEncoded(url); + } catch (SVNException e) { + throw new VCSException(e); + } + SVNRepository repository; + try { + ISVNOptions options = SVNWCUtil.createDefaultOptions(true); + System.setProperty("svnkit.ssh2.key", privateKeyFilePath); + System.setProperty("svnkit.ssh2.username", username); + if (passphrase != null && passphrase.length > 0) { + System.setProperty("svnkit.ssh2.passphrase", Arrays.toString(passphrase)); + } + //System.setProperty("svnkit.ssh2.passphrase", ""); + //System.setProperty("svnkit.ssh2.password", ""); + //System.setProperty("svnkit.ssh2.port", "22"); + + // instanciate svn client manager + SVNClientManager manager = SVNClientManager.newInstance(options); + repository = manager.createRepository(testRepositoryURL, false); + repository.testConnection(); + return repository; + } catch (SVNException e) { + throw new VCSException(e); + } + } + + public static void setupLibrary() { + if (libraryInit) { + return; + } + libraryInit = true; + /* + * For using over http:// and https:// + */ DAVRepositoryFactory.setup(); - // For using over svn:// and svn+xxx:// + /* + * For using over svn:// and svn+xxx:// + */ SVNRepositoryFactoryImpl.setup(); - // For using over file:/// + /* + * For using over file:/// + */ FSRepositoryFactory.setup(); } + /** + * @param typeRepo the type of repo we want to use if possible + * @param uncleanRemotePath remote path (could be unclean) + * @param databaseVersion the database version to use + * @param hostName the hostname to use + * @return the typeRepo to use + * @throws org.codelutin.vcs.VCSException if could not compute SVNURL to tests + */ + public static VCSTypeRepo findTypeRepo(VCSTypeRepo typeRepo, + String uncleanRemotePath, + String databaseVersion, + String hostName) throws VCSException { + + + VCSTypeRepo result; + + String remotePath = AbstractVCSHandler.getRemotePath(typeRepo, uncleanRemotePath); + String remoteDatabase = AbstractVCSHandler.getRemoteDatabase(typeRepo, databaseVersion); + StringBuilder sb = new StringBuilder("svn://").append(hostName); + sb.append("/").append(remotePath); + String url = sb.toString(); + log.info("try svn url " + url + " (" + remoteDatabase + ")"); + + SVNRepository repository; + try { + repository = getAnonymousConnection(url); + } catch (VCSException e) { + log.warn(e); + return null; + } + + try { + SVNNodeKind kind = repository.checkPath(remoteDatabase, SVNRevision.HEAD.getNumber()); + log.info("kind node found for " + remoteDatabase + " : " + kind); + // typeRepo type is ok, use it + if (kind == SVNNodeKind.NONE) { + // could not found the remote database + if (typeRepo == VCSTypeRepo.HEAD) { + // this is a fatal error since head always exists + throw new VCSRuntimeException("could not found svn trunk " + url + " (" + repository.getLocation() + ")"); + } else { + result = VCSTypeRepo.HEAD; + } + } else { + // was found, so keep it + result = typeRepo; + } + } catch (SVNException e) { + throw new VCSRuntimeException(e); + } + log.info("required:" + typeRepo + " available:" + result); + return result; + } } Modified: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNConnexion.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNConnexion.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNConnexion.java 2008-04-06 10:11:00 UTC (rev 392) @@ -18,6 +18,7 @@ import org.codelutin.vcs.VCSConnexionConfig; import org.codelutin.vcs.VCSException; import org.codelutin.vcs.VCSRuntimeException; +import org.codelutin.vcs.SVNProvider; import org.codelutin.vcs.type.VCSConnectionState; import org.codelutin.vcs.type.VCSConnexionMode; import org.codelutin.vcs.util.AbstractVCSConnexion; @@ -90,19 +91,19 @@ // add our svn event logger TODO Remake this logger or use the // DebugLog from svnkit ? - ourClientManager.setEventHandler(new SVNHelper.SVNEventLoggerHandler()); + ourClientManager.setEventHandler(new SVNEventLoggerHandler()); + this.state = VCSConnectionState.INIT; } catch (SVNException e) { // TODO I18N + this.state = VCSConnectionState.ERROR; + throw new VCSRuntimeException("could not compute repository url ", e); } } @Override public void close() throws IllegalStateException { - checkInit(); - if (!isOpen()) { - return; - } + checkOpen(); //TODO to be done log.info(this); } @@ -130,7 +131,7 @@ File path = getConfig().getKeyFile(); try { String passphrase = getConfig().getPassphrase(); - SVNHelper.testSSHConnection(repositoryURL.toString(), getConfig().getUserName(), path == null ? null : path.getAbsolutePath(), passphrase == null ? new char[0] : passphrase.toCharArray()); + SVNProvider.testSSHConnection(repositoryURL.toString(), getConfig().getUserName(), path == null ? null : path.getAbsolutePath(), passphrase == null ? new char[0] : passphrase.toCharArray()); return; } catch (VCSException e) { log.warn(_("lutinvcs.error.vcs.no.ssh.connection", getConfig().getUserName(), path)); @@ -139,7 +140,7 @@ // do not use ssh connection getConfig().setUseSshConnexion(false); // try to test with a anonymous connection - SVNHelper.testAnonymousConnection(repositoryURL.toString()); + SVNProvider.testAnonymousConnection(repositoryURL.toString()); } @@ -161,4 +162,5 @@ return repositoryURL; } + } Added: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNEventLoggerHandler.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNEventLoggerHandler.java (rev 0) +++ trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNEventLoggerHandler.java 2008-04-06 10:11:00 UTC (rev 392) @@ -0,0 +1,239 @@ +/** + * # #% Copyright (C) 2008 Code Lutin, Tony Chemit + * This program is free software; you + * can redistribute it and/or modify it under the terms of the GNU General + * Public License as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. This program is + * distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A + * PARTICULAR PURPOSE. See the GNU General Public License for more details. You + * should have received a copy of the GNU General Public License along with this + * program; if not, write to the Free Software Foundation, Inc., 59 Temple Place + * - Suite 330, Boston, MA 02111-1307, USA. + * # #% + */ +package org.codelutin.vcs.impl.svn; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.tmatesoft.svn.core.SVNCancelException; +import org.tmatesoft.svn.core.SVNException; +import org.tmatesoft.svn.core.SVNProperty; +import org.tmatesoft.svn.core.wc.ISVNEventHandler; +import org.tmatesoft.svn.core.wc.SVNEvent; +import org.tmatesoft.svn.core.wc.SVNEventAction; +import org.tmatesoft.svn.core.wc.SVNStatusType; + +/** + * A svn logger + * + * @author chemit + */ +public class SVNEventLoggerHandler implements ISVNEventHandler { + + static private Log log = LogFactory.getLog(SVNEventLoggerHandler.class); + + /* + * progress is currently reserved for future purposes and now is always + * ISVNEventHandler.UNKNOWN + */ + + public boolean handleEventWC(SVNEvent event, double progress) { + /* + * Gets the current action. An action is represented by + * SVNEventAction. + */ + SVNEventAction action = event.getAction(); + String trace = null; + if (action == SVNEventAction.ADD) { + /* + * The item is scheduled for addition. + */ + trace = "A "; + } else if (action == SVNEventAction.COPY) { + /* + * The item is scheduled for addition with history (copied, in + * other words). + */ + trace = "A + "; + } else if (action == SVNEventAction.REVERT) { + /* + * The item is scheduled for revertion. + */ + trace = "R "; + } else if (action == SVNEventAction.DELETE) { + /* + * The item is scheduled for deletion. + */ + trace = "D "; + } else if (action == SVNEventAction.LOCKED) { + /* + * The item is locked. + */ + trace = "L "; + } else if (action == SVNEventAction.LOCK_FAILED) { + /* + * Locking operation failed. + */ + trace = "failed to lock "; + } + + if (trace != null) { + logInfo(trace, event); + return true; + } + + return false; + + } + + public boolean handleEventCommit(SVNEvent event, double progress) { + /* + * Gets the current action. An action is represented by + * SVNEventAction. In case of a commit an action can be determined + * via comparing SVNEvent.getAction() with + * SVNEventAction.COMMIT_-like constants. + */ + SVNEventAction action = event.getAction(); + String trace = null; + if (action == SVNEventAction.COMMIT_COMPLETED) { + trace = "Complete "; + } else if (action == SVNEventAction.COMMIT_MODIFIED) { + trace = "Sending "; + } else if (action == SVNEventAction.COMMIT_DELETED) { + trace = "Deleting "; + } else if (action == SVNEventAction.COMMIT_REPLACED) { + trace = "Replacing "; + } else if (action == SVNEventAction.COMMIT_DELTA_SENT) { + trace = "Transmitting file data...."; + } else if (action == SVNEventAction.COMMIT_ADDED) { + /* + * Gets the MIME-type of the item. + */ + String mimeType = event.getMimeType(); + if (SVNProperty.isBinaryMimeType(mimeType)) { + /* + * If the item is a binary file + */ + trace = "Adding (bin) "; + } else { + trace = "Adding "; + } + } + + if (trace != null) { + logInfo(trace, event); + return true; + } + + return false; + } + + public boolean handleEventUpdate(SVNEvent event, double progress) { + /* + * Gets the current action. An action is represented by + * SVNEventAction. In case of an update an action can be determined + * via comparing SVNEvent.getAction() and + * SVNEventAction.UPDATE_-like constants. + */ + SVNEventAction action = event.getAction(); + String pathChangeType = null; + String trace = null; + if (action == SVNEventAction.UPDATE_ADD) { + /* + * the item was added + */ + pathChangeType = "A"; + } else if (action == SVNEventAction.UPDATE_DELETE) { + /* + * the item was deleted + */ + pathChangeType = "D"; + } else if (action == SVNEventAction.UPDATE_UPDATE) { + + /* + * Find out in details what state the item is (after having been + * updated). + * + * Gets the status of file/directory item contents. It is + * SVNStatusType who contains information on the state of an + * item. + */ + SVNStatusType contentsStatus = event.getContentsStatus(); + if (contentsStatus == SVNStatusType.CHANGED) { + /* + * the item was modified in the repository (got the changes + * from the repository + */ + pathChangeType = "U"; + } else if (contentsStatus == SVNStatusType.CONFLICTED) { + /* + * The file item is in a state of Conflict. That is, changes + * received from the repository during an update, overlap + * with local changes the user has in his working copy. + */ + pathChangeType = "C"; + } else if (contentsStatus == SVNStatusType.MERGED) { + /* + * The file item was merGed (those changes that came from + * the repository did not overlap local changes and were + * merged into the file). + */ + pathChangeType = "G"; + } + + } else if (action == SVNEventAction.UPDATE_EXTERNAL) { + /* for externals definitions */ + trace = "Fetching external item into '" + + event.getFile().getAbsolutePath() + "'"; + trace += "\nExternal at revision " + event.getRevision(); + + } else if (action == SVNEventAction.UPDATE_COMPLETED) { + /* + * Updating the working copy is completed. Prints out the + * revision. + */ + trace = "At revision " + event.getRevision(); + } + + if (trace != null) { + logInfo(trace, event); + return true; + } + + if (pathChangeType != null) { + logInfo(trace, event); + return true; + + } + return false; + } + + protected void logInfo(String trace, SVNEvent event) { + final String anObject = event.getAction() + ""; + if (!"update_none".equals(anObject) + && !"status_completed".equals(anObject)) + log.debug("-- svn log on file [" + event.getPath() + + "] action [" + event.getAction() + "] : " + trace); + } + + public void handleEvent(SVNEvent event, double progress) + throws SVNException { + /* + * Gets the current action. An action is represented by + * SVNEventAction. + */ + if (handleEventWC(event, progress)) + return; + if (handleEventCommit(event, progress)) + return; + if (handleEventUpdate(event, progress)) + return; + + logInfo("unkown event ", event); + } + + public void checkCancelled() throws SVNCancelException { + + } +} Deleted: trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNHelper.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNHelper.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-svn/src/main/java/org/codelutin/vcs/impl/svn/SVNHelper.java 2008-04-06 10:11:00 UTC (rev 392) @@ -1,461 +0,0 @@ -/* *##% -* Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 Code Lutin, -* Benjamin Poussin, Tony Chemit -* -* -* This program is free software; you can redistribute it and/or -* modify it under the terms of the GNU General Public License -* as published by the Free Software Foundation; either version 2 -* of the License, or (at your option) any later version. -* -* This program is distributed in the hope that it will be useful, -* but WITHOUT ANY WARRANTY; without even the implied warranty of -* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -* GNU General Public License for more details. -* -* You should have received a copy of the GNU General Public License -* along with this program; if not, write to the Free Software -* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -*##%*/ -package org.codelutin.vcs.impl.svn; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codelutin.vcs.VCSException; -import org.codelutin.vcs.util.AbstractVCSHandler; -import org.codelutin.vcs.VCSRuntimeException; -import org.codelutin.vcs.type.VCSTypeRepo; -import org.tmatesoft.svn.core.SVNCancelException; -import org.tmatesoft.svn.core.SVNException; -import org.tmatesoft.svn.core.SVNNodeKind; -import org.tmatesoft.svn.core.SVNProperty; -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.io.SVNRepository; -import org.tmatesoft.svn.core.wc.ISVNEventHandler; -import org.tmatesoft.svn.core.wc.ISVNOptions; -import org.tmatesoft.svn.core.wc.SVNClientManager; -import org.tmatesoft.svn.core.wc.SVNEvent; -import org.tmatesoft.svn.core.wc.SVNEventAction; -import org.tmatesoft.svn.core.wc.SVNRevision; -import org.tmatesoft.svn.core.wc.SVNStatusType; -import org.tmatesoft.svn.core.wc.SVNWCUtil; - -import java.util.Arrays; - -/** - * A helper for SVN to test connection, find a svn url... - * - * @author chemit - */ - -public class SVNHelper { - public static boolean libraryInit = false; - - static protected final Log log = LogFactory.getLog(SVNHelper.class); - - /** - * Test if a anonymous svn connection can be openned. - * - * @param url the svn url to test - * @return <code>true</code> if connection is ok,<code>false</code> otherwise. - * @throws VCSException if could not compute the SVNURL - */ - public static boolean testAnonymousConnection(String url) throws VCSException { - boolean result = true; - - SVNRepository repository = getAnonymousConnection(url); - try { - repository.testConnection(); - } catch (SVNException e) { - result = false; - } finally { - if (repository != null) { - try { - repository.closeSession(); - } catch (Exception e) { - log.warn(e); - } - } - } - return result; - } - - /** - * Test if a anonymous svn connection can be openned. - * - * @param url the svn url to test - * @param username user name - * @param privateKeyFilePath the file to used as private key file - * @param passphrase passphrase to use - * @return <code>true</code> if connection is ok,<code>false</code> otherwise. - * @throws VCSException if could not compute the SVNURL - */ - public static boolean testSSHConnection(String url, String username, String privateKeyFilePath, char[] passphrase) throws VCSException { - boolean result = true; - - SVNRepository repository = getSSHConnection(url, username, privateKeyFilePath, passphrase); - try { - repository.testConnection(); - } catch (SVNException e) { - result = false; - } finally { - if (repository != null) { - try { - repository.closeSession(); - } catch (Exception e) { - log.warn(e); - } - } - } - return result; - } - - public static SVNRepository getAnonymousConnection(String url) throws VCSException { - - setupLibrary(); - - SVNURL testRepositoryURL; - try { - testRepositoryURL = SVNURL.parseURIEncoded(url); - } catch (SVNException e) { - throw new VCSException(e); - } - SVNRepository repository; - try { - ISVNOptions options = SVNWCUtil.createDefaultOptions(true); - SVNClientManager manager = SVNClientManager.newInstance(options, "anonymous", "anonymous"); - repository = manager.createRepository(testRepositoryURL, false); - repository.testConnection(); - return repository; - } catch (SVNException e) { - throw new VCSException(e); - } - } - - public static SVNRepository getSSHConnection(String url, String username, String privateKeyFilePath, char[] passphrase) throws VCSException { - - setupLibrary(); - - SVNURL testRepositoryURL; - try { - testRepositoryURL = SVNURL.parseURIEncoded(url); - } catch (SVNException e) { - throw new VCSException(e); - } - SVNRepository repository; - try { - ISVNOptions options = SVNWCUtil.createDefaultOptions(true); - System.setProperty("svnkit.ssh2.key", privateKeyFilePath); - System.setProperty("svnkit.ssh2.username", username); - if (passphrase != null && passphrase.length > 0) { - System.setProperty("svnkit.ssh2.passphrase", Arrays.toString(passphrase)); - } - //System.setProperty("svnkit.ssh2.passphrase", ""); - //System.setProperty("svnkit.ssh2.password", ""); - //System.setProperty("svnkit.ssh2.port", "22"); - - // instanciate svn client manager - SVNClientManager manager = SVNClientManager.newInstance(options); - repository = manager.createRepository(testRepositoryURL, false); - repository.testConnection(); - return repository; - } catch (SVNException e) { - throw new VCSException(e); - } - } - - /** - * @param typeRepo the type of repo we want to use if possible - * @param uncleanRemotePath remote path (could be unclean) - * @param databaseVersion the database version to use - * @param hostName the hostname to use - * @return the typeRepo to use - * @throws VCSException if could not compute SVNURL to tests - */ - public static VCSTypeRepo findTypeRepo(VCSTypeRepo typeRepo, - String uncleanRemotePath, - String databaseVersion, - String hostName) throws VCSException { - - - VCSTypeRepo result; - - String remotePath = AbstractVCSHandler.getRemotePath(typeRepo, uncleanRemotePath); - String remoteDatabase = AbstractVCSHandler.getRemoteDatabase(typeRepo, databaseVersion); - StringBuilder sb = new StringBuilder("svn://").append(hostName); - sb.append("/").append(remotePath); - String url = sb.toString(); - log.info("try svn url " + url + " (" + remoteDatabase + ")"); - - SVNRepository repository; - try { - repository = getAnonymousConnection(url); - } catch (VCSException e) { - log.warn(e); - return null; - } - - try { - SVNNodeKind kind = repository.checkPath(remoteDatabase, SVNRevision.HEAD.getNumber()); - log.info("kind node found for " + remoteDatabase + " : " + kind); - // typeRepo type is ok, use it - if (kind == SVNNodeKind.NONE) { - // could not found the remote database - if (typeRepo == VCSTypeRepo.HEAD) { - // this is a fatal error since head always exists - throw new VCSRuntimeException("could not found svn trunk " + url + " (" + repository.getLocation() + ")"); - } else { - result = VCSTypeRepo.HEAD; - } - } else { - // was found, so keep it - result = typeRepo; - } - } catch (SVNException e) { - throw new VCSRuntimeException(e); - } - log.info("required:" + typeRepo + " available:" + result); - return result; - }/* - * Initializes the library to work with a repository via different - * protocols. - */ - - public static void setupLibrary() { - if (libraryInit) { - return; - } - libraryInit = true; - /* - * For using over http:// and https:// - */ - DAVRepositoryFactory.setup(); - - /* - * For using over svn:// and svn+xxx:// - */ - SVNRepositoryFactoryImpl.setup(); - - /* - * For using over file:/// - */ - FSRepositoryFactory.setup(); - } - - /** - * A svn logger - * - * @author chemit - */ - public static class SVNEventLoggerHandler implements ISVNEventHandler { - - static private Log log = LogFactory.getLog(SVNEventLoggerHandler.class); - - /* - * progress is currently reserved for future purposes and now is always - * ISVNEventHandler.UNKNOWN - */ - - public boolean handleEventWC(SVNEvent event, double progress) { - /* - * Gets the current action. An action is represented by - * SVNEventAction. - */ - SVNEventAction action = event.getAction(); - String trace = null; - if (action == SVNEventAction.ADD) { - /* - * The item is scheduled for addition. - */ - trace = "A "; - } else if (action == SVNEventAction.COPY) { - /* - * The item is scheduled for addition with history (copied, in - * other words). - */ - trace = "A + "; - } else if (action == SVNEventAction.REVERT) { - /* - * The item is scheduled for revertion. - */ - trace = "R "; - } else if (action == SVNEventAction.DELETE) { - /* - * The item is scheduled for deletion. - */ - trace = "D "; - } else if (action == SVNEventAction.LOCKED) { - /* - * The item is locked. - */ - trace = "L "; - } else if (action == SVNEventAction.LOCK_FAILED) { - /* - * Locking operation failed. - */ - trace = "failed to lock "; - } - - if (trace != null) { - logInfo(trace, event); - return true; - } - - return false; - - } - - public boolean handleEventCommit(SVNEvent event, double progress) { - /* - * Gets the current action. An action is represented by - * SVNEventAction. In case of a commit an action can be determined - * via comparing SVNEvent.getAction() with - * SVNEventAction.COMMIT_-like constants. - */ - SVNEventAction action = event.getAction(); - String trace = null; - if (action == SVNEventAction.COMMIT_COMPLETED) { - trace = "Complete "; - } else if (action == SVNEventAction.COMMIT_MODIFIED) { - trace = "Sending "; - } else if (action == SVNEventAction.COMMIT_DELETED) { - trace = "Deleting "; - } else if (action == SVNEventAction.COMMIT_REPLACED) { - trace = "Replacing "; - } else if (action == SVNEventAction.COMMIT_DELTA_SENT) { - trace = "Transmitting file data...."; - } else if (action == SVNEventAction.COMMIT_ADDED) { - /* - * Gets the MIME-type of the item. - */ - String mimeType = event.getMimeType(); - if (SVNProperty.isBinaryMimeType(mimeType)) { - /* - * If the item is a binary file - */ - trace = "Adding (bin) "; - } else { - trace = "Adding "; - } - } - - if (trace != null) { - logInfo(trace, event); - return true; - } - - return false; - } - - public boolean handleEventUpdate(SVNEvent event, double progress) { - /* - * Gets the current action. An action is represented by - * SVNEventAction. In case of an update an action can be determined - * via comparing SVNEvent.getAction() and - * SVNEventAction.UPDATE_-like constants. - */ - SVNEventAction action = event.getAction(); - String pathChangeType = null; - String trace = null; - if (action == SVNEventAction.UPDATE_ADD) { - /* - * the item was added - */ - pathChangeType = "A"; - } else if (action == SVNEventAction.UPDATE_DELETE) { - /* - * the item was deleted - */ - pathChangeType = "D"; - } else if (action == SVNEventAction.UPDATE_UPDATE) { - - /* - * Find out in details what state the item is (after having been - * updated). - * - * Gets the status of file/directory item contents. It is - * SVNStatusType who contains information on the state of an - * item. - */ - SVNStatusType contentsStatus = event.getContentsStatus(); - if (contentsStatus == org.tmatesoft.svn.core.wc.SVNStatusType.CHANGED) { - /* - * the item was modified in the repository (got the changes - * from the repository - */ - pathChangeType = "U"; - } else if (contentsStatus == org.tmatesoft.svn.core.wc.SVNStatusType.CONFLICTED) { - /* - * The file item is in a state of Conflict. That is, changes - * received from the repository during an update, overlap - * with local changes the user has in his working copy. - */ - pathChangeType = "C"; - } else if (contentsStatus == org.tmatesoft.svn.core.wc.SVNStatusType.MERGED) { - /* - * The file item was merGed (those changes that came from - * the repository did not overlap local changes and were - * merged into the file). - */ - pathChangeType = "G"; - } - - } else if (action == SVNEventAction.UPDATE_EXTERNAL) { - /* for externals definitions */ - trace = "Fetching external item into '" - + event.getFile().getAbsolutePath() + "'"; - trace += "\nExternal at revision " + event.getRevision(); - - } else if (action == SVNEventAction.UPDATE_COMPLETED) { - /* - * Updating the working copy is completed. Prints out the - * revision. - */ - trace = "At revision " + event.getRevision(); - } - - if (trace != null) { - logInfo(trace, event); - return true; - } - - if (pathChangeType != null) { - logInfo(trace, event); - return true; - - } - return false; - } - - protected void logInfo(String trace, SVNEvent event) { - final String anObject = event.getAction() + ""; - if (!"update_none".equals(anObject) - && !"status_completed".equals(anObject)) - log.debug("-- svn log on file [" + event.getPath() - + "] action [" + event.getAction() + "] : " + trace); - } - - public void handleEvent(SVNEvent event, double progress) - throws SVNException { - /* - * Gets the current action. An action is represented by - * SVNEventAction. - */ - if (handleEventWC(event, progress)) - return; - if (handleEventCommit(event, progress)) - return; - if (handleEventUpdate(event, progress)) - return; - - logInfo("unkown event ", event); - } - - public void checkCancelled() throws SVNCancelException { - - } - } -} Modified: trunk/lutinvcs/lutinvcs-provider-svn/src/test/java/org/codelutin/vcs/impl/svn/FindTypeRepoTest.java =================================================================== --- trunk/lutinvcs/lutinvcs-provider-svn/src/test/java/org/codelutin/vcs/impl/svn/FindTypeRepoTest.java 2008-04-06 10:00:07 UTC (rev 391) +++ trunk/lutinvcs/lutinvcs-provider-svn/src/test/java/org/codelutin/vcs/impl/svn/FindTypeRepoTest.java 2008-04-06 10:11:00 UTC (rev 392) @@ -2,6 +2,7 @@ import junit.framework.TestCase; import org.codelutin.vcs.VCSException; +import org.codelutin.vcs.SVNProvider; import org.codelutin.vcs.type.VCSTypeRepo; /** @@ -23,7 +24,7 @@ vcsTypeRepo = VCSTypeRepo.BRANCH; path = "svnroot/isis-fish-data"; version = "3.1.0"; - result = SVNHelper.findTypeRepo(vcsTypeRepo, path, version, hostname); + result = SVNProvider.findTypeRepo(vcsTypeRepo, path, version, hostname); assertEquals(VCSTypeRepo.BRANCH, result); } @@ -31,11 +32,11 @@ vcsTypeRepo = VCSTypeRepo.BRANCH; version = "3.0.0"; path = "svnroot/isis-fish-data"; - result = SVNHelper.findTypeRepo(vcsTypeRepo, path, version, hostname); + result = SVNProvider.findTypeRepo(vcsTypeRepo, path, version, hostname); assertEquals(VCSTypeRepo.HEAD, result); try { path = "svnroot/sis-fish-data"; - result = SVNHelper.findTypeRepo(vcsTypeRepo, path, version, hostname); + result = SVNProvider.findTypeRepo(vcsTypeRepo, path, version, hostname); fail(); } catch (Exception e) { assertTrue(true); @@ -46,7 +47,7 @@ vcsTypeRepo = VCSTypeRepo.HEAD; path = "svnroot/isis-fish-data"; version = "3.0.0"; - result = SVNHelper.findTypeRepo(vcsTypeRepo, path, version, hostname); + result = SVNProvider.findTypeRepo(vcsTypeRepo, path, version, hostname); assertEquals(VCSTypeRepo.HEAD, result); } @@ -55,7 +56,7 @@ path = "svnroot/sis-fish-data"; version = "3.0.0"; try { - result = SVNHelper.findTypeRepo(vcsTypeRepo, path, version, hostname); + result = SVNProvider.findTypeRepo(vcsTypeRepo, path, version, hostname); fail(); } catch (Exception e) { assertTrue(true);
participants (1)
-
tchemit@users.labs.libre-entreprise.org