/** Show dialog for the project */
 public static void showDialogForProject(final Project project) {
   GitVcs vcs = GitVcs.getInstance(project);
   List<VirtualFile> roots = GitRepositoryAction.getGitRoots(project, vcs);
   if (roots == null) {
     return;
   }
   List<VcsException> pushExceptions = new ArrayList<VcsException>();
   showDialog(project, roots, pushExceptions);
   vcs.showErrors(pushExceptions, GitBundle.getString("push.active.action.name"));
 }
  private boolean merge(boolean mergeDialogInvokedFromNotification) {
    try {
      final Collection<VirtualFile> initiallyUnmergedFiles = getUnmergedFiles(myRoots);
      if (initiallyUnmergedFiles.isEmpty()) {
        LOG.info("merge: no unmerged files");
        return mergeDialogInvokedFromNotification ? true : proceedIfNothingToMerge();
      } else {
        showMergeDialog(initiallyUnmergedFiles);

        final Collection<VirtualFile> unmergedFilesAfterResolve = getUnmergedFiles(myRoots);
        if (unmergedFilesAfterResolve.isEmpty()) {
          LOG.info("merge no more unmerged files");
          return mergeDialogInvokedFromNotification ? true : proceedAfterAllMerged();
        } else {
          LOG.info("mergeFiles unmerged files remain: " + unmergedFilesAfterResolve);
          if (mergeDialogInvokedFromNotification) {
            notifyUnresolvedRemainAfterNotification();
          } else {
            notifyUnresolvedRemain();
          }
        }
      }
    } catch (VcsException e) {
      if (myVcs.getExecutableValidator().checkExecutableAndNotifyIfNeeded()) {
        notifyException(e);
      }
    }
    return false;
  }
 /**
  * Setup remotes combobox. The default remote for the current branch is selected by default.
  *
  * @param project the project
  * @param root the git root
  * @param currentBranch the current branch
  * @param remoteCombobox the combobox to update
  * @param fetchUrl if true, the fetch url is shown for remotes, push otherwise
  */
 public static void setupRemotes(
     final Project project,
     final VirtualFile root,
     final String currentBranch,
     final JComboBox remoteCombobox,
     final boolean fetchUrl) {
   try {
     List<GitDeprecatedRemote> remotes = GitDeprecatedRemote.list(project, root);
     String remote = null;
     if (currentBranch != null) {
       remote = GitConfigUtil.getValue(project, root, "branch." + currentBranch + ".remote");
     }
     remoteCombobox.setRenderer(
         getGitRemoteListCellRenderer(remote, fetchUrl, remoteCombobox.getRenderer()));
     GitDeprecatedRemote toSelect = null;
     remoteCombobox.removeAllItems();
     for (GitDeprecatedRemote r : remotes) {
       remoteCombobox.addItem(r);
       if (r.name().equals(remote)) {
         toSelect = r;
       }
     }
     if (toSelect != null) {
       remoteCombobox.setSelectedItem(toSelect);
     }
   } catch (VcsException e) {
     GitVcs.getInstance(project)
         .showErrors(Collections.singletonList(e), GitBundle.getString("pull.retrieving.remotes"));
   }
 }
