/**
   * Returns absolute paths which have changed remotely comparing to the current branch, i.e.
   * performs <code>git diff --name-only master..origin/master</code>
   *
   * <p>Paths are absolute, Git-formatted (i.e. with forward slashes).
   */
  @NotNull
  public static Collection<String> getPathsDiffBetweenRefs(
      @NotNull Git git,
      @NotNull GitRepository repository,
      @NotNull String beforeRef,
      @NotNull String afterRef)
      throws VcsException {
    List<String> parameters = Arrays.asList("--name-only", "--pretty=format:");
    String range = beforeRef + ".." + afterRef;
    GitCommandResult result = git.diff(repository, parameters, range);
    if (!result.success()) {
      LOG.info(
          String.format(
              "Couldn't get diff in range [%s] for repository [%s]",
              range, repository.toLogString()));
      return Collections.emptyList();
    }

    final Collection<String> remoteChanges = new HashSet<String>();
    for (StringScanner s = new StringScanner(result.getOutputAsJoinedString()); s.hasMoreData(); ) {
      final String relative = s.line();
      if (StringUtil.isEmptyOrSpaces(relative)) {
        continue;
      }
      final String path = repository.getRoot().getPath() + "/" + unescapePath(relative);
      remoteChanges.add(path);
    }
    return remoteChanges;
  }
  public static void getLocalCommittedChanges(
      final Project project,
      final VirtualFile root,
      final Consumer<GitSimpleHandler> parametersSpecifier,
      final Consumer<GitCommittedChangeList> consumer,
      boolean skipDiffsForMerge)
      throws VcsException {
    GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.LOG);
    h.setSilent(true);
    h.addParameters(
        "--pretty=format:%x04%x01" + GitChangeUtils.COMMITTED_CHANGELIST_FORMAT, "--name-status");
    parametersSpecifier.consume(h);

    String output = h.run();
    LOG.debug("getLocalCommittedChanges output: '" + output + "'");
    StringScanner s = new StringScanner(output);
    final StringBuilder sb = new StringBuilder();
    boolean firstStep = true;
    while (s.hasMoreData()) {
      final String line = s.line();
      final boolean lineIsAStart = line.startsWith("\u0004\u0001");
      if ((!firstStep) && lineIsAStart) {
        final StringScanner innerScanner = new StringScanner(sb.toString());
        sb.setLength(0);
        consumer.consume(
            GitChangeUtils.parseChangeList(
                project, root, innerScanner, skipDiffsForMerge, h, false, false));
      }
      sb.append(lineIsAStart ? line.substring(2) : line).append('\n');
      firstStep = false;
    }
    if (sb.length() > 0) {
      final StringScanner innerScanner = new StringScanner(sb.toString());
      sb.setLength(0);
      consumer.consume(
          GitChangeUtils.parseChangeList(
              project, root, innerScanner, skipDiffsForMerge, h, false, false));
    }
    if (s.hasMoreData()) {
      throw new IllegalStateException("More input is avaialble: " + s.line());
    }
  }
 /**
  * Scan working tree and detect locally modified files
  *
  * @param project the project to scan
  * @param root the root to scan
  * @param files the collection with files
  * @throws VcsException if there problem with running git or working tree is dirty in unsupported
  *     way
  */
 private static void scanFiles(Project project, VirtualFile root, List<String> files)
     throws VcsException {
   String rootPath = root.getPath();
   GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.DIFF);
   h.addParameters("--name-status");
   h.setNoSSH(true);
   h.setSilent(true);
   h.setStdoutSuppressed(true);
   StringScanner s = new StringScanner(h.run());
   while (s.hasMoreData()) {
     if (s.isEol()) {
       s.line();
       continue;
     }
     if (s.tryConsume("M\t")) {
       String path = rootPath + "/" + GitUtil.unescapePath(s.line());
       files.add(path);
     } else {
       throw new VcsException("Working tree is dirty in unsupported way: " + s.line());
     }
   }
 }
  /**
   * Parse changes from lines
   *
   * @param root the git root
   * @return a set of unmerged files
   * @throws com.intellij.openapi.vcs.VcsException if the input format does not matches expected
   *     format
   */
  private List<VirtualFile> unmergedFiles(final VirtualFile root) throws VcsException {
    GitRepository repository = myRepositoryManager.getRepositoryForRoot(root);
    if (repository == null) {
      LOG.error("Repository not found for root " + root);
      return Collections.emptyList();
    }

    GitCommandResult result = myGit.getUnmergedFiles(repository);
    if (!result.success()) {
      throw new VcsException(result.getErrorOutputAsJoinedString());
    }

    String output = StringUtil.join(result.getOutput(), "\n");
    HashSet<String> unmergedPaths = ContainerUtil.newHashSet();
    for (StringScanner s = new StringScanner(output); s.hasMoreData(); ) {
      if (s.isEol()) {
        s.nextLine();
        continue;
      }
      s.boundedToken('\t');
      String relative = s.line();
      unmergedPaths.add(GitUtil.unescapePath(relative));
    }

    if (unmergedPaths.size() == 0) {
      return Collections.emptyList();
    } else {
      List<File> files =
          ContainerUtil.map(
              unmergedPaths,
              new Function<String, File>() {
                @Override
                public File fun(String path) {
                  return new File(root.getPath(), path);
                }
              });
      return sortVirtualFilesByPresentation(findVirtualFilesWithRefresh(files));
    }
  }