IDEA-68731 Batch process files in hg status
authorKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 26 Apr 2011 12:21:44 +0000 (16:21 +0400)
committerKirill Likhodedov <kirill.likhodedov@jetbrains.com>
Tue, 26 Apr 2011 12:25:38 +0000 (16:25 +0400)
1. HgStatusCommand processes several files at once
2. More optimizations of HgChangeProvider.

plugins/hg4idea/src/org/zmlx/hg4idea/command/HgStatusCommand.java
plugins/hg4idea/src/org/zmlx/hg4idea/provider/HgChangeProvider.java

index e535c058ab9d0700467792c3bc8a0038eec546d6..25c336e26b364c622a358c9fae40fbeaa2f756fe 100644 (file)
@@ -14,8 +14,11 @@ package org.zmlx.hg4idea.command;
 
 import com.intellij.openapi.diagnostic.Logger;
 import com.intellij.openapi.project.Project;
+import com.intellij.openapi.vcs.FilePath;
 import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.vcsUtil.VcsFileUtil;
 import org.apache.commons.lang.StringUtils;
+import org.jetbrains.annotations.Nullable;
 import org.zmlx.hg4idea.HgChange;
 import org.zmlx.hg4idea.HgFile;
 import org.zmlx.hg4idea.HgFileStatusEnum;
@@ -89,7 +92,7 @@ public class HgStatusCommand {
     return execute(repo, null);
   }
 