Example #4
0
 /**
  * The constructor
  *
  * @param project the context project
  */
 public GitVcsPanel(@NotNull Project project) {
   myVcs = GitVcs.getInstance(project);
   myAppSettings = GitVcsApplicationSettings.getInstance();
   myProjectSettings = GitVcsSettings.getInstance(project);
   myProject = project;
   mySSHExecutableComboBox.addItem(IDEA_SSH);
   mySSHExecutableComboBox.addItem(NATIVE_SSH);
   mySSHExecutableComboBox.setSelectedItem(
       GitVcsSettings.isDefaultIdeaSsh() ? IDEA_SSH : NATIVE_SSH);
   mySSHExecutableComboBox.setToolTipText(
       GitBundle.message(
           "git.vcs.config.ssh.mode.tooltip",
           ApplicationNamesInfo.getInstance().getFullProductName()));
   myTestButton.addActionListener(
       new ActionListener() {
         public void actionPerformed(ActionEvent e) {
           testConnection();
         }
       });
   myConvertTextFilesComboBox.addItem(CRLF_DO_NOT_CONVERT);
   myConvertTextFilesComboBox.addItem(CRLF_CONVERT_TO_PROJECT);
   myConvertTextFilesComboBox.addItem(CRLF_ASK);
   myConvertTextFilesComboBox.setSelectedItem(CRLF_ASK);
   myGitField.addBrowseFolderListener(
       GitBundle.getString("find.git.title"),
       GitBundle.getString("find.git.description"),
       project,
       new FileChooserDescriptor(true, false, false, false, false, false));
 }
 @Override
 public void directoryMappingChanged() {
   GitVcs vcs = GitVcs.getInstance(myProject);
   if (vcs == null) {
     return;
   }
   final VirtualFile[] roots = myVcsManager.getRootsUnderVcs(vcs);
   final Collection<VirtualFile> rootsToCheck =
       ContainerUtil.filter(
           roots,
           new Condition<VirtualFile>() {
             @Override
             public boolean value(VirtualFile root) {
               return getUser(root) == null;
             }
           });
   if (!rootsToCheck.isEmpty()) {
     ApplicationManager.getApplication()
         .executeOnPooledThread(
             new Runnable() {
               public void run() {
                 for (VirtualFile root : rootsToCheck) {
                   getOrReadUser(root);
                 }
               }
             });
   }
 }
 /** Adds {@code stash@{x}} parameter to the handler, quotes it if needed. */
 private void addStashParameter(@NotNull GitHandler handler, @NotNull String stash) {
   if (GitVersionSpecialty.NEEDS_QUOTES_IN_STASH_NAME.existsIn(myVcs.getVersion())) {
     handler.addParameters("\"" + stash + "\"");
     handler.dontEscapeQuotes();
   } else {
     handler.addParameters(stash);
   }
 }
Example #7
0
 /**
  * @param fetchAll Pass {@code true} to fetch all remotes and all branches (like {@code git fetch}
  *     without parameters does). Pass {@code false} to fetch only the tracked branch of the
  *     current branch.
  */
 public GitFetcher(
     @NotNull Project project, @NotNull ProgressIndicator progressIndicator, boolean fetchAll) {
   myProject = project;
   myProgressIndicator = progressIndicator;
   myFetchAll = fetchAll;
   myRepositoryManager = GitUtil.getRepositoryManager(myProject);
   myVcs = GitVcs.getInstance(project);
 }
 /**
  * Handles a low-level Git execution exception. Checks that Git executable is valid. If it is not,
  * then shows proper notification with an option to fix the path to Git. If it's valid, then we
  * don't know what could happen and just display the general error notification.
  */
 public static void checkGitExecutableAndShowNotification(final Project project, VcsException e) {
   if (GitVcs.getInstance(project).getExecutableValidator().checkExecutableAndNotifyIfNeeded()) {
     GitVcs.IMPORTANT_ERROR_NOTIFICATION
         .createNotification(
             GitBundle.getString("general.error"),
             e.getLocalizedMessage(),
             NotificationType.ERROR,
             null)
         .notify(project);
   }
 }
 public GitLogProvider(
     @NotNull Project project,
     @NotNull GitRepositoryManager repositoryManager,
     @NotNull VcsLogObjectsFactory factory,
     @NotNull GitUserRegistry userRegistry) {
   myProject = project;
   myRepositoryManager = repositoryManager;
   myUserRegistry = userRegistry;
   myRefSorter = new GitRefManager(myRepositoryManager);
   myVcsObjectsFactory = factory;
   myVcs = ObjectUtils.assertNotNull(GitVcs.getInstance(project));
 }
