diff options
3 files changed, 115 insertions, 9 deletions
diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java index 6065ea692..3030ae030 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/resources/EclipseFile.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -617,7 +617,9 @@ public class EclipseFile extends EclipseResource implements ICVSFile { // isMerged() must be called because when a file is updated and merged by the cvs server the timestamps // are equal. Merged files should however be reported as dirty because the user should take action and commit // or review the merged contents. - if(ResourceSyncInfo.isAddition(syncBytes) || ResourceSyncInfo.isMerge(syncBytes) || !exists()) { + if (ResourceSyncInfo.isAddition(syncBytes) + || ResourceSyncInfo.isMerge(syncBytes) + || ResourceSyncInfo.wasDeleted(syncBytes) || !exists()) { dirty = true; } else { // TODO: non-optimal as ResourceSyncInfo is created each time diff --git a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSyncInfo.java b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSyncInfo.java index 09bbfb404..9f241c266 100644 --- a/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSyncInfo.java +++ b/bundles/org.eclipse.team.cvs.core/src/org/eclipse/team/internal/ccvs/core/syncinfo/ResourceSyncInfo.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2010 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -69,10 +69,12 @@ public class ResourceSyncInfo { protected static final int TYPE_REGULAR = 1; protected static final int TYPE_MERGED = 2; protected static final int TYPE_MERGED_WITH_CONFLICTS = 3; + protected static final int TYPE_DELETED_AND_RESTORED = 4; protected static final String TIMESTAMP_DUMMY = "dummy timestamp"; //$NON-NLS-1$ protected static final String TIMESTAMP_MERGED = "Result of merge"; //$NON-NLS-1$ protected static final String TIMESTAMP_MERGED_WITH_CONFLICT = TIMESTAMP_MERGED + "+"; //$NON-NLS-1$ + protected static final String TIMESTAMP_DELETED_AND_RESTORED = "restored+"; //$NON-NLS-1$ protected static final String TIMESTAMP_SERVER_MERGED = "+modified"; //$NON-NLS-1$ protected static final String TIMESTAMP_SERVER_MERGED_WITH_CONFLICT = "+="; //$NON-NLS-1$ @@ -421,6 +423,9 @@ public class ResourceSyncInfo { } else if(date.indexOf(TIMESTAMP_MERGED)!=-1) { syncType = TYPE_MERGED; date = null; + } else if (date.indexOf(TIMESTAMP_DELETED_AND_RESTORED) != -1) { + syncType = TYPE_DELETED_AND_RESTORED; + date = date.substring(date.indexOf("+") + 1); //$NON-NLS-1$ } if(date==null || "".equals(date)) { //$NON-NLS-1$ @@ -494,6 +499,8 @@ public class ResourceSyncInfo { entryLineTimestamp = TIMESTAMP_MERGED; break; case TYPE_MERGED_WITH_CONFLICTS: entryLineTimestamp = TIMESTAMP_MERGED_WITH_CONFLICT + CVSDateFormatter.dateToEntryLine(timeStamp); break; + case TYPE_DELETED_AND_RESTORED: + entryLineTimestamp = TIMESTAMP_DELETED_AND_RESTORED + CVSDateFormatter.dateToEntryLine(timeStamp); break; } } result.append(entryLineTimestamp); @@ -658,6 +665,25 @@ public class ResourceSyncInfo { byte[] newSyncBytes = new byte[syncBytes.length - 1]; System.arraycopy(syncBytes, 0, newSyncBytes, 0, index + 1); System.arraycopy(syncBytes, index + 2, newSyncBytes, index + 1, newSyncBytes.length - index - 1); + + String syncTimestamp = Util.getSubstring(syncBytes, SEPARATOR_BYTE, + 3, false); + if (getSyncType(new String(syncTimestamp)) == TYPE_REGULAR) { + syncTimestamp = TIMESTAMP_DELETED_AND_RESTORED + syncTimestamp; + byte[] oldSyncBytes = newSyncBytes; + newSyncBytes = new byte[oldSyncBytes.length + + TIMESTAMP_DELETED_AND_RESTORED.length()]; + System.arraycopy(oldSyncBytes, 0, newSyncBytes, 0, + startOfSlot(oldSyncBytes, 3) + 1); + System.arraycopy(syncTimestamp.getBytes(), 0, newSyncBytes, + startOfSlot(oldSyncBytes, 3) + 1, + syncTimestamp.length()); + System.arraycopy(oldSyncBytes, + startOfSlot(oldSyncBytes, 4) - 1, newSyncBytes, + startOfSlot(oldSyncBytes, 3) + syncTimestamp.length(), + oldSyncBytes.length + - (startOfSlot(oldSyncBytes, 4) - 1)); + } return newSyncBytes; } return syncBytes; @@ -731,7 +757,9 @@ public class ResourceSyncInfo { throw new CVSException(NLS.bind(CVSMessages.ResourceSyncInfo_malformedSyncBytes, new String[] { new String(syncBytes) })); } int syncType = getSyncType(syncTimestamp); - if (syncType != TYPE_REGULAR) { + if (syncType == TYPE_DELETED_AND_RESTORED) { + return syncTimestamp.substring(syncTimestamp.indexOf("+") + 1); //$NON-NLS-1$ + } else if (syncType != TYPE_REGULAR) { if (syncType == TYPE_MERGED_WITH_CONFLICTS && fileTimestamp.equals(getTimestamp(syncTimestamp))) { return TIMESTAMP_SERVER_MERGED_WITH_CONFLICT; } else { @@ -785,6 +813,8 @@ public class ResourceSyncInfo { return TYPE_MERGED_WITH_CONFLICTS; } else if(date.indexOf(TIMESTAMP_MERGED)!=-1) { return TYPE_MERGED; + } else if (date.indexOf(TIMESTAMP_DELETED_AND_RESTORED) != -1) { + return TYPE_DELETED_AND_RESTORED; } return TYPE_REGULAR; } @@ -875,6 +905,25 @@ public class ResourceSyncInfo { } /** + * Checks if the ResourceSyncInfo was deleted and restored afterwards. + * Parses the timestamp in <code>syncBytes</code> and searches for markers. + * + * @param syncBytes + * @return boolean + */ + public static boolean wasDeleted(byte[] syncBytes) throws CVSException { + String timestamp = Util.getSubstring(syncBytes, SEPARATOR_BYTE, 3, + false); + if (timestamp == null) { + throw new CVSException(NLS.bind( + CVSMessages.ResourceSyncInfo_malformedSyncBytes, + new String[] { new String(syncBytes) })); + } + int syncType = getSyncType(timestamp); + return syncType == TYPE_DELETED_AND_RESTORED; + } + + /** * Method isMerge. * @param syncBytes1 * @return boolean diff --git a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/IsModifiedTests.java b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/IsModifiedTests.java index 58be726b6..246cac846 100644 --- a/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/IsModifiedTests.java +++ b/tests/org.eclipse.team.tests.cvs.core/src/org/eclipse/team/tests/ccvs/core/provider/IsModifiedTests.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2000, 2007 IBM Corporation and others. + * Copyright (c) 2000, 2011 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -11,16 +11,33 @@ package org.eclipse.team.tests.ccvs.core.provider; import java.io.ByteArrayInputStream; +import java.io.File; import java.io.IOException; -import java.util.*; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Set; import junit.framework.Test; import junit.framework.TestSuite; -import org.eclipse.core.resources.*; -import org.eclipse.core.runtime.*; +import org.eclipse.core.resources.IContainer; +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IProject; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IPath; +import org.eclipse.core.runtime.Path; import org.eclipse.team.core.TeamException; -import org.eclipse.team.internal.ccvs.core.*; +import org.eclipse.team.internal.ccvs.core.CVSException; +import org.eclipse.team.internal.ccvs.core.ICVSFile; +import org.eclipse.team.internal.ccvs.core.ICVSFolder; +import org.eclipse.team.internal.ccvs.core.ICVSResource; +import org.eclipse.team.internal.ccvs.core.ICVSResourceVisitor; +import org.eclipse.team.internal.ccvs.core.IResourceStateChangeListener; import org.eclipse.team.internal.ccvs.core.resources.CVSWorkspaceRoot; import org.eclipse.team.internal.ccvs.core.util.ResourceStateChangeListeners; import org.eclipse.team.tests.ccvs.core.CVSTestSetup; @@ -548,5 +565,43 @@ public class IsModifiedTests extends EclipseTest { assertModificationState(copy, null, true); } + public void testBug62547() throws TeamException, CoreException, + UnsupportedEncodingException { + IProject project = createProject("testBug62547Project", new String[] { + "file1.txt", "file2.txt" }); + + project.getFile("file1.txt").setContents( + new ByteArrayInputStream("Sample text 1".getBytes("UTF-8")), + true, true, getMonitor()); + project.getFile("file2.txt").setContents( + new ByteArrayInputStream("Sample text 2".getBytes("UTF-8")), + true, true, getMonitor()); + long currentTime = System.currentTimeMillis(); + new File(project.getFile("file1.txt").getLocationURI()) + .setLastModified(currentTime); + project.getFile("file1.txt").refreshLocal(1, getMonitor()); + + assertEquals(currentTime, project.getFile("file1.txt") + .getLocalTimeStamp()); + + new File(project.getFile("file2.txt").getLocationURI()) + .setLastModified(currentTime); + project.getFile("file2.txt").refreshLocal(1, getMonitor()); + assertEquals(currentTime, project.getFile("file2.txt") + .getLocalTimeStamp()); + + commitResources(project, new String[] { "file1.txt", "file2.txt" }); + + project.getFile("file1.txt").delete(true, getMonitor()); + project.getFile("file2.txt").copy( + project.getFile("file1.txt").getFullPath(), true, getMonitor()); + + assertEquals(project.getFile("file1.txt").getLocalTimeStamp(), project + .getFile("file2.txt").getLocalTimeStamp()); + + assertModificationState(project, new String[] { ".", "file1.txt" }, + true); + + } } |