private static void rollbackUnderProgress(
     @NotNull final Project project,
     @NotNull final VirtualFile virtualFile,
     @NotNull final Label labelToRevert) {
   ProgressManager.getInstance()
       .runProcessWithProgressSynchronously(
           () -> {
             try {
               labelToRevert.revert(project, virtualFile);
               VcsNotifier.getInstance(project)
                   .notifyImportantWarning(
                       "Apply Patch Aborted",
                       "All files changed during apply patch action were rolled back");
             } catch (LocalHistoryException e) {
               VcsNotifier.getInstance(project)
                   .notifyImportantWarning(
                       "Rollback Failed",
                       String.format(
                           "Try using local history dialog for %s and perform revert manually.",
                           virtualFile.getName()));
             }
           },
           "Rollback Applied Changes...",
           true,
           project);
 }
  private boolean doDeleteRemote(
      @NotNull String branchName, @NotNull Collection<GitRepository> repositories) {
    Couple<String> pair = splitNameOfRemoteBranch(branchName);
    String remoteName = pair.getFirst();
    String branch = pair.getSecond();

    GitCompoundResult result = new GitCompoundResult(myProject);
    for (GitRepository repository : repositories) {
      GitCommandResult res;
      GitRemote remote = getRemoteByName(repository, remoteName);
      if (remote == null) {
        String error = "Couldn't find remote by name: " + remoteName;
        LOG.error(error);
        res = GitCommandResult.error(error);
      } else {
        res = pushDeletion(repository, remote, branch);
        if (!res.success() && isAlreadyDeletedError(res.getErrorOutputAsJoinedString())) {
          res = myGit.remotePrune(repository, remote);
        }
      }
      result.append(repository, res);
      repository.update();
    }
    if (!result.totalSuccess()) {
      VcsNotifier.getInstance(myProject)
          .notifyError(
              "Failed to delete remote branch " + branchName,
              result.getErrorOutputWithReposIndication());
    }
    return result.totalSuccess();
  }
 @Override
 protected void notifyUnresolvedRemain() {
   VcsNotifier.getInstance(myProject)
       .notifyImportantWarning(
           "Local changes were restored with conflicts",
           "Your uncommitted changes were saved to <a href='saver'>stash</a>.<br/>"
               + "Unstash is not complete, you have unresolved merges in your working tree<br/>"
               + "<a href='resolve'>Resolve</a> conflicts and drop the stash.",
           new NotificationListener() {
             @Override
             public void hyperlinkUpdate(
                 @NotNull Notification notification, @NotNull HyperlinkEvent event) {
               if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                 if (event.getDescription().equals("saver")) {
                   // we don't use #showSavedChanges to specify unmerged root first
                   GitUnstashDialog.showUnstashDialog(
                       myProject,
                       new ArrayList<VirtualFile>(myStashedRoots),
                       myStashedRoots.iterator().next());
                 } else if (event.getDescription().equals("resolve")) {
                   mergeNoProceed();
                 }
               }
             }
           });
 }
  @NotNull
  public static <CommitInfo> List<CommitInfo> getCommitRecords(
      @NotNull Project project,
      @Nullable HgCommandResult result,
      @NotNull Function<String, CommitInfo> converter,
      boolean silent) {
    final List<CommitInfo> revisions = new LinkedList<CommitInfo>();
    if (result == null) {
      return revisions;
    }

    List<String> errors = result.getErrorLines();
    if (errors != null && !errors.isEmpty()) {
      if (result.getExitValue() != 0) {
        if (silent) {
          LOG.warn(errors.toString());
        } else {
          VcsNotifier.getInstance(project)
              .notifyError(
                  HgVcsMessages.message("hg4idea.error.log.command.execution"), errors.toString());
        }
        return Collections.emptyList();
      }
      LOG.warn(errors.toString());
    }
    String output = result.getRawOutput();
    List<String> changeSets = StringUtil.split(output, HgChangesetUtil.CHANGESET_SEPARATOR);
    return ContainerUtil.mapNotNull(changeSets, converter);
  }
 private void notifySuccessfulDeletion(
     @NotNull String remoteBranchName, @NotNull Collection<String> localBranches) {
   String message = "";
   if (!localBranches.isEmpty()) {
     message =
         "Also deleted local "
             + StringUtil.pluralize("branch", localBranches.size())
             + ": "
             + StringUtil.join(localBranches, ", ");
   }
   VcsNotifier.getInstance(myProject)
       .notifySuccess("Deleted remote branch " + remoteBranchName, message);
 }
 private void notifyException(VcsException e) {
   LOG.info("mergeFiles ", e);
   final String description =
       "Couldn't check the working tree for unmerged files because of an error.";
   VcsNotifier.getInstance(myProject)
       .notifyError(
           myParams.myErrorNotificationTitle,
           description
               + myParams.myErrorNotificationAdditionalDescription
               + "<br/>"
               + e.getLocalizedMessage(),
           new ResolveNotificationListener());
 }
 private void notifySuccess(final Project project, final String title, final String message) {
   VcsNotifier.getInstance(project)
       .notifyImportantInfo(
           title,
           message,
           new NotificationListener() {
             @Override
             public void hyperlinkUpdate(
                 @NotNull final Notification n, @NotNull final HyperlinkEvent e) {
               BrowserUtil.browse(e.getURL());
             }
           });
 }
 public void notifyLocalChangesAreNotRestored() {
   if (wereChangesSaved()) {
     LOG.info("Update is incomplete, changes are not restored");
     VcsNotifier.getInstance(myProject)
         .notifyImportantWarning(
             "Local changes were not restored",
             "Before update your uncommitted changes were saved to <a href='saver'>"
                 + getSaverName()
                 + "</a>.<br/>"
                 + "Update is not complete, you have unresolved merges in your working tree<br/>"
                 + "Resolve conflicts, complete update and restore changes manually.",
             new ShowSavedChangesNotificationListener());
   }
 }
  public void rescanAndNotifyIfNeeded() {
    Collection<VcsRootError> errors = scan();
    if (errors.isEmpty()) {
      synchronized (NOTIFICATION_LOCK) {
        expireNotification();
      }
      return;
    }

    Collection<VcsRootError> importantUnregisteredRoots = getImportantUnregisteredMappings(errors);
    Collection<VcsRootError> invalidRoots = getInvalidRoots(errors);

    List<String> unregRootPaths =
        ContainerUtil.map(importantUnregisteredRoots, PATH_FROM_ROOT_ERROR);
    if (invalidRoots.isEmpty()
        && (importantUnregisteredRoots.isEmpty()
            || myReportedUnregisteredRoots.containsAll(unregRootPaths))) {
      return;
    }
    myReportedUnregisteredRoots.addAll(unregRootPaths);

    String title = makeTitle(importantUnregisteredRoots, invalidRoots);
    String description = makeDescription(importantUnregisteredRoots, invalidRoots);

    synchronized (NOTIFICATION_LOCK) {
      expireNotification();
      NotificationListener listener =
          new MyNotificationListener(
              myProject, mySettings, myVcsManager, importantUnregisteredRoots);
      VcsNotifier notifier = VcsNotifier.getInstance(myProject);
      myNotification =
          invalidRoots.isEmpty()
              ? notifier.notifyMinorInfo(title, description, listener)
              : notifier.notifyError(title, description, listener);
    }
  }
 /**
  * Checks Git version and updates the myVersion variable. In the case of exception or unsupported
  * version reports the problem. Note that unsupported version is also applied - some functionality
  * might not work (we warn about that), but no need to disable at all.
  */
 public void checkVersion() {
   final String executable = myAppSettings.getPathToGit();
   try {
     myVersion = GitVersion.identifyVersion(executable);
     if (!myVersion.isSupported()) {
       log.info("Unsupported Git version: " + myVersion);
       final String SETTINGS_LINK = "settings";
       final String UPDATE_LINK = "update";
       String message =
           String.format(
               "The <a href='"
                   + SETTINGS_LINK
                   + "'>configured</a> version of Git is not supported: %s.<br/> "
                   + "The minimal supported version is %s. Please <a href='"
                   + UPDATE_LINK
                   + "'>update</a>.",
               myVersion,
               GitVersion.MIN);
       VcsNotifier.getInstance(myProject)
           .notifyError(
               "Unsupported Git version",
               message,
               new NotificationListener.Adapter() {
                 @Override
                 protected void hyperlinkActivated(
                     @NotNull Notification notification, @NotNull HyperlinkEvent e) {
                   if (SETTINGS_LINK.equals(e.getDescription())) {
                     ShowSettingsUtil.getInstance()
                         .showSettingsDialog(myProject, getConfigurable().getDisplayName());
                   } else if (UPDATE_LINK.equals(e.getDescription())) {
                     BrowserUtil.browse("http://git-scm.com");
                   }
                 }
               });
     }
   } catch (Exception e) {
     if (getExecutableValidator()
         .checkExecutableAndNotifyIfNeeded()) { // check executable before notifying error
       final String reason = (e.getCause() != null ? e.getCause() : e).getMessage();
       String message = GitBundle.message("vcs.unable.to.run.git", executable, reason);
       if (!myProject.isDefault()) {
         showMessage(message, ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
       }
       VcsBalloonProblemNotifier.showOverVersionControlView(myProject, message, MessageType.ERROR);
     }
   }
 }
  /**
   * Displays notification about {@code untracked files would be overwritten by checkout} error.
   * Clicking on the link in the notification opens a simple dialog with the list of these files.
   *
   * @param root
   * @param relativePaths
   * @param operation the name of the Git operation that caused the error: {@code rebase, merge,
   *     checkout}.
   * @param description the content of the notification or null if the deafult content is to be
   *     used.
   */
  public static void notifyUntrackedFilesOverwrittenBy(
      @NotNull final Project project,
      @NotNull final VirtualFile root,
      @NotNull Collection<String> relativePaths,
      @NotNull final String operation,
      @Nullable String description) {
    final String notificationTitle = StringUtil.capitalize(operation) + " failed";
    final String notificationDesc =
        description == null
            ? createUntrackedFilesOverwrittenDescription(operation, true)
            : description;

    final Collection<String> absolutePaths = GitUtil.toAbsolute(root, relativePaths);
    final List<VirtualFile> untrackedFiles =
        ContainerUtil.mapNotNull(
            absolutePaths,
            new Function<String, VirtualFile>() {
              @Override
              public VirtualFile fun(String absolutePath) {
                return GitUtil.findRefreshFileOrLog(absolutePath);
              }
            });

    VcsNotifier.getInstance(project)
        .notifyError(
            notificationTitle,
            notificationDesc,
            new NotificationListener() {
              @Override
              public void hyperlinkUpdate(
                  @NotNull Notification notification, @NotNull HyperlinkEvent event) {
                if (event.getEventType() == HyperlinkEvent.EventType.ACTIVATED) {
                  final String dialogDesc =
                      createUntrackedFilesOverwrittenDescription(operation, false);
                  String title = "Untracked Files Preventing " + StringUtil.capitalize(operation);
                  if (untrackedFiles.isEmpty()) {
                    GitUtil.showPathsInDialog(project, absolutePaths, title, dialogDesc);
                  } else {
                    DialogWrapper dialog;
                    dialog = new UntrackedFilesDialog(project, untrackedFiles, dialogDesc);
                    dialog.setTitle(title);
                    dialog.show();
                  }
                }
              }
            });
  }
 private void notifyWarning(String title, String content) {
   VcsNotifier.getInstance(myProject)
       .notifyImportantWarning(title, content, new ResolveNotificationListener());
 }
 private void notifyError(final Project project, final String title, final String message) {
   VcsNotifier.getInstance(project).notifyError(title, message);
 }