Example #10
0
  private GitFetchResult fetchNatively(
      @NotNull VirtualFile root, @NotNull GitRemote remote, @Nullable String branch) {
    final GitLineHandlerPasswordRequestAware h =
        new GitLineHandlerPasswordRequestAware(myProject, root, GitCommand.FETCH);
    h.addProgressParameter();
    if (GitVersionSpecialty.SUPPORTS_FETCH_PRUNE.existsIn(myVcs.getVersion())) {
      h.addParameters("--prune");
    }

    String remoteName = remote.getName();
    h.addParameters(remoteName);
    if (branch != null) {
      h.addParameters(getFetchSpecForBranch(branch, remoteName));
    }

    final GitTask fetchTask = new GitTask(myProject, h, "Fetching " + remote.getFirstUrl());
    fetchTask.setProgressIndicator(myProgressIndicator);
    fetchTask.setProgressAnalyzer(new GitStandardProgressAnalyzer());

    GitFetchPruneDetector pruneDetector = new GitFetchPruneDetector();
    h.addLineListener(pruneDetector);

    final AtomicReference<GitFetchResult> result = new AtomicReference<GitFetchResult>();
    fetchTask.execute(
        true,
        false,
        new GitTaskResultHandlerAdapter() {
          @Override
          protected void onSuccess() {
            result.set(GitFetchResult.success());
          }

          @Override
          protected void onCancel() {
            LOG.info("Cancelled fetch.");
            result.set(GitFetchResult.cancel());
          }

          @Override
          protected void onFailure() {
            LOG.info("Error fetching: " + h.errors());
            if (!h.hadAuthRequest()) {
              myErrors.addAll(h.errors());
            } else {
              myErrors.add(new VcsException("Authentication failed"));
            }
            result.set(GitFetchResult.error(myErrors));
          }
        });

    result.get().addPruneInfo(pruneDetector.getPrunedRefs());
    return result.get();
  }
Example #11
0
 public static void displayFetchResult(
     @NotNull Project project,
     @NotNull GitFetchResult result,
     @Nullable String errorNotificationTitle,
     @NotNull Collection<? extends Exception> errors) {
   if (result.isSuccess()) {
     GitVcs.NOTIFICATION_GROUP_ID
         .createNotification(
             "Fetched successfully" + result.getAdditionalInfo(), NotificationType.INFORMATION)
         .notify(project);
   } else if (result.isCancelled()) {
     GitVcs.NOTIFICATION_GROUP_ID
         .createNotification(
             "Fetch cancelled by user" + result.getAdditionalInfo(), NotificationType.WARNING)
         .notify(project);
   } else if (result.isNotAuthorized()) {
     String title;
     String description;
     if (errorNotificationTitle != null) {
       title = errorNotificationTitle;
       description = "Fetch failed: couldn't authorize";
     } else {
       title = "Fetch failed";
       description = "Couldn't authorize";
     }
     description += result.getAdditionalInfo();
     GitUIUtil.notifyMessage(project, title, description, NotificationType.ERROR, true, null);
   } else {
     GitVcs instance = GitVcs.getInstance(project);
     if (instance != null && instance.getExecutableValidator().isExecutableValid()) {
       GitUIUtil.notifyMessage(
           project,
           "Fetch failed",
           result.getAdditionalInfo(),
           NotificationType.ERROR,
           true,
           errors);
     }
   }
 }
 @NotNull
 @Override
 public List<? extends VcsFullCommitDetails> readFullDetails(
     @NotNull VirtualFile root, @NotNull List<String> hashes) throws VcsException {
   String noWalk =
       GitVersionSpecialty.NO_WALK_UNSORTED.existsIn(myVcs.getVersion())
           ? "--no-walk=unsorted"
           : "--no-walk";
   List<String> params = new ArrayList<String>();
   params.add(noWalk);
   params.addAll(hashes);
   return GitHistoryUtils.history(myProject, root, ArrayUtil.toStringArray(params));
 }
 public GitConflictResolver(
     @NotNull Project project,
     @NotNull Git git,
     @NotNull Collection<VirtualFile> roots,
     @NotNull Params params) {
   myProject = project;
   myGit = git;
   myRoots = roots;
   myParams = params;
   myRepositoryManager = GitUtil.getRepositoryManager(myProject);
   myVcsHelper = AbstractVcsHelper.getInstance(project);
   myVcs = assertNotNull(GitVcs.getInstance(myProject));
 }
  @Before
  public void setUp() throws Throwable {
    IdeaTestApplication.getInstance();

    myTestName = createTestName();
    myProjectFixture =
        IdeaTestFixtureFactory.getFixtureFactory().createFixtureBuilder(myTestName).getFixture();

    edt(
        new ThrowableRunnable<Exception>() {
          @Override
          public void run() throws Exception {
            myProjectFixture.setUp();
          }
        });

    myProject = myProjectFixture.getProject();

    myProjectRoot = myProject.getBasePath();
    myProjectDir = myProject.getBaseDir();
    myTestRoot = myProjectRoot;

    myGit = ServiceManager.getService(myProject, Git.class);
    mySettings = GitVcsSettings.getInstance(myProject);
    mySettings.getAppSettings().setPathToGit(GitExecutor.PathHolder.GIT_EXECUTABLE);

    // dynamic overriding is used instead of making it in plugin.xml,
    // because MockVcsHelper is not ready to be a full featured implementation for all tests.
    myVcsHelper =
        GitTestUtil.overrideService(myProject, AbstractVcsHelper.class, MockVcsHelper.class);
    myChangeListManager = ChangeListManagerImpl.getInstanceImpl(myProject);
    myNotificator = (TestVcsNotifier) ServiceManager.getService(myProject, VcsNotifier.class);
    myVcs = GitVcs.getInstance(myProject);
    myRepositoryManager = GitUtil.getRepositoryManager(myProject);

    virtualCommits = new GitTestVirtualCommitsHolder();
    myAsyncTasks = new ArrayList<>();

    cd(myProjectRoot);
    myRepository = GitTestUtil.createRepository(myProject, myProjectRoot);

    ProjectLevelVcsManagerImpl vcsManager =
        (ProjectLevelVcsManagerImpl) ProjectLevelVcsManager.getInstance(myProject);
    AbstractVcs vcs = vcsManager.findVcsByName("Git");
    Assert.assertEquals(1, vcsManager.getRootsUnderVcs(vcs).length);

    GitTestUtil.assumeSupportedGitVersion(myVcs);
    LOG.info(getStartTestMarker());
  }
  @Override
  public void actionPerformed(@NotNull AnActionEvent event) {
    final Project project = event.getProject();
    if (project == null) {
      return;
    }

    final Set<VirtualFile> conflictedFiles =
        new TreeSet<VirtualFile>(
            new Comparator<VirtualFile>() {
              @Override
              public int compare(@NotNull VirtualFile f1, @NotNull VirtualFile f2) {
                return f1.getPresentableUrl().compareTo(f2.getPresentableUrl());
              }
            });
    for (Change change : ChangeListManager.getInstance(project).getAllChanges()) {
      if (change.getFileStatus() != FileStatus.MERGED_WITH_CONFLICTS) {
        continue;
      }
      final ContentRevision before = change.getBeforeRevision();
      final ContentRevision after = change.getAfterRevision();
      if (before != null) {
        final VirtualFile file = before.getFile().getVirtualFile();
        if (file != null) {
          conflictedFiles.add(file);
        }
      }
      if (after != null) {
        final VirtualFile file = after.getFile().getVirtualFile();
        if (file != null) {
          conflictedFiles.add(file);
        }
      }
    }

    AbstractVcsHelper.getInstance(project)
        .showMergeDialog(
            new ArrayList<VirtualFile>(conflictedFiles),
            GitVcs.getInstance(project).getMergeProvider());
    for (VirtualFile conflictedFile : conflictedFiles) {
      final GitRepository repo =
          GitRepositoryManager.getInstance(project).getRepositoryForFile(conflictedFile);
      if (repo != null) {
        repo.update(GitRepository.TrackedTopic.ALL_CURRENT);
      }
    }
  }
 protected GitUpdater(
     @NotNull Project project,
     @NotNull Git git,
     @NotNull VirtualFile root,
     @NotNull Map<VirtualFile, GitBranchPair> trackedBranches,
     @NotNull ProgressIndicator progressIndicator,
     @NotNull UpdatedFiles updatedFiles) {
   myProject = project;
   myGit = git;
   myRoot = root;
   myTrackedBranches = trackedBranches;
   myProgressIndicator = progressIndicator;
   myUpdatedFiles = updatedFiles;
   myVcsHelper = AbstractVcsHelper.getInstance(project);
   myVcs = GitVcs.getInstance(project);
   myRepositoryManager = GitUtil.getRepositoryManager(myProject);
 }
 public synchronized byte[] getContent() throws IOException, VcsException {
   if (myNoCache) {
     return loadContent();
   }
   return ContentRevisionCache.getOrLoadAsBytes(
       project,
       path,
       revision,
       GitVcs.getKey(),
       ContentRevisionCache.UniqueType.REPOSITORY_CONTENT,
       new Throwable2Computable<byte[], VcsException, IOException>() {
         @Override
         public byte[] compute() throws VcsException, IOException {
           return loadContent();
         }
       });
 }
