public void launchLoadDiffInfo(@NotNull final BranchInfo branch) { if (branch.getForkInfo().getRemoteName() == null) return; if (branch.getDiffInfoTask() != null) return; synchronized (branch.LOCK) { if (branch.getDiffInfoTask() != null) return; launchFetchRemote(branch.getForkInfo()); MasterFutureTask<Void> masterTask = branch.getForkInfo().getFetchTask(); assert masterTask != null; final SlaveFutureTask<DiffInfo> task = new SlaveFutureTask<DiffInfo>( masterTask, new Callable<DiffInfo>() { @Override public DiffInfo call() throws VcsException { return doLoadDiffInfo(branch); } }); branch.setDiffInfoTask(task); ApplicationManager.getApplication() .executeOnPooledThread( new Runnable() { @Override public void run() { task.run(); } }); } }
public boolean checkAction(@Nullable final BranchInfo branch) { if (branch == null) { GithubNotifications.showWarningDialog( myProject, CANNOT_CREATE_PULL_REQUEST, "Target branch is not selected"); return false; } 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 true; } if (info == null) { return true; } ForkInfo fork = branch.getForkInfo(); String localBranchName = "'" + myCurrentBranch + "'"; String targetBranchName = "'" + fork.getRemoteName() + "/" + branch.getRemoteName() + "'"; if (info.getInfo().getBranchToHeadCommits(myGitRepository).isEmpty()) { return GithubNotifications.showYesNoDialog( myProject, "Do you want to proceed anyway?", "Empty pull request: the branch " + localBranchName + " is fully merged to the branch " + targetBranchName); } if (!info.getInfo().getHeadToBranchCommits(myGitRepository).isEmpty()) { return GithubNotifications.showYesNoDialog( myProject, "Do you want to proceed anyway?", "The branch " + targetBranchName + " is not fully merged to the branch " + localBranchName); } return true; }
@Nullable public DiffInfo getDiffInfo(@NotNull final BranchInfo branch) throws IOException { if (branch.getForkInfo().getRemoteName() == null) return null; launchLoadDiffInfo(branch); assert branch.getDiffInfoTask() != null; try { return branch.getDiffInfoTask().get(); } catch (InterruptedException e) { throw new GithubOperationCanceledException(e); } catch (ExecutionException e) { Throwable ex = e.getCause(); if (ex instanceof VcsException) throw new IOException(ex); LOG.error(ex); return null; } }
@NotNull private DiffInfo doLoadDiffInfo(@NotNull final BranchInfo branch) throws VcsException { // TODO: make cancelable and abort old speculative requests (when git4idea will allow to do so) String currentBranch = myCurrentBranch; String targetBranch = branch.getForkInfo().getRemoteName() + "/" + branch.getRemoteName(); List<GitCommit> commits1 = GitHistoryUtils.history(myProject, myGitRepository.getRoot(), ".." + targetBranch); List<GitCommit> commits2 = GitHistoryUtils.history(myProject, myGitRepository.getRoot(), targetBranch + ".."); Collection<Change> diff = GitChangeUtils.getDiff( myProject, myGitRepository.getRoot(), targetBranch, myCurrentBranch, null); GitCommitCompareInfo info = new GitCommitCompareInfo(GitCommitCompareInfo.InfoType.BRANCH_TO_HEAD); info.put(myGitRepository, diff); info.put(myGitRepository, Couple.of(commits1, commits2)); return new DiffInfo(info, currentBranch, targetBranch); }
@NotNull public Couple<String> getDefaultDescriptionMessage(@NotNull final BranchInfo branch) { Couple<String> message = branch.getDefaultMessage(); if (message != null) return message; if (branch.getForkInfo().getRemoteName() == null) { return getSimpleDefaultDescriptionMessage(branch); } return GithubUtil.computeValueInModal( myProject, "Collecting additional data...", false, new Convertor<ProgressIndicator, Couple<String>>() { @Override public Couple<String> convert(ProgressIndicator o) { String localBranch = myCurrentBranch; String targetBranch = branch.getForkInfo().getRemoteName() + "/" + branch.getRemoteName(); try { List<VcsCommitMetadata> commits = GitHistoryUtils.readLastCommits( myProject, myGitRepository.getRoot(), localBranch, targetBranch); if (commits == null) return getSimpleDefaultDescriptionMessage(branch); VcsCommitMetadata localCommit = commits.get(0); VcsCommitMetadata targetCommit = commits.get(1); if (localCommit.getParents().contains(targetCommit.getId())) { return Couple.of(localCommit.getSubject(), localCommit.getFullMessage()); } return getSimpleDefaultDescriptionMessage(branch); } catch (VcsException e) { GithubNotifications.showWarning(myProject, "Can't collect additional data", e); return getSimpleDefaultDescriptionMessage(branch); } } }); }
@Nullable private GithubPullRequest doCreatePullRequest( @NotNull ProgressIndicator indicator, @NotNull final BranchInfo branch, @NotNull final String title, @NotNull final String description) { final ForkInfo fork = branch.getForkInfo(); final String head = myPath.getUser() + ":" + myCurrentBranch; final String base = branch.getRemoteName(); try { return GithubUtil.runTask( myProject, myAuthHolder, indicator, new ThrowableConvertor<GithubConnection, GithubPullRequest, IOException>() { @NotNull @Override public GithubPullRequest convert(@NotNull GithubConnection connection) throws IOException { return GithubApiUtil.createPullRequest( connection, fork.getPath().getUser(), fork.getPath().getRepository(), title, description, head, base); } }); } catch (IOException e) { GithubNotifications.showError(myProject, CANNOT_CREATE_PULL_REQUEST, e); return null; } }