118571 Implemented ability to configure svn command line client locale in "Subversion" settings (instead of using "svn.executable.locale" registry key)

This commit is contained in:
Konstantin Kolosovsky
2014-10-22 20:42:20 +04:00
parent 17c554f98a
commit 95055340e3
11 changed files with 101 additions and 28 deletions
@@ -21,6 +21,7 @@ import com.intellij.ui.components.JBTextField;
import com.intellij.util.ReflectionUtil;
import com.intellij.util.ui.MacUIUtil;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
@@ -47,7 +48,7 @@ public class FixedComboBoxEditor implements ComboBoxEditor {
public static final Border EDITOR_BORDER = new MacComboBoxEditorBorder(false);
public static final Border DISABLED_EDITOR_BORDER = new MacComboBoxEditorBorder(true);
private JBTextField myField;
@NotNull private final JBTextField myField;
private Object oldValue;
public FixedComboBoxEditor() {
@@ -60,7 +61,8 @@ public class FixedComboBoxEditor implements ComboBoxEditor {
}
}
protected JTextField getField() {
@NotNull
public JBTextField getField() {
return myField;
}
@@ -353,7 +353,6 @@ search.everywhere.configurations=true
search.everywhere.settings=false
svn.use.incoming.optimization=false
svn.executable.locale=en_US.UTF-8
svn.lowest.supported.format.for.command.line=1.7.0
svn.use.svnkit.for.https.server.certificate.check=true
@@ -18,6 +18,7 @@ package org.jetbrains.idea.svn;
import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.components.*;
import com.intellij.openapi.project.Project;
import org.jetbrains.annotations.NotNull;
import org.tmatesoft.svn.core.SVNException;
import org.tmatesoft.svn.core.SVNURL;
@@ -43,6 +44,7 @@ public class SvnApplicationSettings implements PersistentStateComponent<SvnAppli
public List<String> myCheckoutURLs = new ArrayList<String>();
public List<String> myTypedURLs = new ArrayList<String>();
public String mySvnCommandLine = "svn";
public String myExecutableLocale = SvnConfigurable.EN_US_LOCALE;
}
private ConfigurationBean myConfigurationBean;
@@ -74,6 +76,15 @@ public class SvnApplicationSettings implements PersistentStateComponent<SvnAppli
return myConfigurationBean.mySvnCommandLine;
}
@NotNull
public String getExecutableLocale() {
return myConfigurationBean.myExecutableLocale;
}
public void setExecutableLocale(@NotNull String locale) {
myConfigurationBean.myExecutableLocale = locale;
}
private LimitedStringsList getTypedList() {
if (myLimitedStringsList == null) {
checkFillTypedFromCheckout();
@@ -204,6 +204,8 @@ confirmation.title.clear.authentication.cache=Clear Authentication Cache
command.line.interactive.mode.title=Enable interactive mode
command.line.interactive.mode.description=<html>Emulates the behavior when Subversion commands are executed directly from the terminal (in the interactive mode).<br>\
This is required to handle password/passphrase prompts for svn+ssh repositories, and trust invalid server certificates for https repositories.</html>
command.line.locale.label=Locale\:
command.line.locale.system.default.title=<System Default>
ssh.settings.title=SSH Settings
ssh.settings.executable.label=SSH executable\:
@@ -18,7 +18,7 @@
<properties/>
<border type="none"/>
<children>
<grid id="2ae3a" layout-manager="GridLayoutManager" row-count="7" column-count="3" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<grid id="2ae3a" layout-manager="GridLayoutManager" row-count="8" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<tabbedpane title="General"/>
@@ -29,7 +29,7 @@
<grid id="a4729" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="5" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -87,7 +87,7 @@
</grid>
<component id="df054" class="javax.swing.JCheckBox" binding="myUseDefaultCheckBox">
<constraints>
<grid row="3" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
<grid row="4" column="0" row-span="1" col-span="3" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="checkbox.configure.use.system.default.configuration.directory"/>
@@ -96,7 +96,7 @@
<grid id="137aa" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="6" column="0" row-span="1" col-span="2" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="7" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -123,18 +123,18 @@
</grid>
<hspacer id="e8f24">
<constraints>
<grid row="6" column="2" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
<grid row="7" column="3" row-span="1" col-span="1" vsize-policy="1" hsize-policy="6" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
</constraints>
</hspacer>
<vspacer id="aa6b2">
<constraints>
<grid row="5" column="0" row-span="1" col-span="2" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
<grid row="6" column="0" row-span="1" col-span="3" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
</constraints>
</vspacer>
<grid id="12735" layout-manager="GridLayoutManager" row-count="1" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
<margin top="0" left="0" bottom="0" right="0"/>
<constraints>
<grid row="0" column="0" row-span="1" col-span="3" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
<grid row="0" column="0" row-span="1" col-span="4" vsize-policy="3" hsize-policy="3" anchor="0" fill="3" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
<border type="none"/>
@@ -158,7 +158,7 @@
</grid>
<component id="df957" class="com.intellij.ui.components.JBCheckBox" binding="myRunUnderTerminal">
<constraints>
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
<grid row="1" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
</constraints>
<properties>
<margin top="2" left="-2" bottom="2" right="3"/>
@@ -167,12 +167,26 @@
</component>
<component id="40f21" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
<grid row="2" column="0" row-span="1" col-span="2" vsize-policy="0" hsize-policy="3" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="command.line.interactive.mode.description"/>
</properties>
</component>
<component id="b1eea" class="com.intellij.ui.components.JBLabel">
<constraints>
<grid row="3" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="3" use-parent-layout="false"/>
</constraints>
<properties>
<text resource-bundle="org/jetbrains/idea/svn/SvnBundle" key="command.line.locale.label"/>
</properties>
</component>
<component id="4d20a" class="com.intellij.openapi.ui.ComboBox" binding="myLocalesList">
<constraints>
<grid row="3" column="1" row-span="1" col-span="1" vsize-policy="0" hsize-policy="2" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
</constraints>
<properties/>
</component>
</children>
</grid>
<grid id="718dd" layout-manager="GridLayoutManager" row-count="5" column-count="4" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
@@ -24,6 +24,8 @@ import com.intellij.openapi.fileChooser.FileChooserDescriptorFactory;
import com.intellij.openapi.options.Configurable;
import com.intellij.openapi.options.ConfigurationException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.ComboBox;
import com.intellij.openapi.ui.FixedComboBoxEditor;
import com.intellij.openapi.ui.TextFieldWithBrowseButton;
import com.intellij.openapi.util.Comparing;
import com.intellij.openapi.util.SystemInfo;
@@ -31,10 +33,13 @@ import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vcs.changes.VcsDirtyScopeManager;
import com.intellij.openapi.vfs.VirtualFile;
import com.intellij.openapi.vfs.VirtualFileManager;
import com.intellij.ui.CollectionComboBoxModel;
import com.intellij.ui.ListCellRendererWrapper;
import com.intellij.ui.MultiLineTooltipUI;
import com.intellij.ui.components.JBCheckBox;
import com.intellij.ui.components.JBRadioButton;
import com.intellij.util.Consumer;
import com.intellij.util.containers.ContainerUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
@@ -47,11 +52,18 @@ import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.io.File;
import java.util.List;
public class SvnConfigurable implements Configurable {
public static final String DISPLAY_NAME = SvnVcs.VCS_DISPLAY_NAME;
public static final String EN_US_LOCALE = "en_US.UTF-8";
public static final List<String> EXECUTABLE_LOCALES = ContainerUtil.newArrayList("", EN_US_LOCALE, "C.UTF-8", "C");
private final Project myProject;
private JCheckBox myUseDefaultCheckBox;
private TextFieldWithBrowseButton myConfigurationDirectoryText;
@@ -68,6 +80,7 @@ public class SvnConfigurable implements Configurable {
private JCheckBox myShowMergeSourceInAnnotate;
private JBCheckBox myWithCommandLineClient;
private JBCheckBox myRunUnderTerminal;
private ComboBox myLocalesList;
private JSpinner myNumRevsInAnnotations;
private JCheckBox myMaximumNumberOfRevisionsCheckBox;
private JSpinner mySSHConnectionTimeout;
@@ -108,7 +121,28 @@ public class SvnConfigurable implements Configurable {
}
});
myCommandLineClient.addBrowseFolderListener("Subversion", "Select path to Subversion executable (1.7+)", project,
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor());
FileChooserDescriptorFactory.createSingleFileNoJarsDescriptor());
//noinspection unchecked
myLocalesList.setModel(new CollectionComboBoxModel(EXECUTABLE_LOCALES));
myLocalesList.setEditable(true);
FixedComboBoxEditor editor = new FixedComboBoxEditor();
editor.getField().getEmptyText().setText(SvnBundle.message("command.line.locale.system.default.title"));
myLocalesList.setEditor(editor);
myLocalesList.setRenderer(new ListCellRendererWrapper<String>() {
@Override
public void customize(JList list, String value, int index, boolean selected, boolean hasFocus) {
setText(StringUtil.isEmpty(value) ? SvnBundle.message("command.line.locale.system.default.title") : value);
}
});
myLocalesList.addItemListener(new ItemListener() {
@Override
public void itemStateChanged(ItemEvent e) {
if (e.getStateChange() == ItemEvent.SELECTED) {
myLocalesList.getEditor().setItem(myLocalesList.getSelectedItem());
}
}
});
myClearAuthButton.addActionListener(new ActionListener(){
public void actionPerformed(final ActionEvent e) {
@@ -263,6 +297,7 @@ public class SvnConfigurable implements Configurable {
if (! getSelectedSSL().equals(configuration.getSslProtocols())) return true;
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
if (! Comparing.equal(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim())) return true;
if (!Comparing.equal(applicationSettings17.getExecutableLocale(), myLocalesList.getEditor().getItem())) return true;
if (!configuration.getConfigurationDirectory().equals(myConfigurationDirectoryText.getText().trim())) return true;
return mySshSettingsPanel.isModified(configuration);
}
@@ -292,13 +327,16 @@ public class SvnConfigurable implements Configurable {
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
boolean reloadWorkingCopies = !acceleration().equals(configuration.getUseAcceleration()) ||
!StringUtil.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim());
!StringUtil.equals(applicationSettings17.getCommandLinePath(), myCommandLineClient.getText().trim()) ||
!StringUtil.equals(applicationSettings17.getExecutableLocale(),
myLocalesList.getEditor().getItem().toString());
configuration.setUseAcceleration(acceleration());
configuration.setRunUnderTerminal(myRunUnderTerminal.isSelected());
configuration.setSslProtocols(getSelectedSSL());
SvnVcs.getInstance(myProject).getSvnKitManager().refreshSSLProperty();
applicationSettings17.setCommandLinePath(myCommandLineClient.getText().trim());
applicationSettings17.setExecutableLocale(myLocalesList.getEditor().getItem().toString());
boolean isClientValid = vcs17.checkCommandLineVersion();
if (isClientValid && reloadWorkingCopies) {
vcs17.invokeRefreshSvnRoots();
@@ -345,6 +383,7 @@ public class SvnConfigurable implements Configurable {
myRunUnderTerminal.setEnabled(myWithCommandLineClient.isSelected());
final SvnApplicationSettings applicationSettings17 = SvnApplicationSettings.getInstance();
myCommandLineClient.setText(applicationSettings17.getCommandLinePath());
myLocalesList.setSelectedItem(applicationSettings17.getExecutableLocale());
if (SvnConfiguration.SSLProtocols.sslv3.equals(configuration.getSslProtocols())) {
mySSLv3RadioButton.setSelected(true);
@@ -30,7 +30,8 @@ public class CmdVersionClient extends BaseSvnClient implements VersionClient {
Command command = new Command(SvnCommandName.version);
command.put("--quiet");
CommandExecutor executor = new CommandExecutor(SvnApplicationSettings.getInstance().getCommandLinePath(), command);
SvnApplicationSettings settings = SvnApplicationSettings.getInstance();
CommandExecutor executor = new CommandExecutor(settings.getCommandLinePath(), settings.getExecutableLocale(), command);
executor.run(30 * 1000);
return executor.getProcessOutput();
@@ -23,7 +23,6 @@ import com.intellij.openapi.application.PathManager;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.io.FileUtil;
import com.intellij.openapi.util.registry.Registry;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.openapi.vfs.CharsetToolkit;
import com.intellij.util.EventDispatcher;
@@ -58,6 +57,7 @@ public class CommandExecutor {
private volatile String myDestroyReason;
private volatile boolean myWasCancelled;
@NotNull protected final GeneralCommandLine myCommandLine;
@NotNull protected final String myLocale;
protected Process myProcess;
protected SvnProcessHandler myHandler;
private OutputStreamWriter myProcessWriter;
@@ -72,7 +72,7 @@ public class CommandExecutor {
@Nullable private final LineCommandListener myResultBuilder;
@NotNull private final Command myCommand;
public CommandExecutor(@NotNull @NonNls String exePath, @NotNull Command command) {
public CommandExecutor(@NotNull @NonNls String exePath, @NotNull String locale, @NotNull Command command) {
myCommand = command;
myResultBuilder = command.getResultBuilder();
if (myResultBuilder != null) {
@@ -89,6 +89,7 @@ public class CommandExecutor {
}
myCommandLine.addParameter(command.getName().getName());
myCommandLine.addParameters(prepareParameters(command));
myLocale = locale;
myExitCodeReference = new AtomicReference<Integer>();
}
@@ -158,13 +159,11 @@ public class CommandExecutor {
}
private void setupLocale() {
String locale = Registry.stringValue("svn.executable.locale");
if (!StringUtil.isEmpty(locale)) {
if (!StringUtil.isEmpty(myLocale)) {
Map<String, String> environment = myCommandLine.getEnvironment();
environment.put("LANGUAGE", "");
environment.put("LC_ALL", locale);
environment.put("LC_ALL", myLocale);
}
}
@@ -43,11 +43,15 @@ public class CommandRuntime {
@NotNull private final SvnVcs myVcs;
@NotNull private final List<CommandRuntimeModule> myModules;
private final String exePath;
@NotNull private final String executableLocale;
public CommandRuntime(@NotNull SvnVcs vcs, @NotNull AuthenticationService authenticationService) {
myVcs = vcs;
myAuthenticationService = authenticationService;
exePath = SvnApplicationSettings.getInstance().getCommandLinePath();
SvnApplicationSettings settings = SvnApplicationSettings.getInstance();
exePath = settings.getCommandLinePath();
executableLocale = settings.getExecutableLocale();
myModules = ContainerUtil.newArrayList();
myModules.add(new CommandParametersResolutionModule(this));
@@ -218,7 +222,7 @@ public class CommandRuntime {
if (!myVcs.getSvnConfiguration().isRunUnderTerminal() || isLocal(command)) {
command.putIfNotPresent("--non-interactive");
executor = new CommandExecutor(exePath, command);
executor = new CommandExecutor(exePath, executableLocale, command);
}
else {
// do not explicitly specify "--force-interactive" as it is not supported in svn 1.7 - commands will be interactive by default as
@@ -234,7 +238,9 @@ public class CommandRuntime {
@NotNull
private TerminalExecutor newTerminalExecutor(@NotNull Command command) {
return SystemInfo.isWindows ? new WinTerminalExecutor(exePath, command) : new TerminalExecutor(exePath, command);
return SystemInfo.isWindows
? new WinTerminalExecutor(exePath, executableLocale, command)
: new TerminalExecutor(exePath, executableLocale, command);
}
public static boolean isLocal(@NotNull Command command) {
@@ -35,8 +35,8 @@ public class TerminalExecutor extends CommandExecutor {
private final List<InteractiveCommandListener> myInteractiveListeners = ContainerUtil.createLockFreeCopyOnWriteList();
public TerminalExecutor(@NotNull @NonNls String exePath, @NotNull Command command) {
super(exePath, command);
public TerminalExecutor(@NotNull @NonNls String exePath, @NotNull String locale, @NotNull Command command) {
super(exePath, locale, command);
}
public void addInteractiveListener(@NotNull InteractiveCommandListener listener) {
@@ -49,8 +49,8 @@ public class WinTerminalExecutor extends TerminalExecutor {
@Nullable private File myRedirectFile;
@Nullable private FileInputStream myRedirectStream;
public WinTerminalExecutor(@NotNull @NonNls String exePath, @NotNull Command command) {
super(exePath, command);
public WinTerminalExecutor(@NotNull @NonNls String exePath, @NotNull String locale, @NotNull Command command) {
super(exePath, locale, command);
}
@NotNull