Example #18
0
 /**
  * Save configuration panel state into settings object
  *
  * @param settings the settings object
  */
 public void save(@NotNull GitVcsSettings settings) {
   settings.getAppSettings().setPathToGit(myGitField.getText());
   myVcs.checkVersion();
   settings.setIdeaSsh(IDEA_SSH.equals(mySSHExecutableComboBox.getSelectedItem()));
   Object policyItem = myConvertTextFilesComboBox.getSelectedItem();
   GitVcsSettings.ConversionPolicy conversionPolicy;
   if (CRLF_DO_NOT_CONVERT.equals(policyItem)) {
     conversionPolicy = GitVcsSettings.ConversionPolicy.NONE;
   } else if (CRLF_CONVERT_TO_PROJECT.equals(policyItem)) {
     conversionPolicy = GitVcsSettings.ConversionPolicy.CONVERT;
   } else if (CRLF_ASK.equals(policyItem)) {
     conversionPolicy = GitVcsSettings.ConversionPolicy.ASK;
   } else {
     throw new IllegalStateException("Unknown selected CRLF policy: " + policyItem);
   }
   settings.setLineSeparatorsConversion(conversionPolicy);
 }
 @Nullable
 @Override
 protected String getLastCommitMessage(@NotNull VirtualFile root) throws VcsException {
   GitSimpleHandler h = new GitSimpleHandler(myProject, root, GitCommand.LOG);
   h.addParameters("--max-count=1");
   String formatPattern;
   if (GitVersionSpecialty.STARTED_USING_RAW_BODY_IN_FORMAT.existsIn(myVcs.getVersion())) {
     formatPattern = "%B";
   } else {
     // only message: subject + body; "%-b" means that preceding line-feeds will be deleted if
     // the body is empty
     // %s strips newlines from subject; there is no way to work around it before 1.7.2 with %B
     // (unless parsing some fixed format)
     formatPattern = "%s%n%n%-b";
   }
   h.addParameters("--pretty=format:" + formatPattern);
   return h.run();
 }
    GitCheckinOptions(@NotNull final Project project, @NotNull CheckinProjectPanel panel) {
      super(project, panel);
      myVcs = GitVcs.getInstance(project);
      final Insets insets = new Insets(2, 2, 2, 2);
      // add authors drop down
      GridBagConstraints c = new GridBagConstraints();
      c.gridx = 0;
      c.gridy = 0;
      c.anchor = GridBagConstraints.WEST;
      c.insets = insets;
      final JLabel authorLabel = new JLabel(GitBundle.message("commit.author"));
      myPanel.add(authorLabel, c);

      c = new GridBagConstraints();
      c.anchor = GridBagConstraints.CENTER;
      c.insets = insets;
      c.gridx = 1;
      c.gridy = 0;
      c.weightx = 1;
      c.fill = GridBagConstraints.HORIZONTAL;
      final List<String> usersList = getUsersList(project);
      final Set<String> authors =
          usersList == null ? new HashSet<String>() : new HashSet<String>(usersList);
      ContainerUtil.addAll(authors, mySettings.getCommitAuthors());
      List<String> list = new ArrayList<String>(authors);
      Collections.sort(list);
      list =
          ObjectsConvertor.convert(
              list,
              new Convertor<String, String>() {
                @Override
                public String convert(String o) {
                  return StringUtil.shortenTextWithEllipsis(o, 30, 0);
                }
              });
      myAuthor = new ComboBox(ArrayUtil.toObjectArray(list));
      myAuthor.insertItemAt("", 0);
      myAuthor.setSelectedItem("");
      myAuthor.setEditable(true);
      authorLabel.setLabelFor(myAuthor);
      myAuthor.setToolTipText(GitBundle.getString("commit.author.tooltip"));
      myPanel.add(myAuthor, c);
    }
  @Override
  public void actionPerformed(AnActionEvent e) {
    Data data = Data.collect(e);
    if (!data.isValid()) {
      return;
    }

    List<VcsFullCommitDetails> details = data.log.getSelectedDetails();
    if (details.size() != 1) {
      return;
    }
    VcsFullCommitDetails commit = details.get(0);

    GitRepositoryManager repositoryManager =
        ServiceManager.getService(data.project, GitRepositoryManager.class);
    final GitRepository repository = repositoryManager.getRepositoryForRoot(commit.getRoot());
    if (repository == null) {
      DvcsUtil.noVcsRepositoryForRoot(
          LOG, commit.getRoot(), data.project, repositoryManager, GitVcs.getInstance(data.project));
      return;
    }

    actionPerformed(repository, commit);
  }
    private ReturnResult checkUserName() {
      Project project = myPanel.getProject();
      GitVcs vcs = GitVcs.getInstance(project);
      assert vcs != null;

      Collection<VirtualFile> notDefined = new ArrayList<VirtualFile>();
      Map<VirtualFile, Pair<String, String>> defined =
          new HashMap<VirtualFile, Pair<String, String>>();
      Collection<VirtualFile> allRoots =
          new ArrayList<VirtualFile>(
              Arrays.asList(ProjectLevelVcsManager.getInstance(project).getRootsUnderVcs(vcs)));

      Collection<VirtualFile> affectedRoots = getSelectedRoots();
      for (VirtualFile root : affectedRoots) {
        try {
          Pair<String, String> nameAndEmail = getUserNameAndEmailFromGitConfig(project, root);
          String name = nameAndEmail.getFirst();
          String email = nameAndEmail.getSecond();
          if (name == null || email == null) {
            notDefined.add(root);
          } else {
            defined.put(root, nameAndEmail);
          }
        } catch (VcsException e) {
          LOG.error("Couldn't get user.name and user.email for root " + root, e);
          // doing nothing - let commit with possibly empty user.name/email
        }
      }

      if (notDefined.isEmpty()) {
        return ReturnResult.COMMIT;
      }

      GitVersion version = vcs.getVersion();
      if (System.getenv("HOME") == null
          && GitVersionSpecialty.DOESNT_DEFINE_HOME_ENV_VAR.existsIn(version)) {
        Messages.showErrorDialog(
            project,
            "You are using Git "
                + version
                + " which doesn't define %HOME% environment variable properly.\n"
                + "Consider updating Git to a newer version "
                + "or define %HOME% to point to the place where the global .gitconfig is stored \n"
                + "(it is usually %USERPROFILE% or %HOMEDRIVE%%HOMEPATH%).",
            "HOME Variable Is Not Defined");
        return ReturnResult.CANCEL;
      }

      if (defined.isEmpty() && allRoots.size() > affectedRoots.size()) {
        allRoots.removeAll(affectedRoots);
        for (VirtualFile root : allRoots) {
          try {
            Pair<String, String> nameAndEmail = getUserNameAndEmailFromGitConfig(project, root);
            String name = nameAndEmail.getFirst();
            String email = nameAndEmail.getSecond();
            if (name != null && email != null) {
              defined.put(root, nameAndEmail);
              break;
            }
          } catch (VcsException e) {
            LOG.error("Couldn't get user.name and user.email for root " + root, e);
            // doing nothing - not critical not to find the values for other roots not affected by
            // commit
          }
        }
      }

      GitUserNameNotDefinedDialog dialog =
          new GitUserNameNotDefinedDialog(project, notDefined, affectedRoots, defined);
      dialog.show();
      if (dialog.isOK()) {
        try {
          if (dialog.isGlobal()) {
            GitConfigUtil.setValue(
                project,
                notDefined.iterator().next(),
                GitConfigUtil.USER_NAME,
                dialog.getUserName(),
                "--global");
            GitConfigUtil.setValue(
                project,
                notDefined.iterator().next(),
                GitConfigUtil.USER_EMAIL,
                dialog.getUserEmail(),
                "--global");
          } else {
            for (VirtualFile root : notDefined) {
              GitConfigUtil.setValue(project, root, GitConfigUtil.USER_NAME, dialog.getUserName());
              GitConfigUtil.setValue(
                  project, root, GitConfigUtil.USER_EMAIL, dialog.getUserEmail());
            }
          }
        } catch (VcsException e) {
          String message = "Couldn't set user.name and user.email";
          LOG.error(message, e);
          Messages.showErrorDialog(myPanel.getComponent(), message);
          return ReturnResult.CANCEL;
        }
        return ReturnResult.COMMIT;
      }
      return ReturnResult.CLOSE_WINDOW;
    }
 public GitCheckinHandlerFactory() {
   super(GitVcs.getKey());
 }
  /**
   * Constructs new dialog. Loads settings, registers listeners.
   *
   * @param project the project
   * @param vcsRoots the vcs roots
   * @param roots the loaded information about roots
   */
  private GitPushActiveBranchesDialog(
      final Project project, List<VirtualFile> vcsRoots, List<Root> roots) {
    super(project, true);
    myVcs = GitVcs.getInstance(project);
    myProject = project;
    myVcsRoots = vcsRoots;
    myGeneralSettings = GeneralSettings.getInstance();
    myProjectManager = ProjectManagerEx.getInstanceEx();

    updateTree(roots, null);
    updateUI();

    final GitVcsSettings settings = GitVcsSettings.getInstance(project);
    if (settings != null) {
      UpdatePolicyUtils.updatePolicyItem(
          settings.getPushActiveBranchesRebaseSavePolicy(),
          myStashRadioButton,
          myShelveRadioButton);
    }
    ChangeListener listener =
        new ChangeListener() {
          public void stateChanged(ChangeEvent e) {
            if (settings != null) {
              settings.setPushActiveBranchesRebaseSavePolicy(
                  UpdatePolicyUtils.getUpdatePolicy(myStashRadioButton, myShelveRadioButton));
            }
          }
        };
    myStashRadioButton.addChangeListener(listener);
    myShelveRadioButton.addChangeListener(listener);
    myCommitTree
        .getSelectionModel()
        .addTreeSelectionListener(
            new TreeSelectionListener() {
              public void valueChanged(TreeSelectionEvent e) {
                TreePath path = myCommitTree.getSelectionModel().getSelectionPath();
                if (path == null) {
                  myViewButton.setEnabled(false);
                  return;
                }
                DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
                myViewButton.setEnabled(
                    node != null
                        && myCommitTree.getSelectionCount() == 1
                        && node.getUserObject() instanceof Commit);
              }
            });
    myViewButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            TreePath path = myCommitTree.getSelectionModel().getSelectionPath();
            if (path == null) {
              return;
            }
            DefaultMutableTreeNode node = (DefaultMutableTreeNode) path.getLastPathComponent();
            if (node == null || !(node.getUserObject() instanceof Commit)) {
              return;
            }
            Commit c = (Commit) node.getUserObject();
            GitShowAllSubmittedFilesAction.showSubmittedFiles(
                project, c.revision.asString(), c.root.root);
          }
        });
    myFetchButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            fetch();
          }
        });
    myRebaseButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            rebase();
          }
        });

    myPushButton.addActionListener(
        new ActionListener() {
          @Override
          public void actionPerformed(ActionEvent e) {
            push();
          }
        });

    setTitle(GitBundle.getString("push.active.title"));
    setOKButtonText(GitBundle.getString("push.active.rebase.and.push"));
    setCancelButtonText(GitBundle.getString("git.push.active.close"));
    init();
  }
  /**
   * 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);
        }
      }
    }
  }
  /**
   * 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);
  }
 @NotNull
 @Override
 public VcsKey getSupportedVcs() {
   return GitVcs.getKey();
 }
 boolean isValid() {
   return project != null && log != null && DvcsUtil.logHasRootForVcs(log, GitVcs.getKey());
 }
 public static void assumeSupportedGitVersion(@NotNull GitVcs vcs) {
   GitVersion version = vcs.getVersion();
   assumeTrue("Unsupported Git version: " + version, version.isSupported());
 }
  /**
   * A constructor
   *
   * @param project the project
   * @param roots the list of the roots
   * @param defaultRoot the default root to select
   */
  public GitUnstashDialog(
      final Project project, final List<VirtualFile> roots, final VirtualFile defaultRoot) {
    super(project, true);
    setModal(false);
    myProject = project;
    myVcs = GitVcs.getInstance(project);
    setTitle(GitBundle.getString("unstash.title"));
    setOKButtonText(GitBundle.getString("unstash.button.apply"));
    GitUIUtil.setupRootChooser(project, roots, defaultRoot, myGitRootComboBox, myCurrentBranch);
    myStashList.setModel(new DefaultListModel());
    refreshStashList();
    myGitRootComboBox.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            refreshStashList();
            updateDialogState();
          }
        });
    myStashList.addListSelectionListener(
        new ListSelectionListener() {
          public void valueChanged(final ListSelectionEvent e) {
            updateDialogState();
          }
        });
    myBranchTextField
        .getDocument()
        .addDocumentListener(
            new DocumentAdapter() {
              protected void textChanged(final DocumentEvent e) {
                updateDialogState();
              }
            });
    myPopStashCheckBox.addActionListener(
        new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            updateDialogState();
          }
        });
    myClearButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            if (Messages.YES
                == Messages.showYesNoDialog(
                    GitUnstashDialog.this.getContentPane(),
                    GitBundle.message("git.unstash.clear.confirmation.message"),
                    GitBundle.message("git.unstash.clear.confirmation.title"),
                    Messages.getWarningIcon())) {
              GitLineHandler h = new GitLineHandler(myProject, getGitRoot(), GitCommand.STASH);
              h.setNoSSH(true);
              h.addParameters("clear");
              GitHandlerUtil.doSynchronously(
                  h, GitBundle.getString("unstash.clearing.stashes"), h.printableCommandLine());
              refreshStashList();
              updateDialogState();
            }
          }
        });
    myDropButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            final StashInfo stash = getSelectedStash();
            if (Messages.YES
                == Messages.showYesNoDialog(
                    GitUnstashDialog.this.getContentPane(),
                    GitBundle.message(
                        "git.unstash.drop.confirmation.message",
                        stash.getStash(),
                        stash.getMessage()),
                    GitBundle.message("git.unstash.drop.confirmation.title", stash.getStash()),
                    Messages.getQuestionIcon())) {
              final ModalityState current = ModalityState.current();
              ProgressManager.getInstance()
                  .run(
                      new Task.Modal(myProject, "Removing stash " + stash.getStash(), false) {
                        @Override
                        public void run(@NotNull ProgressIndicator indicator) {
                          final GitSimpleHandler h = dropHandler(stash.getStash());
                          try {
                            h.run();
                            h.unsilence();
                          } catch (final VcsException ex) {
                            ApplicationManager.getApplication()
                                .invokeLater(
                                    new Runnable() {
                                      @Override
                                      public void run() {
                                        GitUIUtil.showOperationError(
                                            myProject, ex, h.printableCommandLine());
                                      }
                                    },
                                    current);
                          }
                        }
                      });
              refreshStashList();
              updateDialogState();
            }
          }

          private GitSimpleHandler dropHandler(String stash) {
            GitSimpleHandler h = new GitSimpleHandler(myProject, getGitRoot(), GitCommand.STASH);
            h.setNoSSH(true);
            h.addParameters("drop");
            addStashParameter(h, stash);
            return h;
          }
        });
    myViewButton.addActionListener(
        new ActionListener() {
          public void actionPerformed(final ActionEvent e) {
            final VirtualFile root = getGitRoot();
            String resolvedStash;
            String selectedStash = getSelectedStash().getStash();
            try {
              GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.REV_LIST);
              h.setNoSSH(true);
              h.setSilent(true);
              h.addParameters("--timestamp", "--max-count=1");
              addStashParameter(h, selectedStash);
              h.endOptions();
              final String output = h.run();
              resolvedStash =
                  GitRevisionNumber.parseRevlistOutputAsRevisionNumber(h, output).asString();
            } catch (VcsException ex) {
              GitUIUtil.showOperationError(myProject, ex, "resolving revision");
              return;
            }
            GitShowAllSubmittedFilesAction.showSubmittedFiles(
                myProject, resolvedStash, root, true, false);
          }
        });
    init();
    updateDialogState();
  }