diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java index ce50780d317b..a455db4cae84 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/HgFileRevision.java @@ -38,11 +38,11 @@ public class HgFileRevision implements VcsFileRevision { private final Set myFilesModified; private final Set myFilesAdded; private final Set myFilesDeleted; - private final Map myFilesCopied; + private final Map myFilesMoved; // actually we collect moved and track copied as added public HgFileRevision(Project project, @NotNull HgFile hgFile, @NotNull HgRevisionNumber vcsRevisionNumber, String branchName, Date revisionDate, String author, String commitMessage, - Set filesModified, Set filesAdded, Set filesDeleted, Map filesCopied) { + Set filesModified, Set filesAdded, Set filesDeleted, Map filesMoved) { myProject = project; myFile = hgFile; myRevisionNumber = vcsRevisionNumber; @@ -53,7 +53,7 @@ public class HgFileRevision implements VcsFileRevision { myFilesModified = filesModified; myFilesAdded = filesAdded; myFilesDeleted = filesDeleted; - myFilesCopied = filesCopied; + myFilesMoved = filesMoved; } @NotNull @@ -101,8 +101,8 @@ public class HgFileRevision implements VcsFileRevision { } @NotNull - public Map getCopiedFiles() { - return myFilesCopied; + public Map getMovedFiles() { + return myFilesMoved; } @NotNull diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java index 83770418c739..ad383521105c 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/log/HgHistoryUtil.java @@ -43,6 +43,7 @@ import org.jetbrains.annotations.Nullable; import org.zmlx.hg4idea.*; import org.zmlx.hg4idea.command.HgLogCommand; import org.zmlx.hg4idea.execution.HgCommandResult; +import org.zmlx.hg4idea.provider.HgChangeProvider; import org.zmlx.hg4idea.util.HgChangesetUtil; import org.zmlx.hg4idea.util.HgUtil; import org.zmlx.hg4idea.util.HgVersion; @@ -163,9 +164,9 @@ public class HgHistoryUtil { for (String file : revision.getDeletedFiles()) { changes.add(createChange(project, root, file, firstParent, null, vcsRevisionNumber, FileStatus.DELETED)); } - for (Map.Entry copiedFile : revision.getCopiedFiles().entrySet()) { - changes - .add(createChange(project, root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, FileStatus.ADDED)); + for (Map.Entry copiedFile : revision.getMovedFiles().entrySet()) { + changes.add(createChange(project, root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, + HgChangeProvider.RENAMED)); } vcsFullCommitDetailsList.add(factory.createFullDetails(factory.createHash(vcsRevisionNumber.getChangeset()), parentsHash, diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommittedChangesProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommittedChangesProvider.java index 9cff9c5c130b..940fccc3ccce 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommittedChangesProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgCachingCommittedChangesProvider.java @@ -240,8 +240,9 @@ public class HgCachingCommittedChangesProvider implements CachingCommittedChange for (String file : revision.getDeletedFiles()) { changes.add(createChange(root, file, firstParent, null, vcsRevisionNumber, FileStatus.DELETED)); } - for (Map.Entry copiedFile : revision.getCopiedFiles().entrySet()) { - changes.add(createChange(root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, FileStatus.ADDED)); + for (Map.Entry copiedFile : revision.getMovedFiles().entrySet()) { + changes + .add(createChange(root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, HgChangeProvider.RENAMED)); } result.add(new HgCommittedChangeList(myVcs, vcsRevisionNumber, revision.getBranchName(), revision.getCommitMessage(), @@ -352,8 +353,8 @@ public class HgCachingCommittedChangesProvider implements CachingCommittedChange for (String file : localRevision.getDeletedFiles()) { changes.add(createChange(root, file, firstParent, null, vcsRevisionNumber, FileStatus.DELETED)); } - for (Map.Entry copiedFile : localRevision.getCopiedFiles().entrySet()) { - changes.add(createChange(root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, HgChangeProvider.COPIED)); + for (Map.Entry copiedFile : localRevision.getMovedFiles().entrySet()) { + changes.add(createChange(root, copiedFile.getKey(), firstParent, copiedFile.getValue(), vcsRevisionNumber, HgChangeProvider.RENAMED)); } return new HgCommittedChangeList(myVcs, vcsRevisionNumber, localRevision.getBranchName(), localRevision.getCommitMessage(), diff --git a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java index 209cf6c70f3c..1845f7424d35 100644 --- a/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java +++ b/plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgHistoryProvider.java @@ -88,7 +88,7 @@ public class HgHistoryProvider implements VcsHistoryProvider { final List history = getHistory(filePath, vcsRoot, myProject); if (history.size() == 0) return; - final VcsAbstractHistorySession emptySession = createAppendableSession(vcsRoot, Collections.emptyList(), null); + final VcsAbstractHistorySession emptySession = createAppendableSession(vcsRoot, Collections.emptyList(), null); partner.reportCreatedEmptySession(emptySession); for (HgFileRevision hgFileRevision : history) { @@ -126,12 +126,21 @@ public class HgHistoryProvider implements VcsHistoryProvider { @NotNull VirtualFile vcsRoot, @NotNull Project project, @Nullable HgRevisionNumber revisionNumber, int limit) { - final HgFile hgFile = new HgFile(vcsRoot, filePath); - FilePath originalFileName = HgUtil.getOriginalFileName(hgFile.toFilePath(), ChangeListManager.getInstance(project)); - HgFile originalHgFile = new HgFile(hgFile.getRepo(), originalFileName); - if (revisionNumber == null && !filePath.isDirectory() && !originalHgFile.toFilePath().equals(hgFile.toFilePath())) { + /* The standard way to get history following renames is to call hg log --follow. However: + 1. It is broken in case of uncommitted rename (i.e. if the file is currently renamed in the working dir): + in this case we use a special python template "follow(path)" which handles this case. + 2. We don't use this python "follow(path)" function for all cases, because it is fully supported only since hg 2.6, + and it is a bit slower and possibly less reliable than plain --follow parameter. + 3. It doesn't work with "-r": in this case --follow is simply ignored (hg commit 24208:8b4b9ee6001a). + As a workaround we could use the same follow(path) python, but this function requires current name of the file, + which is unknown in case of "-r", and identifying it would be very slow. + + As a result we don't follow renames in annotate called from diff or from an old revision, which we can survive. +*/ + FilePath originalFilePath = HgUtil.getOriginalFileName(filePath, ChangeListManager.getInstance(project)); + if (revisionNumber == null && !filePath.isDirectory() && !filePath.equals(originalFilePath)) { // uncommitted renames detected - return getHistoryForUncommittedRenamed(originalHgFile, vcsRoot, project, limit); + return getHistoryForUncommittedRenamed(originalFilePath, vcsRoot, project, limit); } final HgLogCommand logCommand = new HgLogCommand(project); logCommand.setFollowCopies(!filePath.isDirectory()); @@ -139,22 +148,18 @@ public class HgHistoryProvider implements VcsHistoryProvider { List args = new ArrayList(); if (revisionNumber != null) { args.add("--rev"); - args.add("reverse(0::" + revisionNumber.getChangeset() + ")");// hg ignors --follow if --rev presented - // reverse needed because of mercurial default order problem -r rev set with and without -f option + args.add("reverse(0::" + revisionNumber.getChangeset() + ")"); } - return logCommand.execute(hgFile, limit, false, args); + return logCommand.execute(new HgFile(vcsRoot, filePath), limit, false, args); } - /** * Workaround for getting follow file history in case of uncommitted move/rename change */ - private static List getHistoryForUncommittedRenamed(@NotNull HgFile originalHgFile, + private static List getHistoryForUncommittedRenamed(@NotNull FilePath originalHgFilePath, @NotNull VirtualFile vcsRoot, @NotNull Project project, int limit) { - //mercurial can't follow custom revision; - // the only way to do it if you have working dir file name then use python follow function for it, - // but we have to use local(last committed) name as a parameter + HgFile originalHgFile = new HgFile(vcsRoot, originalHgFilePath); final HgLogCommand logCommand = new HgLogCommand(project); logCommand.setIncludeRemoved(true); final HgVersion version = logCommand.getVersion();