Commit 79e57376 authored by Kirill Likhodedov's avatar Kirill Likhodedov
Browse files

GitVersion: checking for version only on plugin activation and when changing...

GitVersion: checking for version only on plugin activation and when changing the executable. Identifying current version by using a direct CapturingProcessHandler without going into GitHandler procedure.
parent 3b6a1bf0
Showing with 71 additions and 106 deletions
+71 -106
......@@ -57,8 +57,6 @@ import git4idea.changes.GitOutgoingChangesProvider;
import git4idea.checkin.GitCheckinEnvironment;
import git4idea.checkin.GitCheckinHandlerFactory;
import git4idea.checkin.GitCommitAndPushExecutor;
import git4idea.commands.GitCommand;
import git4idea.commands.GitSimpleHandler;
import git4idea.config.*;
import git4idea.diff.GitDiffProvider;
import git4idea.diff.GitTreeDiffProvider;
......@@ -73,7 +71,6 @@ import git4idea.vfs.*;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Collections;
import java.util.Date;
......@@ -108,9 +105,6 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
private final GitCommittedChangeListProvider myCommittedChangeListProvider;
private GitVFSListener myVFSListener; // a VFS listener that tracks file addition, deletion, and renaming.
@SuppressWarnings({"FieldAccessedSynchronizedAndUnsynchronized"}) private GitVersion myVersion; // The currently detected git version or null.
private final Object myCheckingVersion = new Object(); // Checking the version lock (used to prevent infinite recursion)
private String myVersionCheckExcecutable = ""; // The path to executable at the time of version check
private GitRootTracker myRootTracker; // The tracker that checks validity of git roots
private final EventDispatcher<GitRootsListener> myRootListeners = EventDispatcher.create(GitRootsListener.class);
......@@ -128,6 +122,8 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
private RepositoryChangeListener myIndexChangeListener;
private GitBranchWidget myBranchWidget;
private GitVersion myVersion; // version of Git which this plugin uses.
@Nullable
public static GitVcs getInstance(Project project) {
if (project == null || project.isDisposed()) {
......@@ -340,6 +336,7 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
isActivated = true;
myExecutableValidator = new GitExecutableValidator(myProject);
myExecutableValidator.checkExecutableAndShowDialogIfNeeded();
checkVersion();
if (!myProject.isDefault() && myRootTracker == null) {
myRootTracker = new GitRootTracker(this, myProject, myRootListeners.getMulticaster());
}
......@@ -456,60 +453,30 @@ public class GitVcs extends AbstractVcs<CommittedChangeList> {
}
/**
* Check version and report problem
* Checks Git version and updates the myVersion variable. In the case of exception or unsupported version reports the problem.
*/
public void checkVersion() {
final String executable = myAppSettings.getPathToGit();
synchronized (myCheckingVersion) {
if (myVersion != null && myVersionCheckExcecutable.equals(executable)) {
return;
}
myVersionCheckExcecutable = executable;
// this assignment is done to prevent recursive version check
myVersion = GitVersion.INVALID;
final String version;
try {
version = version(myProject).trim();
}
catch (VcsException e) {
String reason = (e.getCause() != null ? e.getCause() : e).getMessage();
if (!myProject.isDefault()) {
showMessage(GitBundle.message("vcs.unable.to.run.git", executable, reason), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
}
return;
}
myVersion = GitVersion.parse(version);
if (!GitVersion.parse(version).isSupported() && !myProject.isDefault()) {
try {
final GitVersion version = GitVersion.identifyVersion(executable);
if (!version.isSupported() && !myProject.isDefault()) {
showMessage(GitBundle.message("vcs.unsupported.version", version, GitVersion.MIN),
ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
} else {
myVersion = version;
}
} catch (Exception e) {
final String reason = (e.getCause() != null ? e.getCause() : e).getMessage();
if (!myProject.isDefault()) {
showMessage(GitBundle.message("vcs.unable.to.run.git", executable, reason), ConsoleViewContentType.SYSTEM_OUTPUT.getAttributes());
}
}
}
/**
* @return the configured version of git
*/
public GitVersion version() {
checkVersion();
public GitVersion getVersion() {
return myVersion;
}
/**
* Get the version of configured git
*
* @param project the project
* @return a version of configured git
* @throws VcsException an error if there is a problem with running git
*/
public static String version(Project project) throws VcsException {
final String s;
GitSimpleHandler h = new GitSimpleHandler(project, new File("."), GitCommand.VERSION);
h.setNoSSH(true);
h.setSilent(true);
s = h.run();
return s;
}
/**
* Shows a command line message in the Version Control Console
*/
......
......@@ -23,11 +23,7 @@ import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VirtualFile;
import git4idea.GitVcs;
import git4idea.actions.BasicAction;
import git4idea.commands.GitCommand;
import git4idea.commands.GitHandlerUtil;
import git4idea.commands.GitLineHandler;
import git4idea.commands.GitTask;
import git4idea.commands.GitTaskResult;
import git4idea.commands.*;
import git4idea.config.GitVersion;
import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
......@@ -115,7 +111,7 @@ public class GitCheckoutProvider implements CheckoutProvider {
*/
public static GitLineHandler clone(Project project, final String url, final File directory, final String name, final String originName) {
GitLineHandler handler = new GitLineHandler(project, directory, GitCommand.CLONE);
if (VERBOSE_CLONE_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).version())) {
if (VERBOSE_CLONE_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).getVersion())) {
handler.addParameters("-v");
}
if (originName != null && originName.length() > 0) {
......
......@@ -40,14 +40,7 @@ import org.jetbrains.git4idea.ssh.GitSSHService;
import java.io.File;
import java.io.OutputStream;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
import java.util.concurrent.LinkedBlockingQueue;
/**
......@@ -120,9 +113,6 @@ public abstract class GitHandler {
}
}
myVcs = GitVcs.getInstance(project);
if (myVcs != null) {
myVcs.checkVersion();
}
myWorkingDirectory = directory;
myCommandLine = new GeneralCommandLine();
if (myAppSettings != null) {
......
......@@ -20,7 +20,6 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptor;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.vcs.VcsException;
import git4idea.GitVcs;
import git4idea.i18n.GitBundle;
import org.jetbrains.annotations.NotNull;
......@@ -46,6 +45,7 @@ public class GitVcsPanel {
private static final String NATIVE_SSH = GitBundle.getString("git.vcs.config.ssh.mode.native"); // Native SSH value
private static final String CRLF_CONVERT_TO_PROJECT = GitBundle.getString("git.vcs.config.convert.project");
private static final String CRLF_DO_NOT_CONVERT = GitBundle.getString("git.vcs.config.convert.do.not.convert");
private GitVcs myVcs;
/**
* The constructor
......@@ -53,6 +53,7 @@ public class GitVcsPanel {
* @param project the context project
*/
public GitVcsPanel(@NotNull Project project) {
myVcs = GitVcs.getInstance(project);
myAppSettings = GitVcsApplicationSettings.getInstance();
myProjectSettings = GitVcsSettings.getInstance(project);
myProject = project;
......@@ -78,22 +79,22 @@ public class GitVcsPanel {
* Test availability of the connection
*/
private void testConnection() {
final String executable = myGitField.getText();
if (myAppSettings != null) {
myAppSettings.setPathToGit(myGitField.getText());
myAppSettings.setPathToGit(executable);
}
final String s;
final GitVersion version;
try {
s = GitVcs.version(myProject);
}
catch (VcsException e) {
version = GitVersion.identifyVersion(executable);
} catch (Exception e) {
Messages.showErrorDialog(myProject, e.getMessage(), GitBundle.getString("find.git.error.title"));
return;
}
if (GitVersion.parse(s).isSupported()) {
Messages.showInfoMessage(myProject, s, GitBundle.getString("find.git.success.title"));
}
else {
Messages.showWarningDialog(myProject, GitBundle.message("find.git.unsupported.message", s, GitVersion.MIN),
if (version.isSupported()) {
Messages.showInfoMessage(myProject, version.toString(), GitBundle.getString("find.git.success.title"));
} else {
Messages.showWarningDialog(myProject, GitBundle.message("find.git.unsupported.message", version.toString(), GitVersion.MIN),
GitBundle.getString("find.git.success.title"));
}
}
......@@ -158,6 +159,7 @@ public class GitVcsPanel {
*/
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;
......
......@@ -15,10 +15,18 @@
*/
package git4idea.config;
import com.intellij.execution.ExecutionException;
import com.intellij.execution.configurations.GeneralCommandLine;
import com.intellij.execution.process.CapturingProcessHandler;
import com.intellij.execution.process.ProcessOutput;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.SystemInfo;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import org.apache.commons.lang.builder.HashCodeBuilder;
import java.text.ParseException;
import java.util.concurrent.TimeoutException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
......@@ -77,13 +85,13 @@ public final class GitVersion implements Comparable<GitVersion> {
/**
* Parses output of "git version" command.
*/
public static GitVersion parse(String output) {
if (output == null || output.isEmpty()) {
throw new IllegalArgumentException("Empty git --version output: " + output);
public static GitVersion parse(String output) throws ParseException {
if (StringUtil.isEmptyOrSpaces(output)) {
throw new ParseException("Empty git --version output: " + output, 0);
}
Matcher m = FORMAT.matcher(output.trim());
if (!m.matches()) {
throw new IllegalArgumentException("Unsupported format of git --version output: " + output);
throw new ParseException("Unsupported format of git --version output: " + output, 0);
}
int major = getIntGroup(m, 1);
int minor = getIntGroup(m, 2);
......@@ -112,6 +120,27 @@ public final class GitVersion implements Comparable<GitVersion> {
return Integer.parseInt(match);
}
public static GitVersion identifyVersion(String gitExecutable) throws TimeoutException, ExecutionException, ParseException {
GeneralCommandLine commandLine = new GeneralCommandLine();
commandLine.setExePath(gitExecutable);
commandLine.addParameter("--version");
CapturingProcessHandler handler = new CapturingProcessHandler(commandLine.createProcess(), CharsetToolkit.getDefaultSystemCharset());
ProcessOutput result = handler.runProcess(30 * 1000);
if (result.isTimeout()) {
throw new TimeoutException("Coulnd't identify the version of Git - stopped by timeout.");
}
if (result.getExitCode() != 0 || !result.getStderr().isEmpty()) {
LOG.info("getVersion exitCode=" + result.getExitCode() + " errors: " + result.getStderr());
// anyway trying to parse
try {
parse(result.getStdout());
} catch (ParseException pe) {
throw new ExecutionException("Errors while executing git --version. exitCode=" + result.getExitCode() + " errors: " + result.getStderr());
}
}
return parse(result.getStdout());
}
/**
* @return true if the version is supported by the plugin
*/
......
......@@ -24,11 +24,7 @@ import com.intellij.openapi.vcs.changes.Change;
import com.intellij.openapi.vfs.LocalFileSystem;
import com.intellij.openapi.vfs.VfsUtil;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.ui.CheckboxTree;
import com.intellij.ui.CheckboxTreeBase;
import com.intellij.ui.CheckedTreeNode;
import com.intellij.ui.ColoredTreeCellRenderer;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.ui.*;
import com.intellij.util.Processor;
import com.intellij.util.containers.HashMap;
import com.intellij.util.ui.UIUtil;
......@@ -42,25 +38,14 @@ import git4idea.config.GitVcsSettings;
import git4idea.config.GitVersion;
import git4idea.i18n.GitBundle;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.Icon;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JPanel;
import javax.swing.JTree;
import java.awt.Color;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.*;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
* This dialog allows converting the specified files before committing them.
......@@ -271,7 +256,7 @@ public class GitConvertFilesDialog extends DialogWrapper {
* @throws VcsException if there is problem with running git
*/
private static void ignoreFilesWithCrlfUnset(Project project, Map<VirtualFile, Set<VirtualFile>> files) throws VcsException {
boolean stdin = CHECK_ATTR_STDIN_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).version());
boolean stdin = CHECK_ATTR_STDIN_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).getVersion());
stdin = false;
for (final Map.Entry<VirtualFile, Set<VirtualFile>> e : files.entrySet()) {
final VirtualFile r = e.getKey();
......
......@@ -43,11 +43,7 @@ import org.jetbrains.annotations.Nullable;
import javax.swing.event.ChangeEvent;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.*;
/**
* The class contains utilities for creating and removing stashes.
......@@ -89,7 +85,7 @@ public class GitStashUtils {
handler.setNoSSH(true);
handler.addParameters("pop");
handler.ignoreErrorCode(1);
if (QUIET_STASH_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).version())) {
if (QUIET_STASH_SUPPORTED.isLessOrEqual(GitVcs.getInstance(project).getVersion())) {
handler.addParameters("--quiet");
}
handler.run();
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment