@NotNull
 private Set<VcsRef> readBranches(@NotNull GitRepository repository) {
   StopWatch sw = StopWatch.start("readBranches in " + repository.getRoot().getName());
   VirtualFile root = repository.getRoot();
   repository.update();
   Collection<GitLocalBranch> localBranches = repository.getBranches().getLocalBranches();
   Collection<GitRemoteBranch> remoteBranches = repository.getBranches().getRemoteBranches();
   Set<VcsRef> refs = new THashSet<VcsRef>(localBranches.size() + remoteBranches.size());
   for (GitLocalBranch localBranch : localBranches) {
     refs.add(
         myVcsObjectsFactory.createRef(
             localBranch.getHash(), localBranch.getName(), GitRefManager.LOCAL_BRANCH, root));
   }
   for (GitRemoteBranch remoteBranch : remoteBranches) {
     refs.add(
         myVcsObjectsFactory.createRef(
             remoteBranch.getHash(),
             remoteBranch.getNameForLocalOperations(),
             GitRefManager.REMOTE_BRANCH,
             root));
   }
   String currentRevision = repository.getCurrentRevision();
   if (currentRevision != null) { // null => fresh repository
     refs.add(
         myVcsObjectsFactory.createRef(
             HashImpl.build(currentRevision), "HEAD", GitRefManager.HEAD, root));
   }
   sw.report();
   return refs;
 }
 private static <T> void addNewElements(
     @NotNull Collection<T> original, @NotNull Collection<T> toAdd) {
   for (T item : toAdd) {
     if (!original.contains(item)) {
       original.add(item);
     }
   }
 }
  @NotNull
  @Override
  public List<TimedVcsCommit> getCommitsMatchingFilter(
      @NotNull final VirtualFile root,
      @NotNull VcsLogFilterCollection filterCollection,
      int maxCount)
      throws VcsException {
    if (!isRepositoryReady(root)) {
      return Collections.emptyList();
    }

    List<String> filterParameters = ContainerUtil.newArrayList();

    if (filterCollection.getBranchFilter() != null
        && !filterCollection.getBranchFilter().getBranchNames().isEmpty()) {
      GitRepository repository = getRepository(root);
      assert repository != null
          : "repository is null for root " + root + " but was previously reported as 'ready'";

      boolean atLeastOneBranchExists = false;
      for (String branchName : filterCollection.getBranchFilter().getBranchNames()) {
        if (branchName.equals("HEAD")
            || repository.getBranches().findBranchByName(branchName) != null) {
          filterParameters.add(branchName);
          atLeastOneBranchExists = true;
        }
      }
      if (!atLeastOneBranchExists) { // no such branches in this repository => filter matches
        // nothing
        return Collections.emptyList();
      }
    } else {
      filterParameters.addAll(GitHistoryUtils.LOG_ALL);
    }

    if (filterCollection.getUserFilter() != null) {
      String authorFilter =
          StringUtil.join(
              ContainerUtil.map(
                  filterCollection.getUserFilter().getUserNames(root), UserNameRegex.INSTANCE),
              "|");
      filterParameters.add(prepareParameter("author", StringUtil.escapeBackSlashes(authorFilter)));
      filterParameters.add(
          "--extended-regexp"); // extended regexp required for correctly filtering user names
    }

    if (filterCollection.getDateFilter() != null) {
      // assuming there is only one date filter, until filter expressions are defined
      VcsLogDateFilter filter = filterCollection.getDateFilter();
      if (filter.getAfter() != null) {
        filterParameters.add(prepareParameter("after", filter.getAfter().toString()));
      }
      if (filter.getBefore() != null) {
        filterParameters.add(prepareParameter("before", filter.getBefore().toString()));
      }
    }

    if (filterCollection.getTextFilter() != null) {
      String textFilter = filterCollection.getTextFilter().getText();
      filterParameters.add(prepareParameter("grep", StringUtil.escapeChars(textFilter, '[', ']')));
    }

    filterParameters.add(
        "--regexp-ignore-case"); // affects case sensitivity of any filter (except file filter)
    if (maxCount > 0) {
      filterParameters.add(prepareParameter("max-count", String.valueOf(maxCount)));
    }

    // note: structure filter must be the last parameter, because it uses "--" which separates
    // parameters from paths
    if (filterCollection.getStructureFilter() != null) {
      Collection<VirtualFile> files = filterCollection.getStructureFilter().getFiles();
      if (!files.isEmpty()) {
        filterParameters.add("--full-history");
        filterParameters.add("--simplify-merges");
        filterParameters.add("--");
        for (VirtualFile file : files) {
          filterParameters.add(file.getPath());
        }
      }
    }

    List<TimedVcsCommit> commits = ContainerUtil.newArrayList();
    GitHistoryUtils.readCommits(
        myProject,
        root,
        filterParameters,
        EmptyConsumer.<VcsUser>getInstance(),
        EmptyConsumer.<VcsRef>getInstance(),
        new CollectConsumer<TimedVcsCommit>(commits));
    return commits;
  }