1 /****************************************************************************
2 **
3 ** Copyright (C) 2016 The Qt Company Ltd.
4 ** Contact: https://www.qt.io/licensing/
5 **
6 ** This file is part of Qt Creator.
7 **
8 ** Commercial License Usage
9 ** Licensees holding valid commercial Qt licenses may use this file in
10 ** accordance with the commercial license agreement provided with the
11 ** Software or, alternatively, in accordance with the terms contained in
12 ** a written agreement between you and The Qt Company. For licensing terms
13 ** and conditions see https://www.qt.io/terms-conditions. For further
14 ** information use the contact form at https://www.qt.io/contact-us.
15 **
16 ** GNU General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU
18 ** General Public License version 3 as published by the Free Software
19 ** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
20 ** included in the packaging of this file. Please review the following
21 ** information to ensure the GNU General Public License requirements will
22 ** be met: https://www.gnu.org/licenses/gpl-3.0.html.
23 **
24 ****************************************************************************/
25 
26 #include "commonvcssettings.h"
27 
28 #include "vcsbaseconstants.h"
29 
30 #include <coreplugin/icore.h>
31 #include <coreplugin/iversioncontrol.h>
32 #include <coreplugin/vcsmanager.h>
33 
34 #include <utils/environment.h>
35 #include <utils/hostosinfo.h>
36 #include <utils/layoutbuilder.h>
37 
38 #include <QDebug>
39 #include <QPushButton>
40 
41 using namespace Utils;
42 
43 namespace VcsBase {
44 namespace Internal {
45 
46 // Return default for the ssh-askpass command (default to environment)
sshPasswordPromptDefault()47 static QString sshPasswordPromptDefault()
48 {
49     const QByteArray envSetting = qgetenv("SSH_ASKPASS");
50     if (!envSetting.isEmpty())
51         return QString::fromLocal8Bit(envSetting);
52     if (HostOsInfo::isWindowsHost())
53         return QLatin1String("win-ssh-askpass");
54     return QLatin1String("ssh-askpass");
55 }
56 
CommonVcsSettings()57 CommonVcsSettings::CommonVcsSettings()
58 {
59     setSettingsGroup("VCS");
60     setAutoApply(false);
61 
62     registerAspect(&nickNameMailMap);
63     nickNameMailMap.setSettingsKey("NickNameMailMap");
64     nickNameMailMap.setDisplayStyle(StringAspect::PathChooserDisplay);
65     nickNameMailMap.setExpectedKind(PathChooser::File);
66     nickNameMailMap.setHistoryCompleter("Vcs.NickMap.History");
67     nickNameMailMap.setLabelText(tr("User/&alias configuration file:"));
68     nickNameMailMap.setToolTip(tr("A file listing nicknames in a 4-column mailmap format:\n"
69         "'name <email> alias <email>'."));
70 
71     registerAspect(&nickNameFieldListFile);
72     nickNameFieldListFile.setSettingsKey("NickNameFieldListFile");
73     nickNameFieldListFile.setDisplayStyle(StringAspect::PathChooserDisplay);
74     nickNameFieldListFile.setExpectedKind(PathChooser::File);
75     nickNameFieldListFile.setHistoryCompleter("Vcs.NickFields.History");
76     nickNameFieldListFile.setLabelText(tr("User &fields configuration file:"));
77     nickNameFieldListFile.setToolTip(tr("A simple file containing lines with field names like "
78         "\"Reviewed-By:\" which will be added below the submit editor."));
79 
80     registerAspect(&submitMessageCheckScript);
81     submitMessageCheckScript.setSettingsKey("SubmitMessageCheckScript");
82     submitMessageCheckScript.setDisplayStyle(StringAspect::PathChooserDisplay);
83     submitMessageCheckScript.setExpectedKind(PathChooser::ExistingCommand);
84     submitMessageCheckScript.setHistoryCompleter("Vcs.MessageCheckScript.History");
85     submitMessageCheckScript.setLabelText(tr("Submit message &check script:"));
86     submitMessageCheckScript.setToolTip(tr("An executable which is called with the submit message "
87         "in a temporary file as first argument. It should return with an exit != 0 and a message "
88         "on standard error to indicate failure."));
89 
90     registerAspect(&sshPasswordPrompt);
91     sshPasswordPrompt.setSettingsKey("SshPasswordPrompt");
92     sshPasswordPrompt.setDisplayStyle(StringAspect::PathChooserDisplay);
93     sshPasswordPrompt.setExpectedKind(PathChooser::ExistingCommand);
94     sshPasswordPrompt.setHistoryCompleter("Vcs.SshPrompt.History");
95     sshPasswordPrompt.setDefaultValue(sshPasswordPromptDefault());
96     sshPasswordPrompt.setLabelText(tr("&SSH prompt command:"));
97     sshPasswordPrompt.setToolTip(tr("Specifies a command that is executed to graphically prompt "
98         "for a password,\nshould a repository require SSH-authentication "
99         "(see documentation on SSH and the environment variable SSH_ASKPASS)."));
100 
101     registerAspect(&lineWrap);
102     lineWrap.setSettingsKey("LineWrap");
103     lineWrap.setDefaultValue(true);
104     lineWrap.setLabelText(tr("Wrap submit message at:"));
105 
106     registerAspect(&lineWrapWidth);
107     lineWrapWidth.setSettingsKey("LineWrapWidth");
108     lineWrapWidth.setSuffix(tr(" characters"));
109     lineWrapWidth.setDefaultValue(72);
110 }
111 
112 // CommonSettingsWidget
113 
114 class CommonSettingsWidget final : public Core::IOptionsPageWidget
115 {
116 public:
117     CommonSettingsWidget(CommonOptionsPage *page);
118 
119     void apply() final;
120 
121 private:
122     void updatePath();
123     CommonOptionsPage *m_page;
124 };
125 
126 
CommonSettingsWidget(CommonOptionsPage * page)127 CommonSettingsWidget::CommonSettingsWidget(CommonOptionsPage *page)
128     : m_page(page)
129 {
130     CommonVcsSettings &s = m_page->settings();
131 
132     auto cacheResetButton = new QPushButton(CommonVcsSettings::tr("Reset VCS Cache"));
133     cacheResetButton->setToolTip(CommonVcsSettings::tr("Reset information about which "
134         "version control system handles which directory."));
135 
136     updatePath();
137 
138     using namespace Layouting;
139     Column {
140         Row { s.lineWrap, s.lineWrapWidth, Stretch() },
141         Form {
142             s.submitMessageCheckScript,
143             s.nickNameMailMap,
144             s.nickNameFieldListFile,
145             s.sshPasswordPrompt,
146             {}, cacheResetButton
147         }
148     }.attachTo(this);
149 
150     connect(Core::VcsManager::instance(), &Core::VcsManager::configurationChanged,
151             this, &CommonSettingsWidget::updatePath);
152     connect(cacheResetButton, &QPushButton::clicked,
153             Core::VcsManager::instance(), &Core::VcsManager::clearVersionControlCache);
154 }
155 
updatePath()156 void CommonSettingsWidget::updatePath()
157 {
158     Environment env = Environment::systemEnvironment();
159     QStringList toAdd = Core::VcsManager::additionalToolsPath();
160     env.appendOrSetPath(toAdd.join(HostOsInfo::pathListSeparator()));
161     m_page->settings().sshPasswordPrompt.setEnvironment(env);
162 }
163 
apply()164 void CommonSettingsWidget::apply()
165 {
166     CommonVcsSettings &s = m_page->settings();
167     if (s.isDirty()) {
168         s.apply();
169         s.writeSettings(Core::ICore::settings());
170         emit m_page->settingsChanged();
171     }
172 }
173 
174 // CommonOptionsPage
175 
CommonOptionsPage()176 CommonOptionsPage::CommonOptionsPage()
177 {
178     m_settings.readSettings(Core::ICore::settings());
179 
180     setId(Constants::VCS_COMMON_SETTINGS_ID);
181     setDisplayName(QCoreApplication::translate("VcsBase", Constants::VCS_COMMON_SETTINGS_NAME));
182     setCategory(Constants::VCS_SETTINGS_CATEGORY);
183     // The following act as blueprint for other pages in the same category:
184     setDisplayCategory(QCoreApplication::translate("VcsBase", "Version Control"));
185     setCategoryIconPath(":/vcsbase/images/settingscategory_vcs.png");
186     setWidgetCreator([this] { return new CommonSettingsWidget(this); });
187 }
188 
189 } // namespace Internal
190 } // namespace VcsBase
191