| 1 | package net.oni2.svnaccess; | 
 
 
 
 
 | 2 |  | 
 
 
 
 
 | 3 | import static java.lang.System.err; | 
 
 
 
 
 | 4 |  | 
 
 
 
 
 | 5 | import java.io.File; | 
 
 
 
 
 | 6 | import java.util.Vector; | 
 
 
 
 
 | 7 |  | 
 
 
 
 
 | 8 | import net.oni2.ProxySettings; | 
 
 
 
 
 | 9 |  | 
 
 
 
 
 | 10 | import org.tmatesoft.svn.core.SVNDepth; | 
 
 
 
 
 | 11 | import org.tmatesoft.svn.core.SVNDirEntry; | 
 
 
 
 
 | 12 | import org.tmatesoft.svn.core.SVNException; | 
 
 
 
 
 | 13 | import org.tmatesoft.svn.core.SVNURL; | 
 
 
 
 
 | 14 | import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; | 
 
 
 
 
 | 15 | import org.tmatesoft.svn.core.auth.SVNAuthentication; | 
 
 
 
 
 | 16 | import org.tmatesoft.svn.core.internal.io.dav.DAVRepositoryFactory; | 
 
 
 
 
 | 17 | import org.tmatesoft.svn.core.internal.io.fs.FSRepositoryFactory; | 
 
 
 
 
 | 18 | import org.tmatesoft.svn.core.internal.io.svn.SVNRepositoryFactoryImpl; | 
 
 
 
 
 | 19 | import org.tmatesoft.svn.core.wc.ISVNStatusHandler; | 
 
 
 
 
 | 20 | import org.tmatesoft.svn.core.wc.SVNClientManager; | 
 
 
 
 
 | 21 | import org.tmatesoft.svn.core.wc.SVNInfo; | 
 
 
 
 
 | 22 | import org.tmatesoft.svn.core.wc.SVNRevision; | 
 
 
 
 
 | 23 | import org.tmatesoft.svn.core.wc.SVNStatus; | 
 
 
 
 
 | 24 | import org.tmatesoft.svn.core.wc.SVNStatusType; | 
 
 
 
 
 | 25 | import org.tmatesoft.svn.core.wc.SVNWCUtil; | 
 
 
 
 
 | 26 |  | 
 
 
 
 
 | 27 | /** | 
 
 
 
 
 | 28 | * SVN handling | 
 
 
 
 
 | 29 | * | 
 
 
 
 
 | 30 | * @author Christian Illy | 
 
 
 
 
 | 31 | */ | 
 
 
 
 
 | 32 | public class SVN { | 
 
 
 
 
 | 33 |  | 
 
 
 
 
 | 34 | SVNClientManager svnCManager = null; | 
 
 
 
 
 | 35 |  | 
 
 
 
 
 | 36 | private void setup() { | 
 
 
 
 
 | 37 | // For using over http:// and https:// | 
 
 
 
 
 | 38 | DAVRepositoryFactory.setup(); | 
 
 
 
 
 | 39 | // For using over svn:// and svn+xxx:// | 
 
 
 
 
 | 40 | SVNRepositoryFactoryImpl.setup(); | 
 
 
 
 
 | 41 | // For using over file:/// | 
 
 
 
 
 | 42 | FSRepositoryFactory.setup(); | 
 
 
 
 
 | 43 | } | 
 
 
 
 
 | 44 |  | 
 
 
 
 
 | 45 | private void setProxy(BasicAuthenticationManager authMan) { | 
 
 
 
 
 | 46 | ProxySettings prox = ProxySettings.getInstance(); | 
 
 
 
 
 | 47 | if (prox.validate()) { | 
 
 
 
 
 | 48 | authMan.setProxy(prox.getHostOrIp(), prox.getPort(), null, null); | 
 
 
 
 
 | 49 | } | 
 
 
 
 
 | 50 | } | 
 
 
 
 
 | 51 |  | 
 
 
 
 
 | 52 | private BasicAuthenticationManager getAuthManager() { | 
 
 
 
 
 | 53 | BasicAuthenticationManager auth = new BasicAuthenticationManager( | 
 
 
 
 
 | 54 | new SVNAuthentication[0]); | 
 
 
 
 
 | 55 | setProxy(auth); | 
 
 
 
 
 | 56 | return auth; | 
 
 
 
 
 | 57 | } | 
 
 
 
 
 | 58 |  | 
 
 
 
 
 | 59 | private BasicAuthenticationManager getAuthManager(String username, | 
 
 
 
 
 | 60 | String password) { | 
 
 
 
 
 | 61 | BasicAuthenticationManager auth = new BasicAuthenticationManager( | 
 
 
 
 
 | 62 | username, password); | 
 
 
 
 
 | 63 | setProxy(auth); | 
 
 
 
 
 | 64 | return auth; | 
 
 
 
 
 | 65 | } | 
 
 
 
 
 | 66 |  | 
 
 
 
 
 | 67 | /** | 
 
 
 
 
 | 68 | * Constructor | 
 
 
 
 
 | 69 | */ | 
 
 
 
 
 | 70 | public SVN() { | 
 
 
 
 
 | 71 | setup(); | 
 
 
 
 
 | 72 |  | 
 
 
 
 
 | 73 | svnCManager = SVNClientManager.newInstance( | 
 
 
 
 
 | 74 | SVNWCUtil.createDefaultOptions(true), getAuthManager()); | 
 
 
 
 
 | 75 | } | 
 
 
 
 
 | 76 |  | 
 
 
 
 
 | 77 | /** | 
 
 
 
 
 | 78 | * Constructor with init values | 
 
 
 
 
 | 79 | * | 
 
 
 
 
 | 80 | * @param username | 
 
 
 
 
 | 81 | *            Username | 
 
 
 
 
 | 82 | * @param password | 
 
 
 
 
 | 83 | *            Password | 
 
 
 
 
 | 84 | */ | 
 
 
 
 
 | 85 | public SVN(String username, String password) { | 
 
 
 
 
 | 86 | setup(); | 
 
 
 
 
 | 87 |  | 
 
 
 
 
 | 88 | svnCManager = SVNClientManager.newInstance( | 
 
 
 
 
 | 89 | SVNWCUtil.createDefaultOptions(true), | 
 
 
 
 
 | 90 | getAuthManager(username, password)); | 
 
 
 
 
 | 91 | } | 
 
 
 
 
 | 92 |  | 
 
 
 
 
 | 93 | /** | 
 
 
 
 
 | 94 | * Checkout/update a repository to a local path | 
 
 
 
 
 | 95 | * | 
 
 
 
 
 | 96 | * @param reposUrl | 
 
 
 
 
 | 97 | *            Repository URL | 
 
 
 
 
 | 98 | * @param wcDir | 
 
 
 
 
 | 99 | *            Local path | 
 
 
 
 
 | 100 | * @param listener | 
 
 
 
 
 | 101 | *            The listener for the status events | 
 
 
 
 
 | 102 | * @return True if successful | 
 
 
 
 
 | 103 | * @throws Exception | 
 
 
 
 
 | 104 | *             if missing parameters or something went wrong | 
 
 
 
 
 | 105 | */ | 
 
 
 
 
 | 106 | public boolean updateWC(String reposUrl, File wcDir, | 
 
 
 
 
 | 107 | SVNUpdateListener listener) throws Exception { | 
 
 
 
 
 | 108 | SVNURL repos = SVNURL.parseURIEncoded(reposUrl); | 
 
 
 
 
 | 109 |  | 
 
 
 
 
 | 110 | if (wcDir.exists()) { | 
 
 
 
 
 | 111 | int rev = pathIsWCof(repos, wcDir); | 
 
 
 
 
 | 112 | if (rev < 0) | 
 
 
 
 
 | 113 | throw new Exception( | 
 
 
 
 
 | 114 | "Destination path exists but is not a Working Copy of the SVN"); | 
 
 
 
 
 | 115 | return update(repos, wcDir, rev, listener); | 
 
 
 
 
 | 116 | } else { | 
 
 
 
 
 | 117 | return checkout(repos, wcDir, listener); | 
 
 
 
 
 | 118 | } | 
 
 
 
 
 | 119 | } | 
 
 
 
 
 | 120 |  | 
 
 
 
 
 | 121 | /** | 
 
 
 
 
 | 122 | * Checks if the SVN contains newer revisions than the local working copy | 
 
 
 
 
 | 123 | * | 
 
 
 
 
 | 124 | * @param reposUrl | 
 
 
 
 
 | 125 | *            URL of repository to check for newer revisions | 
 
 
 
 
 | 126 | * @param wcDir | 
 
 
 
 
 | 127 | *            Local working copy path to compare against | 
 
 
 
 
 | 128 | * @return -1: No local working copy yet<br> | 
 
 
 
 
 | 129 | *         0: Revisions are equal<br> | 
 
 
 
 
 | 130 | *         1: SVN contains newer revisions<br> | 
 
 
 
 
 | 131 | *         2: WC has manually deleted files | 
 
 
 
 
 | 132 | * @throws Exception | 
 
 
 
 
 | 133 | *             If destination is not a WC of the given repository | 
 
 
 
 
 | 134 | */ | 
 
 
 
 
 | 135 | public int checkSVN(String reposUrl, File wcDir) throws Exception { | 
 
 
 
 
 | 136 | SVNURL repos = SVNURL.parseURIEncoded(reposUrl); | 
 
 
 
 
 | 137 |  | 
 
 
 
 
 | 138 | if (wcDir.exists()) { | 
 
 
 
 
 | 139 | int localRev = pathIsWCof(repos, wcDir); | 
 
 
 
 
 | 140 | if (localRev < 0) | 
 
 
 
 
 | 141 | throw new Exception( | 
 
 
 
 
 | 142 | "Destination path exists but is not a Working Copy of the SVN"); | 
 
 
 
 
 | 143 | int remoteRev = getRemoteHeadRevision(repos); | 
 
 
 
 
 | 144 | if (remoteRev > localRev) | 
 
 
 
 
 | 145 | return 1; | 
 
 
 
 
 | 146 | else { | 
 
 
 
 
 | 147 | if (getMissingFiles(wcDir)) | 
 
 
 
 
 | 148 | return 2; | 
 
 
 
 
 | 149 | else | 
 
 
 
 
 | 150 | return 0; | 
 
 
 
 
 | 151 | } | 
 
 
 
 
 | 152 | } else { | 
 
 
 
 
 | 153 | return -1; | 
 
 
 
 
 | 154 | } | 
 
 
 
 
 | 155 | } | 
 
 
 
 
 | 156 |  | 
 
 
 
 
 | 157 | private boolean getMissingFiles(File wcDir) { | 
 
 
 
 
 | 158 | try { | 
 
 
 
 
 | 159 | final Vector<String> files = new Vector<String>(); | 
 
 
 
 
 | 160 | svnCManager.getStatusClient().doStatus(wcDir, null, | 
 
 
 
 
 | 161 | SVNDepth.INFINITY, false, false, false, false, | 
 
 
 
 
 | 162 | new ISVNStatusHandler() { | 
 
 
 
 
 | 163 | @Override | 
 
 
 
 
 | 164 | public void handleStatus(SVNStatus status) | 
 
 
 
 
 | 165 | throws SVNException { | 
 
 
 
 
 | 166 | SVNStatusType stat = status | 
 
 
 
 
 | 167 | .getCombinedNodeAndContentsStatus(); | 
 
 
 
 
 | 168 | if (stat == SVNStatusType.MISSING | 
 
 
 
 
 | 169 | || stat == SVNStatusType.STATUS_MISSING) { | 
 
 
 
 
 | 170 | files.add(status.getFile().getPath()); | 
 
 
 
 
 | 171 | } | 
 
 
 
 
 | 172 | } | 
 
 
 
 
 | 173 | }, null); | 
 
 
 
 
 | 174 | return files.size() > 0; | 
 
 
 
 
 | 175 | } catch (SVNException e) { | 
 
 
 
 
 | 176 | e.printStackTrace(); | 
 
 
 
 
 | 177 | } | 
 
 
 
 
 | 178 | return false; | 
 
 
 
 
 | 179 | } | 
 
 
 
 
 | 180 |  | 
 
 
 
 
 | 181 | private int getRemoteHeadRevision(SVNURL reposUrl) { | 
 
 
 
 
 | 182 | try { | 
 
 
 
 
 | 183 | SVNInfo info = svnCManager.getWCClient().doInfo(reposUrl, | 
 
 
 
 
 | 184 | SVNRevision.HEAD, SVNRevision.HEAD); | 
 
 
 
 
 | 185 | return (int) info.getRevision().getNumber(); | 
 
 
 
 
 | 186 | } catch (SVNException e) { | 
 
 
 
 
 | 187 | e.printStackTrace(); | 
 
 
 
 
 | 188 | } | 
 
 
 
 
 | 189 | return -1; | 
 
 
 
 
 | 190 | } | 
 
 
 
 
 | 191 |  | 
 
 
 
 
 | 192 | private int pathIsWCof(SVNURL reposUrl, File wcDir) { | 
 
 
 
 
 | 193 | if (wcDir.exists()) { | 
 
 
 
 
 | 194 | try { | 
 
 
 
 
 | 195 | SVNInfo info = svnCManager.getWCClient().doInfo(wcDir, | 
 
 
 
 
 | 196 | SVNRevision.WORKING); | 
 
 
 
 
 | 197 |  | 
 
 
 
 
 | 198 | if (info.getURL().equals(reposUrl)) | 
 
 
 
 
 | 199 | return (int) info.getRevision().getNumber(); | 
 
 
 
 
 | 200 | } catch (SVNException e) { | 
 
 
 
 
 | 201 | err.println("Error while getting information of working copy for the location '" | 
 
 
 
 
 | 202 | + reposUrl + "': " + e.getMessage()); | 
 
 
 
 
 | 203 | } | 
 
 
 
 
 | 204 | } | 
 
 
 
 
 | 205 | return -1; | 
 
 
 
 
 | 206 | } | 
 
 
 
 
 | 207 |  | 
 
 
 
 
 | 208 | private Vector<String> getUpdatedFilesInRepository(SVNURL reposUrl, | 
 
 
 
 
 | 209 | int fromRev) { | 
 
 
 
 
 | 210 | Vector<String> list = new Vector<String>(); | 
 
 
 
 
 | 211 | try { | 
 
 
 
 
 | 212 | svnCManager.getLogClient().doLog(reposUrl, | 
 
 
 
 
 | 213 | new String[] { reposUrl.getPath() }, SVNRevision.HEAD, | 
 
 
 
 
 | 214 | SVNRevision.create(fromRev + 1), SVNRevision.HEAD, true, | 
 
 
 
 
 | 215 | true, 0, new LogEntryHandler(list, reposUrl.getPath())); | 
 
 
 
 
 | 216 | } catch (Exception e) { | 
 
 
 
 
 | 217 | if (!e.getMessage().contains("No such revision ")) { | 
 
 
 
 
 | 218 | err.println("Error while getting the list of updated files of the location '" | 
 
 
 
 
 | 219 | + reposUrl + "': " + e.getMessage()); | 
 
 
 
 
 | 220 | e.printStackTrace(); | 
 
 
 
 
 | 221 | } | 
 
 
 
 
 | 222 | } | 
 
 
 
 
 | 223 |  | 
 
 
 
 
 | 224 | return list; | 
 
 
 
 
 | 225 | } | 
 
 
 
 
 | 226 |  | 
 
 
 
 
 | 227 | private boolean update(SVNURL reposUrl, File wcDir, int fromRev, | 
 
 
 
 
 | 228 | SVNUpdateListener listener) throws Exception { | 
 
 
 
 
 | 229 | Vector<String> updatedFiles = getUpdatedFilesInRepository(reposUrl, | 
 
 
 
 
 | 230 | fromRev); | 
 
 
 
 
 | 231 |  | 
 
 
 
 
 | 232 | svnCManager.getUpdateClient().setEventHandler( | 
 
 
 
 
 | 233 | new UpdateEventHandler(updatedFiles, listener)); | 
 
 
 
 
 | 234 |  | 
 
 
 
 
 | 235 | try { | 
 
 
 
 
 | 236 | svnCManager.getUpdateClient().doUpdate(wcDir, SVNRevision.HEAD, | 
 
 
 
 
 | 237 | SVNDepth.INFINITY, true, true); | 
 
 
 
 
 | 238 | return true; | 
 
 
 
 
 | 239 | } catch (Exception e) { | 
 
 
 
 
 | 240 | err.println("Error while updating the working copy for the location '" | 
 
 
 
 
 | 241 | + reposUrl + "': " + e.getMessage()); | 
 
 
 
 
 | 242 | } | 
 
 
 
 
 | 243 | return false; | 
 
 
 
 
 | 244 | } | 
 
 
 
 
 | 245 |  | 
 
 
 
 
 | 246 | private Vector<String> getFilesInRepository(SVNURL reposUrl) | 
 
 
 
 
 | 247 | throws Exception { | 
 
 
 
 
 | 248 | Vector<String> list = new Vector<String>(); | 
 
 
 
 
 | 249 | try { | 
 
 
 
 
 | 250 | svnCManager.getLogClient().doList(reposUrl, SVNRevision.HEAD, | 
 
 
 
 
 | 251 | SVNRevision.HEAD, false, SVNDepth.INFINITY, | 
 
 
 
 
 | 252 | SVNDirEntry.DIRENT_ALL, new DirEntryHandler(list)); | 
 
 
 
 
 | 253 | } catch (Exception e) { | 
 
 
 
 
 | 254 | err.println("Error while getting the list of files of the location '" | 
 
 
 
 
 | 255 | + reposUrl + "': " + e.getMessage()); | 
 
 
 
 
 | 256 | } | 
 
 
 
 
 | 257 | return list; | 
 
 
 
 
 | 258 | } | 
 
 
 
 
 | 259 |  | 
 
 
 
 
 | 260 | private boolean checkout(SVNURL reposUrl, File wcDir, | 
 
 
 
 
 | 261 | SVNUpdateListener listener) throws Exception { | 
 
 
 
 
 | 262 | Vector<String> newFiles = getFilesInRepository(reposUrl); | 
 
 
 
 
 | 263 | svnCManager.getUpdateClient().setEventHandler( | 
 
 
 
 
 | 264 | new UpdateEventHandler(newFiles, listener)); | 
 
 
 
 
 | 265 |  | 
 
 
 
 
 | 266 | boolean result = false; | 
 
 
 
 
 | 267 | try { | 
 
 
 
 
 | 268 | wcDir.mkdirs(); | 
 
 
 
 
 | 269 | svnCManager.getUpdateClient() | 
 
 
 
 
 | 270 | .doCheckout(reposUrl, wcDir, SVNRevision.HEAD, | 
 
 
 
 
 | 271 | SVNRevision.HEAD, SVNDepth.INFINITY, true); | 
 
 
 
 
 | 272 | result = true; | 
 
 
 
 
 | 273 | } catch (Exception e) { | 
 
 
 
 
 | 274 | err.println("Error while checking out a working copy for the location '" | 
 
 
 
 
 | 275 | + reposUrl + "': " + e.getMessage()); | 
 
 
 
 
 | 276 | } | 
 
 
 
 
 | 277 | return result; | 
 
 
 
 
 | 278 | } | 
 
 
 
 
 | 279 | } |