/**
   * This method calculates the commits and diff information against the tip of current branch and
   * the common ancestor of source branch (current branch) and target branch (selected remote
   * branch).
   *
   * <p>If there is no common parent (two branches are parallel), return an empty
   * GitCommitCompareInfo
   *
   * <p>This is potentially an expensive calculation, probably should do it on a background thread.
   * We will also attempt to cache the result
   *
   * <p>default access for testing so we bypass UI code, TODO: reevaluate the testing to properly
   * shutoff the access level
   *
   * @return gitChangesContainer on what has changed on source branch
   */
  GitChangesContainer getMyChangesCompareInfo() throws VcsException {

    final GitBranch currBranch = this.getSourceBranch();

    final GitRemoteBranch selectedRemoteBranch = this.getTargetBranch();

    // if source branch or currentBranch isn't set, just return empty diff
    if (selectedRemoteBranch == null || currBranch == null) {
      return GitChangesContainer.createChangesContainer(
          null,
          null,
          null,
          null,
          getDiffCompareInfoProvider().getEmptyDiff(this.gitRepository),
          this.gitRepository);
    }

    final String remoteBranchHash = selectedRemoteBranch.getHash().asString();
    final String currBranchHash = currBranch.getHash().asString();

    try {
      GitCommitCompareInfo changes =
          this.diffCache.get(new Pair<String, String>(currBranchHash, remoteBranchHash));

      return GitChangesContainer.createChangesContainer(
          currBranch.getName(),
          selectedRemoteBranch.getName(),
          currBranchHash,
          remoteBranchHash,
          changes,
          this.gitRepository);
    } catch (ExecutionException e) {
      throw new VcsException(e.getCause());
    }
  }
  /* if user has changed the dropdown while we calculate the diff, this diff is out of date */
  private boolean isChangesUpToDate(final GitChangesContainer changesContainer) {

    // target branches must match
    final GitRemoteBranch targetBranch = this.getTargetBranch();
    if (changesContainer.getTargetBranchName() != null && targetBranch != null) {
      if (!changesContainer.getTargetBranchName().equals(targetBranch.getName())) {
        return false;
      }
    }

    // source branches must match
    final GitLocalBranch sourceBranch = this.getSourceBranch();
    if (changesContainer.getSourceBranchName() != null && sourceBranch != null) {
      if (!changesContainer.getSourceBranchName().equals(sourceBranch.getName())) {
        return false;
      }
    }

    return true;
  }