/* * Copyright 2012-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package at.nonblocking.maven.nonsnapshot.impl; import java.io.File; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.Properties; import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.util.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.tmatesoft.svn.core.*; import org.tmatesoft.svn.core.auth.BasicAuthenticationManager; import org.tmatesoft.svn.core.auth.ISVNAuthenticationManager; 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; import at.nonblocking.maven.nonsnapshot.ScmHandler; import at.nonblocking.maven.nonsnapshot.exception.NonSnapshotPluginException; /** * SVN implementation of {@link ScmHandler} based on SvnKit. * * @author Juergen Kofler */ @Component(role = ScmHandler.class, hint = "SVN") public class ScmHandlerSvnImpl implements ScmHandler { private static final Logger LOG = LoggerFactory.getLogger(ScmHandlerSvnImpl.class); private SVNClientManager svnClientManager = SVNClientManager.newInstance(); public ScmHandlerSvnImpl() { } @Override public boolean isWorkingCopy(File path) { return SVNWCUtil.isVersionedDirectory(toCanonicalPath(path)); } @Override public boolean checkChangesSinceRevision(final File moduleDirectory, final long sinceRevision, final long workspaceRevision) { final Boolean[] changes = new Boolean[1]; changes[0] = false; try { this.svnClientManager.getLogClient().doLog(new File[] { moduleDirectory }, SVNRevision.WORKING, SVNRevision.create(sinceRevision + 1), SVNRevision.create(workspaceRevision), false, false, 100L, new ISVNLogEntryHandler() { @Override public void handleLogEntry(SVNLogEntry svnLogEntry) throws SVNException { if (!svnLogEntry.getMessage().startsWith(NONSNAPSHOT_COMMIT_MESSAGE_PREFIX)) { LOG.debug("Module folder {}: Change since last commit: rev{} @ {} ({})", new Object[]{ moduleDirectory.getAbsolutePath(), svnLogEntry.getRevision(), svnLogEntry.getDate(), svnLogEntry.getMessage() }); changes[0] = true; } } }); } catch (SVNException e) { LOG.warn("Failed to check changes for path: {}" + moduleDirectory.getAbsolutePath(), e); return true; } return changes[0]; } @Override public boolean checkChangesSinceDate(final File moduleDirectory, final Date sinceDate, final Date workspaceLastCommitDate) { final Boolean[] changes = new Boolean[1]; changes[0] = false; try { this.svnClientManager.getLogClient().doLog(new File[] { moduleDirectory }, SVNRevision.WORKING, SVNRevision.create(sinceDate), SVNRevision.create(workspaceLastCommitDate), false, true, 100L, new ISVNLogEntryHandler() { @Override public void handleLogEntry(SVNLogEntry svnLogEntry) throws SVNException { if (!svnLogEntry.getMessage().startsWith(NONSNAPSHOT_COMMIT_MESSAGE_PREFIX)) { LOG.debug("Module folder {}: Change since last commit: rev{} @ {} ({})", new Object[]{ moduleDirectory.getAbsolutePath(), svnLogEntry.getRevision(), svnLogEntry.getDate(), svnLogEntry.getMessage() }); changes[0] = true; } } }); } catch (SVNException e) { LOG.warn("Failed to check changes for path: {}" + moduleDirectory.getAbsolutePath(), e); return true; } return changes[0]; } @Override public Date getLastCommitDate(File path) { try { SVNInfo info = this.svnClientManager.getWCClient().doInfo(path, null); return info.getCommittedDate(); } catch (SVNException e) { throw new NonSnapshotPluginException("Failed to obtain current revision number for path: " + path.getAbsolutePath(), e); } } @Override public long getCurrentRevisionId(File path) { try { SVNInfo info = this.svnClientManager.getWCClient().doInfo(path, null); return info.getRevision().getNumber(); } catch (SVNException e) { throw new NonSnapshotPluginException("Failed to obtain current revision number for path: " + path.getAbsolutePath(), e); } } @Override public void commitFiles(List<File> files, String commitMessage) { LOG.debug("Committing files: {}", files); try { SVNCommitInfo info = this.svnClientManager.getCommitClient().doCommit(files.toArray(new File[files.size()]), false, commitMessage, null, null, false, false, SVNDepth.FILES); if (info.getErrorMessage() != null) { throw new NonSnapshotPluginException("Failed to commit files. Message: " + info.getErrorMessage().getMessage()); } LOG.debug("Files committed. New revision: {}", info.getNewRevision()); } catch (SVNException e) { throw new NonSnapshotPluginException("Failed to commit files!", e); } } @Override public void init(File localRepoPath, String scmUser, String scmPassword, Properties properties) { if (StringUtils.isEmpty(scmUser) || StringUtils.isEmpty(scmPassword)) { throw new NonSnapshotPluginException("Parameters 'scmUser' and 'scmPassword' are required!"); } ISVNAuthenticationManager authManager = new BasicAuthenticationManager(scmUser, scmPassword); this.svnClientManager.setAuthenticationManager(authManager); } private File toCanonicalPath(File path) { try { return path.getCanonicalFile(); } catch (IOException e) { throw new NonSnapshotPluginException(e.getMessage(), e); } } }