/* * ==================================================================== * Copyright (c) 2004-2012 TMate Software Ltd. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://svnkit.com/license.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * ==================================================================== */ package org.tmatesoft.svn.core.wc.admin; import java.util.Iterator; import org.tmatesoft.svn.core.ISVNLogEntryHandler; import org.tmatesoft.svn.core.SVNErrorCode; import org.tmatesoft.svn.core.SVNErrorMessage; import org.tmatesoft.svn.core.SVNException; import org.tmatesoft.svn.core.SVNProperties; import org.tmatesoft.svn.core.SVNProperty; import org.tmatesoft.svn.core.SVNPropertyValue; import org.tmatesoft.svn.core.SVNRevisionProperty; import org.tmatesoft.svn.core.internal.wc.SVNAdminHelper; import org.tmatesoft.svn.core.internal.wc.SVNCancellableEditor; import org.tmatesoft.svn.core.internal.wc.SVNErrorManager; import org.tmatesoft.svn.core.internal.wc.SVNSynchronizeEditor; import org.tmatesoft.svn.core.io.ISVNEditor; import org.tmatesoft.svn.core.io.ISVNReplayHandler; import org.tmatesoft.svn.core.io.SVNRepository; import org.tmatesoft.svn.core.wc.ISVNEventHandler; import org.tmatesoft.svn.util.ISVNDebugLog; import org.tmatesoft.svn.util.SVNLogType; /** * <code>SVNReplayHandler</code> is an implementation of {@link ISVNReplayHandler} that is used in * {@link SVNAdminClient#doSynchronize(org.tmatesoft.svn.core.SVNURL)}. * * @version 1.3 * @author TMate Software Ltd. * @since 1.2 */ public class SVNReplayHandler implements ISVNReplayHandler { private SVNRepository myTargetRepository; private boolean myHasCommitRevPropsCapability; private ISVNLogEntryHandler myLogEntryHandler; private ISVNDebugLog myDebugLog; private ISVNEventHandler myCanceller; private SVNSynchronizeEditor mySyncEditor; private SVNAdminClient myAdminClient; private int myNormalizedRevPropsCount; /** * Creates a new replay handler. * * @param targetRepository * @param hasCommitRevPropsCapability * @param logEntryHandler * @param debugLog * @param canceller * @param adminClient */ public SVNReplayHandler(SVNRepository targetRepository, boolean hasCommitRevPropsCapability, ISVNLogEntryHandler logEntryHandler, ISVNDebugLog debugLog, ISVNEventHandler canceller, SVNAdminClient adminClient) { myTargetRepository = targetRepository; myHasCommitRevPropsCapability = hasCommitRevPropsCapability; myLogEntryHandler = logEntryHandler; myDebugLog = debugLog; myCanceller = canceller; myAdminClient = adminClient; myNormalizedRevPropsCount = 0; } /** * @param revision * @param revisionProperties * @return editor to replicate the revision * @throws SVNException */ public ISVNEditor handleStartRevision(long revision, SVNProperties revisionProperties) throws SVNException { myTargetRepository.setRevisionPropertyValue(0, SVNRevisionProperty.CURRENTLY_COPYING, SVNPropertyValue.create(SVNProperty.toString(revision))); SVNProperties filtered = new SVNProperties(); filterProperties(revisionProperties, filtered, true); if (!filtered.containsName(SVNRevisionProperty.LOG)) { filtered.put(SVNRevisionProperty.LOG, ""); } SVNProperties normalizedProps = SVNAdminClient.normalizeRevisionProperties(filtered); myNormalizedRevPropsCount += normalizedProps.size(); if (mySyncEditor == null) { mySyncEditor = new SVNSynchronizeEditor(myTargetRepository, myLogEntryHandler, revision - 1, filtered); } else { mySyncEditor.reset(revision - 1, filtered); } ISVNEditor cancellableEditor = SVNCancellableEditor.newInstance(mySyncEditor, myCanceller, myDebugLog); return cancellableEditor; } /** * @param revision * @param revisionProperties * @param editor * @throws SVNException */ public void handleEndRevision(long revision, SVNProperties revisionProperties, ISVNEditor editor) throws SVNException { editor.closeEdit(); if (mySyncEditor.getCommitInfo().getNewRevision() != revision) { SVNErrorMessage err = SVNErrorMessage.create(SVNErrorCode.IO_ERROR, "Commit created rev {0} but should have created {1}", new Object[] { String.valueOf(mySyncEditor.getCommitInfo().getNewRevision()), String.valueOf(revision) }); SVNErrorManager.error(err, SVNLogType.FSFS); } SVNProperties existingProperties = myTargetRepository.getRevisionProperties(revision, null); SVNProperties filtered = new SVNProperties(); filterProperties(revisionProperties, filtered, false); SVNProperties normalizedProps = SVNAdminClient.normalizeRevisionProperties(filtered); myNormalizedRevPropsCount += normalizedProps.size(); int filteredCount = SVNAdminHelper.writeRevisionProperties(myTargetRepository, revision, filtered); SVNAdminHelper.removePropertiesNotInSource(myTargetRepository, revision, revisionProperties, existingProperties); myTargetRepository.setRevisionPropertyValue(0, SVNRevisionProperty.LAST_MERGED_REVISION, SVNPropertyValue.create(SVNProperty.toString(revision))); myTargetRepository.setRevisionPropertyValue(0, SVNRevisionProperty.CURRENTLY_COPYING, null); myAdminClient.handlePropertesCopied(filteredCount > 0, revision); } public int getNormalizedRevPropsCount() { return myNormalizedRevPropsCount; } public int getNormalizedNodePropsCount() { return mySyncEditor == null ? 0 : mySyncEditor.getNormalizedNodePropsCounter(); } private int filterProperties(SVNProperties revProps, SVNProperties filteredProps, boolean isStart) { int filteredCount = 0; for (Iterator propNamesIter = revProps.nameSet().iterator(); propNamesIter.hasNext();) { String propName = (String) propNamesIter.next(); SVNPropertyValue propValue = revProps.getSVNPropertyValue(propName); boolean filter = false; if (isStart) { if (myHasCommitRevPropsCapability) { filter = filterExcludeDateAuthorSync(propName); } else { filter = filterIncludeLog(propName); } } else { if (myHasCommitRevPropsCapability) { filter = filterIncludeDateAuthorSync(propName); } else { filter = filterExcludeLog(propName); } } if (!filter) { filteredProps.put(propName, propValue); } else { filteredCount += 1; } } return filteredCount; } private boolean filterIncludeDateAuthorSync(String propName) { return !filterExcludeDateAuthorSync(propName); } private boolean filterExcludeDateAuthorSync(String propName) { return SVNRevisionProperty.AUTHOR.equals(propName) || SVNRevisionProperty.DATE.equals(propName) || propName.startsWith(SVNProperty.SVN_SYNC_PREFIX); } private boolean filterIncludeLog(String propName) { return !filterExcludeLog(propName); } private boolean filterExcludeLog(String propName) { return SVNRevisionProperty.LOG.equals(propName); } }