/** * This is called when "Rebase and Push" button (default button) is pressed. 1. Closes the dialog. * 2. Fetches project and rebases. 3. Repeats step 2 if needed - while current repository is * behind the parent one. 4. Then pushes. It may fail on one of these steps (especially on * rebasing with conflict) - then a notification error will be shown and the process will be * interrupted. */ private void rebaseAndPush() { final Task.Backgroundable rebaseAndPushTask = new Task.Backgroundable(myProject, GitBundle.getString("push.active.fetching")) { public void run(@NotNull ProgressIndicator indicator) { List<VcsException> exceptions = new ArrayList<VcsException>(); List<VcsException> pushExceptions = new ArrayList<VcsException>(); for (int i = 0; i < 3; i++) { RebaseInfo rebaseInfo = collectRebaseInfo(); if (rebaseInfo.reorderedCommits .isEmpty()) { // if we have to reorder commits, rebase must pre final Collection<Root> rootsToPush = getRootsToPush(); // collect roots from the dialog exceptions = executePushCommand(rootsToPush); if (exceptions.isEmpty() && !rootsToPush.isEmpty()) { // if nothing to push, execute rebase anyway int commitsNum = 0; for (Root root : rootsToPush) { commitsNum += root.commits.size(); Set<String> unchecked = rebaseInfo.uncheckedCommits.get(root.root); if (unchecked != null) { commitsNum -= unchecked.size(); } } final String pushMessage = "Pushed " + commitsNum + " " + StringUtil.pluralize("commit", commitsNum); VcsBalloonProblemNotifier.showOverVersionControlView( myVcs.getProject(), pushMessage, MessageType.INFO); for (Root root : rootsToPush) { GitRepositoryManager.getInstance(myProject) .updateRepository(root.root, GitRepository.TrackedTopic.ALL); } return; } pushExceptions = new ArrayList<VcsException>(exceptions); exceptions.clear(); } final List<Root> roots = loadRoots(myProject, myVcsRoots, exceptions, true); // fetch if (!exceptions.isEmpty()) { notifyMessage( myProject, "Failed to fetch", null, NotificationType.ERROR, true, exceptions); return; } updateTree(roots, rebaseInfo.uncheckedCommits); if (isRebaseNeeded()) { rebaseInfo = collectRebaseInfo(); executeRebase(exceptions, rebaseInfo); if (!exceptions.isEmpty()) { notifyMessage( myProject, "Failed to rebase", null, NotificationType.ERROR, true, exceptions); return; } VcsFileUtil.refreshFiles(myProject, rebaseInfo.roots); } } notifyMessage( myProject, "Failed to push", "Update project and push again", NotificationType.ERROR, true, pushExceptions); } }; GitVcs.runInBackground(rebaseAndPushTask); }
/** * The most general execution method. * * @param sync Set to <code>true</code> to make the calling thread wait for the task execution. * @param modal If <code>true</code>, the task will be modal with a modal progress dialog. If * false, the task will be executed in background. <code>modal</code> implies <code>sync * </code>, i.e. if modal then sync doesn't matter: you'll wait anyway. * @param resultHandler Handle the result. * @see #execute(boolean) */ public void execute(boolean sync, boolean modal, final GitTaskResultHandler resultHandler) { final Object LOCK = new Object(); final AtomicBoolean completed = new AtomicBoolean(); if (modal) { final ModalTask task = new ModalTask(myProject, myHandler, myTitle) { @Override public void onSuccess() { commonOnSuccess(LOCK, resultHandler); completed.set(true); } @Override public void onCancel() { commonOnCancel(LOCK, resultHandler); completed.set(true); } }; GuiUtils.invokeAndWaitIfNeeded( new Runnable() { @Override public void run() { ProgressManager.getInstance().run(task); } }, ModalityState.defaultModalityState()); } else { final BackgroundableTask task = new BackgroundableTask(myProject, myHandler, myTitle) { @Override public void onSuccess() { commonOnSuccess(LOCK, resultHandler); completed.set(true); } @Override public void onCancel() { commonOnCancel(LOCK, resultHandler); completed.set(true); } }; if (myProgressIndicator == null) { GitVcs.runInBackground(task); } else { task.runAlone(); } } if (sync) { while (!completed.get()) { try { synchronized (LOCK) { LOCK.wait(50); } } catch (InterruptedException e) { LOG.info(e); } } } }