private void generateToken() {
   try {
     myToken.setText(
         GithubUtil.computeValueInModal(
             myProject,
             "Access to GitHub",
             new ThrowableConvertor<ProgressIndicator, String, IOException>() {
               @NotNull
               @Override
               public String convert(ProgressIndicator indicator) throws IOException {
                 return GithubUtil.runTaskWithBasicAuthForHost(
                     myProject,
                     GithubAuthDataHolder.createFromSettings(),
                     indicator,
                     getHost(),
                     new ThrowableConvertor<GithubAuthData, String, IOException>() {
                       @NotNull
                       @Override
                       public String convert(@NotNull GithubAuthData auth) throws IOException {
                         return GithubApiUtil.getReadOnlyToken(
                             auth, getRepoAuthor(), getRepoName(), "Intellij tasks plugin");
                       }
                     });
               }
             }));
   } catch (GithubOperationCanceledException ignore) {
   } catch (IOException e) {
     GithubNotifications.showErrorDialog(myProject, "Can't get access token", e);
   }
 }
  public void showDiffDialog(@NotNull String branch) {
    if (canShowDiff()) {
      DiffInfo info = getDiffInfoWithModal(branch);
      if (info == null) {
        GithubNotifications.showErrorDialog(myProject, "Can't Show Diff", "Can't get diff info");
        return;
      }

      GitCompareBranchesDialog dialog =
          new GitCompareBranchesDialog(
              myProject, info.getTo(), info.getFrom(), info.getInfo(), myGitRepository);
      dialog.show();
    }
  }
  @Nullable
  private static GithubInfo2 getAvailableForksInModal(
      @NotNull final Project project,
      @NotNull final GitRepository gitRepository,
      @NotNull final GithubAuthData auth,
      @NotNull final GithubFullPath path) {
    try {
      return GithubUtil.computeValueInModal(
          project,
          "Access to GitHub",
          new ThrowableConvertor<ProgressIndicator, GithubInfo2, IOException>() {
            @Override
            public GithubInfo2 convert(ProgressIndicator indicator) throws IOException {
              final Set<GithubFullPath> forks = new HashSet<GithubFullPath>();

              // GitHub
              GithubRepoDetailed repo =
                  GithubApiUtil.getDetailedRepoInfo(auth, path.getUser(), path.getRepository());
              forks.add(path);
              if (repo.getParent() != null) {
                forks.add(repo.getParent().getFullPath());
              }
              if (repo.getSource() != null) {
                forks.add(repo.getSource().getFullPath());
              }

              // Git
              forks.addAll(getAvailableForksFromGit(gitRepository));

              GithubRepo forkTreeRoot = repo.getSource() == null ? repo : repo.getSource();
              return new GithubInfo2(forks, forkTreeRoot);
            }
          });
    } catch (GithubAuthenticationCanceledException e) {
      return null;
    } catch (IOException e) {
      GithubNotifications.showErrorDialog(project, CANNOT_CREATE_PULL_REQUEST, e);
      return null;
    }
  }
  public void showDiffDialog(@Nullable final BranchInfo branch) {
    if (branch == null) {
      GithubNotifications.showWarningDialog(
          myProject, "Can't Show Diff", "Target branch is not selected");
      return;
    }

    DiffInfo info;
    try {
      info =
          GithubUtil.computeValueInModal(
              myProject,
              "Collecting diff data...",
              new ThrowableConvertor<ProgressIndicator, DiffInfo, IOException>() {
                @Override
                public DiffInfo convert(ProgressIndicator indicator) throws IOException {
                  return GithubUtil.runInterruptable(
                      indicator,
                      new ThrowableComputable<DiffInfo, IOException>() {
                        @Override
                        public DiffInfo compute() throws IOException {
                          return getDiffInfo(branch);
                        }
                      });
                }
              });
    } catch (IOException e) {
      GithubNotifications.showError(myProject, "Can't collect diff data", e);
      return;
    }
    if (info == null) {
      GithubNotifications.showErrorDialog(myProject, "Can't Show Diff", "Can't collect diff data");
      return;
    }

    GitCompareBranchesDialog dialog =
        new GitCompareBranchesDialog(
            myProject, info.getTo(), info.getFrom(), info.getInfo(), myGitRepository, true);
    dialog.show();
  }
  @Nullable
  private static GithubInfo loadGithubInfoWithModal(
      @NotNull final GithubAuthDataHolder authHolder, @NotNull final Project project) {
    try {
      return GithubUtil.computeValueInModal(
          project,
          "Access to GitHub",
          new ThrowableConvertor<ProgressIndicator, GithubInfo, IOException>() {
            @NotNull
            @Override
            public GithubInfo convert(ProgressIndicator indicator) throws IOException {
              // get existing github repos (network) and validate auth data
              return GithubUtil.runTask(
                  project,
                  authHolder,
                  indicator,
                  new ThrowableConvertor<GithubAuthData, GithubInfo, IOException>() {
                    @NotNull
                    @Override
                    public GithubInfo convert(@NotNull GithubAuthData auth) throws IOException {
                      // check access to private repos (network)
                      GithubUserDetailed userInfo = GithubApiUtil.getCurrentUserDetailed(auth);

                      HashSet<String> names = new HashSet<String>();
                      for (GithubRepo info : GithubApiUtil.getUserRepos(auth)) {
                        names.add(info.getName());
                      }
                      return new GithubInfo(userInfo, names);
                    }
                  });
            }
          });
    } catch (GithubOperationCanceledException e) {
      return null;
    } catch (IOException e) {
      GithubNotifications.showErrorDialog(project, "Failed to connect to GitHub", e);
      return null;
    }
  }
  @Nullable
  public GithubTargetInfo setTarget(@NotNull final GithubFullPath forkPath) {
    try {
      GithubInfo info =
          GithubUtil.computeValueInModal(
              myProject,
              "Access to GitHub",
              new ThrowableConvertor<ProgressIndicator, GithubInfo, IOException>() {
                @Override
                public GithubInfo convert(ProgressIndicator indicator) throws IOException {
                  // configure remote
                  GitRemote targetRemote = GithubUtil.findGithubRemote(myGitRepository, forkPath);
                  String targetRemoteName = targetRemote == null ? null : targetRemote.getName();
                  if (targetRemoteName == null) {
                    final AtomicReference<Integer> responseRef = new AtomicReference<Integer>();
                    ApplicationManager.getApplication()
                        .invokeAndWait(
                            new Runnable() {
                              @Override
                              public void run() {
                                responseRef.set(
                                    GithubNotifications.showYesNoDialog(
                                        myProject,
                                        "Can't Find Remote",
                                        "Configure remote for '" + forkPath.getUser() + "'?"));
                              }
                            },
                            indicator.getModalityState());
                    if (responseRef.get() == Messages.YES) {
                      targetRemoteName = configureRemote(myProject, myGitRepository, forkPath);
                    }
                  }

                  // load available branches
                  List<String> branches =
                      ContainerUtil.map(
                          GithubApiUtil.getRepoBranches(
                              myAuth, forkPath.getUser(), forkPath.getRepository()),
                          new Function<GithubBranch, String>() {
                            @Override
                            public String fun(GithubBranch githubBranch) {
                              return githubBranch.getName();
                            }
                          });

                  // fetch
                  if (targetRemoteName != null) {
                    GitFetchResult result =
                        new GitFetcher(myProject, indicator, false)
                            .fetch(myGitRepository.getRoot(), targetRemoteName, null);
                    if (!result.isSuccess()) {
                      GitFetcher.displayFetchResult(myProject, result, null, result.getErrors());
                      targetRemoteName = null;
                    }
                  }

                  return new GithubInfo(branches, targetRemoteName);
                }
              });

      myForkPath = forkPath;
      myTargetRemote = info.getTargetRemote();

      myDiffInfos.clear();
      if (canShowDiff()) {
        for (final String branch : info.getBranches()) {
          myDiffInfos.put(
              branch,
              new FutureTask<DiffInfo>(
                  new Callable<DiffInfo>() {
                    @Override
                    public DiffInfo call() throws Exception {
                      return loadDiffInfo(
                          myProject,
                          myGitRepository,
                          myCurrentBranch,
                          myTargetRemote + "/" + branch);
                    }
                  }));
        }
      }

      return new GithubTargetInfo(info.getBranches());
    } catch (GithubAuthenticationCanceledException e) {
      return null;
    } catch (IOException e) {
      GithubNotifications.showErrorDialog(myProject, CANNOT_CREATE_PULL_REQUEST, e);
      return null;
    }
  }