From 95055340e3500568ff40cd6ed1f641d2f303ffe6 Mon Sep 17 00:00:00 2001 From: Konstantin Kolosovsky Date: Wed, 22 Oct 2014 20:42:20 +0400 Subject: [PATCH] 118571 Implemented ability to configure svn command line client locale in "Subversion" settings (instead of using "svn.executable.locale" registry key) --- .../openapi/ui/FixedComboBoxEditor.java | 6 ++- .../util/resources/misc/registry.properties | 1 - .../idea/svn/SvnApplicationSettings.java | 11 +++++ .../jetbrains/idea/svn/SvnBundle.properties | 2 + .../jetbrains/idea/svn/SvnConfigurable.form | 32 ++++++++++---- .../jetbrains/idea/svn/SvnConfigurable.java | 43 ++++++++++++++++++- .../idea/svn/api/CmdVersionClient.java | 3 +- .../idea/svn/commandLine/CommandExecutor.java | 11 +++-- .../idea/svn/commandLine/CommandRuntime.java | 12 ++++-- .../svn/commandLine/TerminalExecutor.java | 4 +- .../svn/commandLine/WinTerminalExecutor.java | 4 +- 11 files changed, 101 insertions(+), 28 deletions(-) diff --git a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java index 2066f661ca89..317d44c364bd 100644 --- a/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java +++ b/platform/platform-api/src/com/intellij/openapi/ui/FixedComboBoxEditor.java @@ -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; } diff --git a/platform/util/resources/misc/registry.properties b/platform/util/resources/misc/registry.properties index d2365fb50adc..92ff474f2d4f 100644 --- a/platform/util/resources/misc/registry.properties +++ b/platform/util/resources/misc/registry.properties @@ -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 diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java index a01dc322d9a3..5cf6d6db4389 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnApplicationSettings.java @@ -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 myCheckoutURLs = new ArrayList(); public List myTypedURLs = new ArrayList(); public String mySvnCommandLine = "svn"; + public String myExecutableLocale = SvnConfigurable.EN_US_LOCALE; } private ConfigurationBean myConfigurationBean; @@ -74,6 +76,15 @@ public class SvnApplicationSettings implements PersistentStateComponentEmulates the behavior when Subversion commands are executed directly from the terminal (in the interactive mode).
\ This is required to handle password/passphrase prompts for svn+ssh repositories, and trust invalid server certificates for https repositories. +command.line.locale.label=Locale\: +command.line.locale.system.default.title= ssh.settings.title=SSH Settings ssh.settings.executable.label=SSH executable\: diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form index b3d5afb2e2d4..12ca521de64a 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.form @@ -18,7 +18,7 @@ - + @@ -29,7 +29,7 @@ - + @@ -87,7 +87,7 @@ - + @@ -96,7 +96,7 @@ - + @@ -123,18 +123,18 @@ - + - + - + @@ -158,7 +158,7 @@ - + @@ -167,12 +167,26 @@ - + + + + + + + + + + + + + + + diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java index 2433a816adce..e28fe277beb1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/SvnConfigurable.java @@ -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 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() { + + @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); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java index 5b1484944285..95b4734f84d1 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/api/CmdVersionClient.java @@ -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(); diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java index e00b8f1e3183..97c5f9c00ed2 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandExecutor.java @@ -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(); } @@ -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 environment = myCommandLine.getEnvironment(); environment.put("LANGUAGE", ""); - environment.put("LC_ALL", locale); + environment.put("LC_ALL", myLocale); } } diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java index 46b716c3bde2..a64821e24aad 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/CommandRuntime.java @@ -43,11 +43,15 @@ public class CommandRuntime { @NotNull private final SvnVcs myVcs; @NotNull private final List 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) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java index 63fa3bbc0700..1509629b032b 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/TerminalExecutor.java @@ -35,8 +35,8 @@ public class TerminalExecutor extends CommandExecutor { private final List 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) { diff --git a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java index e08594d33c28..08979ab6d3e3 100644 --- a/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java +++ b/plugins/svn4idea/src/org/jetbrains/idea/svn/commandLine/WinTerminalExecutor.java @@ -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