-  public Set<HgChange> execute(VirtualFile repo, String relativePath) {
+  public Set<HgChange> execute(VirtualFile repo, @Nullable Collection<FilePath> paths) {
     if (repo == null) {
       return Collections.emptySet();
     }
@@ -97,44 +100,57 @@ public class HgStatusCommand {
     HgCommandExecutor executor = new HgCommandExecutor(project);
     executor.setSilent(true);
 
-    List<String> arguments = new LinkedList<String>();
+    List<String> options = new LinkedList<String>();
     if (includeAdded) {
-      arguments.add("--added");
+      options.add("--added");
     }
     if (includeModified) {
-      arguments.add("--modified");
+      options.add("--modified");
     }
     if (includeRemoved) {
-      arguments.add("--removed");
+      options.add("--removed");
     }
     if (includeDeleted) {
-      arguments.add("--deleted");
+      options.add("--deleted");
     }
     if (includeUnknown) {
-      arguments.add("--unknown");
+      options.add("--unknown");
     }
     if (includeIgnored) {
-      arguments.add("--ignored");
+      options.add("--ignored");
     }
     if (includeCopySource) {
-      arguments.add("--copies");
+      options.add("--copies");
     }
     if (baseRevision != null) {
-      arguments.add("--rev");
-      arguments.add(baseRevision.getChangeset());
+      options.add("--rev");
+      options.add(baseRevision.getChangeset());
       if (targetRevision != null) {
-        arguments.add("--rev");
-        arguments.add(targetRevision.getChangeset());
+        options.add("--rev");
+        options.add(targetRevision.getChangeset());
       }
     }
 
-    if (relativePath != null) {
-      arguments.add(relativePath);
+    final Set<HgChange> changes = new HashSet<HgChange>();
+
+    if (paths != null) {
+      final List<List<String>> chunked = VcsFileUtil.chunkPaths(repo, paths);
+      for (List<String> chunk : chunked) {
+        List<String> args = new ArrayList<String>();
+        args.addAll(options);
+        args.addAll(chunk);
+        HgCommandResult result = executor.executeInCurrentThread(repo, "status", args);
+        changes.addAll(parseChangesFromResult(repo, result));
+      }
+    } else {
+      HgCommandResult result = executor.executeInCurrentThread(repo, "status", options);
+      changes.addAll(parseChangesFromResult(repo, result));
     }
+    return changes;
+  }
 
-    //executor.setSilent(true);
-    HgCommandResult result = executor.executeInCurrentThread(repo, "status", arguments);
-    Set<HgChange> changes = new HashSet<HgChange>();
+  private static Collection<HgChange> parseChangesFromResult(VirtualFile repo, HgCommandResult result) {
+    final Set<HgChange> changes = new HashSet<HgChange>();
     HgChange previous = null;
     if (result == null) {
       return changes;
index 87d45cd10486a4d92752d82a4373b5881e833d37..b63b812ba89ed5c4b93a5284155c1139c2e67084 100644 (file)
@@ -21,7 +21,11 @@ import com.intellij.openapi.vcs.changes.*;
 import com.intellij.openapi.vfs.VirtualFile;
 import com.intellij.vcsUtil.VcsUtil;
 import org.zmlx.hg4idea.*;
-import org.zmlx.hg4idea.command.*;
+import org.zmlx.hg4idea.command.HgResolveCommand;
+import org.zmlx.hg4idea.command.HgResolveStatusEnum;
+import org.zmlx.hg4idea.command.HgStatusCommand;
+import org.zmlx.hg4idea.command.HgWorkingCopyRevisionsCommand;
+import org.zmlx.hg4idea.util.HgUtil;
 
 import java.awt.*;
 import java.util.*;
@@ -56,42 +60,33 @@ public class HgChangeProvider implements ChangeProvider {
     myVcsKey = vcsKey;
   }
 
+  public boolean isModifiedDocumentTrackingRequired() {
+    return true;
+  }
+
+  public void doCleanup(List<VirtualFile> files) {
+  }
+
   public void getChanges(VcsDirtyScope dirtyScope, ChangelistBuilder builder,
                          ProgressIndicator progress, ChangeListManagerGate addGate) throws VcsException {
     final Collection<HgChange> changes = new HashSet<HgChange>();
-
-    for (FilePath filePath : dirtyScope.getRecursivelyDirtyDirectories()) {
-      changes.addAll(process(builder, filePath));
-    }
-    for (FilePath filePath : dirtyScope.getDirtyFiles()) {
-      changes.addAll(process(builder, filePath));
-    }
-
+    changes.addAll(process(builder, dirtyScope.getRecursivelyDirtyDirectories()));
+    changes.addAll(process(builder, dirtyScope.getDirtyFiles()));
     processUnsavedChanges(builder, dirtyScope.getDirtyFilesNoExpand(), changes);
   }
 
-  public boolean isModifiedDocumentTrackingRequired() {
-    return true;
-  }
+  private Collection<HgChange> process(ChangelistBuilder builder, Collection<FilePath> files) {
+    final Set<HgChange> hgChanges = new HashSet<HgChange>();
+    for (Map.Entry<VirtualFile, Collection<FilePath>> entry : HgUtil.groupFilePathsByHgRoots(myProject, files).entrySet()) {
+      VirtualFile repo = entry.getKey();
 
-  public void doCleanup(List<VirtualFile> files) {
-  }
+      final HgRevisionNumber workingRevision = new HgWorkingCopyRevisionsCommand(myProject).identify(repo);
+      final HgRevisionNumber parentRevision = new HgWorkingCopyRevisionsCommand(myProject).firstParent(repo);
+      final Map<HgFile, HgResolveStatusEnum> list = new HgResolveCommand(myProject).getListSynchronously(repo);
 
-  private Collection<HgChange> process(ChangelistBuilder builder,
-    FilePath filePath) {
-    VirtualFile repo = VcsUtil.getVcsRootFor(myProject, filePath);
-    if (repo == null) {
-      return new HashSet<HgChange>();
+      hgChanges.addAll(new HgStatusCommand(myProject).execute(repo, entry.getValue()));
+      sendChanges(builder, hgChanges, list, workingRevision, parentRevision);
     }
-    Set<HgChange> hgChanges = new HgStatusCommand(myProject).execute(repo, filePath.getPath());
-    if (hgChanges == null || hgChanges.isEmpty()) {
-      return new HashSet<HgChange>();
-    }
-    sendChanges(builder, hgChanges,
-      new HgResolveCommand(myProject).getListSynchronously(repo),
-      new HgWorkingCopyRevisionsCommand(myProject).identify(repo),
-      new HgWorkingCopyRevisionsCommand(myProject).firstParent(repo)
-    );
     return hgChanges;
   }