mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Merge branch 'executable_validator'
This commit is contained in:
@@ -1,34 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.intellij.execution.util.ExecutableDialog">
|
||||
<grid id="27dc6" binding="myCenterPanel" layout-manager="GridLayoutManager" row-count="3" column-count="1" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
|
||||
<margin top="0" left="0" bottom="0" right="0"/>
|
||||
<constraints>
|
||||
<xy x="20" y="20" width="564" height="400"/>
|
||||
</constraints>
|
||||
<properties/>
|
||||
<border type="none"/>
|
||||
<children>
|
||||
<component id="2e454" class="com.intellij.openapi.ui.TextFieldWithBrowseButton" binding="myExecutablePath" custom-create="true">
|
||||
<constraints>
|
||||
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="3" hsize-policy="7" anchor="1" fill="1" indent="0" use-parent-layout="false">
|
||||
<preferred-size width="400" height="-1"/>
|
||||
</grid>
|
||||
</constraints>
|
||||
<properties/>
|
||||
</component>
|
||||
<component id="a1421" class="javax.swing.JLabel" binding="myInfoLabel">
|
||||
<constraints>
|
||||
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
<properties>
|
||||
<text value=""/>
|
||||
</properties>
|
||||
</component>
|
||||
<vspacer id="4c273">
|
||||
<constraints>
|
||||
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
|
||||
</constraints>
|
||||
</vspacer>
|
||||
</children>
|
||||
</grid>
|
||||
</form>
|
||||
@@ -1,76 +0,0 @@
|
||||
// Copyright 2008-2010 Victor Iacoban
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software distributed under
|
||||
// the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
|
||||
// either express or implied. See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
package com.intellij.execution.util;
|
||||
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptor;
|
||||
import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.ui.DialogWrapper;
|
||||
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
|
||||
import com.intellij.ui.DocumentAdapter;
|
||||
|
||||
import javax.swing.*;
|
||||
import javax.swing.event.DocumentEvent;
|
||||
|
||||
public class ExecutableDialog extends DialogWrapper {
|
||||
private JPanel myCenterPanel;
|
||||
private TextFieldWithBrowseButton myExecutablePath;
|
||||
private JLabel myInfoLabel;
|
||||
private final ExecutableValidator myExecutableValidator;
|
||||
private String myErrorNotValidText;
|
||||
|
||||
public ExecutableDialog(Project project, ExecutableValidator executableValidator) {
|
||||
super(project, false);
|
||||
myExecutableValidator = executableValidator;
|
||||
myErrorNotValidText = executableValidator.getDialogErrorText();
|
||||
init();
|
||||
updateUI();
|
||||
setTitle(myExecutableValidator.getDialogTitle());
|
||||
myInfoLabel.setText(myExecutableValidator.getDialogDescription());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JComponent createCenterPanel() {
|
||||
return myCenterPanel;
|
||||
}
|
||||
|
||||
// disable OK button if current executable is not valid
|
||||
private void updateUI() {
|
||||
final String path = myExecutablePath.getText();
|
||||
if (myExecutableValidator.isExecutableValid(path)) {
|
||||
setErrorText(null);
|
||||
getOKAction().setEnabled(true);
|
||||
} else {
|
||||
setErrorText(myErrorNotValidText);
|
||||
getOKAction().setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
private void createUIComponents() {
|
||||
myExecutablePath = new TextFieldWithBrowseButton();
|
||||
myExecutablePath.setText(myExecutableValidator.getCurrentExecutable());
|
||||
FileChooserDescriptor descriptor = FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor();
|
||||
myExecutablePath.addBrowseFolderListener(myExecutableValidator.getFileChooserTitle(), myExecutableValidator.getFileChooserDescription(),
|
||||
null, descriptor);
|
||||
myExecutablePath.getTextField().getDocument().addDocumentListener(new DocumentAdapter() {
|
||||
@Override
|
||||
protected void textChanged(DocumentEvent e) {
|
||||
updateUI();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return myExecutablePath.getText();
|
||||
}
|
||||
}
|
||||
@@ -1,229 +0,0 @@
|
||||
/*
|
||||
* Copyright 2000-2010 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution.util;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.notification.Notification;
|
||||
import com.intellij.notification.NotificationListener;
|
||||
import com.intellij.notification.NotificationType;
|
||||
import com.intellij.notification.Notifications;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.util.ui.UIUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
|
||||
/**
|
||||
* Validates the supplied external executable.
|
||||
* Shows notification or a dialog to fix it.
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public abstract class ExecutableValidator {
|
||||
|
||||
private Notification myNotification;
|
||||
protected final Project myProject;
|
||||
private final String myNotificationGroupId;
|
||||
|
||||
private String myNotificationErrorTitle = "Executable not valid";
|
||||
private String myNotificationErrorDescription = "You haven't configured a valid executable. <a href=''>Fix</a>";
|
||||
private String myDialogTitle = "Executable";
|
||||
private String myDialogDescription = "Specify the full path to the executable";
|
||||
private String myDialogErrorText = "It doesn't appear to be a valid executable";
|
||||
private String myFileChooserTitle = "Executable";
|
||||
private String myFileChooserDescription = "Specify the full path to the executable";
|
||||
|
||||
public ExecutableValidator(Project project, String notificationGroupId) {
|
||||
myProject = project;
|
||||
myNotificationGroupId = notificationGroupId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures notification and dialog by setting text messages and titles specific to the whoever uses the validator.
|
||||
* @param notificationErrorTitle title of the notification about not valid executable.
|
||||
* @param notificationErrorDescription description of this notification with a link to fix it (link action is defined by
|
||||
* {@link #notificationHyperlinkUpdate(com.intellij.notification.Notification, javax.swing.event.HyperlinkEvent)}
|
||||
* @param dialogTitle
|
||||
* @param dialogDescription
|
||||
* @param dialogErrorText
|
||||
* @param fileChooserTitle
|
||||
*/
|
||||
public void setMessagesAndTitles(String notificationErrorTitle, String notificationErrorDescription,
|
||||
String dialogTitle, String dialogDescription, String dialogErrorText,
|
||||
String fileChooserTitle, String fileChooserDescription) {
|
||||
myNotificationErrorTitle = notificationErrorTitle;
|
||||
myNotificationErrorDescription = notificationErrorDescription;
|
||||
myDialogTitle = dialogTitle;
|
||||
myDialogDescription = dialogDescription;
|
||||
myDialogErrorText = dialogErrorText;
|
||||
myFileChooserTitle = fileChooserTitle;
|
||||
myFileChooserDescription = fileChooserDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns current executable persisted in the settings or elsewhere.
|
||||
* @return Path to current executable.
|
||||
*/
|
||||
protected abstract String getCurrentExecutable();
|
||||
|
||||
/**
|
||||
* Override this to save new (correct) executable path entered in the dialog.
|
||||
* @param executable
|
||||
*/
|
||||
protected void saveCurrentExecutable(String executable) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the configurable page for the vcs containing settings for executable.
|
||||
* This configurable will be opened if user presses "Fix" on the notification about invalid executable.
|
||||
* May return null - in this case the settings dialog won't be displayed.
|
||||
*/
|
||||
@Nullable
|
||||
protected Configurable getConfigurable(Project project) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the supplied executable is valid.
|
||||
* Default implementation: try to execute the given executable and test if output returned errors.
|
||||
* @param executable Path to executable.
|
||||
* @return true if process with the supplied executable completed without errors and with exit code 0.
|
||||
*/
|
||||
@SuppressWarnings({"MethodMayBeStatic"})
|
||||
public boolean isExecutableValid(String executable) {
|
||||
try {
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine();
|
||||
commandLine.setExePath(executable);
|
||||
CapturingProcessHandler handler = new CapturingProcessHandler(commandLine.createProcess(), CharsetToolkit.getDefaultSystemCharset());
|
||||
ProcessOutput result = handler.runProcess(60 * 1000);
|
||||
return !result.isTimeout() && (result.getExitCode() == 0) && result.getStderr().isEmpty();
|
||||
} catch (Throwable e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean showDialog() {
|
||||
final ExecutableDialog dialog = new ExecutableDialog(myProject, this);
|
||||
UIUtil.invokeAndWaitIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
dialog.show();
|
||||
}
|
||||
});
|
||||
if (dialog.isOK()) {
|
||||
saveCurrentExecutable(dialog.getPath());
|
||||
return true;
|
||||
} else { // user pressed cancel
|
||||
showExecutableNotConfiguredNotification();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean checkExecutableAndShowDialogIfNeeded() {
|
||||
if (!isExecutableValid(getCurrentExecutable())) {
|
||||
return showDialog();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a notification about not configured executable with a link to the Settings to fix it.
|
||||
* Expires the notification if user fixes the path from the opened Settings dialog.
|
||||
* Makes sure that there is always only one notification about the problem in the stack of notifications.
|
||||
*/
|
||||
public void showExecutableNotConfiguredNotification() {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() || ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Notification newNotification = new Notification(myNotificationGroupId, myNotificationErrorTitle,
|
||||
myNotificationErrorDescription, NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
notificationHyperlinkUpdate(notification, event);
|
||||
}
|
||||
});
|
||||
|
||||
// expire() needs to be called from AWT thread.
|
||||
// we also want to be sure that previous notification expires before new one is shown (and assigned to myNotification).
|
||||
UIUtil.invokeLaterIfNeeded(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (myNotification != null && !myNotification.isExpired()) {
|
||||
// don't store this notification twice, but redisplay it again so that popup appears.
|
||||
myNotification.expire();
|
||||
}
|
||||
myNotification = newNotification;
|
||||
Notifications.Bus.notify(myNotification, myProject.isDefault() ? null : myProject);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* The action which will be executed when the user presses "Fix" link in the notification description.
|
||||
* By default it opens the Settings dialog on the page correspondent to the supplied configurable (e.g. Git configurable)
|
||||
* and expires the notification after dialog is closed if executable was fixed in that dialog.
|
||||
* One may override the method.
|
||||
* Parameters are the same as in {@link com.intellij.notification.NotificationListener#hyperlinkUpdate(com.intellij.notification.Notification, javax.swing.event.HyperlinkEvent)}
|
||||
*/
|
||||
protected void notificationHyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
Configurable configurable = getConfigurable(myProject);
|
||||
if (configurable != null) {
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, configurable);
|
||||
if (isExecutableValid(getCurrentExecutable())) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if executable is valid and displays the notification if not.
|
||||
* @return true if executable was valid, false - if not valid (and notification is shown in that case).
|
||||
*/
|
||||
public boolean checkExecutableAndNotifyIfNeeded() {
|
||||
if (!isExecutableValid(getCurrentExecutable())) {
|
||||
showExecutableNotConfiguredNotification();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
String getDialogTitle() {
|
||||
return myDialogTitle;
|
||||
}
|
||||
|
||||
String getDialogErrorText() {
|
||||
return myDialogErrorText;
|
||||
}
|
||||
|
||||
String getFileChooserDescription() {
|
||||
return myFileChooserDescription;
|
||||
}
|
||||
|
||||
String getFileChooserTitle() {
|
||||
return myFileChooserTitle;
|
||||
}
|
||||
|
||||
public String getDialogDescription() {
|
||||
return myDialogDescription;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 2000-2011 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.intellij.execution;
|
||||
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.notification.*;
|
||||
import com.intellij.openapi.application.ApplicationManager;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.options.ShowSettingsUtil;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import com.intellij.openapi.wm.ToolWindowId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import javax.swing.event.HyperlinkEvent;
|
||||
|
||||
/**
|
||||
* Validates the given external executable.
|
||||
* If it is not valid, shows notification to fix it.
|
||||
* Notification balloon in the upper right corner is shown only the first time. After it is shown in the toolwindow group.
|
||||
* This is done, because it is hard to discover whether notification balloon is showing or not, and showing several balloons about a single
|
||||
* problem is a bad idea.
|
||||
*
|
||||
* @author Kirill Likhodedov
|
||||
*/
|
||||
public abstract class ExecutableValidator {
|
||||
|
||||
public static final String NOTIFICATION_ID = "External Executable Critical Failures";
|
||||
private final NotificationGroup myNotificationGroup = new NotificationGroup(NOTIFICATION_ID, NotificationDisplayType.TOOL_WINDOW, true,
|
||||
ToolWindowId.VCS);
|
||||
|
||||
private final Project myProject;
|
||||
private final String myNotificationErrorTitle;
|
||||
private final String myNotificationErrorDescription;
|
||||
|
||||
/**
|
||||
* Configures notification and dialog by setting text messages and titles specific to the whoever uses the validator.
|
||||
* @param notificationErrorTitle title of the notification about not valid executable.
|
||||
* @param notificationErrorDescription description of this notification with a link to fix it (link action is defined by
|
||||
* {@link #showSettingsAndExpireIfFixed(com.intellij.notification.Notification)}
|
||||
*/
|
||||
public ExecutableValidator(Project project, String notificationErrorTitle, String notificationErrorDescription) {
|
||||
myProject = project;
|
||||
myNotificationErrorTitle = notificationErrorTitle;
|
||||
myNotificationErrorDescription = notificationErrorDescription;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return path to current executable.
|
||||
*/
|
||||
protected abstract String getCurrentExecutable();
|
||||
|
||||
/**
|
||||
* @return the settings configurable where the executable is shown and can be fixed.
|
||||
* This configurable will be opened if user presses "Fix" on the notification about invalid executable.
|
||||
*/
|
||||
@NotNull
|
||||
protected abstract Configurable getConfigurable();
|
||||
|
||||
/**
|
||||
* Returns true if the supplied executable is valid.
|
||||
* Default implementation: try to execute the given executable and test if output returned errors.
|
||||
* This can take a long time since it spawns external process.
|
||||
* @param executable Path to executable.
|
||||
* @return true if process with the supplied executable completed without errors and with exit code 0.
|
||||
*/
|
||||
protected boolean isExecutableValid(String executable) {
|
||||
try {
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine();
|
||||
commandLine.setExePath(executable);
|
||||
CapturingProcessHandler handler = new CapturingProcessHandler(commandLine.createProcess(), CharsetToolkit.getDefaultSystemCharset());
|
||||
ProcessOutput result = handler.runProcess(60 * 1000);
|
||||
return !result.isTimeout() && (result.getExitCode() == 0) && result.getStderr().isEmpty();
|
||||
} catch (Throwable e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a notification about not configured executable with a link to the Settings to fix it.
|
||||
* Expires the notification if user fixes the path from the opened Settings dialog.
|
||||
* Makes sure that there is always only one notification about the problem in the stack of notifications.
|
||||
*/
|
||||
private void showExecutableNotConfiguredNotification() {
|
||||
if (ApplicationManager.getApplication().isUnitTestMode() || ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
return;
|
||||
}
|
||||
|
||||
myNotificationGroup.createNotification("", prepareDescription(), NotificationType.ERROR,
|
||||
new NotificationListener() {
|
||||
public void hyperlinkUpdate(@NotNull Notification notification, @NotNull HyperlinkEvent event) {
|
||||
showSettingsAndExpireIfFixed(notification);
|
||||
}
|
||||
}
|
||||
).notify(myProject.isDefault() ? null : myProject);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private String prepareDescription() {
|
||||
String executable = getCurrentExecutable();
|
||||
if (executable.isEmpty()) {
|
||||
return String.format("<b>%s</b>%s", myNotificationErrorTitle, myNotificationErrorDescription);
|
||||
} else {
|
||||
return String.format("<b>%s:</b> <code>%s</code><br/>%s", myNotificationErrorTitle, executable, myNotificationErrorDescription);
|
||||
}
|
||||
}
|
||||
|
||||
private void showSettingsAndExpireIfFixed(@NotNull Notification notification) {
|
||||
Configurable configurable = getConfigurable();
|
||||
ShowSettingsUtil.getInstance().showSettingsDialog(myProject, configurable);
|
||||
if (isExecutableValid(getCurrentExecutable())) {
|
||||
notification.expire();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if executable is valid and displays the notification if not.
|
||||
* @return true if executable was valid, false - if not valid (and notification was shown in that case).
|
||||
*/
|
||||
public boolean checkExecutableAndNotifyIfNeeded() {
|
||||
if (!isExecutableValid(getCurrentExecutable())) {
|
||||
showExecutableNotConfiguredNotification();
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isExecutableValid() {
|
||||
return isExecutableValid(getCurrentExecutable());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -127,12 +127,10 @@ public class EventLog implements Notifications {
|
||||
if (content.startsWith("<") && !content.startsWith("<a ")) {
|
||||
showMore = true;
|
||||
}
|
||||
else {
|
||||
if (StringUtil.isNotEmpty(mainText)) {
|
||||
mainText += ": ";
|
||||
}
|
||||
mainText += content;
|
||||
if (StringUtil.isNotEmpty(mainText)) {
|
||||
mainText += ": ";
|
||||
}
|
||||
mainText += content;
|
||||
}
|
||||
|
||||
int nlIndex = eolIndex(mainText);
|
||||
|
||||
@@ -49,9 +49,9 @@ public class Git {
|
||||
* // TODO use common format
|
||||
*/
|
||||
public static void init(Project project, VirtualFile root) throws VcsException {
|
||||
GitLineHandler h = new GitLineHandler(project, root, GitCommand.INIT);
|
||||
GitSimpleHandler h = new GitSimpleHandler(project, root, GitCommand.INIT);
|
||||
h.setNoSSH(true);
|
||||
GitHandlerUtil.runInCurrentThread(h, null);
|
||||
h.run();
|
||||
if (!h.errors().isEmpty()) {
|
||||
throw h.errors().get(0);
|
||||
}
|
||||
|
||||
@@ -128,10 +128,10 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
private final GitCommitAndPushExecutor myCommitAndPushExecutor;
|
||||
private GitReferenceTracker myReferenceTracker;
|
||||
private boolean isActivated; // If true, the vcs was activated
|
||||
private GitExecutableValidator myExecutableValidator;
|
||||
private final GitExecutableValidator myExecutableValidator;
|
||||
private GitBranchWidget myBranchWidget;
|
||||
|
||||
private GitVersion myVersion; // version of Git which this plugin uses.
|
||||
private GitVersion myVersion = GitVersion.NULL; // version of Git which this plugin uses.
|
||||
|
||||
@Nullable
|
||||
public static GitVcs getInstance(Project project) {
|
||||
@@ -169,6 +169,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
myCommitAndPushExecutor = new GitCommitAndPushExecutor(myCheckinEnvironment);
|
||||
myReferenceTracker = new GitReferenceTracker(myProject, this, myReferenceListeners.getMulticaster());
|
||||
myTaskQueue = new BackgroundTaskQueue(myProject, GitBundle.getString("task.queue.title"));
|
||||
myExecutableValidator = new GitExecutableValidator(myProject, this);
|
||||
}
|
||||
|
||||
|
||||
@@ -345,11 +346,11 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
@Override
|
||||
protected void activate() {
|
||||
isActivated = true;
|
||||
myExecutableValidator = new GitExecutableValidator(myProject);
|
||||
|
||||
if (!ApplicationManager.getApplication().isHeadlessEnvironment()) {
|
||||
myExecutableValidator.checkExecutableAndShowDialogIfNeeded();
|
||||
checkVersion();
|
||||
if (myExecutableValidator.checkExecutableAndNotifyIfNeeded()) {
|
||||
checkVersion();
|
||||
}
|
||||
}
|
||||
|
||||
if (!myProject.isDefault() && myRootTracker == null) {
|
||||
@@ -483,23 +484,22 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
VcsBalloonProblemNotifier.showOverVersionControlView(myProject, message, MessageType.ERROR);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
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());
|
||||
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);
|
||||
}
|
||||
VcsBalloonProblemNotifier.showOverVersionControlView(myProject, message, MessageType.ERROR);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version number of Git, which is used by IDEA. <code>null</code> can be returned if the GitVcs hasn't yet activated.
|
||||
* @return the version number of Git, which is used by IDEA. Or {@link GitVersion#NULL} if version info is unavailable yet.
|
||||
*/
|
||||
@Nullable
|
||||
@NotNull
|
||||
public GitVersion getVersion() {
|
||||
if (myVersion == null) {
|
||||
checkVersion();
|
||||
}
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
@@ -590,6 +590,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
|
||||
return isActivated;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public GitExecutableValidator getExecutableValidator() {
|
||||
return myExecutableValidator;
|
||||
}
|
||||
|
||||
@@ -74,10 +74,13 @@ public class GitInit extends DumbAwareAction {
|
||||
}
|
||||
}
|
||||
|
||||
GitVcs vcs = GitVcs.getInstance(project);
|
||||
try {
|
||||
Git.init(project, root);
|
||||
} catch (VcsException ex) {
|
||||
GitUIUtil.showOperationErrors(project, Collections.singleton(ex), "git init");
|
||||
if (vcs == null || vcs.getExecutableValidator().isExecutableValid()) {
|
||||
GitUIUtil.showOperationErrors(project, Collections.singleton(ex), "git init");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -89,8 +92,7 @@ public class GitInit extends DumbAwareAction {
|
||||
}
|
||||
final String path = root.equals(baseDir) ? "" : root.getPath();
|
||||
final Project finalProject = project;
|
||||
GitVcs.getInstance(project).runInBackground(new Task.Backgroundable(finalProject, GitBundle.getString("common.refreshing")) {
|
||||
|
||||
GitVcs.runInBackground(new Task.Backgroundable(finalProject, GitBundle.getString("common.refreshing")) {
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
refreshAndConfigureVcsMappings(finalProject, root, path);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.openapi.progress.ProgressIndicator;
|
||||
import com.intellij.openapi.progress.Task;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.io.FileUtil;
|
||||
import com.intellij.openapi.vcs.CheckoutProvider;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
|
||||
@@ -26,6 +27,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.vcsUtil.VcsUtil;
|
||||
import git4idea.Git;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.actions.BasicAction;
|
||||
import git4idea.commands.GitCommand;
|
||||
import git4idea.commands.GitSimpleHandler;
|
||||
@@ -102,15 +104,27 @@ public class GitCheckoutProvider implements CheckoutProvider {
|
||||
}
|
||||
|
||||
private static boolean doClone(ProgressIndicator indicator, Project project, String directoryName, String parentDirectory, String sourceRepositoryURL) {
|
||||
final VirtualFile root = mkdir(project, directoryName, parentDirectory);
|
||||
if (root == null) { return false; }
|
||||
if (!init(project, root)) { return false; }
|
||||
if (!addRemote(project, root, sourceRepositoryURL)) { return false; }
|
||||
if (!fetch(project, root, indicator)) { return false; }
|
||||
return checkout(project, root);
|
||||
File dir = mkdir(project, directoryName, parentDirectory);
|
||||
if (dir == null) {
|
||||
return false;
|
||||
}
|
||||
VirtualFile root = VcsUtil.getVirtualFileWithRefresh(dir);
|
||||
if (root != null &&
|
||||
init(project, root) &&
|
||||
addRemote(project, root, sourceRepositoryURL) &&
|
||||
fetch(project, root, indicator) &&
|
||||
checkout(project, root)) {
|
||||
return true;
|
||||
}
|
||||
cleanup(dir);
|
||||
return false;
|
||||
}
|
||||
|
||||
private static @Nullable VirtualFile mkdir(Project project, String directoryName, String parentDirectory) {
|
||||
private static void cleanup(@NotNull File dir) {
|
||||
FileUtil.delete(dir);
|
||||
}
|
||||
|
||||
private static @Nullable File mkdir(Project project, String directoryName, String parentDirectory) {
|
||||
final File dir = new File(parentDirectory, directoryName);
|
||||
if (dir.exists()) {
|
||||
GitUIUtil.notifyError(project, "Couldn't clone", "Directory <code>" + dir + "</code> already exists.");
|
||||
@@ -120,8 +134,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
|
||||
GitUIUtil.notifyError(project, "Couldn't clone", "Can't create directory <code>" + dir + "</code>");
|
||||
return null;
|
||||
}
|
||||
|
||||
return VcsUtil.getVirtualFileWithRefresh(dir);
|
||||
return dir;
|
||||
}
|
||||
|
||||
private static boolean init(Project project, VirtualFile root) {
|
||||
@@ -129,7 +142,10 @@ public class GitCheckoutProvider implements CheckoutProvider {
|
||||
Git.init(project, root);
|
||||
} catch (VcsException e) {
|
||||
LOG.info("init ", e);
|
||||
GitUIUtil.notifyError(project, "Couldn't clone", "Couldn't <code>git init</code> in <code>" + root.getPresentableUrl() + "</code>", true, e);
|
||||
GitVcs vcs = GitVcs.getInstance(project);
|
||||
if (vcs == null || vcs.getExecutableValidator().isExecutableValid()) { // invalid executable will be notified in GitHandler.start()
|
||||
GitUIUtil.notifyError(project, "Couldn't clone", "Couldn't <code>git init</code> in <code>" + root.getPresentableUrl() + "</code>", true, e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -325,19 +325,4 @@ public class GitCloneDialog extends DialogWrapper {
|
||||
return "reference.VersionControl.Git.CloneRepository";
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare check repository handler. To do this ls-remote command is executed and attempts to match
|
||||
* master tag. This will likely return only single entry or none, if there is no master
|
||||
* branch. Stdout output is ignored. Stderr is used to construct exception message and shown
|
||||
* in error message box if exit is negative.
|
||||
*
|
||||
* @param project the project
|
||||
* @param url the url to check
|
||||
* @return a simple handler that does the task
|
||||
*/
|
||||
private static GitSimpleHandler checkRepository(Project project, final String url) {
|
||||
GitSimpleHandler handler = new GitSimpleHandler(project, new File("."), GitCommand.LS_REMOTE);
|
||||
handler.addParameters(url, "master");
|
||||
return handler;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -412,6 +412,7 @@ public abstract class GitHandler {
|
||||
startHandlingStreams();
|
||||
}
|
||||
catch (Throwable t) {
|
||||
myVcs.getExecutableValidator().checkExecutableAndNotifyIfNeeded();
|
||||
cleanupEnv();
|
||||
myListeners.getMulticaster().startFailed(t);
|
||||
}
|
||||
|
||||
@@ -15,16 +15,18 @@
|
||||
*/
|
||||
package git4idea.config;
|
||||
|
||||
import com.intellij.execution.ExecutableValidator;
|
||||
import com.intellij.execution.configurations.GeneralCommandLine;
|
||||
import com.intellij.execution.process.CapturingProcessHandler;
|
||||
import com.intellij.execution.process.ProcessOutput;
|
||||
import com.intellij.execution.util.ExecutableValidator;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.vcs.VcsException;
|
||||
import com.intellij.openapi.vfs.CharsetToolkit;
|
||||
import git4idea.GitVcs;
|
||||
import git4idea.i18n.GitBundle;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
/**
|
||||
* Project service that is used to check whether currently set git executable is valid (just calls 'git version' and parses the output),
|
||||
@@ -35,30 +37,25 @@ public class GitExecutableValidator extends ExecutableValidator {
|
||||
|
||||
private GitVcs myVcs;
|
||||
|
||||
public GitExecutableValidator(Project project) {
|
||||
super(project, GitVcs.NOTIFICATION_GROUP_ID.getDisplayId());
|
||||
myVcs = GitVcs.getInstance(project);
|
||||
setMessagesAndTitles(GitBundle.message("git.executable.notification.title"),
|
||||
GitBundle.message("git.executable.notification.description"),
|
||||
GitBundle.message("git.executable.dialog.title"),
|
||||
GitBundle.message("git.executable.dialog.description"),
|
||||
GitBundle.message("git.executable.dialog.error"),
|
||||
GitBundle.message("git.executable.filechooser.title"),
|
||||
GitBundle.message("git.executable.filechooser.description"));
|
||||
public GitExecutableValidator(@NotNull Project project, @Nullable GitVcs vcs) {
|
||||
super(project,
|
||||
GitBundle.message("git.executable.notification.title"), GitBundle.message("git.executable.notification.description"));
|
||||
myVcs = vcs;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCurrentExecutable() {
|
||||
return myVcs.getAppSettings().getPathToGit();
|
||||
return GitVcsApplicationSettings.getInstance().getPathToGit();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Configurable getConfigurable() {
|
||||
return myVcs.getConfigurable();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Configurable getConfigurable(Project project) {
|
||||
return myVcs == null ? null : myVcs.getConfigurable();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isExecutableValid(String executable) {
|
||||
public boolean isExecutableValid(@NotNull String executable) {
|
||||
try {
|
||||
GeneralCommandLine commandLine = new GeneralCommandLine();
|
||||
commandLine.setExePath(executable);
|
||||
@@ -71,12 +68,6 @@ public class GitExecutableValidator extends ExecutableValidator {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveCurrentExecutable(String executable) {
|
||||
myVcs.getAppSettings().setPathToGit(executable);
|
||||
myVcs.checkVersion();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if git executable is valid. If not (which is a common case for low-level vcs exceptions), shows the
|
||||
* notification. Otherwise throws the exception.
|
||||
|
||||
@@ -21,7 +21,7 @@ import com.intellij.openapi.components.State;
|
||||
import com.intellij.openapi.components.Storage;
|
||||
import com.intellij.openapi.util.SystemInfo;
|
||||
import org.jetbrains.annotations.NonNls;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
@@ -60,6 +60,7 @@ public class GitVcsApplicationSettings implements PersistentStateComponent<GitVc
|
||||
/**
|
||||
* @return the default executable name depending on the platform
|
||||
*/
|
||||
@NotNull
|
||||
public String defaultGit() {
|
||||
if (myState.myPathToGit == null) {
|
||||
String[] paths;
|
||||
@@ -86,7 +87,7 @@ public class GitVcsApplicationSettings implements PersistentStateComponent<GitVc
|
||||
return myState.myPathToGit;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@NotNull
|
||||
public String getPathToGit() {
|
||||
return myState.myPathToGit == null ? defaultGit() : myState.myPathToGit;
|
||||
}
|
||||
|
||||
@@ -45,7 +45,13 @@ public final class GitVersion implements Comparable<GitVersion> {
|
||||
* Type UNDEFINED means that the type doesn't matter in certain condition.
|
||||
*/
|
||||
public static enum Type {
|
||||
UNDEFINED, UNIX, MSYS, CYGWIN
|
||||
UNIX,
|
||||
MSYS,
|
||||
CYGWIN,
|
||||
/** The type doesn't matter or couldn't be detected. */
|
||||
UNDEFINED,
|
||||
/** Information about Git version is unavailable because the GitVcs hasn't fully initialized yet, or because Git executable is invalid. */
|
||||
NULL
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -53,13 +59,19 @@ public final class GitVersion implements Comparable<GitVersion> {
|
||||
*/
|
||||
public static final GitVersion MIN = new GitVersion(1, 6, 0, 0);
|
||||
|
||||
/**
|
||||
* Special version with a special Type which indicates, that Git version information is unavailable.
|
||||
* Probably, because of invalid executable, or when GitVcs hasn't fully initialized yet.
|
||||
*/
|
||||
public static final GitVersion NULL = new GitVersion(0, 0, 0, 0, Type.NULL);
|
||||
|
||||
private static final Pattern FORMAT = Pattern.compile("git version (\\d+)\\.(\\d+)\\.(\\d+)(?:\\.(\\d+))?(?:\\.(msysgit))?[\\.\\-\\d\\w]*", Pattern.CASE_INSENSITIVE);
|
||||
private static final Logger LOG = Logger.getInstance(GitVersion.class.getName());
|
||||
|
||||
private final int myMajor; // Major version number
|
||||
private final int myMinor; // Minor version number
|
||||
private final int myRevision; // Revision number
|
||||
private final int myPatchLevel; // Patch level
|
||||
private final int myMajor;
|
||||
private final int myMinor;
|
||||
private final int myRevision;
|
||||
private final int myPatchLevel;
|
||||
private final Type myType;
|
||||
|
||||
private final int myHashCode;
|
||||
@@ -145,7 +157,7 @@ public final class GitVersion implements Comparable<GitVersion> {
|
||||
* @return true if the version is supported by the plugin
|
||||
*/
|
||||
public boolean isSupported() {
|
||||
return compareTo(MIN) >= 0;
|
||||
return getType() != Type.NULL && compareTo(MIN) >= 0;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -183,8 +195,13 @@ public final class GitVersion implements Comparable<GitVersion> {
|
||||
* (msys git 1.7.3).compareTo(cygwin git 1.7.3) == 0
|
||||
* BUT
|
||||
* (msys git 1.7.3).equals(cygwin git 1.7.3) == false
|
||||
*
|
||||
* {@link GitVersion#NULL} is less than any other not-NULL version.
|
||||
*/
|
||||
public int compareTo(final GitVersion o) {
|
||||
public int compareTo(@NotNull GitVersion o) {
|
||||
if (o.getType() == Type.NULL) {
|
||||
return (getType() == Type.NULL ? 0 : 1);
|
||||
}
|
||||
int d = myMajor - o.myMajor;
|
||||
if (d != 0) {
|
||||
return d;
|
||||
@@ -224,4 +241,8 @@ public final class GitVersion implements Comparable<GitVersion> {
|
||||
return myType;
|
||||
}
|
||||
|
||||
public boolean isNull() {
|
||||
return getType() == Type.NULL;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -183,17 +183,21 @@ public class GitHistoryProvider implements VcsHistoryProvider, VcsCacheableHisto
|
||||
final VcsAbstractHistorySession emptySession = createSession(path, Collections.<VcsFileRevision>emptyList(), null);
|
||||
partner.reportCreatedEmptySession(emptySession);
|
||||
final GitExecutableValidator validator = GitVcs.getInstance(myProject).getExecutableValidator();
|
||||
GitHistoryUtils.history(myProject, path, null, new Consumer<GitFileRevision>() {
|
||||
public void consume(GitFileRevision gitFileRevision) {
|
||||
partner.acceptRevision(gitFileRevision);
|
||||
}
|
||||
}, new Consumer<VcsException>() {
|
||||
public void consume(VcsException e) {
|
||||
if (validator.checkExecutableAndNotifyIfNeeded()) {
|
||||
partner.reportException(e);
|
||||
try {
|
||||
GitHistoryUtils.history(myProject, path, null, new Consumer<GitFileRevision>() {
|
||||
public void consume(GitFileRevision gitFileRevision) {
|
||||
partner.acceptRevision(gitFileRevision);
|
||||
}
|
||||
}
|
||||
});
|
||||
}, new Consumer<VcsException>() {
|
||||
public void consume(VcsException e) {
|
||||
if (validator.checkExecutableAndNotifyIfNeeded()) {
|
||||
partner.reportException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (VcsException e) {
|
||||
validator.showNotificationOrThrow(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+2
-6
@@ -233,7 +233,7 @@ public class SelectRepositoryAndShowLogAction extends AnAction {
|
||||
|
||||
@Override
|
||||
public void onSuccess() {
|
||||
if (myVersion.myVersion == null) return;
|
||||
if (myVersion.myVersion.isNull()) return;
|
||||
if (myProject.isDisposed()) return;
|
||||
new MyDialog(myProject, myCorrectRoots).show();
|
||||
}
|
||||
@@ -249,12 +249,8 @@ public class SelectRepositoryAndShowLogAction extends AnAction {
|
||||
@Override
|
||||
public void run(@NotNull ProgressIndicator indicator) {
|
||||
GitVcs vcs = GitVcs.getInstance(myProject);
|
||||
if (vcs == null) { return; }
|
||||
myVersion = vcs.getVersion();
|
||||
if (myVersion == null) {
|
||||
vcs.checkVersion();
|
||||
}
|
||||
myVersion = vcs.getVersion();
|
||||
if (myVersion == null) return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -495,8 +495,8 @@ executable.error.description = Git couldn't be started. Probably the path to Git
|
||||
git.commit.message.empty=Please specify commit message
|
||||
git.commit.message.empty.title=Commit message is empty
|
||||
|
||||
git.executable.notification.title=Git executable problem
|
||||
git.executable.notification.description=Git couldn't be started. Probably the path to Git executable is not valid. <a href="">Fix it.</a>
|
||||
git.executable.notification.title=Can't start Git
|
||||
git.executable.notification.description=Probably the path to Git executable is not valid. <a href=''>Fix it.</a>
|
||||
git.executable.dialog.title=Git executable
|
||||
git.executable.dialog.description=Specify the full path to Git executable
|
||||
git.executable.dialog.error=It doesn't appear to be a valid Git executable
|
||||
|
||||
@@ -112,9 +112,6 @@ public class GitChangeProvider implements ChangeProvider {
|
||||
return false;
|
||||
}
|
||||
final GitVersion version = vcs.getVersion();
|
||||
if (version == null) {
|
||||
return false;
|
||||
}
|
||||
return GitVersionSpecialty.KNOWS_STATUS_PORCELAIN.existsIn(version);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,7 +66,7 @@ public class GitUIUtil {
|
||||
desc += "<hr/>" + StringUtil.join(messages, "<br/>");
|
||||
}
|
||||
NotificationGroup group = important ? GitVcs.IMPORTANT_ERROR_NOTIFICATION : GitVcs.NOTIFICATION_GROUP_ID;
|
||||
group.createNotification(title, desc, type, null).notify(project);
|
||||
group.createNotification(title, desc, type, null).notify(project.isDefault() ? null : project);
|
||||
}
|
||||
|
||||
public static void notifyMessage(Project project, @Nullable String title, @Nullable String description, NotificationType type, boolean important, @Nullable Collection<VcsException> errors) {
|
||||
|
||||
@@ -55,13 +55,8 @@ hg4idea.commit.partial.merge.message=<html>Partial commits are not allowed durin
|
||||
hg4idea.commit.partial.merge.title=Partial Merge Commit
|
||||
hg4idea.commit.error.messageEmpty=Please provide a commit message
|
||||
|
||||
hg4idea.executable.notification.title=Mercurial executable is not valid
|
||||
hg4idea.executable.notification.description=You haven't configured a valid executable. Mercurial integration won't work. <a href=''>Fix</a>
|
||||
hg4idea.executable.dialog.title=Mercurial executable
|
||||
hg4idea.executable.dialog.description=Specify the full path to hg executable
|
||||
hg4idea.executable.dialog.error=It doesn't appear to be a valid hg executable
|
||||
hg4idea.executable.filechooser.title=Mercurial executable
|
||||
hg4idea.executable.filechooser.description=Specify the full path to hg executable
|
||||
hg4idea.executable.notification.title=Can't start Mercurial
|
||||
hg4idea.executable.notification.description=Probably the path to hg executable is not valid. <a href=''>Fix it.</a>
|
||||
|
||||
hg4idea.init.dialog.title=Create Mercurial repository
|
||||
hg4idea.init.dialog.incorrect.path=The specified path is incorrect
|
||||
|
||||
@@ -12,25 +12,21 @@
|
||||
// limitations under the License.
|
||||
package org.zmlx.hg4idea;
|
||||
|
||||
import com.intellij.execution.util.ExecutableValidator;
|
||||
import com.intellij.execution.ExecutableValidator;
|
||||
import com.intellij.openapi.options.Configurable;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.zmlx.hg4idea.command.HgVersionCommand;
|
||||
|
||||
public class HgExecutableValidator extends ExecutableValidator {
|
||||
|
||||
private final HgVcs myVcs;
|
||||
|
||||
public HgExecutableValidator(Project project) {
|
||||
super(project, HgVcs.NOTIFICATION_GROUP_ID);
|
||||
myVcs = HgVcs.getInstance(project);
|
||||
setMessagesAndTitles(HgVcsMessages.message("hg4idea.executable.notification.title"),
|
||||
HgVcsMessages.message("hg4idea.executable.notification.description"),
|
||||
HgVcsMessages.message("hg4idea.executable.dialog.title"),
|
||||
HgVcsMessages.message("hg4idea.executable.dialog.description"),
|
||||
HgVcsMessages.message("hg4idea.executable.dialog.error"),
|
||||
HgVcsMessages.message("hg4idea.executable.filechooser.title"),
|
||||
HgVcsMessages.message("hg4idea.executable.filechooser.description"));
|
||||
public HgExecutableValidator(@NotNull Project project, @NotNull HgVcs vcs) {
|
||||
super(project,
|
||||
HgVcsMessages.message("hg4idea.executable.notification.title"),
|
||||
HgVcsMessages.message("hg4idea.executable.notification.description"));
|
||||
myVcs = vcs;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -38,9 +34,10 @@ public class HgExecutableValidator extends ExecutableValidator {
|
||||
return myVcs.getHgExecutable();
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
protected Configurable getConfigurable(Project project) {
|
||||
return myVcs == null ? null : myVcs.getConfigurable();
|
||||
protected Configurable getConfigurable() {
|
||||
return myVcs.getConfigurable();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -48,9 +45,4 @@ public class HgExecutableValidator extends ExecutableValidator {
|
||||
return new HgVersionCommand().isValid(executable, myVcs.getGlobalSettings().isRunViaBash());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveCurrentExecutable(String executable) {
|
||||
myVcs.getGlobalSettings().setHgExecutable(executable);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -260,7 +260,7 @@ public class HgVcs extends AbstractVcs<CommittedChangeList> {
|
||||
public void activate() {
|
||||
// validate hg executable on start
|
||||
if (!ApplicationManager.getApplication().isUnitTestMode()) {
|
||||
getExecutableValidator().checkExecutableAndShowDialogIfNeeded();
|
||||
getExecutableValidator().checkExecutableAndNotifyIfNeeded();
|
||||
}
|
||||
|
||||
// status bar
|
||||
@@ -372,7 +372,7 @@ public class HgVcs extends AbstractVcs<CommittedChangeList> {
|
||||
public HgExecutableValidator getExecutableValidator() {
|
||||
synchronized (myExecutableValidatorLock) {
|
||||
if (myExecutableValidator == null) {
|
||||
myExecutableValidator = new HgExecutableValidator(myProject);
|
||||
myExecutableValidator = new HgExecutableValidator(myProject, this);
|
||||
}
|
||||
return myExecutableValidator;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user