/*
* ====================================================================
* 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.internal.wc.admin;
import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Iterator;
import org.tmatesoft.svn.core.SVNErrorCode;
import org.tmatesoft.svn.core.SVNErrorMessage;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNNodeKind;
import org.tmatesoft.svn.core.SVNProperties;
import org.tmatesoft.svn.core.SVNProperty;
import org.tmatesoft.svn.core.SVNPropertyValue;
import org.tmatesoft.svn.core.internal.util.SVNDate;
import org.tmatesoft.svn.core.internal.wc.SVNAdminUtil;
import org.tmatesoft.svn.core.internal.wc.SVNErrorManager;
import org.tmatesoft.svn.core.wc.SVNStatusType;
import org.tmatesoft.svn.util.SVNLogType;
/**
* @version 1.3
* @author TMate Software Ltd.
*/
public abstract class SVNLog {
public static final String DELETE_CHANGELIST = "delete-changelist";
public static final String DELETE_ENTRY = "delete-entry";
public static final String MODIFY_ENTRY = "modify-entry";
public static final String MODIFY_WC_PROPERTY = "modify-wcprop";
public static final String DELETE_LOCK = "delete-lock";
public static final String MOVE = "mv";
public static final String APPEND = "append";
public static final String DELETE = "rm";
public static final String READONLY = "readonly";
public static final String COPY_AND_TRANSLATE = "cp-and-translate";
public static final String COPY_AND_DETRANSLATE = "cp-and-detranslate";
public static final String COPY = "cp";
public static final String MERGE = "merge";
public static final String MAYBE_READONLY = "maybe-readonly";
public static final String MAYBE_EXECUTABLE = "maybe-executable";
public static final String SET_TIMESTAMP = "set-timestamp";
public static final String COMMIT = "committed";
public static final String UPGRADE_FORMAT = "upgrade-format";
public static final String ADD_TREE_CONFLICT = "add-tree-conflict";
public static final String NAME_ATTR = "name";
public static final String DATA_ATTR = "data";
public static final String PROPERTY_NAME_ATTR = "propname";
public static final String PROPERTY_VALUE_ATTR = "propval";
public static final String DEST_ATTR = "dest";
public static final String TIMESTAMP_ATTR = "timestamp";
public static final String REVISION_ATTR = "revision";
public static final String FORMAT_ATTR = "format";
public static final String FORCE_ATTR = "force";
public static final String ATTR1 = "arg1";
public static final String ATTR2 = "arg2";
public static final String ATTR3 = "arg3";
public static final String ATTR4 = "arg4";
public static final String ATTR5 = "arg5";
public static final String ATTR6 = "arg6";
public static final String WC_TIMESTAMP = "working";
public static final String WC_WORKING_SIZE = "working";
protected Collection myCache;
protected SVNAdminArea myAdminArea;
public abstract void save() throws SVNException;
public abstract String toString();
public abstract void delete() throws SVNException;
public abstract boolean exists();
protected SVNLog(SVNAdminArea adminArea) {
myAdminArea = adminArea;
}
public void addCommand(String name, SVNProperties attributes, boolean save) throws SVNException {
if (myCache == null) {
myCache = new ArrayList();
}
attributes = new SVNProperties(attributes);
attributes.put("", name);
myCache.add(attributes);
if (save) {
save();
}
}
public void deleteCommandsByName(String name, boolean save) throws SVNException {
if (myCache == null) {
return;
}
for (Iterator iterator = myCache.iterator(); iterator.hasNext(); ) {
Object command = iterator.next();
if (!(command instanceof SVNProperties)) {
continue;
}
SVNProperties attributes = (SVNProperties) command;
String commandName = attributes.getStringValue("");
if (!name.equals(commandName)) {
continue;
}
iterator.remove();
}
if (save) {
save();
}
}
public void deleteLastCommand(boolean save) throws SVNException {
if (myCache == null) {
return;
}
int size = myCache.size();
int commandIdex = 0;
for (Iterator iterator = myCache.iterator(); iterator.hasNext(); ) {
if (commandIdex == size - 1) {
iterator.remove();
}
commandIdex++;
}
if (save) {
save();
}
}
public void deleteCommandsByNameAndAttributes(String name, SVNProperties attributes, boolean save) throws SVNException {
if (myCache == null) {
return;
}
for (Iterator iterator = myCache.iterator(); iterator.hasNext(); ) {
Object command = iterator.next();
if (!(command instanceof SVNProperties)) {
continue;
}
SVNProperties commandAttributes = (SVNProperties) command;
String commandName = commandAttributes.getStringValue("");
if (!name.equals(commandName)) {
continue;
}
SVNProperties commandAttributesWithoutName = new SVNProperties(commandAttributes);
commandAttributesWithoutName.remove("");
if (!commandAttributesWithoutName.equals(attributes)) {
continue;
}
iterator.remove();
}
if (save) {
save();
}
}
public SVNStatusType logChangedEntryProperties(String name, SVNProperties modifiedEntryProps) throws SVNException {
SVNStatusType status = SVNStatusType.LOCK_UNCHANGED;
if (modifiedEntryProps != null) {
SVNProperties command = new SVNProperties();
command.put(SVNLog.NAME_ATTR, name);
for (Iterator names = modifiedEntryProps.nameSet().iterator(); names.hasNext();) {
String propName = (String) names.next();
SVNPropertyValue propValue = modifiedEntryProps.getSVNPropertyValue(propName);
String longPropName = !propName.startsWith(SVNProperty.SVN_ENTRY_PREFIX) ? SVNProperty.SVN_ENTRY_PREFIX + propName : propName;
if (SVNProperty.LOCK_TOKEN.equals(longPropName)) {
SVNProperties deleteLockCommand = new SVNProperties();
deleteLockCommand.put(SVNLog.NAME_ATTR, name);
addCommand(SVNLog.DELETE_LOCK, deleteLockCommand, false);
status = SVNStatusType.LOCK_UNLOCKED;
} else if (propValue != null) {
command.put(propName, propValue);
}
}
addCommand(SVNLog.MODIFY_ENTRY, command, false);
command.clear();
}
return status;
}
public void logChangedWCProperties(String name, SVNProperties modifiedWCProps) throws SVNException {
if (modifiedWCProps != null) {
SVNProperties command = new SVNProperties();
command.put(SVNLog.NAME_ATTR, name);
for (Iterator names = modifiedWCProps.nameSet().iterator(); names.hasNext();) {
String propName = (String) names.next();
SVNPropertyValue propValue = modifiedWCProps.getSVNPropertyValue(propName);
command.put(SVNLog.PROPERTY_NAME_ATTR, propName);
if (propValue != null) {
command.put(SVNLog.PROPERTY_VALUE_ATTR, propValue);
} else {
command.remove(SVNLog.PROPERTY_VALUE_ATTR);
}
addCommand(SVNLog.MODIFY_WC_PROPERTY, command, false);
}
}
}
public void logTweakEntry(String name, String newURL, long newRevision) throws SVNException {
SVNProperties attributes = new SVNProperties();
attributes.put(SVNProperty.shortPropertyName(SVNProperty.KIND), SVNProperty.KIND_FILE);
attributes.put(SVNProperty.shortPropertyName(SVNProperty.REVISION), Long.toString(newRevision));
attributes.put(SVNProperty.shortPropertyName(SVNProperty.DELETED), Boolean.FALSE.toString());
attributes.put(SVNProperty.shortPropertyName(SVNProperty.ABSENT), Boolean.FALSE.toString());
attributes.put(SVNProperty.shortPropertyName(SVNProperty.WORKING_SIZE), Long.toString(SVNProperty.WORKING_SIZE_UNKNOWN));
attributes.put(SVNProperty.shortPropertyName(SVNProperty.TEXT_TIME), SVNDate.NULL.format());
if (newURL != null) {
attributes.put(SVNProperty.shortPropertyName(SVNProperty.URL), newURL);
}
logChangedEntryProperties(name, attributes);
}
public void logRemoveRevertFile(String name, SVNAdminArea adminArea, boolean isProp) throws SVNException {
String revertPath = null;
if (isProp) {
revertPath = SVNAdminUtil.getPropRevertPath(name, SVNNodeKind.FILE, false);
} else {
revertPath = SVNAdminUtil.getTextRevertPath(name, false);
}
File revertFile = adminArea.getFile(revertPath);
if (revertFile.isFile()) {
SVNProperties command = new SVNProperties();
command.put(SVNLog.NAME_ATTR, revertPath);
addCommand(SVNLog.DELETE, command, false);
command.clear();
}
}
public void run(SVNLogRunner runner) throws SVNException {
Collection commands = readCommands();
if (commands == null || commands.isEmpty()) {
return;
}
try {
int count = 0;
for (Iterator cmds = commands.iterator(); cmds.hasNext();) {
SVNProperties command = (SVNProperties) cmds.next();
String name = command.getStringValue("");
String attrName = command.getStringValue(SVNLog.NAME_ATTR);
if (attrName == null && !SVNLog.UPGRADE_FORMAT.equals(name)) {
SVNErrorCode code = count <= 1 ? SVNErrorCode.WC_BAD_ADM_LOG_START : SVNErrorCode.WC_BAD_ADM_LOG;
SVNErrorMessage err = SVNErrorMessage.create(code,
"Log entry missing ''name'' attribute (entry ''{0}'' for directory ''{1}'')",
new Object[] { name, myAdminArea.getRoot() });
SVNErrorManager.error(err, SVNLogType.WC);
}
if (runner != null) {
runner.runCommand(myAdminArea, name, command, ++count);
}
cmds.remove();
}
} catch (SVNException e) {
// save failed command and unexecuted commands back to the log file.
myCache = null;
for (Iterator cmds = commands.iterator(); cmds.hasNext();) {
SVNProperties command = (SVNProperties) cmds.next();
SVNPropertyValue name = command.remove("");
addCommand(name.getString(), command, false);
}
save();
throw e;
}
}
protected abstract Collection readCommands() throws SVNException;
}