diff --git a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java index 7ab196a1b4b1..56c13f48e643 100644 --- a/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java +++ b/platform/vcs-impl/src/com/intellij/openapi/diff/impl/patch/formove/PathsVerifier.java @@ -516,18 +516,13 @@ public class PathsVerifier { public VirtualFile doMove() throws IOException { final VirtualFile oldParent = myCurrent.getParent(); - final VirtualFile afterFile; - if (myNewParent.equals(oldParent)) { - // rename: no move - afterFile = myCurrent; - } else { - myCurrent.move(PatchApplier.class, myNewParent); - afterFile = myCurrent; - } if (! Comparing.equal(myCurrent.getName(), myNewName)) { - afterFile.rename(PatchApplier.class, myNewName); + myCurrent.rename(PatchApplier.class, myNewName); } - return afterFile; + if (! myNewParent.equals(oldParent)) { + myCurrent.move(PatchApplier.class, myNewParent); + } + return myCurrent; } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java index 8b68d5a0fa82..1e2d66ab3a9e 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/history/SvnChangeList.java @@ -71,7 +71,7 @@ public class SvnChangeList implements CommittedChangeList { private boolean myCachedInfoLoaded; // key: added path, value: copied-from - private final Map myCopiedAddedPaths = new HashMap(); + private final TreeMap myCopiedAddedPaths = new TreeMap(); private RootUrlInfo myWcRoot; private final CommonPathSearcher myCommonPathSearcher; private final Set myKnownAsDirectories; @@ -188,26 +188,32 @@ public class SvnChangeList implements CommittedChangeList { // key: copied-from final Map copiedAddedChanges = new HashMap(); + correctBeforePaths(); + final List copyDeleted = new ArrayList(myDeletedPaths); + for(String path: myAddedPaths) { final Change addedChange; if (myCopiedAddedPaths.containsKey(path)) { - if (myDeletedPaths.contains(myCopiedAddedPaths.get(path))) { - addedChange = new ExternallyRenamedChange(myListsHolder.createRevisionLazily(myCopiedAddedPaths.get(path), true), - myListsHolder.createRevisionLazily(path, false), myCopiedAddedPaths.get(path)); + final String copyTarget = myCopiedAddedPaths.get(path); + if (copyDeleted.contains(copyTarget)) { + addedChange = new ExternallyRenamedChange(myListsHolder.createRevisionLazily(copyTarget, true), + myListsHolder.createRevisionLazily(path, false), copyTarget); addedChange.getMoveRelativePath(myVcs.getProject()); ((ExternallyRenamedChange) addedChange).setCopied(false); + copyDeleted.remove(copyTarget); } else { - addedChange = new ExternallyRenamedChange(null, myListsHolder.createRevisionLazily(path, false), myCopiedAddedPaths.get(path)); + addedChange = new ExternallyRenamedChange(null, myListsHolder.createRevisionLazily(path, false), copyTarget); } - copiedAddedChanges.put(myCopiedAddedPaths.get(path), (ExternallyRenamedChange) addedChange); + copiedAddedChanges.put(copyTarget, (ExternallyRenamedChange) addedChange); } else { addedChange = new Change(null, myListsHolder.createRevisionLazily(path, false)); } myListsHolder.add(path, addedChange); } - for(String path: myDeletedPaths) { + for(String path: copyDeleted) { final Change deletedChange; if (copiedAddedChanges.containsKey(path)) { + // seems never occurs any more final ExternallyRenamedChange addedChange = copiedAddedChanges.get(path); final FilePath source = addedChange.getAfterRevision().getFile(); deletedChange = new ExternallyRenamedChange(myListsHolder.createDeletedItemRevision(path, true), null, path); @@ -261,6 +267,31 @@ public class SvnChangeList implements CommittedChangeList { } } + private void correctBeforePaths() { + processDeletedForBeforePaths(myDeletedPaths); + processModifiedForBeforePaths(myChangedPaths); + processModifiedForBeforePaths(myReplacedPaths); + } + + private void processModifiedForBeforePaths(Set paths) { + final RenameHelper helper = new RenameHelper(); + for (String s : paths) { + final String converted = helper.convertBeforePath(s, myCopiedAddedPaths); + if (! s.equals(converted)) { + myCopiedAddedPaths.put(s, converted); + } + } + } + + private void processDeletedForBeforePaths(Set paths) { + final RenameHelper helper = new RenameHelper(); + final HashSet copy = new HashSet(paths); + paths.clear(); + for (String s : copy) { + paths.add(helper.convertBeforePath(s, myCopiedAddedPaths)); + } + } + @Nullable private FilePath getLocalPath(final String path, final NotNullFunction detector) { final String fullPath = myRepositoryRoot + path; @@ -301,21 +332,25 @@ public class SvnChangeList implements CommittedChangeList { return myPathToChangeMapping.get(path); } - private FilePath localDeletedPath(final String fullPath) { + private FilePath localDeletedPath(final String fullPath, final boolean isDir) { final SvnFileUrlMapping urlMapping = myVcs.getSvnFileUrlMapping(); final String path = urlMapping.getLocalPath(fullPath); if (path != null) { final File file = new File(path); - return FilePathImpl.createForDeletedFile(file, file.isDirectory()); + return FilePathImpl.createForDeletedFile(file, isDir || file.isDirectory()); } return null; } public SvnRepositoryContentRevision createDeletedItemRevision(final String path, final boolean isBeforeRevision) { + final boolean knownAsDirectory = myKnownAsDirectories.contains(path); final String fullPath = myRepositoryRoot + path; - myWithoutDirStatus.add(new Pair(myList.size(), isBeforeRevision)); - return SvnRepositoryContentRevision.create(myVcs, myRepositoryRoot, path, localDeletedPath(fullPath), getRevision(isBeforeRevision)); + if (! knownAsDirectory) { + myWithoutDirStatus.add(new Pair(myList.size(), isBeforeRevision)); + } + return SvnRepositoryContentRevision.create(myVcs, myRepositoryRoot, path, localDeletedPath(fullPath, knownAsDirectory), + getRevision(isBeforeRevision)); } public SvnRepositoryContentRevision createRevisionLazily(final String path, final boolean isBeforeRevision) { @@ -350,6 +385,10 @@ public class SvnChangeList implements CommittedChangeList { doRemoteDetails(); uploadDeletedRenamedChildren(); + // remove duplicates + final HashSet set = new HashSet(myDetailedList); + myDetailedList.clear(); + myDetailedList.addAll(set); } catch (SVNException e) { LOG.info(e); @@ -457,6 +496,33 @@ public class SvnChangeList implements CommittedChangeList { } } + private static class RenameHelper { + /*private final TreeMap myRenamesMap; + + private RenameHelper(final List svnRepositoryChanges) { + myRenamesMap = new TreeMap(); + for (Change change : svnRepositoryChanges) { + if (change.isMoved() || change.isRenamed()) { + final SvnRepositoryContentRevision before = (SvnRepositoryContentRevision) change.getBeforeRevision(); + final SvnRepositoryContentRevision after = (SvnRepositoryContentRevision) change.getAfterRevision(); + myRenamesMap.put(after.getPath(), before.getPath()); + } + } + } */ + + public String convertBeforePath(final String path, final TreeMap after2before) { + String current = path; + // backwards + for (String key : after2before.descendingKeySet()) { + if (SVNPathUtil.isAncestor(key, current)) { + final String relativePath = SVNPathUtil.getRelativePath(key, current); + current = SVNPathUtil.append(after2before.get(key), relativePath); + } + } + return current; + } + } + private void patchChange(Change change, final String path) { final SVNURL becameUrl; SVNURL wasUrl;