From 086d18a569864f03a1720f9f0a455cf5ffdb5dbf Mon Sep 17 00:00:00 2001 From: RussKie Date: Sun, 14 Aug 2016 23:58:57 +1000 Subject: [PATCH] refactor: Management of remote repositories Remote repositories are accessible on a several forms, however the experience is quite inconsistent. The management of the remotes is quite poor too, UX is confusing and buggy. In the original implementation the UI and the BL concerns intertwined which makes it difficult to maintain, extend and test. * The new implementation moves the functionality concerning dealing with the remotes repositories into a separate controller abstracting the data management from the UI. * The controller enables testing * The controller also simplifies the remotes management (FormRemotes). The "remote repositories" tab's layout has also been reworked and updated. * All affected forms now need to instantiate a controller, load the remotes and bind them to the desired UI control (i.e. to a combo). The following reported bugs are fixed: - #2550 - Remote Repositories > Separate Push URL not working (https://github.com/gitextensions/gitextensions/issues/2550) - #1465 - Tab Stop Order in Remote Repositories dialog is very messed up (https://github.com/gitextensions/gitextensions/issues/1465) The following change was undone, as it introduced quite inconsistent and confusing UX: - #1208 - Rearrange buttons in "Manage Remote Repositories" dialog (https://github.com/gitextensions/gitextensions/pull/1208) Translations: The following items added in FormRemotes: - lblMgtPuttyPanelHeader.Text - _gitMessage.Text - _gbMgtPanelHeaderNew.Text - _gbMgtPanelHeaderEdit.Text - lblMgtDetailsPanelHeader.Text The following items removed from FormRemotes: - New.Text - Delete.Text - buttonClose.Text - PuTTYSSH.Text - _hintDelete.Text - groupBox1.Text --- GitCommands/Config/SettingKeyString.cs | 20 +- GitCommands/Git/GitRef.cs | 8 +- GitExtensionsTest/GitExtensionsTest.csproj | 1 + .../GitUI/Objects/GitRemoteControllerTests.cs | 178 ++++ GitUI/CommandsDialogs/FormPull.cs | 63 +- GitUI/CommandsDialogs/FormPush.Designer.cs | 27 +- GitUI/CommandsDialogs/FormPush.cs | 154 +-- GitUI/CommandsDialogs/FormRemotes.Designer.cs | 882 ++++++++++-------- GitUI/CommandsDialogs/FormRemotes.cs | 361 ++++--- GitUI/CommandsDialogs/FormRemotes.resx | 27 + GitUI/GitUI.csproj | 7 +- GitUI/Objects/GitRemote.cs | 33 + GitUI/Objects/GitRemoteController.cs | 248 +++++ GitUI/Objects/GitRemoteSaveResult.cs | 24 + GitUI/Properties/Resources.Designer.cs | 10 + GitUI/Properties/Resources.resx | 5 +- GitUI/Resources/Icons/86.png | Bin 0 -> 435 bytes GitUI/Translation/English.xlf | 30 +- GitUI/UserControls/RemotesComboboxControl.cs | 6 +- .../GitUIPluginInterfaces.csproj | 3 + Plugins/GitUIPluginInterfaces/IGitModule.cs | 15 +- ResourceManager/GitExtensionsFormBase.cs | 19 + 22 files changed, 1405 insertions(+), 716 deletions(-) create mode 100644 GitExtensionsTest/GitUI/Objects/GitRemoteControllerTests.cs create mode 100644 GitUI/Objects/GitRemote.cs create mode 100644 GitUI/Objects/GitRemoteController.cs create mode 100644 GitUI/Objects/GitRemoteSaveResult.cs create mode 100644 GitUI/Resources/Icons/86.png diff --git a/GitCommands/Config/SettingKeyString.cs b/GitCommands/Config/SettingKeyString.cs index d83d52ff666..7992df8572e 100644 --- a/GitCommands/Config/SettingKeyString.cs +++ b/GitCommands/Config/SettingKeyString.cs @@ -5,26 +5,36 @@ namespace GitCommands.Config /// Defines the strings to access certain git config settings. /// Goal is to eliminate duplicate string constants in the code. /// - public class SettingKeyString + public static class SettingKeyString { + /// + /// "remote.{0}.push" + /// + public static string RemotePush = "remote.{0}.push"; + /// /// "remote.{0}.pushurl" /// - public const string RemotePushUrl = "remote.{0}.pushurl"; + public static string RemotePushUrl = "remote.{0}.pushurl"; /// /// "remote.{0}.url" /// - public const string RemoteUrl = "remote.{0}.url"; + public static string RemoteUrl = "remote.{0}.url"; + + /// + /// "remote.{0}.puttykeyfile" + /// + public static string RemotePuttySshKey = "remote.{0}.puttykeyfile"; /// /// user.name /// - public const string UserName = "user.name"; + public static string UserName = "user.name"; /// /// user.email /// - public const string UserEmail = "user.email"; + public static string UserEmail = "user.email"; } } diff --git a/GitCommands/Git/GitRef.cs b/GitCommands/Git/GitRef.cs index fb262addf5e..f0d577d7b0f 100644 --- a/GitCommands/Git/GitRef.cs +++ b/GitCommands/Git/GitRef.cs @@ -1,7 +1,7 @@ using System; using System.Collections.Generic; -using GitCommands.Config; using GitCommands.Settings; +using GitUIPluginInterfaces; namespace GitCommands { @@ -22,12 +22,12 @@ public class GitRef : IGitItem /// "^{}" public static readonly string TagDereferenceSuffix = "^{}"; - public GitModule Module { get; private set; } + public IGitModule Module { get; private set; } - public GitRef(GitModule module, string guid, string completeName) + public GitRef(IGitModule module, string guid, string completeName) : this(module, guid, completeName, string.Empty) { } - public GitRef(GitModule module, string guid, string completeName, string remote) + public GitRef(IGitModule module, string guid, string completeName, string remote) { Module = module; Guid = guid; diff --git a/GitExtensionsTest/GitExtensionsTest.csproj b/GitExtensionsTest/GitExtensionsTest.csproj index 8087a6b7ec3..59d8ef7e32f 100644 --- a/GitExtensionsTest/GitExtensionsTest.csproj +++ b/GitExtensionsTest/GitExtensionsTest.csproj @@ -100,6 +100,7 @@ + diff --git a/GitExtensionsTest/GitUI/Objects/GitRemoteControllerTests.cs b/GitExtensionsTest/GitUI/Objects/GitRemoteControllerTests.cs new file mode 100644 index 00000000000..8d34a360fde --- /dev/null +++ b/GitExtensionsTest/GitUI/Objects/GitRemoteControllerTests.cs @@ -0,0 +1,178 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using FluentAssertions; +using GitCommands.Config; +using GitUI.Objects; +using GitUIPluginInterfaces; +using NSubstitute; +using NUnit.Framework; + +namespace GitExtensionsTest.GitUI.Objects +{ + [TestFixture] + class GitRemoteControllerTests + { + private IGitModule _module; + private IGitRemoteController _controller; + + + [SetUp] + public void Setup() + { + _module = Substitute.For(); + + _controller = new GitRemoteController(_module); + } + + + [Test] + public void LoadRemotes_should_not_throw_if_module_is_null() + { + _module = null; + + ((Action)(() => _controller.LoadRemotes())).ShouldNotThrow(); + } + + [Test] + public void LoadRemotes_should_not_populate_remotes_if_none() + { + _module.GetRemotes().Returns(x => Enumerable.Empty()); + + _controller.LoadRemotes(); + + _controller.Remotes.Count.Should().Be(0); + _module.Received(1).GetRemotes(); + _module.DidNotReceive().GetSetting(Arg.Any()); + _module.DidNotReceive().GetSettings(Arg.Any()); + } + + [Test] + public void LoadRemotes_should_not_populate_remotes_if_those_are_null_or_whitespace() + { + _module.GetRemotes().Returns(x => new[] { null, "", " ", " ", "\t" }); + + _controller.LoadRemotes(); + + _controller.Remotes.Count.Should().Be(0); + _module.Received(1).GetRemotes(); + _module.DidNotReceive().GetSetting(Arg.Any()); + _module.DidNotReceive().GetSettings(Arg.Any()); + } + + [Test] + public void LoadRemotes_should_populate_remotes_if_any() + { + const string remote = "a"; + _module.GetRemotes().Returns(x => new[] { null, "", " ", " ", remote, "\t" }); + + _controller.LoadRemotes(); + + _controller.Remotes.Count.Should().Be(1); + _module.Received(1).GetRemotes(); + _module.Received(1).GetSetting(string.Format(SettingKeyString.RemoteUrl, remote)); + _module.Received(1).GetSetting(string.Format(SettingKeyString.RemotePushUrl, remote)); + _module.Received(1).GetSetting(string.Format(SettingKeyString.RemotePuttySshKey, remote)); + _module.Received(1).GetSettings(string.Format(SettingKeyString.RemotePush, remote)); + } + + [Test] + public void RemoveRemote_should_throw_if_remote_is_null() + { + ((Action)(() => _controller.RemoveRemote(null))).ShouldThrow() + .WithMessage("Value cannot be null.\r\nParameter name: remote"); + } + + [Test] + public void RemoveRemote_success() + { + var remote = new GitRemote { Name = "bla" }; + + _controller.RemoveRemote(remote); + + _module.Received(1).RemoveRemote(remote.Name); + } + + [Test] + public void SaveRemote_should_throw_if_remoteName_is_null() + { + ((Action)(() => _controller.SaveRemote(null, null, "b", "c", "d"))).ShouldThrow() + .WithMessage("Value cannot be null.\r\nParameter name: remoteName"); + } + + [Test] + public void SaveRemote_null_remote_should_invoke_AddRemote_and_require_update() + { + const string remoteName = "a"; + const string remoteUrl = "b"; + const string output = "yes!"; + _module.AddRemote(Arg.Any(), Arg.Any()).Returns(x => output); + + var result = _controller.SaveRemote(null, remoteName, remoteUrl, null, null); + + result.UserMessage.Should().Be(output); + result.ShouldUpdateRemote.Should().BeTrue(); + _module.Received(1).AddRemote(remoteName, remoteUrl); + } + + [Test] + public void SaveRemote_populated_remote_should_invoke_RenameRemote_if_remoteName_mismatch_no_update_required() + { + const string remoteName = "a"; + const string remoteUrl = "b"; + const string output = "yes!"; + var gitRemote = new GitRemote { Name = "old", Url = remoteUrl }; + _module.RenameRemote(Arg.Any(), Arg.Any()).Returns(x => output); + + var result = _controller.SaveRemote(gitRemote, remoteName, remoteUrl, null, null); + + result.UserMessage.Should().Be(output); + result.ShouldUpdateRemote.Should().BeFalse(); + _module.Received(1).RenameRemote(gitRemote.Name, remoteName); + } + + [Test] + public void SaveRemote_populated_remote_should_require_update_if_remoteUrl_mismatch() + { + const string remoteName = "a"; + const string remoteUrl = "b"; + const string output = "yes!"; + var gitRemote = new GitRemote { Name = "old", Url = "old" }; + _module.RenameRemote(Arg.Any(), Arg.Any()).Returns(x => output); + + var result = _controller.SaveRemote(gitRemote, remoteName, remoteUrl, null, null); + + result.UserMessage.Should().Be(output); + result.ShouldUpdateRemote.Should().BeTrue(); + _module.Received(1).RenameRemote(gitRemote.Name, remoteName); + } + + [TestCase(null, null, null)] + [TestCase("a", null, null)] + [TestCase("a", "b", null)] + [TestCase("a", "b", "c")] + public void SaveRemote_should_update_settings(string remoteUrl, string remotePushUrl, string remotePuttySshKey) + { + var remote = new GitRemote { Name = "bla", Url = remoteUrl }; + + _controller.SaveRemote(remote, remote.Name, remoteUrl, remotePushUrl, remotePuttySshKey); + + Action ensure = (setting, value) => + { + setting = string.Format(setting, remote.Name); + if (!string.IsNullOrWhiteSpace(value)) + { + _module.Received(1).SetSetting(setting, value); + } + else + { + _module.Received(1).UnsetSetting(setting); + } + }; + ensure(SettingKeyString.RemoteUrl, remoteUrl); + ensure(SettingKeyString.RemotePushUrl, remotePushUrl); + ensure(SettingKeyString.RemotePuttySshKey, remotePuttySshKey); + } + } +} diff --git a/GitUI/CommandsDialogs/FormPull.cs b/GitUI/CommandsDialogs/FormPull.cs index 66e8f38d58a..e0dc4ae780f 100644 --- a/GitUI/CommandsDialogs/FormPull.cs +++ b/GitUI/CommandsDialogs/FormPull.cs @@ -3,11 +3,13 @@ using System.ComponentModel; using System.Diagnostics; using System.IO; +using System.Linq; using System.Text.RegularExpressions; using System.Windows.Forms; using GitCommands; using GitCommands.Config; using GitCommands.Repository; +using GitUI.Objects; using GitUI.Properties; using GitUI.Script; using GitUI.UserControls; @@ -95,6 +97,8 @@ public partial class FormPull : GitModuleForm private IList _heads; private string _branch; private const string AllRemotes = "[ All ]"; + private readonly IGitRemoteController _gitRemoteController; + private FormPull() : this(null, null, null) @@ -110,7 +114,10 @@ public FormPull(GitUICommands aCommands, string defaultRemoteBranch, string defa helpImageDisplayUserControl1.IsOnHoverShowImage2NoticeText = _hoverShowImageLabelText.Text; if (aCommands != null) + { + _gitRemoteController = new GitRemoteController(Module); Init(defaultRemote); + } Merge.Checked = Settings.FormPullAction == Settings.PullAction.Merge; Rebase.Checked = Settings.FormPullAction == Settings.PullAction.Rebase; @@ -135,40 +142,42 @@ public FormPull(GitUICommands aCommands, string defaultRemoteBranch, string defa } } + private void Init(string defaultRemote) { - UpdateRemotesList(); - _branch = Module.GetSelectedBranch(); + localBranch.Text = _branch; + + BindRemotesDropDown(defaultRemote); + } + + private void BindRemotesDropDown(string selectedRemoteName) + { + // refresh registered git remotes + _gitRemoteController.LoadRemotes(); + + _NO_TRANSLATE_Remotes.Sorted = false; + _NO_TRANSLATE_Remotes.DataSource = new[] { new GitRemote { Name = AllRemotes } }.Union(_gitRemoteController.Remotes).ToList(); + _NO_TRANSLATE_Remotes.DisplayMember = "Name"; + _NO_TRANSLATE_Remotes.SelectedIndex = -1; + ComboBoxHelper.ResizeComboBoxDropDownWidth(_NO_TRANSLATE_Remotes, AppSettings.BranchDropDownMinWidth, AppSettings.BranchDropDownMaxWidth); - string currentBranchRemote; - if (defaultRemote.IsNullOrEmpty()) + var currentBranchRemote = _gitRemoteController.Remotes.FirstOrDefault(x => x.Name.Equals(selectedRemoteName, StringComparison.OrdinalIgnoreCase)); + if (currentBranchRemote != null) { - currentBranchRemote = Module.GetSetting(string.Format("branch.{0}.remote", _branch)); + _NO_TRANSLATE_Remotes.SelectedItem = currentBranchRemote; } - else + else if (_gitRemoteController.Remotes.Any()) { - currentBranchRemote = defaultRemote; + // we couldn't find the default assigned remote for the selected branch + // it is usually gets mapped via FormRemotes -> "default pull behavior" tab + // so pick the default user remote + _NO_TRANSLATE_Remotes.SelectedIndex = 1; } - - if (currentBranchRemote.IsNullOrEmpty() && _NO_TRANSLATE_Remotes.Items.Count >= 3) + else { - IList remotes = (IList)_NO_TRANSLATE_Remotes.DataSource; - int i = remotes.IndexOf("origin"); - _NO_TRANSLATE_Remotes.SelectedIndex = i >= 0 ? i : 1; + _NO_TRANSLATE_Remotes.SelectedIndex = 0; } - else - _NO_TRANSLATE_Remotes.Text = currentBranchRemote; - localBranch.Text = _branch; - } - - private void UpdateRemotesList() - { - IList remotes = new List(Module.GetRemotes()); - remotes.Insert(0, AllRemotes); - _NO_TRANSLATE_Remotes.DataSource = remotes; - - ComboBoxHelper.ResizeComboBoxDropDownWidth (_NO_TRANSLATE_Remotes, AppSettings.BranchDropDownMinWidth, AppSettings.BranchDropDownMaxWidth); } public DialogResult PullAndShowDialogWhenFailed(IWin32Window owner) @@ -785,11 +794,7 @@ private void AddRemoteClick(object sender, EventArgs e) _bInternalUpdate = true; string origText = _NO_TRANSLATE_Remotes.Text; - UpdateRemotesList(); - if (_NO_TRANSLATE_Remotes.Items.Contains(origText)) // else first item gets selected - { - _NO_TRANSLATE_Remotes.Text = origText; - } + BindRemotesDropDown(origText); _bInternalUpdate = false; } diff --git a/GitUI/CommandsDialogs/FormPush.Designer.cs b/GitUI/CommandsDialogs/FormPush.Designer.cs index 347a0b55997..75928777cb6 100644 --- a/GitUI/CommandsDialogs/FormPush.Designer.cs +++ b/GitUI/CommandsDialogs/FormPush.Designer.cs @@ -140,7 +140,7 @@ private void InitializeComponent() this.Push.DialogResult = System.Windows.Forms.DialogResult.OK; this.Push.Image = global::GitUI.Properties.Resources.ArrowUp; this.Push.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.Push.Location = new System.Drawing.Point(519, 219); + this.Push.Location = new System.Drawing.Point(521, 234); this.Push.Name = "Push"; this.Push.Size = new System.Drawing.Size(101, 25); this.Push.TabIndex = 9; @@ -163,7 +163,7 @@ private void InitializeComponent() this.TabControlTagBranch.Name = "TabControlTagBranch"; this.TabControlTagBranch.SelectedIndex = 0; this.TabControlTagBranch.ShowToolTips = true; - this.TabControlTagBranch.Size = new System.Drawing.Size(614, 113); + this.TabControlTagBranch.Size = new System.Drawing.Size(614, 130); this.TabControlTagBranch.TabIndex = 6; this.TabControlTagBranch.Selected += new System.Windows.Forms.TabControlEventHandler(this.TabControlTagBranch_Selected); // @@ -174,7 +174,7 @@ private void InitializeComponent() this.BranchTab.Location = new System.Drawing.Point(4, 22); this.BranchTab.Name = "BranchTab"; this.BranchTab.Padding = new System.Windows.Forms.Padding(3); - this.BranchTab.Size = new System.Drawing.Size(606, 87); + this.BranchTab.Size = new System.Drawing.Size(606, 104); this.BranchTab.TabIndex = 0; this.BranchTab.Text = "Push branches"; this.BranchTab.ToolTipText = "Push branches and commits to remote repository."; @@ -191,7 +191,7 @@ private void InitializeComponent() this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox1.Location = new System.Drawing.Point(3, 3); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(600, 81); + this.groupBox1.Size = new System.Drawing.Size(600, 98); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; this.groupBox1.Text = "Branch"; @@ -273,7 +273,7 @@ private void InitializeComponent() this.PushOptionsPanel.Controls.Add(this._createPullRequestCB); this.PushOptionsPanel.Location = new System.Drawing.Point(47, 61); this.PushOptionsPanel.Name = "PushOptionsPanel"; - this.PushOptionsPanel.Size = new System.Drawing.Size(514, 20); + this.PushOptionsPanel.Size = new System.Drawing.Size(514, 37); this.PushOptionsPanel.TabIndex = 25; this.PushOptionsPanel.Visible = false; // @@ -351,7 +351,7 @@ private void InitializeComponent() this.TagTab.Location = new System.Drawing.Point(4, 22); this.TagTab.Name = "TagTab"; this.TagTab.Padding = new System.Windows.Forms.Padding(3); - this.TagTab.Size = new System.Drawing.Size(606, 87); + this.TagTab.Size = new System.Drawing.Size(606, 104); this.TagTab.TabIndex = 1; this.TagTab.Text = "Push tags"; this.TagTab.ToolTipText = "Push tags to remote repository"; @@ -365,7 +365,7 @@ private void InitializeComponent() this.groupBox3.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox3.Location = new System.Drawing.Point(3, 3); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(600, 81); + this.groupBox3.Size = new System.Drawing.Size(600, 98); this.groupBox3.TabIndex = 23; this.groupBox3.TabStop = false; this.groupBox3.Text = "Tag"; @@ -405,7 +405,7 @@ private void InitializeComponent() this.MultipleBranchTab.Location = new System.Drawing.Point(4, 22); this.MultipleBranchTab.Name = "MultipleBranchTab"; this.MultipleBranchTab.Padding = new System.Windows.Forms.Padding(3); - this.MultipleBranchTab.Size = new System.Drawing.Size(606, 87); + this.MultipleBranchTab.Size = new System.Drawing.Size(606, 104); this.MultipleBranchTab.TabIndex = 2; this.MultipleBranchTab.Text = "Push multiple branches"; this.MultipleBranchTab.UseVisualStyleBackColor = true; @@ -416,7 +416,7 @@ private void InitializeComponent() this.groupBox4.Dock = System.Windows.Forms.DockStyle.Fill; this.groupBox4.Location = new System.Drawing.Point(3, 3); this.groupBox4.Name = "groupBox4"; - this.groupBox4.Size = new System.Drawing.Size(600, 81); + this.groupBox4.Size = new System.Drawing.Size(600, 98); this.groupBox4.TabIndex = 0; this.groupBox4.TabStop = false; this.groupBox4.Text = "Select Branches to Push"; @@ -437,7 +437,7 @@ private void InitializeComponent() this.BranchGrid.Location = new System.Drawing.Point(3, 17); this.BranchGrid.Name = "BranchGrid"; this.BranchGrid.RowHeadersVisible = false; - this.BranchGrid.Size = new System.Drawing.Size(594, 61); + this.BranchGrid.Size = new System.Drawing.Size(594, 78); this.BranchGrid.TabIndex = 0; this.BranchGrid.CurrentCellDirtyStateChanged += new System.EventHandler(this.BranchGrid_CurrentCellDirtyStateChanged); // @@ -493,7 +493,7 @@ private void InitializeComponent() this.LoadSSHKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.LoadSSHKey.Image = global::GitUI.Properties.Resources.putty; this.LoadSSHKey.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.LoadSSHKey.Location = new System.Drawing.Point(372, 219); + this.LoadSSHKey.Location = new System.Drawing.Point(378, 234); this.LoadSSHKey.Name = "LoadSSHKey"; this.LoadSSHKey.Size = new System.Drawing.Size(137, 25); this.LoadSSHKey.TabIndex = 8; @@ -526,11 +526,10 @@ private void InitializeComponent() this._NO_TRANSLATE_Remotes.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this._NO_TRANSLATE_Remotes.FormattingEnabled = true; this._NO_TRANSLATE_Remotes.Location = new System.Drawing.Point(128, 19); + this._NO_TRANSLATE_Remotes.Margin = new System.Windows.Forms.Padding(4); this._NO_TRANSLATE_Remotes.Name = "_NO_TRANSLATE_Remotes"; this._NO_TRANSLATE_Remotes.Size = new System.Drawing.Size(320, 21); this._NO_TRANSLATE_Remotes.TabIndex = 1; - this._NO_TRANSLATE_Remotes.SelectedIndexChanged += new System.EventHandler(this.RemotesUpdated); - this._NO_TRANSLATE_Remotes.TextUpdate += new System.EventHandler(this.RemotesUpdated); this._NO_TRANSLATE_Remotes.Validated += new System.EventHandler(this.RemotesValidated); // // AddRemote @@ -572,7 +571,7 @@ private void InitializeComponent() // Pull // this.Pull.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.Pull.Location = new System.Drawing.Point(12, 219); + this.Pull.Location = new System.Drawing.Point(12, 234); this.Pull.Name = "Pull"; this.Pull.Size = new System.Drawing.Size(101, 25); this.Pull.TabIndex = 7; diff --git a/GitUI/CommandsDialogs/FormPush.cs b/GitUI/CommandsDialogs/FormPush.cs index 653bb358fd7..8f05c435db2 100644 --- a/GitUI/CommandsDialogs/FormPush.cs +++ b/GitUI/CommandsDialogs/FormPush.cs @@ -8,6 +8,7 @@ using GitCommands; using GitCommands.Config; using GitCommands.Repository; +using GitUI.Objects; using GitUI.Script; using GitUI.UserControls; using ResourceManager; @@ -19,12 +20,12 @@ public partial class FormPush : GitModuleForm private const string HeadText = "HEAD"; private const string AllRefs = "[ All ]"; private string _currentBranch; - private string _currentBranchRemote; + private GitRemote _currentBranchRemote; private bool _candidateForRebasingMergeCommit; private string _selectedBranch; - private string _selectedBranchRemote; + private GitRemote _selectedRemote; private string _selectedRemoteBranchName; - + private readonly IGitRemoteController _gitRemoteController; private readonly AsyncLoader _remoteBranchesLoader = new AsyncLoader(); public bool ErrorOccurred { get; private set; } @@ -96,9 +97,13 @@ public FormPush(GitUICommands aCommands) //can't be set in OnLoad, because after PushAndShowDialogWhenFailed() //they are reset to false if (aCommands != null) + { + _gitRemoteController = new GitRemoteController(Module); Init(); + } } + private void Init() { if (GitCommandHelpers.VersionInUse.SupportPushWithRecursiveSubmodulesCheck) @@ -116,24 +121,15 @@ private void Init() _currentBranch = Module.GetSelectedBranch(); - _NO_TRANSLATE_Remotes.DataSource = Module.GetRemotes(); + // refresh registered git remotes + _gitRemoteController.LoadRemotes(); + BindRemotesDropDown(_currentBranch); UpdateBranchDropDown(); UpdateRemoteBranchDropDown(); Push.Focus(); - _currentBranchRemote = Module.GetSetting(string.Format("branch.{0}.remote", _currentBranch)); - if (_currentBranchRemote.IsNullOrEmpty() && _NO_TRANSLATE_Remotes.Items.Count >= 2) - { - IList remotes = (IList)_NO_TRANSLATE_Remotes.DataSource; - int i = remotes.IndexOf("origin"); - _NO_TRANSLATE_Remotes.SelectedIndex = i >= 0 ? i : 0; - } - else - _NO_TRANSLATE_Remotes.Text = _currentBranchRemote; - RemotesUpdated(null, null); - if (AppSettings.AlwaysShowAdvOpt) ShowOptions_LinkClicked(null, null); } @@ -150,30 +146,42 @@ public DialogResult PushAndShowDialogWhenFailed() return PushAndShowDialogWhenFailed(null); } + private void PushClick(object sender, EventArgs e) { if (PushChanges(this)) Close(); } - private string GetDefaultPushRemote(String remote, String branch) + private void BindRemotesDropDown(string selectedRemoteName) { - Func IsSettingForBranch = (aSetting, aBranch) => - { - var head = new GitRef(Module, string.Empty, aSetting); - return head.IsHead && head.Name.Equals(aBranch); - }; + _NO_TRANSLATE_Remotes.SelectedIndexChanged -= RemotesUpdated; + _NO_TRANSLATE_Remotes.TextUpdate -= RemotesUpdated; - var pushSettings = Module.GetSettings(string.Format("remote.{0}.push", remote)); - var remoteHead = pushSettings. - Select(s => s.Split(':')). - Where(t => t.Length == 2). - Where(t => IsSettingForBranch(t[0], branch)). - Select(t => new GitRef(Module, string.Empty, t[1])). - Where(h => h.IsHead). - FirstOrDefault(); + _NO_TRANSLATE_Remotes.Sorted = false; + _NO_TRANSLATE_Remotes.DataSource = _gitRemoteController.Remotes; + _NO_TRANSLATE_Remotes.DisplayMember = "Name"; + _NO_TRANSLATE_Remotes.SelectedIndex = -1; - return remoteHead == null ? null : remoteHead.Name; + _NO_TRANSLATE_Remotes.SelectedIndexChanged += RemotesUpdated; + _NO_TRANSLATE_Remotes.TextUpdate += RemotesUpdated; + + _currentBranchRemote = _gitRemoteController.Remotes.FirstOrDefault(x => x.Name.Equals(selectedRemoteName, StringComparison.OrdinalIgnoreCase)); + if (_currentBranchRemote != null) + { + _NO_TRANSLATE_Remotes.SelectedItem = _currentBranchRemote; + } + else if (_gitRemoteController.Remotes.Any()) + { + // we couldn't find the default assigned remote for the selected branch + // it is usually gets mapped via FormRemotes -> "default pull behavior" tab + // so pick the default user remote + _NO_TRANSLATE_Remotes.SelectedIndex = 1; + } + else + { + _NO_TRANSLATE_Remotes.SelectedIndex = -1; + } } private bool IsBranchKnownToRemote(string remote, string branch) @@ -196,7 +204,9 @@ private bool PushChanges(IWin32Window owner) MessageBox.Show(owner, _selectDestinationDirectory.Text); return false; } - if (PushToRemote.Checked && string.IsNullOrEmpty(_NO_TRANSLATE_Remotes.Text)) + + var selectedRemoteName = _selectedRemote.Name; + if (PushToRemote.Checked && string.IsNullOrEmpty(selectedRemoteName)) { MessageBox.Show(owner, _selectRemote.Text); return false; @@ -216,8 +226,8 @@ private bool PushChanges(IWin32Window owner) //If the current branch is not the default push, and not known by the remote //(as far as we know since we are disconnected....) if (_NO_TRANSLATE_Branch.Text != AllRefs && - RemoteBranch.Text != GetDefaultPushRemote(_NO_TRANSLATE_Remotes.Text, _NO_TRANSLATE_Branch.Text) && - !IsBranchKnownToRemote(_NO_TRANSLATE_Remotes.Text, RemoteBranch.Text)) + RemoteBranch.Text != _gitRemoteController.GetDefaultPushRemote(_selectedRemote, _NO_TRANSLATE_Branch.Text) && + !IsBranchKnownToRemote(selectedRemoteName, RemoteBranch.Text)) { //Ask if this is really what the user wants if (!AppSettings.DontConfirmPushNewBranch && @@ -246,11 +256,11 @@ private bool PushChanges(IWin32Window owner) if (!File.Exists(AppSettings.Pageant)) MessageBoxes.PAgentNotFound(owner); else - Module.StartPageantForRemote(_NO_TRANSLATE_Remotes.Text); + Module.StartPageantForRemote(selectedRemoteName); } - destination = _NO_TRANSLATE_Remotes.Text; - remote = _NO_TRANSLATE_Remotes.Text.Trim(); + destination = selectedRemoteName; + remote = selectedRemoteName.Trim(); } string pushCmd; @@ -260,13 +270,9 @@ private bool PushChanges(IWin32Window owner) if (!track && !string.IsNullOrWhiteSpace(RemoteBranch.Text)) { GitRef selectedLocalBranch = _NO_TRANSLATE_Branch.SelectedItem as GitRef; - track = selectedLocalBranch != null && string.IsNullOrEmpty(selectedLocalBranch.TrackingRemote); - string[] remotes = _NO_TRANSLATE_Remotes.DataSource as string[]; - if (remotes != null) - foreach (string remoteBranch in remotes) - if (!string.IsNullOrEmpty(remoteBranch) && _NO_TRANSLATE_Branch.Text.StartsWith(remoteBranch)) - track = false; + track = selectedLocalBranch != null && string.IsNullOrEmpty(selectedLocalBranch.TrackingRemote) && + !_gitRemoteController.Remotes.Any(x => _NO_TRANSLATE_Branch.Text.StartsWith(x.Name, StringComparison.OrdinalIgnoreCase)); var autoSetupMerge = Module.EffectiveConfigFile.GetValue("branch.autoSetupMerge"); if (autoSetupMerge.IsNotNullOrWhitespace() && autoSetupMerge.ToLowerInvariant() == "false") { @@ -275,7 +281,6 @@ private bool PushChanges(IWin32Window owner) if (track && !AppSettings.DontConfirmAddTrackingRef) { DialogResult result = MessageBox.Show(String.Format(_updateTrackingReference.Text, selectedLocalBranch.Name, RemoteBranch.Text), _pushCaption.Text, MessageBoxButtons.YesNoCancel); - if (result == DialogResult.Cancel) return false; @@ -349,7 +354,6 @@ private bool PushChanges(IWin32Window owner) //controls can be accessed only from UI thread _selectedBranch = _NO_TRANSLATE_Branch.Text; _candidateForRebasingMergeCommit = PushToRemote.Checked && (_selectedBranch != AllRefs) && TabControlTagBranch.SelectedTab == BranchTab; - _selectedBranchRemote = _NO_TRANSLATE_Remotes.Text; _selectedRemoteBranchName = RemoteBranch.Text; using (var form = new FormRemoteProcess(Module, pushCmd) @@ -388,21 +392,17 @@ private ForcePushOptions GetForcePushOption() return ForcePushOptions.DoNotForce; } - private bool IsRebasingMergeCommit() { if (AppSettings.FormPullAction == AppSettings.PullAction.Rebase && _candidateForRebasingMergeCommit) { - if (_selectedBranch == _currentBranch && _selectedBranchRemote == _currentBranchRemote) + if (_selectedBranch == _currentBranch && _selectedRemote == _currentBranchRemote) { - string remoteBranchName = _selectedBranchRemote + "/" + _selectedRemoteBranchName; + string remoteBranchName = _selectedRemote + "/" + _selectedRemoteBranchName; return Module.ExistsMergeCommit(remoteBranchName, _selectedBranch); } - else - return false; } - else - return false; + return false; } private bool HandlePushOnExit(ref bool isError, FormProcess form) @@ -428,7 +428,7 @@ private bool HandlePushOnExit(ref bool isError, FormProcess form) if (AppSettings.AutoPullOnPushRejectedAction == null) { bool cancel = false; - string destination = PushToRemote.Checked ? _NO_TRANSLATE_Remotes.Text : PushDestination.Text; + string destination = PushToRemote.Checked ? _selectedRemote.Name : PushDestination.Text; string buttons = _pullRepositoryButtons.Text; switch (Module.LastPullAction) { @@ -537,7 +537,7 @@ private bool HandlePushOnExit(ref bool isError, FormProcess form) } bool pullCompleted; - UICommands.StartPullDialog(owner, true, null, _selectedBranchRemote, out pullCompleted, false); + UICommands.StartPullDialog(owner, true, null, _selectedRemote.Name, out pullCompleted, false); if (pullCompleted) { form.Retry(); @@ -611,19 +611,16 @@ private void BranchSelectedValueChanged(object sender, EventArgs e) if (PushToRemote.Checked) { var branch = _NO_TRANSLATE_Branch.SelectedItem as GitRef; - if (branch != null) { - - string defaultRemote = GetDefaultPushRemote(_NO_TRANSLATE_Remotes.Text.Trim(), branch.Name); - + string defaultRemote = _gitRemoteController.GetDefaultPushRemote(_selectedRemote, branch.Name); if (!defaultRemote.IsNullOrEmpty()) { RemoteBranch.Text = defaultRemote; return; } - if (branch.TrackingRemote.Equals(_NO_TRANSLATE_Remotes.Text.Trim())) + if (branch.TrackingRemote.Equals(_selectedRemote.Name, StringComparison.OrdinalIgnoreCase)) { RemoteBranch.Text = branch.MergeWith; if (!string.IsNullOrEmpty(RemoteBranch.Text)) @@ -648,13 +645,15 @@ private void FormPushLoad(object sender, EventArgs e) private void AddRemoteClick(object sender, EventArgs e) { - UICommands.StartRemotesDialog(this, _NO_TRANSLATE_Remotes.Text); - string origText = _NO_TRANSLATE_Remotes.Text; - _NO_TRANSLATE_Remotes.DataSource = Module.GetRemotes(); - if (_NO_TRANSLATE_Remotes.Items.Contains(origText)) // else first item gets selected - { - _NO_TRANSLATE_Remotes.Text = origText; - } + // store the seleccted remote name + string selectedRemoteName = _selectedRemote.Name; + + // launch remote management dialog + UICommands.StartRemotesDialog(this, selectedRemoteName); + + // coming back from the dialog, update the remotes list + _gitRemoteController.LoadRemotes(); + BindRemotesDropDown(selectedRemoteName); } private void PushToUrlCheckedChanged(object sender, EventArgs e) @@ -675,17 +674,24 @@ private void PushToUrlCheckedChanged(object sender, EventArgs e) private void RemotesUpdated(object sender, EventArgs e) { + _selectedRemote = _NO_TRANSLATE_Remotes.SelectedItem as GitRemote; + if (_selectedRemote == null) + { + return; + } + if (TabControlTagBranch.SelectedTab == MultipleBranchTab) UpdateMultiBranchView(); EnableLoadSshButton(); // update the text box of the Remote Url combobox to show the URL of selected remote + if (_selectedRemote != null) { - string pushUrl = Module.GetPathSetting(string.Format(SettingKeyString.RemotePushUrl, _NO_TRANSLATE_Remotes.Text)); + string pushUrl = _selectedRemote.PushUrl; if (pushUrl.IsNullOrEmpty()) { - pushUrl = Module.GetPathSetting(string.Format(SettingKeyString.RemoteUrl, _NO_TRANSLATE_Remotes.Text)); + pushUrl = _selectedRemote.Url; } PushDestination.Text = pushUrl; } @@ -695,7 +701,7 @@ private void RemotesUpdated(object sender, EventArgs e) // Doing this makes it pretty easy to accidentally create a branch on the remote. // But leaving it blank will do the 'default' thing, meaning all branches are pushed. // Solution: when pushing a branch that doesn't exist on the remote, ask what to do - var currentBranch = new GitRef(Module, null, _currentBranch, _NO_TRANSLATE_Remotes.Text); + var currentBranch = new GitRef(Module, null, _currentBranch, _selectedRemote.Name); _NO_TRANSLATE_Branch.Items.Add(currentBranch); _NO_TRANSLATE_Branch.SelectedItem = currentBranch; } @@ -705,7 +711,7 @@ private void RemotesUpdated(object sender, EventArgs e) private void EnableLoadSshButton() { - LoadSSHKey.Visible = !string.IsNullOrEmpty(Module.GetPuttyKeyFileForRemote(_NO_TRANSLATE_Remotes.Text)); + LoadSSHKey.Visible = _selectedRemote.PuttySshKey.IsNotNullOrWhitespace(); } private void LoadSshKeyClick(object sender, EventArgs e) @@ -713,7 +719,7 @@ private void LoadSshKeyClick(object sender, EventArgs e) if (!File.Exists(AppSettings.Pageant)) MessageBoxes.PAgentNotFound(this); else - Module.StartPageantForRemote(_NO_TRANSLATE_Remotes.Text); + Module.StartPageantForRemote(_selectedRemote.Name); } private void RemotesValidated(object sender, EventArgs e) @@ -732,6 +738,7 @@ private void FillTagDropDown() ComboBoxHelper.ResizeComboBoxDropDownWidth (TagComboBox, AppSettings.BranchDropDownMinWidth, AppSettings.BranchDropDownMaxWidth); } + private void ForcePushBranchesCheckedChanged(object sender, EventArgs e) { if (ForcePushBranches.Checked) @@ -757,12 +764,13 @@ private void UpdateMultiBranchView() var bs = new BindingSource { DataSource = _branchTable }; BranchGrid.DataSource = bs; - string remote = _NO_TRANSLATE_Remotes.Text.Trim(); - if (remote == "") + if (_selectedRemote == null) + { return; + } var localHeads = Module.GetRefs(false, true); - LoadMultiBranchViewData(remote, localHeads); + LoadMultiBranchViewData(_selectedRemote.Name, localHeads); } private void ProcessHeads(string remote, IList localHeads, RemoteActionResult> remoteHeads) diff --git a/GitUI/CommandsDialogs/FormRemotes.Designer.cs b/GitUI/CommandsDialogs/FormRemotes.Designer.cs index a18c7e3ee69..d3741589f30 100644 --- a/GitUI/CommandsDialogs/FormRemotes.Designer.cs +++ b/GitUI/CommandsDialogs/FormRemotes.Designer.cs @@ -30,37 +30,42 @@ protected override void Dispose(bool disposing) private void InitializeComponent() { this.components = new System.ComponentModel.Container(); - this.gitHeadBindingSource = new System.Windows.Forms.BindingSource(this.components); - this.tabControl1 = new System.Windows.Forms.TabControl(); - this.tabPage1 = new System.Windows.Forms.TabPage(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.panel1 = new System.Windows.Forms.Panel(); - this.Remotes = new System.Windows.Forms.ListBox(); - this.panelButtons = new System.Windows.Forms.Panel(); - this.flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel(); - this.New = new System.Windows.Forms.Button(); - this.Delete = new System.Windows.Forms.Button(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); - this.buttonClose = new System.Windows.Forms.Button(); + System.Windows.Forms.TableLayoutPanel flpnlRemoteManagement; + System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; + System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3; + System.Windows.Forms.Label lblHeaderLine2; + System.Windows.Forms.Panel pnlMgtDetails; + System.Windows.Forms.TableLayoutPanel tblpnlMgtDetails; + System.Windows.Forms.Label lblHeaderLine1; + System.Windows.Forms.Panel pnlManagementContainer; this.Save = new System.Windows.Forms.Button(); - this.PuTTYSSH = new System.Windows.Forms.GroupBox(); - this.LoadSSHKey = new System.Windows.Forms.Button(); + this.pnlMgtPuttySsh = new System.Windows.Forms.Panel(); this.PuttySshKey = new System.Windows.Forms.TextBox(); - this.TestConnection = new System.Windows.Forms.Button(); - this.label3 = new System.Windows.Forms.Label(); this.SshBrowse = new System.Windows.Forms.Button(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.label3 = new System.Windows.Forms.Label(); + this.TestConnection = new System.Windows.Forms.Button(); + this.LoadSSHKey = new System.Windows.Forms.Button(); + this.lblMgtPuttyPanelHeader = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); - this.RemoteName = new System.Windows.Forms.TextBox(); - this.folderBrowserButtonUrl = new GitUI.UserControls.FolderBrowserButton(); - this.Url = new System.Windows.Forms.ComboBox(); - this.label2 = new System.Windows.Forms.Label(); - this.checkBoxSepPushUrl = new System.Windows.Forms.CheckBox(); this.folderBrowserButtonPushUrl = new GitUI.UserControls.FolderBrowserButton(); this.comboBoxPushUrl = new System.Windows.Forms.ComboBox(); + this.label2 = new System.Windows.Forms.Label(); + this.Url = new System.Windows.Forms.ComboBox(); this.labelPushUrl = new System.Windows.Forms.Label(); + this.folderBrowserButtonUrl = new GitUI.UserControls.FolderBrowserButton(); + this.checkBoxSepPushUrl = new System.Windows.Forms.CheckBox(); + this.RemoteName = new System.Windows.Forms.TextBox(); + this.lblMgtDetailsPanelHeader = new System.Windows.Forms.Label(); + this.gbMgtPanel = new System.Windows.Forms.GroupBox(); + this.panelButtons = new System.Windows.Forms.FlowLayoutPanel(); + this.New = new System.Windows.Forms.Button(); + this.Delete = new System.Windows.Forms.Button(); + this.gitHeadBindingSource = new System.Windows.Forms.BindingSource(this.components); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.panel1 = new System.Windows.Forms.Panel(); + this.Remotes = new System.Windows.Forms.ListBox(); this.tabPage2 = new System.Windows.Forms.TabPage(); this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); this.splitContainer3 = new System.Windows.Forms.SplitContainer(); @@ -90,23 +95,29 @@ private void InitializeComponent() this.nameDataGridViewTextBoxColumn = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.BName = new System.Windows.Forms.DataGridViewTextBoxColumn(); this.dataGridViewTextBoxColumn1 = new System.Windows.Forms.DataGridViewTextBoxColumn(); - this.tableLayoutPanel4 = new System.Windows.Forms.TableLayoutPanel(); - this.flowLayoutPanel4 = new System.Windows.Forms.FlowLayoutPanel(); + flpnlRemoteManagement = new System.Windows.Forms.TableLayoutPanel(); + flowLayoutPanel2 = new System.Windows.Forms.FlowLayoutPanel(); + tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + flowLayoutPanel3 = new System.Windows.Forms.FlowLayoutPanel(); + lblHeaderLine2 = new System.Windows.Forms.Label(); + pnlMgtDetails = new System.Windows.Forms.Panel(); + tblpnlMgtDetails = new System.Windows.Forms.TableLayoutPanel(); + lblHeaderLine1 = new System.Windows.Forms.Label(); + pnlManagementContainer = new System.Windows.Forms.Panel(); + flpnlRemoteManagement.SuspendLayout(); + flowLayoutPanel2.SuspendLayout(); + this.pnlMgtPuttySsh.SuspendLayout(); + tableLayoutPanel1.SuspendLayout(); + flowLayoutPanel3.SuspendLayout(); + pnlMgtDetails.SuspendLayout(); + tblpnlMgtDetails.SuspendLayout(); + pnlManagementContainer.SuspendLayout(); + this.gbMgtPanel.SuspendLayout(); + this.panelButtons.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.gitHeadBindingSource)).BeginInit(); this.tabControl1.SuspendLayout(); this.tabPage1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); this.panel1.SuspendLayout(); - this.panelButtons.SuspendLayout(); - this.flowLayoutPanel3.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - this.flowLayoutPanel2.SuspendLayout(); - this.PuTTYSSH.SuspendLayout(); - this.groupBox1.SuspendLayout(); - this.tableLayoutPanel3.SuspendLayout(); this.tabPage2.SuspendLayout(); this.tableLayoutPanel2.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); @@ -115,165 +126,46 @@ private void InitializeComponent() this.splitContainer3.SuspendLayout(); ((System.ComponentModel.ISupportInitialize)(this.RemoteBranches)).BeginInit(); this.flowLayoutPanel1.SuspendLayout(); - this.tableLayoutPanel4.SuspendLayout(); - this.flowLayoutPanel4.SuspendLayout(); this.SuspendLayout(); // - // gitHeadBindingSource - // - this.gitHeadBindingSource.DataSource = typeof(GitCommands.GitRef); - // - // tabControl1 - // - this.tabControl1.Controls.Add(this.tabPage1); - this.tabControl1.Controls.Add(this.tabPage2); - this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl1.Location = new System.Drawing.Point(0, 0); - this.tabControl1.Name = "tabControl1"; - this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(704, 394); - this.tabControl1.TabIndex = 1; - // - // tabPage1 - // - this.tabPage1.Controls.Add(this.splitContainer1); - this.tabPage1.Location = new System.Drawing.Point(4, 22); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(696, 368); - this.tabPage1.TabIndex = 0; - this.tabPage1.Text = "Remote repositories"; - this.tabPage1.UseVisualStyleBackColor = true; - // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer1.FixedPanel = System.Windows.Forms.FixedPanel.Panel1; - this.splitContainer1.Location = new System.Drawing.Point(3, 3); - this.splitContainer1.Name = "splitContainer1"; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.panel1); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.Controls.Add(this.tableLayoutPanel1); - this.splitContainer1.Size = new System.Drawing.Size(690, 362); - this.splitContainer1.SplitterDistance = 162; - this.splitContainer1.TabIndex = 0; - // - // panel1 - // - this.panel1.Controls.Add(this.Remotes); - this.panel1.Controls.Add(this.panelButtons); - this.panel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.panel1.Location = new System.Drawing.Point(0, 0); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(162, 362); - this.panel1.TabIndex = 1; - // - // Remotes - // - this.Remotes.Dock = System.Windows.Forms.DockStyle.Fill; - this.Remotes.FormattingEnabled = true; - this.Remotes.Location = new System.Drawing.Point(0, 0); - this.Remotes.Name = "Remotes"; - this.Remotes.Size = new System.Drawing.Size(162, 296); - this.Remotes.TabIndex = 0; - this.Remotes.SelectedIndexChanged += new System.EventHandler(this.RemotesSelectedIndexChanged); - // - // panelButtons - // - this.panelButtons.Controls.Add(this.flowLayoutPanel3); - this.panelButtons.Dock = System.Windows.Forms.DockStyle.Bottom; - this.panelButtons.Location = new System.Drawing.Point(0, 296); - this.panelButtons.Name = "panelButtons"; - this.panelButtons.Size = new System.Drawing.Size(162, 66); - this.panelButtons.TabIndex = 1; - // - // flowLayoutPanel3 - // - this.flowLayoutPanel3.Controls.Add(this.New); - this.flowLayoutPanel3.Controls.Add(this.Delete); - this.flowLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; - this.flowLayoutPanel3.Location = new System.Drawing.Point(0, 0); - this.flowLayoutPanel3.Name = "flowLayoutPanel3"; - this.flowLayoutPanel3.Size = new System.Drawing.Size(162, 66); - this.flowLayoutPanel3.TabIndex = 0; - // - // New - // - this.New.Image = global::GitUI.Properties.Resources.New; - this.New.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.New.Location = new System.Drawing.Point(3, 3); - this.New.Name = "New"; - this.New.Size = new System.Drawing.Size(92, 25); - this.New.TabIndex = 0; - this.New.Text = "New"; - this.New.UseVisualStyleBackColor = true; - this.New.Click += new System.EventHandler(this.NewClick); - // - // Delete - // - this.Delete.Image = global::GitUI.Properties.Resources.Delete; - this.Delete.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.Delete.Location = new System.Drawing.Point(3, 34); - this.Delete.Name = "Delete"; - this.Delete.Size = new System.Drawing.Size(92, 25); - this.Delete.TabIndex = 1; - this.Delete.Text = "Delete"; - this.Delete.UseVisualStyleBackColor = true; - this.Delete.Click += new System.EventHandler(this.DeleteClick); - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.AutoSize = true; - this.tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel1.ColumnCount = 1; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Controls.Add(this.flowLayoutPanel2, 0, 2); - this.tableLayoutPanel1.Controls.Add(this.PuTTYSSH, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.groupBox1, 0, 0); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 3; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(524, 362); - this.tableLayoutPanel1.TabIndex = 13; + // flpnlRemoteManagement + // + flpnlRemoteManagement.AutoSize = true; + flpnlRemoteManagement.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + flpnlRemoteManagement.ColumnCount = 1; + flpnlRemoteManagement.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + flpnlRemoteManagement.Controls.Add(flowLayoutPanel2, 0, 2); + flpnlRemoteManagement.Controls.Add(this.pnlMgtPuttySsh, 0, 1); + flpnlRemoteManagement.Controls.Add(pnlMgtDetails, 0, 0); + flpnlRemoteManagement.Dock = System.Windows.Forms.DockStyle.Fill; + flpnlRemoteManagement.Location = new System.Drawing.Point(3, 17); + flpnlRemoteManagement.Name = "flpnlRemoteManagement"; + flpnlRemoteManagement.RowCount = 3; + flpnlRemoteManagement.RowStyles.Add(new System.Windows.Forms.RowStyle()); + flpnlRemoteManagement.RowStyles.Add(new System.Windows.Forms.RowStyle()); + flpnlRemoteManagement.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + flpnlRemoteManagement.Size = new System.Drawing.Size(479, 283); + flpnlRemoteManagement.TabIndex = 0; // // flowLayoutPanel2 // - this.flowLayoutPanel2.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel2.Controls.Add(this.buttonClose); - this.flowLayoutPanel2.Controls.Add(this.Save); - this.flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.flowLayoutPanel2.Location = new System.Drawing.Point(250, 330); - this.flowLayoutPanel2.Name = "flowLayoutPanel2"; - this.flowLayoutPanel2.Size = new System.Drawing.Size(271, 29); - this.flowLayoutPanel2.TabIndex = 2; - // - // buttonClose - // - this.buttonClose.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.buttonClose.Location = new System.Drawing.Point(193, 3); - this.buttonClose.Name = "buttonClose"; - this.buttonClose.Size = new System.Drawing.Size(75, 25); - this.buttonClose.TabIndex = 1; - this.buttonClose.Text = "Close"; - this.buttonClose.UseVisualStyleBackColor = true; - this.buttonClose.Click += new System.EventHandler(this.buttonClose_Click); + flowLayoutPanel2.AutoSize = true; + flowLayoutPanel2.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + flowLayoutPanel2.Controls.Add(this.Save); + flowLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Top; + flowLayoutPanel2.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; + flowLayoutPanel2.Location = new System.Drawing.Point(3, 249); + flowLayoutPanel2.Name = "flowLayoutPanel2"; + flowLayoutPanel2.Padding = new System.Windows.Forms.Padding(0, 0, 20, 0); + flowLayoutPanel2.Size = new System.Drawing.Size(473, 31); + flowLayoutPanel2.TabIndex = 2; // // Save // this.Save.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); this.Save.Image = global::GitUI.Properties.Resources.IconSave; this.Save.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.Save.Location = new System.Drawing.Point(57, 3); + this.Save.Location = new System.Drawing.Point(320, 3); this.Save.Name = "Save"; this.Save.Size = new System.Drawing.Size(130, 25); this.Save.TabIndex = 0; @@ -281,214 +173,412 @@ private void InitializeComponent() this.Save.UseVisualStyleBackColor = true; this.Save.Click += new System.EventHandler(this.SaveClick); // - // PuTTYSSH + // pnlMgtPuttySsh + // + this.pnlMgtPuttySsh.AutoSize = true; + this.pnlMgtPuttySsh.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.pnlMgtPuttySsh.Controls.Add(tableLayoutPanel1); + this.pnlMgtPuttySsh.Controls.Add(this.lblMgtPuttyPanelHeader); + this.pnlMgtPuttySsh.Controls.Add(lblHeaderLine2); + this.pnlMgtPuttySsh.Dock = System.Windows.Forms.DockStyle.Top; + this.pnlMgtPuttySsh.Location = new System.Drawing.Point(3, 152); + this.pnlMgtPuttySsh.Name = "pnlMgtPuttySsh"; + this.pnlMgtPuttySsh.Padding = new System.Windows.Forms.Padding(0, 0, 0, 8); + this.pnlMgtPuttySsh.Size = new System.Drawing.Size(473, 91); + this.pnlMgtPuttySsh.TabIndex = 1; + this.pnlMgtPuttySsh.Text = "PuTTY SSH"; // - this.PuTTYSSH.AutoSize = true; - this.PuTTYSSH.Controls.Add(this.tableLayoutPanel4); - this.PuTTYSSH.Dock = System.Windows.Forms.DockStyle.Fill; - this.PuTTYSSH.Location = new System.Drawing.Point(3, 140); - this.PuTTYSSH.Name = "PuTTYSSH"; - this.PuTTYSSH.Size = new System.Drawing.Size(518, 88); - this.PuTTYSSH.TabIndex = 1; - this.PuTTYSSH.TabStop = false; - this.PuTTYSSH.Text = "PuTTY SSH"; - // - // LoadSSHKey + // tableLayoutPanel1 // - this.LoadSSHKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.LoadSSHKey.Image = global::GitUI.Properties.Resources.putty; - this.LoadSSHKey.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.LoadSSHKey.Location = new System.Drawing.Point(344, 3); - this.LoadSSHKey.Name = "LoadSSHKey"; - this.LoadSSHKey.Size = new System.Drawing.Size(153, 25); - this.LoadSSHKey.TabIndex = 2; - this.LoadSSHKey.Text = "Load SSH key"; - this.LoadSSHKey.UseVisualStyleBackColor = true; - this.LoadSSHKey.Click += new System.EventHandler(this.LoadSshKeyClick); + tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + tableLayoutPanel1.AutoSize = true; + tableLayoutPanel1.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + tableLayoutPanel1.ColumnCount = 3; + tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120F)); + tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 110F)); + tableLayoutPanel1.Controls.Add(this.PuttySshKey, 1, 0); + tableLayoutPanel1.Controls.Add(this.SshBrowse, 2, 0); + tableLayoutPanel1.Controls.Add(this.label3, 0, 0); + tableLayoutPanel1.Controls.Add(flowLayoutPanel3, 1, 1); + tableLayoutPanel1.Location = new System.Drawing.Point(16, 18); + tableLayoutPanel1.Name = "tableLayoutPanel1"; + tableLayoutPanel1.RowCount = 2; + tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tableLayoutPanel1.Size = new System.Drawing.Size(435, 93); + tableLayoutPanel1.TabIndex = 12; // // PuttySshKey // this.PuttySshKey.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.PuttySshKey.Location = new System.Drawing.Point(87, 3); + this.PuttySshKey.Location = new System.Drawing.Point(123, 3); this.PuttySshKey.Name = "PuttySshKey"; - this.PuttySshKey.Size = new System.Drawing.Size(316, 21); - this.PuttySshKey.TabIndex = 0; + this.PuttySshKey.Size = new System.Drawing.Size(199, 21); + this.PuttySshKey.TabIndex = 1; + // + // SshBrowse + // + this.SshBrowse.Dock = System.Windows.Forms.DockStyle.Fill; + this.SshBrowse.Image = global::GitUI.Properties.Resources.New; + this.SshBrowse.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.SshBrowse.Location = new System.Drawing.Point(328, 3); + this.SshBrowse.Name = "SshBrowse"; + this.SshBrowse.Size = new System.Drawing.Size(104, 25); + this.SshBrowse.TabIndex = 2; + this.SshBrowse.Text = " Browse..."; + this.SshBrowse.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; + this.SshBrowse.UseVisualStyleBackColor = true; + this.SshBrowse.Click += new System.EventHandler(this.SshBrowseClick); + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Dock = System.Windows.Forms.DockStyle.Fill; + this.label3.Location = new System.Drawing.Point(3, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(114, 31); + this.label3.TabIndex = 0; + this.label3.Text = "Private key file"; + this.label3.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + // + // flowLayoutPanel3 + // + flowLayoutPanel3.AutoSize = true; + flowLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + tableLayoutPanel1.SetColumnSpan(flowLayoutPanel3, 2); + flowLayoutPanel3.Controls.Add(this.TestConnection); + flowLayoutPanel3.Controls.Add(this.LoadSSHKey); + flowLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + flowLayoutPanel3.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; + flowLayoutPanel3.Location = new System.Drawing.Point(120, 31); + flowLayoutPanel3.Margin = new System.Windows.Forms.Padding(0); + flowLayoutPanel3.Name = "flowLayoutPanel3"; + flowLayoutPanel3.Size = new System.Drawing.Size(315, 62); + flowLayoutPanel3.TabIndex = 3; // // TestConnection // this.TestConnection.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); this.TestConnection.Image = global::GitUI.Properties.Resources.putty; this.TestConnection.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; - this.TestConnection.Location = new System.Drawing.Point(182, 3); + this.TestConnection.Location = new System.Drawing.Point(156, 3); this.TestConnection.Name = "TestConnection"; this.TestConnection.Size = new System.Drawing.Size(156, 25); - this.TestConnection.TabIndex = 3; + this.TestConnection.TabIndex = 1; this.TestConnection.Text = "Test connection"; this.TestConnection.UseVisualStyleBackColor = true; this.TestConnection.Click += new System.EventHandler(this.TestConnectionClick); // - // label3 + // LoadSSHKey // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(3, 0); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(78, 13); - this.label3.TabIndex = 5; - this.label3.Text = "Private key file"; + this.LoadSSHKey.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.LoadSSHKey.Image = global::GitUI.Properties.Resources.putty; + this.LoadSSHKey.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.LoadSSHKey.Location = new System.Drawing.Point(159, 34); + this.LoadSSHKey.Name = "LoadSSHKey"; + this.LoadSSHKey.Size = new System.Drawing.Size(153, 25); + this.LoadSSHKey.TabIndex = 0; + this.LoadSSHKey.Text = "Load SSH key"; + this.LoadSSHKey.UseVisualStyleBackColor = true; + this.LoadSSHKey.Click += new System.EventHandler(this.LoadSshKeyClick); // - // SshBrowse + // lblMgtPuttyPanelHeader // - this.SshBrowse.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.SshBrowse.Location = new System.Drawing.Point(409, 3); - this.SshBrowse.Name = "SshBrowse"; - this.SshBrowse.Size = new System.Drawing.Size(100, 25); - this.SshBrowse.TabIndex = 1; - this.SshBrowse.Text = "Browse"; - this.SshBrowse.UseVisualStyleBackColor = true; - this.SshBrowse.Click += new System.EventHandler(this.SshBrowseClick); + this.lblMgtPuttyPanelHeader.AutoSize = true; + this.lblMgtPuttyPanelHeader.Location = new System.Drawing.Point(8, 0); + this.lblMgtPuttyPanelHeader.Name = "lblMgtPuttyPanelHeader"; + this.lblMgtPuttyPanelHeader.Size = new System.Drawing.Size(59, 13); + this.lblMgtPuttyPanelHeader.TabIndex = 0; + this.lblMgtPuttyPanelHeader.Text = "PuTTY SSH"; + // + // lblHeaderLine2 // - // groupBox1 - // - this.groupBox1.AutoSize = true; - this.groupBox1.Controls.Add(this.tableLayoutPanel3); - this.groupBox1.Dock = System.Windows.Forms.DockStyle.Fill; - this.groupBox1.Location = new System.Drawing.Point(3, 3); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(518, 131); - this.groupBox1.TabIndex = 0; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Details"; - // - // tableLayoutPanel3 - // - this.tableLayoutPanel3.AutoSize = true; - this.tableLayoutPanel3.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel3.ColumnCount = 3; - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel3.Controls.Add(this.label1, 0, 0); - this.tableLayoutPanel3.Controls.Add(this.folderBrowserButtonPushUrl, 2, 3); - this.tableLayoutPanel3.Controls.Add(this.RemoteName, 1, 0); - this.tableLayoutPanel3.Controls.Add(this.labelPushUrl, 0, 3); - this.tableLayoutPanel3.Controls.Add(this.label2, 0, 1); - this.tableLayoutPanel3.Controls.Add(this.checkBoxSepPushUrl, 0, 2); - this.tableLayoutPanel3.Controls.Add(this.Url, 1, 1); - this.tableLayoutPanel3.Controls.Add(this.comboBoxPushUrl, 1, 3); - this.tableLayoutPanel3.Controls.Add(this.folderBrowserButtonUrl, 2, 1); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel3.Location = new System.Drawing.Point(3, 17); - this.tableLayoutPanel3.Name = "tableLayoutPanel3"; - this.tableLayoutPanel3.RowCount = 4; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel3.Size = new System.Drawing.Size(512, 111); - this.tableLayoutPanel3.TabIndex = 7; + lblHeaderLine2.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + lblHeaderLine2.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + lblHeaderLine2.Location = new System.Drawing.Point(16, 8); + lblHeaderLine2.Name = "lblHeaderLine2"; + lblHeaderLine2.Size = new System.Drawing.Size(446, 3); + lblHeaderLine2.TabIndex = 1; + // + // pnlMgtDetails + // + pnlMgtDetails.AutoSize = true; + pnlMgtDetails.Controls.Add(tblpnlMgtDetails); + pnlMgtDetails.Controls.Add(this.lblMgtDetailsPanelHeader); + pnlMgtDetails.Controls.Add(lblHeaderLine1); + pnlMgtDetails.Dock = System.Windows.Forms.DockStyle.Top; + pnlMgtDetails.Location = new System.Drawing.Point(3, 3); + pnlMgtDetails.Name = "pnlMgtDetails"; + pnlMgtDetails.Padding = new System.Windows.Forms.Padding(0, 0, 0, 8); + pnlMgtDetails.Size = new System.Drawing.Size(473, 143); + pnlMgtDetails.TabIndex = 0; + pnlMgtDetails.Text = "Details"; + // + // tblpnlMgtDetails + // + tblpnlMgtDetails.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + tblpnlMgtDetails.AutoSize = true; + tblpnlMgtDetails.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + tblpnlMgtDetails.ColumnCount = 3; + tblpnlMgtDetails.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 120F)); + tblpnlMgtDetails.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + tblpnlMgtDetails.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Absolute, 110F)); + tblpnlMgtDetails.Controls.Add(this.label1, 0, 0); + tblpnlMgtDetails.Controls.Add(this.folderBrowserButtonPushUrl, 2, 3); + tblpnlMgtDetails.Controls.Add(this.label2, 0, 1); + tblpnlMgtDetails.Controls.Add(this.Url, 1, 1); + tblpnlMgtDetails.Controls.Add(this.comboBoxPushUrl, 1, 3); + tblpnlMgtDetails.Controls.Add(this.labelPushUrl, 0, 3); + tblpnlMgtDetails.Controls.Add(this.folderBrowserButtonUrl, 2, 1); + tblpnlMgtDetails.Controls.Add(this.checkBoxSepPushUrl, 0, 2); + tblpnlMgtDetails.Controls.Add(this.RemoteName, 1, 0); + tblpnlMgtDetails.Location = new System.Drawing.Point(16, 18); + tblpnlMgtDetails.Name = "tblpnlMgtDetails"; + tblpnlMgtDetails.RowCount = 4; + tblpnlMgtDetails.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tblpnlMgtDetails.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tblpnlMgtDetails.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tblpnlMgtDetails.RowStyles.Add(new System.Windows.Forms.RowStyle()); + tblpnlMgtDetails.Size = new System.Drawing.Size(435, 114); + tblpnlMgtDetails.TabIndex = 11; // // label1 // - this.label1.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(3, 7); + this.label1.Dock = System.Windows.Forms.DockStyle.Fill; + this.label1.Location = new System.Drawing.Point(3, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(34, 13); + this.label1.Size = new System.Drawing.Size(114, 29); this.label1.TabIndex = 0; this.label1.Text = "Name"; + this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // - // RemoteName + // folderBrowserButtonPushUrl + // + this.folderBrowserButtonPushUrl.Dock = System.Windows.Forms.DockStyle.Fill; + this.folderBrowserButtonPushUrl.Location = new System.Drawing.Point(328, 86); + this.folderBrowserButtonPushUrl.Name = "folderBrowserButtonPushUrl"; + this.folderBrowserButtonPushUrl.PathShowingControl = this.comboBoxPushUrl; + this.folderBrowserButtonPushUrl.Size = new System.Drawing.Size(104, 25); + this.folderBrowserButtonPushUrl.TabIndex = 8; + this.folderBrowserButtonPushUrl.Visible = false; // - this.RemoteName.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + // comboBoxPushUrl + // + this.comboBoxPushUrl.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.RemoteName.Location = new System.Drawing.Point(121, 3); - this.RemoteName.Name = "RemoteName"; - this.RemoteName.Size = new System.Drawing.Size(282, 21); - this.RemoteName.TabIndex = 0; + this.comboBoxPushUrl.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; + this.comboBoxPushUrl.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; + this.comboBoxPushUrl.FormattingEnabled = true; + this.comboBoxPushUrl.Location = new System.Drawing.Point(123, 86); + this.comboBoxPushUrl.Name = "comboBoxPushUrl"; + this.comboBoxPushUrl.Size = new System.Drawing.Size(199, 21); + this.comboBoxPushUrl.TabIndex = 7; + this.comboBoxPushUrl.Visible = false; // - // folderBrowserButtonUrl + // label2 // - this.folderBrowserButtonUrl.Location = new System.Drawing.Point(409, 30); - this.folderBrowserButtonUrl.Name = "folderBrowserButtonUrl"; - this.folderBrowserButtonUrl.PathShowingControl = this.Url; - this.folderBrowserButtonUrl.Size = new System.Drawing.Size(100, 24); - this.folderBrowserButtonUrl.TabIndex = 2; + this.label2.Dock = System.Windows.Forms.DockStyle.Fill; + this.label2.Location = new System.Drawing.Point(3, 29); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(114, 31); + this.label2.TabIndex = 2; + this.label2.Text = "Url"; + this.label2.TextAlign = System.Drawing.ContentAlignment.MiddleRight; // // Url // - this.Url.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.Url.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.Url.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; this.Url.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; this.Url.FormattingEnabled = true; - this.Url.Location = new System.Drawing.Point(121, 30); + this.Url.Location = new System.Drawing.Point(123, 32); this.Url.Name = "Url"; - this.Url.Size = new System.Drawing.Size(282, 21); - this.Url.TabIndex = 1; + this.Url.Size = new System.Drawing.Size(199, 21); + this.Url.TabIndex = 3; // - // label2 + // labelPushUrl // - this.label2.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 35); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(20, 13); - this.label2.TabIndex = 2; - this.label2.Text = "Url"; + this.labelPushUrl.Dock = System.Windows.Forms.DockStyle.Fill; + this.labelPushUrl.Location = new System.Drawing.Point(3, 83); + this.labelPushUrl.Name = "labelPushUrl"; + this.labelPushUrl.Size = new System.Drawing.Size(114, 31); + this.labelPushUrl.TabIndex = 6; + this.labelPushUrl.Text = "Push Url"; + this.labelPushUrl.TextAlign = System.Drawing.ContentAlignment.MiddleRight; + this.labelPushUrl.Visible = false; + // + // folderBrowserButtonUrl + // + this.folderBrowserButtonUrl.Dock = System.Windows.Forms.DockStyle.Fill; + this.folderBrowserButtonUrl.Location = new System.Drawing.Point(328, 32); + this.folderBrowserButtonUrl.Name = "folderBrowserButtonUrl"; + this.folderBrowserButtonUrl.PathShowingControl = this.Url; + this.folderBrowserButtonUrl.Size = new System.Drawing.Size(104, 25); + this.folderBrowserButtonUrl.TabIndex = 4; // // checkBoxSepPushUrl // - this.checkBoxSepPushUrl.Anchor = System.Windows.Forms.AnchorStyles.Left; this.checkBoxSepPushUrl.AutoSize = true; - this.checkBoxSepPushUrl.Location = new System.Drawing.Point(3, 60); + tblpnlMgtDetails.SetColumnSpan(this.checkBoxSepPushUrl, 2); + this.checkBoxSepPushUrl.Dock = System.Windows.Forms.DockStyle.Fill; + this.checkBoxSepPushUrl.Location = new System.Drawing.Point(3, 63); this.checkBoxSepPushUrl.Name = "checkBoxSepPushUrl"; - this.checkBoxSepPushUrl.Size = new System.Drawing.Size(112, 17); - this.checkBoxSepPushUrl.TabIndex = 3; + this.checkBoxSepPushUrl.Padding = new System.Windows.Forms.Padding(24, 0, 0, 0); + this.checkBoxSepPushUrl.Size = new System.Drawing.Size(319, 17); + this.checkBoxSepPushUrl.TabIndex = 5; this.checkBoxSepPushUrl.Text = "Separate Push Url"; this.checkBoxSepPushUrl.UseVisualStyleBackColor = true; this.checkBoxSepPushUrl.CheckedChanged += new System.EventHandler(this.checkBoxSepPushUrl_CheckedChanged); // - // folderBrowserButtonPushUrl + // RemoteName // - this.folderBrowserButtonPushUrl.Location = new System.Drawing.Point(409, 83); - this.folderBrowserButtonPushUrl.Name = "folderBrowserButtonPushUrl"; - this.folderBrowserButtonPushUrl.PathShowingControl = this.comboBoxPushUrl; - this.folderBrowserButtonPushUrl.Size = new System.Drawing.Size(100, 25); - this.folderBrowserButtonPushUrl.TabIndex = 5; - this.folderBrowserButtonPushUrl.Visible = false; + this.RemoteName.Dock = System.Windows.Forms.DockStyle.Fill; + this.RemoteName.Location = new System.Drawing.Point(123, 3); + this.RemoteName.Name = "RemoteName"; + this.RemoteName.Size = new System.Drawing.Size(199, 21); + this.RemoteName.TabIndex = 1; + this.RemoteName.TextChanged += new System.EventHandler(this.RemoteName_TextChanged); // - // comboBoxPushUrl + // lblMgtDetailsPanelHeader // - this.comboBoxPushUrl.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + this.lblMgtDetailsPanelHeader.AutoSize = true; + this.lblMgtDetailsPanelHeader.Location = new System.Drawing.Point(8, 0); + this.lblMgtDetailsPanelHeader.Name = "lblMgtDetailsPanelHeader"; + this.lblMgtDetailsPanelHeader.Size = new System.Drawing.Size(39, 13); + this.lblMgtDetailsPanelHeader.TabIndex = 0; + this.lblMgtDetailsPanelHeader.Text = "Details"; + // + // lblHeaderLine1 + // + lblHeaderLine1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.comboBoxPushUrl.AutoCompleteMode = System.Windows.Forms.AutoCompleteMode.SuggestAppend; - this.comboBoxPushUrl.AutoCompleteSource = System.Windows.Forms.AutoCompleteSource.ListItems; - this.comboBoxPushUrl.FormattingEnabled = true; - this.comboBoxPushUrl.Location = new System.Drawing.Point(121, 83); - this.comboBoxPushUrl.Name = "comboBoxPushUrl"; - this.comboBoxPushUrl.Size = new System.Drawing.Size(282, 21); - this.comboBoxPushUrl.TabIndex = 4; - this.comboBoxPushUrl.Visible = false; + lblHeaderLine1.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; + lblHeaderLine1.Location = new System.Drawing.Point(16, 8); + lblHeaderLine1.Name = "lblHeaderLine1"; + lblHeaderLine1.Size = new System.Drawing.Size(446, 3); + lblHeaderLine1.TabIndex = 1; + // + // pnlManagementContainer + // + pnlManagementContainer.Controls.Add(this.gbMgtPanel); + pnlManagementContainer.Dock = System.Windows.Forms.DockStyle.Fill; + pnlManagementContainer.Location = new System.Drawing.Point(197, 3); + pnlManagementContainer.Name = "pnlManagementContainer"; + pnlManagementContainer.Padding = new System.Windows.Forms.Padding(8, 4, 8, 8); + pnlManagementContainer.Size = new System.Drawing.Size(501, 293); + pnlManagementContainer.TabIndex = 0; + // + // gbMgtPanel + // + this.gbMgtPanel.AutoSize = true; + this.gbMgtPanel.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; + this.gbMgtPanel.Controls.Add(flpnlRemoteManagement); + this.gbMgtPanel.Dock = System.Windows.Forms.DockStyle.Top; + this.gbMgtPanel.Location = new System.Drawing.Point(8, 4); + this.gbMgtPanel.Name = "gbMgtPanel"; + this.gbMgtPanel.Size = new System.Drawing.Size(485, 303); + this.gbMgtPanel.TabIndex = 0; + this.gbMgtPanel.TabStop = false; + this.gbMgtPanel.Text = "Create New Remote"; // - // labelPushUrl + // panelButtons // - this.labelPushUrl.Anchor = System.Windows.Forms.AnchorStyles.Left; - this.labelPushUrl.AutoSize = true; - this.labelPushUrl.Location = new System.Drawing.Point(3, 89); - this.labelPushUrl.Name = "labelPushUrl"; - this.labelPushUrl.Size = new System.Drawing.Size(46, 13); - this.labelPushUrl.TabIndex = 6; - this.labelPushUrl.Text = "Push Url"; - this.labelPushUrl.Visible = false; + this.panelButtons.AutoSize = true; + this.panelButtons.Controls.Add(this.New); + this.panelButtons.Controls.Add(this.Delete); + this.panelButtons.Dock = System.Windows.Forms.DockStyle.Right; + this.panelButtons.FlowDirection = System.Windows.Forms.FlowDirection.TopDown; + this.panelButtons.Location = new System.Drawing.Point(150, 8); + this.panelButtons.Margin = new System.Windows.Forms.Padding(8); + this.panelButtons.Name = "panelButtons"; + this.panelButtons.Padding = new System.Windows.Forms.Padding(4, 0, 0, 0); + this.panelButtons.Size = new System.Drawing.Size(36, 277); + this.panelButtons.TabIndex = 1; + // + // New + // + this.New.Image = global::GitUI.Properties.Resources.Icon_82; + this.New.Location = new System.Drawing.Point(7, 3); + this.New.Name = "New"; + this.New.Size = new System.Drawing.Size(26, 26); + this.New.TabIndex = 0; + this.New.UseVisualStyleBackColor = true; + this.New.Click += new System.EventHandler(this.NewClick); + // + // Delete + // + this.Delete.Image = global::GitUI.Properties.Resources.Icon_86; + this.Delete.Location = new System.Drawing.Point(7, 35); + this.Delete.Name = "Delete"; + this.Delete.Size = new System.Drawing.Size(26, 26); + this.Delete.TabIndex = 1; + this.Delete.UseVisualStyleBackColor = true; + this.Delete.Click += new System.EventHandler(this.DeleteClick); + // + // gitHeadBindingSource + // + this.gitHeadBindingSource.DataSource = typeof(GitCommands.GitRef); + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.ItemSize = new System.Drawing.Size(117, 24); + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(709, 331); + this.tabControl1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(pnlManagementContainer); + this.tabPage1.Controls.Add(this.panel1); + this.tabPage1.Location = new System.Drawing.Point(4, 28); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(701, 299); + this.tabPage1.TabIndex = 0; + this.tabPage1.Text = "Remote repositories"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // panel1 + // + this.panel1.Controls.Add(this.Remotes); + this.panel1.Controls.Add(this.panelButtons); + this.panel1.Dock = System.Windows.Forms.DockStyle.Left; + this.panel1.Location = new System.Drawing.Point(3, 3); + this.panel1.Name = "panel1"; + this.panel1.Padding = new System.Windows.Forms.Padding(8); + this.panel1.Size = new System.Drawing.Size(194, 293); + this.panel1.TabIndex = 0; + // + // Remotes + // + this.Remotes.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.Remotes.Dock = System.Windows.Forms.DockStyle.Fill; + this.Remotes.FormattingEnabled = true; + this.Remotes.Location = new System.Drawing.Point(8, 8); + this.Remotes.Name = "Remotes"; + this.Remotes.Size = new System.Drawing.Size(142, 277); + this.Remotes.TabIndex = 1; // // tabPage2 // this.tabPage2.Controls.Add(this.tableLayoutPanel2); - this.tabPage2.Location = new System.Drawing.Point(4, 22); + this.tabPage2.Location = new System.Drawing.Point(4, 28); this.tabPage2.Name = "tabPage2"; this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(646, 274); + this.tabPage2.Size = new System.Drawing.Size(701, 299); this.tabPage2.TabIndex = 1; this.tabPage2.Text = "Default pull behavior (fetch & merge)"; this.tabPage2.UseVisualStyleBackColor = true; @@ -505,7 +595,7 @@ private void InitializeComponent() this.tableLayoutPanel2.RowCount = 2; this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel2.Size = new System.Drawing.Size(640, 268); + this.tableLayoutPanel2.Size = new System.Drawing.Size(695, 293); this.tableLayoutPanel2.TabIndex = 12; // // splitContainer3 @@ -527,16 +617,19 @@ private void InitializeComponent() this.splitContainer3.Panel2.Controls.Add(this.label6); this.splitContainer3.Panel2.Controls.Add(this.label5); this.splitContainer3.Panel2.Controls.Add(this.label4); - this.splitContainer3.Size = new System.Drawing.Size(634, 223); - this.splitContainer3.SplitterDistance = 327; + this.splitContainer3.Size = new System.Drawing.Size(689, 250); + this.splitContainer3.SplitterDistance = 353; this.splitContainer3.TabIndex = 0; // // RemoteBranches // this.RemoteBranches.AllowUserToAddRows = false; this.RemoteBranches.AllowUserToDeleteRows = false; + this.RemoteBranches.AllowUserToResizeRows = false; this.RemoteBranches.AutoGenerateColumns = false; this.RemoteBranches.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.Fill; + this.RemoteBranches.BackgroundColor = System.Drawing.SystemColors.Window; + this.RemoteBranches.BorderStyle = System.Windows.Forms.BorderStyle.Fixed3D; this.RemoteBranches.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.RemoteBranches.Columns.AddRange(new System.Windows.Forms.DataGridViewColumn[] { this.BranchName, @@ -553,15 +646,16 @@ private void InitializeComponent() this.mergeWithDataGridViewTextBoxColumn}); this.RemoteBranches.DataSource = this.gitHeadBindingSource; this.RemoteBranches.Dock = System.Windows.Forms.DockStyle.Fill; + this.RemoteBranches.GridColor = System.Drawing.SystemColors.ControlLight; this.RemoteBranches.Location = new System.Drawing.Point(0, 0); this.RemoteBranches.MultiSelect = false; this.RemoteBranches.Name = "RemoteBranches"; this.RemoteBranches.ReadOnly = true; this.RemoteBranches.RowHeadersVisible = false; this.RemoteBranches.SelectionMode = System.Windows.Forms.DataGridViewSelectionMode.FullRowSelect; - this.RemoteBranches.Size = new System.Drawing.Size(327, 223); + this.RemoteBranches.Size = new System.Drawing.Size(353, 250); this.RemoteBranches.TabIndex = 0; - this.RemoteBranches.SelectionChanged += new System.EventHandler(this.RemoteBranchesSelectionChanged); + this.RemoteBranches.DataError += new System.Windows.Forms.DataGridViewDataErrorEventHandler(this.RemoteBranchesDataError); // // BranchName // @@ -658,12 +752,15 @@ private void InitializeComponent() // // SaveDefaultPushPull // - this.SaveDefaultPushPull.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.SaveDefaultPushPull.Location = new System.Drawing.Point(221, 196); + this.SaveDefaultPushPull.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); + this.SaveDefaultPushPull.Image = global::GitUI.Properties.Resources.IconSave; + this.SaveDefaultPushPull.ImageAlign = System.Drawing.ContentAlignment.MiddleLeft; + this.SaveDefaultPushPull.Location = new System.Drawing.Point(197, 88); this.SaveDefaultPushPull.Name = "SaveDefaultPushPull"; - this.SaveDefaultPushPull.Size = new System.Drawing.Size(75, 25); + this.SaveDefaultPushPull.Size = new System.Drawing.Size(130, 25); this.SaveDefaultPushPull.TabIndex = 3; - this.SaveDefaultPushPull.Text = "Save"; + this.SaveDefaultPushPull.Text = "Save changes"; + this.SaveDefaultPushPull.TextImageRelation = System.Windows.Forms.TextImageRelation.ImageBeforeText; this.SaveDefaultPushPull.UseVisualStyleBackColor = true; this.SaveDefaultPushPull.Click += new System.EventHandler(this.SaveDefaultPushPullClick); // @@ -673,7 +770,7 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Right))); this.LocalBranchNameEdit.Location = new System.Drawing.Point(144, 6); this.LocalBranchNameEdit.Name = "LocalBranchNameEdit"; - this.LocalBranchNameEdit.Size = new System.Drawing.Size(152, 21); + this.LocalBranchNameEdit.Size = new System.Drawing.Size(183, 21); this.LocalBranchNameEdit.TabIndex = 0; // // RemoteRepositoryCombo @@ -683,7 +780,7 @@ private void InitializeComponent() this.RemoteRepositoryCombo.FormattingEnabled = true; this.RemoteRepositoryCombo.Location = new System.Drawing.Point(144, 32); this.RemoteRepositoryCombo.Name = "RemoteRepositoryCombo"; - this.RemoteRepositoryCombo.Size = new System.Drawing.Size(152, 21); + this.RemoteRepositoryCombo.Size = new System.Drawing.Size(183, 21); this.RemoteRepositoryCombo.TabIndex = 1; this.RemoteRepositoryCombo.Validated += new System.EventHandler(this.RemoteRepositoryComboValidated); // @@ -694,7 +791,7 @@ private void InitializeComponent() this.DefaultMergeWithCombo.FormattingEnabled = true; this.DefaultMergeWithCombo.Location = new System.Drawing.Point(144, 59); this.DefaultMergeWithCombo.Name = "DefaultMergeWithCombo"; - this.DefaultMergeWithCombo.Size = new System.Drawing.Size(152, 21); + this.DefaultMergeWithCombo.Size = new System.Drawing.Size(183, 21); this.DefaultMergeWithCombo.TabIndex = 2; this.DefaultMergeWithCombo.DropDown += new System.EventHandler(this.DefaultMergeWithComboDropDown); this.DefaultMergeWithCombo.Validated += new System.EventHandler(this.DefaultMergeWithComboValidated); @@ -733,18 +830,18 @@ private void InitializeComponent() this.flowLayoutPanel1.Controls.Add(this.Prune); this.flowLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.flowLayoutPanel1.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 232); + this.flowLayoutPanel1.Location = new System.Drawing.Point(3, 259); this.flowLayoutPanel1.Name = "flowLayoutPanel1"; - this.flowLayoutPanel1.Size = new System.Drawing.Size(634, 33); + this.flowLayoutPanel1.Size = new System.Drawing.Size(689, 31); this.flowLayoutPanel1.TabIndex = 1; this.flowLayoutPanel1.WrapContents = false; // // UpdateBranch // this.UpdateBranch.AutoSize = true; - this.UpdateBranch.Location = new System.Drawing.Point(382, 3); + this.UpdateBranch.Location = new System.Drawing.Point(437, 3); this.UpdateBranch.Name = "UpdateBranch"; - this.UpdateBranch.Size = new System.Drawing.Size(249, 27); + this.UpdateBranch.Size = new System.Drawing.Size(249, 25); this.UpdateBranch.TabIndex = 1; this.UpdateBranch.Text = "Update all remote branch info"; this.UpdateBranch.UseVisualStyleBackColor = true; @@ -753,9 +850,9 @@ private void InitializeComponent() // Prune // this.Prune.AutoSize = true; - this.Prune.Location = new System.Drawing.Point(127, 3); + this.Prune.Location = new System.Drawing.Point(182, 3); this.Prune.Name = "Prune"; - this.Prune.Size = new System.Drawing.Size(249, 27); + this.Prune.Size = new System.Drawing.Size(249, 25); this.Prune.TabIndex = 0; this.Prune.Text = "Prune remote branches"; this.Prune.UseVisualStyleBackColor = true; @@ -781,72 +878,42 @@ private void InitializeComponent() this.dataGridViewTextBoxColumn1.HeaderText = "Name"; this.dataGridViewTextBoxColumn1.Name = "dataGridViewTextBoxColumn1"; // - // tableLayoutPanel4 - // - this.tableLayoutPanel4.AutoSize = true; - this.tableLayoutPanel4.ColumnCount = 3; - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel4.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle()); - this.tableLayoutPanel4.Controls.Add(this.label3, 0, 0); - this.tableLayoutPanel4.Controls.Add(this.PuttySshKey, 1, 0); - this.tableLayoutPanel4.Controls.Add(this.SshBrowse, 2, 0); - this.tableLayoutPanel4.Controls.Add(this.flowLayoutPanel4, 0, 1); - this.tableLayoutPanel4.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel4.Location = new System.Drawing.Point(3, 17); - this.tableLayoutPanel4.Name = "tableLayoutPanel4"; - this.tableLayoutPanel4.RowCount = 2; - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel4.RowStyles.Add(new System.Windows.Forms.RowStyle()); - this.tableLayoutPanel4.Size = new System.Drawing.Size(512, 68); - this.tableLayoutPanel4.TabIndex = 6; - // - // flowLayoutPanel4 - // - this.flowLayoutPanel4.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Right))); - this.flowLayoutPanel4.AutoSizeMode = System.Windows.Forms.AutoSizeMode.GrowAndShrink; - this.tableLayoutPanel4.SetColumnSpan(this.flowLayoutPanel4, 3); - this.flowLayoutPanel4.Controls.Add(this.LoadSSHKey); - this.flowLayoutPanel4.Controls.Add(this.TestConnection); - this.flowLayoutPanel4.FlowDirection = System.Windows.Forms.FlowDirection.RightToLeft; - this.flowLayoutPanel4.Location = new System.Drawing.Point(9, 34); - this.flowLayoutPanel4.Name = "flowLayoutPanel4"; - this.flowLayoutPanel4.Size = new System.Drawing.Size(500, 31); - this.flowLayoutPanel4.TabIndex = 6; - // // FormRemotes // this.AutoScaleDimensions = new System.Drawing.SizeF(96F, 96F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Dpi; - this.ClientSize = new System.Drawing.Size(704, 394); + this.ClientSize = new System.Drawing.Size(709, 331); this.Controls.Add(this.tabControl1); + this.DoubleBuffered = true; this.MaximizeBox = false; this.MinimizeBox = false; - this.MinimumSize = new System.Drawing.Size(670, 333); + this.MinimumSize = new System.Drawing.Size(760, 370); this.Name = "FormRemotes"; + this.SizeGripStyle = System.Windows.Forms.SizeGripStyle.Show; this.StartPosition = System.Windows.Forms.FormStartPosition.CenterParent; this.Text = "Remote repositories"; - this.Load += new System.EventHandler(this.FormRemotesLoad); + flpnlRemoteManagement.ResumeLayout(false); + flpnlRemoteManagement.PerformLayout(); + flowLayoutPanel2.ResumeLayout(false); + this.pnlMgtPuttySsh.ResumeLayout(false); + this.pnlMgtPuttySsh.PerformLayout(); + tableLayoutPanel1.ResumeLayout(false); + tableLayoutPanel1.PerformLayout(); + flowLayoutPanel3.ResumeLayout(false); + pnlMgtDetails.ResumeLayout(false); + pnlMgtDetails.PerformLayout(); + tblpnlMgtDetails.ResumeLayout(false); + tblpnlMgtDetails.PerformLayout(); + pnlManagementContainer.ResumeLayout(false); + pnlManagementContainer.PerformLayout(); + this.gbMgtPanel.ResumeLayout(false); + this.gbMgtPanel.PerformLayout(); + this.panelButtons.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.gitHeadBindingSource)).EndInit(); this.tabControl1.ResumeLayout(false); this.tabPage1.ResumeLayout(false); - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel2.ResumeLayout(false); - this.splitContainer1.Panel2.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); this.panel1.ResumeLayout(false); - this.panelButtons.ResumeLayout(false); - this.flowLayoutPanel3.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.flowLayoutPanel2.ResumeLayout(false); - this.PuTTYSSH.ResumeLayout(false); - this.PuTTYSSH.PerformLayout(); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.tableLayoutPanel3.ResumeLayout(false); - this.tableLayoutPanel3.PerformLayout(); + this.panel1.PerformLayout(); this.tabPage2.ResumeLayout(false); this.tableLayoutPanel2.ResumeLayout(false); this.tableLayoutPanel2.PerformLayout(); @@ -858,16 +925,12 @@ private void InitializeComponent() ((System.ComponentModel.ISupportInitialize)(this.RemoteBranches)).EndInit(); this.flowLayoutPanel1.ResumeLayout(false); this.flowLayoutPanel1.PerformLayout(); - this.tableLayoutPanel4.ResumeLayout(false); - this.tableLayoutPanel4.PerformLayout(); - this.flowLayoutPanel4.ResumeLayout(false); this.ResumeLayout(false); } #endregion - private System.Windows.Forms.SplitContainer splitContainer1; private System.Windows.Forms.ListBox Remotes; private System.Windows.Forms.TabControl tabControl1; private System.Windows.Forms.TabPage tabPage1; @@ -878,8 +941,6 @@ private void InitializeComponent() private System.Windows.Forms.DataGridViewTextBoxColumn dataGridViewTextBoxColumn1; private System.Windows.Forms.Button UpdateBranch; private System.Windows.Forms.Button Prune; - private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.GroupBox PuTTYSSH; private System.Windows.Forms.Button LoadSSHKey; private System.Windows.Forms.TextBox PuttySshKey; private System.Windows.Forms.Button TestConnection; @@ -896,8 +957,6 @@ private void InitializeComponent() private System.Windows.Forms.Label labelPushUrl; private System.Windows.Forms.ComboBox comboBoxPushUrl; private System.Windows.Forms.Panel panel1; - private System.Windows.Forms.Button buttonClose; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; private System.Windows.Forms.TableLayoutPanel tableLayoutPanel2; private System.Windows.Forms.SplitContainer splitContainer3; private System.Windows.Forms.DataGridView RemoteBranches; @@ -923,11 +982,10 @@ private void InitializeComponent() private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel1; private UserControls.FolderBrowserButton folderBrowserButtonUrl; private UserControls.FolderBrowserButton folderBrowserButtonPushUrl; - private System.Windows.Forms.Panel panelButtons; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel3; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel2; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel3; - private System.Windows.Forms.TableLayoutPanel tableLayoutPanel4; - private System.Windows.Forms.FlowLayoutPanel flowLayoutPanel4; + private System.Windows.Forms.FlowLayoutPanel panelButtons; + private System.Windows.Forms.GroupBox gbMgtPanel; + private System.Windows.Forms.Label lblMgtDetailsPanelHeader; + private System.Windows.Forms.Panel pnlMgtPuttySsh; + private System.Windows.Forms.Label lblMgtPuttyPanelHeader; } -} \ No newline at end of file +} diff --git a/GitUI/CommandsDialogs/FormRemotes.cs b/GitUI/CommandsDialogs/FormRemotes.cs index 9db5e2ebaa0..8db8b5d4a8e 100644 --- a/GitUI/CommandsDialogs/FormRemotes.cs +++ b/GitUI/CommandsDialogs/FormRemotes.cs @@ -1,19 +1,24 @@ using System; +using System.ComponentModel; +using System.Linq; using System.Windows.Forms; using GitCommands; using GitCommands.Config; using GitCommands.Repository; +using GitUI.Objects; using ResourceManager; namespace GitUI.CommandsDialogs { public partial class FormRemotes : GitModuleForm { - private string _remote = ""; + private IGitRemoteController _gitRemoteController; + private GitRemote _selectedRemote; + #region Translation private readonly TranslationString _remoteBranchDataError = - new TranslationString("Invalid ´{1}´ found for branch ´{0}´." + Environment.NewLine + - "Value has been reset to empty value."); + new TranslationString("Invalid ´{1}´ found for branch ´{0}´." + Environment.NewLine + + "Value has been reset to empty value."); private readonly TranslationString _questionAutoPullBehaviour = new TranslationString("You have added a new remote repository." + Environment.NewLine + @@ -22,14 +27,8 @@ public partial class FormRemotes : GitModuleForm private readonly TranslationString _questionAutoPullBehaviourCaption = new TranslationString("New remote"); - private readonly TranslationString _warningValidRemote = - new TranslationString("You need to configure a valid url for this remote"); - - private readonly TranslationString _warningValidRemoteCaption = - new TranslationString("Url needed"); - - private readonly TranslationString _hintDelete = - new TranslationString("Delete"); + private readonly TranslationString _gitMessage = + new TranslationString("Message"); private readonly TranslationString _questionDeleteRemote = new TranslationString("Are you sure you want to delete this remote?"); @@ -48,36 +47,27 @@ public partial class FormRemotes : GitModuleForm private readonly TranslationString _labelUrlAsFetch = new TranslationString("Fetch Url"); + private readonly TranslationString _labelUrlAsFetchPush = new TranslationString("Url"); + private readonly TranslationString _gbMgtPanelHeaderNew = + new TranslationString("Create New Remote"); + + private readonly TranslationString _gbMgtPanelHeaderEdit = + new TranslationString("Edit Remote Details"); + #endregion + + public FormRemotes(GitUICommands aCommands) : base(aCommands) { InitializeComponent(); Translate(); - } - private void FormRemotesLoad(object sender, EventArgs e) - { - Initialize(); - - if (!string.IsNullOrEmpty(PreselectRemoteOnLoad)) - { - Remotes.Text = PreselectRemoteOnLoad; - } - - RemotesSelectedIndexChanged(null, null); + Application.Idle += application_Idle; } - private void RemoteBranchesDataError(object sender, DataGridViewDataErrorEventArgs e) - { - MessageBox.Show(this, - string.Format(_remoteBranchDataError.Text, RemoteBranches.Rows[e.RowIndex].Cells[0].Value, - RemoteBranches.Columns[e.ColumnIndex].HeaderText)); - - RemoteBranches.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ""; - } /// /// If this is not null before showing the dialog the given @@ -85,151 +75,184 @@ private void RemoteBranchesDataError(object sender, DataGridViewDataErrorEventAr /// public string PreselectRemoteOnLoad { get; set; } - private void Initialize() - { - FillUrlDropDown(); - FillPushUrlDropDown(); - Remotes.DataSource = Module.GetRemotes(false); + private void Initialize(string preselectRemote = null) + { + // refresh registered git remotes + _gitRemoteController.LoadRemotes(); - var heads = Module.GetRefs(false, true); - RemoteBranches.DataSource = heads; + InitialiseTabRemotes(preselectRemote); + InitialiseTabBehaviors(); + } - RemoteBranches.DataError += RemoteBranchesDataError; + private void InitialiseTabRemotes(string preselectRemote = null) + { + // because the binding the same BindingList to multiple controls, + // and changes in one of the bound control automatically get reflected + // in the other control, which causes rather frustrating UX. + // to address that, re-create binding lists for each individual control + var repos = Repositories.RemoteRepositoryHistory.Repositories; - PuTTYSSH.Visible = GitCommandHelpers.Plink(); + try + { + // to stop the flicker binding the lists and + // when the selected remote is getting reset and then selected again + Url.BeginUpdate(); + comboBoxPushUrl.BeginUpdate(); + Remotes.BeginUpdate(); + + Url.DataSource = new BindingList(repos); + Url.DisplayMember = "Path"; + Url.SelectedItem = null; + + comboBoxPushUrl.DataSource = new BindingList(repos); + comboBoxPushUrl.DisplayMember = "Path"; + comboBoxPushUrl.SelectedItem = null; + + // we need to unwire and rewire the events to avoid excessive flickering + Remotes.SelectedIndexChanged -= Remotes_SelectedIndexChanged; + Remotes.DataSource = _gitRemoteController.Remotes; + Remotes.DisplayMember = "Name"; + Remotes.SelectedIndexChanged += Remotes_SelectedIndexChanged; + + Remotes.SelectedItem = null; + if (_gitRemoteController.Remotes.Any()) + { + if (!string.IsNullOrEmpty(preselectRemote)) + { + Remotes.Text = preselectRemote; + } + // default fallback - if the preselection didn't work select the first available one + if (Remotes.SelectedItem == null) + { + Remotes.SelectedItem = _gitRemoteController.Remotes.First(); + } + } + else + { + RemoteName.Focus(); + } + } + finally + { + Remotes.EndUpdate(); + Url.EndUpdate(); + comboBoxPushUrl.EndUpdate(); + } } - private void FillUrlDropDown() + private void InitialiseTabBehaviors() { - Url.DataSource = Repositories.RemoteRepositoryHistory.Repositories; - Url.DisplayMember = "Path"; + var heads = Module.GetRefs(false, true); + + RemoteRepositoryCombo.Sorted = false; + RemoteRepositoryCombo.DataSource = new[] { new GitRemote() }.Union( _gitRemoteController.Remotes).ToList(); + RemoteRepositoryCombo.DisplayMember = "Name"; + + RemoteBranches.SelectionChanged -= RemoteBranchesSelectionChanged; + RemoteBranches.DataSource = heads; + RemoteBranches.ClearSelection(); + RemoteBranches.SelectionChanged += RemoteBranchesSelectionChanged; + + if (RemoteBranches.Rows.Count > 0) + { + RemoteBranches.Rows[0].Selected = true; + } } - private void FillPushUrlDropDown() + + private void application_Idle(object sender, EventArgs e) { - comboBoxPushUrl.DataSource = Repositories.RemoteRepositoryHistory.Repositories; - comboBoxPushUrl.DisplayMember = "Path"; + // we need this event only once, so unwire + Application.Idle -= application_Idle; + + pnlMgtPuttySsh.Visible = GitCommandHelpers.Plink(); + + if (Module == null) + { + return; + } + _gitRemoteController = new GitRemoteController(Module); + // load the data for the very first time + Initialize(PreselectRemoteOnLoad); } private void SaveClick(object sender, EventArgs e) { - var output = ""; - - if ((string.IsNullOrEmpty(comboBoxPushUrl.Text) && checkBoxSepPushUrl.Checked) || - (comboBoxPushUrl.Text == Url.Text)) + if (string.IsNullOrEmpty(RemoteName.Text)) { - checkBoxSepPushUrl.Checked = false; + return; } - if (string.IsNullOrEmpty(_remote)) + try { - if (string.IsNullOrEmpty(RemoteName.Text) && string.IsNullOrEmpty(Url.Text)) - { - return; - } + // disable the control while saving + tabControl1.Enabled = false; - output = Module.AddRemote(RemoteName.Text, Url.Text); - - if (checkBoxSepPushUrl.Checked) + if ((string.IsNullOrEmpty(comboBoxPushUrl.Text) && checkBoxSepPushUrl.Checked) || + (comboBoxPushUrl.Text.Equals(Url.Text, StringComparison.OrdinalIgnoreCase))) { - Module.SetPathSetting(string.Format(SettingKeyString.RemotePushUrl, RemoteName.Text), comboBoxPushUrl.Text); + checkBoxSepPushUrl.Checked = false; } - if (MessageBox.Show(this, _questionAutoPullBehaviour.Text, _questionAutoPullBehaviourCaption.Text, - MessageBoxButtons.YesNo) == DialogResult.Yes) - { - var remoteUrl = Url.Text; + // update all other remote properties + var result = _gitRemoteController.SaveRemote(_selectedRemote, + RemoteName.Text, + Url.Text, + checkBoxSepPushUrl.Checked ? comboBoxPushUrl.Text : null, + PuttySshKey.Text); - if (!string.IsNullOrEmpty(remoteUrl)) - { - FormRemoteProcess.ShowDialog(this, "remote update"); - ConfigureRemotes(); - } - else - { - MessageBox.Show(this, _warningValidRemote.Text, _warningValidRemoteCaption.Text); - } - } - } - else - { - if (RemoteName.Text != _remote) + if (!string.IsNullOrEmpty(result.UserMessage)) { - output = Module.RenameRemote(_remote, RemoteName.Text); + MessageBox.Show(this, result.UserMessage, _gitMessage.Text); } - Module.SetPathSetting(string.Format(SettingKeyString.RemoteUrl, RemoteName.Text), Url.Text); - Module.SetPathSetting(string.Format("remote.{0}.puttykeyfile", RemoteName.Text), PuttySshKey.Text); - if (checkBoxSepPushUrl.Checked) + // if the user has just created a fresh new remote + // there may be a need to configure it + if (result.ShouldUpdateRemote && !string.IsNullOrEmpty(Url.Text) && + DialogResult.Yes == MessageBox.Show(this, + _questionAutoPullBehaviour.Text, + _questionAutoPullBehaviourCaption.Text, + MessageBoxButtons.YesNo)) { - Module.SetPathSetting(string.Format(SettingKeyString.RemotePushUrl, RemoteName.Text), comboBoxPushUrl.Text); - } - else - { - Module.UnsetSetting(string.Format(SettingKeyString.RemotePushUrl, RemoteName.Text)); + FormRemoteProcess.ShowDialog(this, "remote update"); + _gitRemoteController.ConfigureRemotes(RemoteName.Text); } } - - if (!string.IsNullOrEmpty(output)) - { - MessageBox.Show(this, output, _hintDelete.Text); - } - - Initialize(); - } - - private void ConfigureRemotes() - { - var localConfig = Module.LocalConfigFile; - - foreach (var remoteHead in Module.GetRefs(true, true)) + finally { - foreach (var localHead in Module.GetRefs(true, true)) - { - if (!remoteHead.IsRemote || - localHead.IsRemote || - !string.IsNullOrEmpty(localHead.GetTrackingRemote(localConfig)) || - !string.IsNullOrEmpty(localHead.GetTrackingRemote(localConfig)) || - remoteHead.IsTag || - localHead.IsTag || - !remoteHead.Name.ToLower().Contains(localHead.Name.ToLower()) || - !remoteHead.Name.ToLower().Contains(_remote.ToLower())) - continue; - localHead.TrackingRemote = RemoteName.Text; - localHead.MergeWith = localHead.Name; - } + // re-enable the control and re-initialize + tabControl1.Enabled = true; + Initialize(RemoteName.Text); } } private void NewClick(object sender, EventArgs e) { - var output = Module.AddRemote("", ""); - if (!string.IsNullOrEmpty(output)) - { - MessageBox.Show(this, output, _hintDelete.Text); - } - Initialize(); + Remotes.SelectedItem = null; + RemoteName.Focus(); } private void DeleteClick(object sender, EventArgs e) { - if (string.IsNullOrEmpty(_remote)) + if (_selectedRemote == null) { return; } - if (MessageBox.Show(this, _questionDeleteRemote.Text, _questionDeleteRemoteCaption.Text, MessageBoxButtons.YesNo) == - DialogResult.Yes) + if (DialogResult.Yes == MessageBox.Show(this, + _questionDeleteRemote.Text, + _questionDeleteRemoteCaption.Text, + MessageBoxButtons.YesNo)) { - var output = Module.RemoveRemote(_remote); + var output = _gitRemoteController.RemoveRemote(_selectedRemote); if (!string.IsNullOrEmpty(output)) { - MessageBox.Show(this, output, _hintDelete.Text); + MessageBox.Show(this, output, _gitMessage.Text); } - } - Initialize(); + Initialize(); + } } private void SshBrowseClick(object sender, EventArgs e) @@ -237,7 +260,7 @@ private void SshBrowseClick(object sender, EventArgs e) using (var dialog = new OpenFileDialog { - Filter = _sshKeyOpenFilter.Text + "|*.ppk", + Filter = _sshKeyOpenFilter.Text + @"|*.ppk", InitialDirectory = ".", Title = _sshKeyOpenCaption.Text }) @@ -266,27 +289,34 @@ private void TestConnectionClick(object sender, EventArgs e) private void PruneClick(object sender, EventArgs e) { - FormRemoteProcess.ShowDialog(this, "remote prune " + _remote); + if (_selectedRemote == null) + { + return; + } + FormRemoteProcess.ShowDialog(this, "remote prune " + _selectedRemote.Name); } private void RemoteBranchesSelectionChanged(object sender, EventArgs e) { if (RemoteBranches.SelectedRows.Count != 1) + { return; + } var head = RemoteBranches.SelectedRows[0].DataBoundItem as GitRef; - if (head == null) + { return; + } LocalBranchNameEdit.Text = head.Name; LocalBranchNameEdit.ReadOnly = true; - RemoteRepositoryCombo.Items.Clear(); - RemoteRepositoryCombo.Items.Add(""); - foreach (var remote in Module.GetRemotes()) - RemoteRepositoryCombo.Items.Add(remote); - RemoteRepositoryCombo.Text = head.TrackingRemote; + RemoteRepositoryCombo.SelectedItem = _gitRemoteController.Remotes.FirstOrDefault(x => x.Name.Equals(head.TrackingRemote, StringComparison.OrdinalIgnoreCase)); + if (RemoteRepositoryCombo.SelectedItem == null) + { + RemoteRepositoryCombo.SelectedIndex = 0; + } DefaultMergeWithCombo.Text = head.MergeWith; } @@ -323,6 +353,15 @@ private void DefaultMergeWithComboDropDown(object sender, EventArgs e) } } + private void RemoteBranchesDataError(object sender, DataGridViewDataErrorEventArgs e) + { + MessageBox.Show(this, + string.Format(_remoteBranchDataError.Text, RemoteBranches.Rows[e.RowIndex].Cells[0].Value, + RemoteBranches.Columns[e.ColumnIndex].HeaderText)); + + RemoteBranches.Rows[e.RowIndex].Cells[e.ColumnIndex].Value = ""; + } + private void RemoteRepositoryComboValidated(object sender, EventArgs e) { if (RemoteBranches.SelectedRows.Count != 1) @@ -352,24 +391,41 @@ private void SaveDefaultPushPullClick(object sender, EventArgs e) Initialize(); } - private void RemotesSelectedIndexChanged(object sender, EventArgs e) + private void RemoteName_TextChanged(object sender, EventArgs e) { - if (!(Remotes.SelectedItem is string)) - return; + Save.Enabled = RemoteName.Text.Trim().Length > 0; + } - _remote = (string)Remotes.SelectedItem; - RemoteName.Text = _remote; + private void Remotes_SelectedIndexChanged(object sender, EventArgs e) + { + if (_selectedRemote == Remotes.SelectedItem) + { + return; + } - Url.Text = Module.GetPathSetting(string.Format(SettingKeyString.RemoteUrl, _remote)); + // reset all controls and disable all buttons until we have a selection + New.Enabled = Delete.Enabled = false; + RemoteName.Text = string.Empty; + Url.Text = string.Empty; + comboBoxPushUrl.Text = string.Empty; + checkBoxSepPushUrl.Checked = false; + PuttySshKey.Text = string.Empty; + gbMgtPanel.Text = _gbMgtPanelHeaderNew.Text; + + _selectedRemote = Remotes.SelectedItem as GitRemote; + if (_selectedRemote == null) + { + return; + } - comboBoxPushUrl.Text = Module.GetPathSetting(string.Format(SettingKeyString.RemotePushUrl, _remote)); - if (string.IsNullOrEmpty(comboBoxPushUrl.Text)) - checkBoxSepPushUrl.Checked = false; - else - checkBoxSepPushUrl.Checked = true; + New.Enabled = Delete.Enabled = true; - PuttySshKey.Text = - Module.GetPathSetting(string.Format("remote.{0}.puttykeyfile", RemoteName.Text)); + RemoteName.Text = _selectedRemote.Name; + Url.Text = _selectedRemote.Url; + comboBoxPushUrl.Text = _selectedRemote.PushUrl; + checkBoxSepPushUrl.Checked = !string.IsNullOrEmpty(_selectedRemote.PushUrl); + PuttySshKey.Text = _selectedRemote.PuttySshKey; + gbMgtPanel.Text = _gbMgtPanelHeaderEdit.Text; } private void UpdateBranchClick(object sender, EventArgs e) @@ -379,10 +435,10 @@ private void UpdateBranchClick(object sender, EventArgs e) private void checkBoxSepPushUrl_CheckedChanged(object sender, EventArgs e) { - ShowSeperatePushUrl(checkBoxSepPushUrl.Checked); + ShowSeparatePushUrl(checkBoxSepPushUrl.Checked); } - private void ShowSeperatePushUrl(bool visible) + private void ShowSeparatePushUrl(bool visible) { labelPushUrl.Visible = visible; comboBoxPushUrl.Visible = visible; @@ -393,10 +449,5 @@ private void ShowSeperatePushUrl(bool visible) else label2.Text = _labelUrlAsFetch.Text; } - - private void buttonClose_Click(object sender, EventArgs e) - { - Close(); - } } } \ No newline at end of file diff --git a/GitUI/CommandsDialogs/FormRemotes.resx b/GitUI/CommandsDialogs/FormRemotes.resx index b0cab94b0b0..a59ff6b2df1 100644 --- a/GitUI/CommandsDialogs/FormRemotes.resx +++ b/GitUI/CommandsDialogs/FormRemotes.resx @@ -117,6 +117,33 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + + + False + 17, 17 diff --git a/GitUI/GitUI.csproj b/GitUI/GitUI.csproj index c3271540480..efa81f14c6c 100644 --- a/GitUI/GitUI.csproj +++ b/GitUI/GitUI.csproj @@ -159,9 +159,7 @@ FormMergeSubmodule.cs - - Form - + Form @@ -255,6 +253,9 @@ UserControl + + + diff --git a/GitUI/Objects/GitRemote.cs b/GitUI/Objects/GitRemote.cs new file mode 100644 index 00000000000..55a578e6d6c --- /dev/null +++ b/GitUI/Objects/GitRemote.cs @@ -0,0 +1,33 @@ +using System.Collections.Generic; +using GitCommands.Config; + +namespace GitUI.Objects +{ + public class GitRemote + { + /// + /// Gets or sets the name of the remote branch. + /// + public string Name { get; set; } + + /// + /// Gets or sets value stored in .git/config via key. + /// + public string Url { get; set; } + + /// + /// Gets or sets value stored in .git/config via key. + /// + public IList Push { get; set; } + + /// + /// Gets or sets value stored in .git/config via key. + /// + public string PushUrl { get; set; } + + /// + /// Gets or sets value stored in .git/config via key. + /// + public string PuttySshKey { get; set; } + } +} \ No newline at end of file diff --git a/GitUI/Objects/GitRemoteController.cs b/GitUI/Objects/GitRemoteController.cs new file mode 100644 index 00000000000..bada293d127 --- /dev/null +++ b/GitUI/Objects/GitRemoteController.cs @@ -0,0 +1,248 @@ +using System; +using System.ComponentModel; +using System.Linq; +using GitCommands; +using GitCommands.Config; +using GitUIPluginInterfaces; + +namespace GitUI.Objects +{ + public interface IGitRemoteController + { + /// + /// Gets the list of remotes configured in .git/config file. + /// + BindingList Remotes { get; } + + void ConfigureRemotes(string remoteName); + + /// + /// Returns the default remote for push operation. + /// + /// + /// + /// The if found, otheriwse . + string GetDefaultPushRemote(GitRemote remote, string branch); + + /// + /// Loads the remotes from the .git/config. + /// + void LoadRemotes(); + + /// + /// Removes the specified remote from .git/config file. + /// + /// Remote to remove. + /// Output of the operation. + string RemoveRemote(GitRemote remote); + + /// + /// Saves the remote details by creating a new or updating an existing remote entry in .git/config file. + /// + /// An existing remote instance or if creating a new entry. + /// + /// The remote name. + /// If updating an existing remote and the name changed, it will result in remote name change and prompt for "remote update". + /// + /// + /// The remote URL. + /// If updating an existing remote and the URL changed, it will result in remote URL change and prompt for "remote update". + /// + /// An optional alternative remote push URL. + /// An optional Putty SSH key. + /// Result of the operation. + GitRemoteSaveResult SaveRemote(GitRemote remote, string remoteName, string remoteUrl, string remotePushUrl, string remotePuttySshKey); + } + + public class GitRemoteController : IGitRemoteController + { + private static readonly object SyncRoot = new object(); + private readonly IGitModule _module; + + + public GitRemoteController(IGitModule module) + { + _module = module; + Remotes = new BindingList(); + } + + + /// + /// Gets the list of remotes configured in .git/config file. + /// + public BindingList Remotes { get; private set; } + + + // TODO: moved verbatim from FormRemotes.cs, perhaps needs refactoring + public void ConfigureRemotes(string remoteName) + { + var localConfig = _module.LocalConfigFile; + + foreach (var remoteHead in _module.GetRefs(true, true)) + { + foreach (var localHead in _module.GetRefs(true, true)) + { + if (!remoteHead.IsRemote || + localHead.IsRemote || + !string.IsNullOrEmpty(localHead.GetTrackingRemote(localConfig)) || + remoteHead.IsTag || + localHead.IsTag || + !remoteHead.Name.ToLower().Contains(localHead.Name.ToLower()) || + !remoteHead.Name.ToLower().Contains(remoteName.ToLower())) + { + continue; + } + + localHead.TrackingRemote = remoteName; + localHead.MergeWith = localHead.Name; + } + } + } + + /// + /// Returns the default remote for push operation. + /// + /// + /// + /// The if found, otheriwse . + // TODO: moved verbatim from FormPush.cs, perhaps needs refactoring + public string GetDefaultPushRemote(GitRemote remote, string branch) + { + if (remote == null) + { + throw new ArgumentNullException("remote"); + } + + Func isSettingForBranch = (setting, branchName) => + { + var head = new GitRef(_module, string.Empty, setting); + return head.IsHead && head.Name.Equals(branchName, StringComparison.OrdinalIgnoreCase); + }; + + var remoteHead = remote.Push + .Select(s => s.Split(':')) + .Where(t => t.Length == 2) + .Where(t => isSettingForBranch(t[0], branch)) + .Select(t => new GitRef(_module, string.Empty, t[1])) + .FirstOrDefault(h => h.IsHead); + + return remoteHead == null ? null : remoteHead.Name; + } + + /// + /// Loads the remotes from the .git/config. + /// + // TODO: candidate for Async implementations + public void LoadRemotes() + { + if (_module == null) + { + return; + } + + lock (SyncRoot) + { + Remotes.Clear(); + + var gitRemotes = _module.GetRemotes().Where(x => !string.IsNullOrWhiteSpace(x)).ToList(); + if (gitRemotes.Any()) + { + var remotes = gitRemotes.Select(remote => new GitRemote + { + Name = remote, + Url = _module.GetSetting(string.Format(SettingKeyString.RemoteUrl, remote)), + Push = _module.GetSettings(string.Format(SettingKeyString.RemotePush, remote)).ToList(), + PushUrl = _module.GetSetting(string.Format(SettingKeyString.RemotePushUrl, remote)), + PuttySshKey = _module.GetSetting(string.Format(SettingKeyString.RemotePuttySshKey, remote)), + }).ToList(); + + Remotes.AddAll(remotes.OrderBy(x => x.Name)); + } + } + } + + /// + /// Removes the specified remote from .git/config file. + /// + /// Remote to remove. + /// Output of operation. + public string RemoveRemote(GitRemote remote) + { + if (remote == null) + { + throw new ArgumentNullException("remote"); + } + return _module.RemoveRemote(remote.Name); + } + + /// + /// Saves the remote details by creating a new or updating an existing remote entry in .git/config file. + /// + /// An existing remote instance or if creating a new entry. + /// + /// The remote name. + /// If updating an existing remote and the name changed, it will result in remote name change and prompt for "remote update". + /// + /// + /// The remote URL. + /// If updating an existing remote and the URL changed, it will result in remote URL change and prompt for "remote update". + /// + /// An optional alternative remote push URL. + /// An optional Putty SSH key. + /// Result of the operation. + public GitRemoteSaveResult SaveRemote(GitRemote remote, string remoteName, string remoteUrl, string remotePushUrl, string remotePuttySshKey) + { + if (string.IsNullOrWhiteSpace(remoteName)) + { + throw new ArgumentNullException("remoteName"); + } + + remoteName = remoteName.Trim(); + + // if create a new remote or updated the url - we may need to perform "update remote" + bool updateRemoteRequired = false; + // if operation return anything back, relay that to the user + var output = string.Empty; + + bool creatingNew = remote == null; + if (creatingNew) + { + output = _module.AddRemote(remoteName, remoteUrl); + updateRemoteRequired = true; + } + else + { + if (!string.Equals(remote.Name, remoteName, StringComparison.OrdinalIgnoreCase)) + { + // the name of the remote changed - perform rename + output = _module.RenameRemote(remote.Name, remoteName); + } + + if (!string.Equals(remote.Url, remoteUrl, StringComparison.OrdinalIgnoreCase)) + { + // the remote url changed - we may need to update remote + updateRemoteRequired = true; + } + } + + UpdateSettings(string.Format(SettingKeyString.RemoteUrl, remoteName), remoteUrl); + UpdateSettings(string.Format(SettingKeyString.RemotePushUrl, remoteName), remotePushUrl); + UpdateSettings(string.Format(SettingKeyString.RemotePuttySshKey, remoteName), remotePuttySshKey); + + return new GitRemoteSaveResult(output, updateRemoteRequired); + } + + + private void UpdateSettings(string settingName, string value) + { + if (!string.IsNullOrWhiteSpace(value)) + { + _module.SetSetting(settingName, value); + } + else + { + _module.UnsetSetting(settingName); + } + } + } +} diff --git a/GitUI/Objects/GitRemoteSaveResult.cs b/GitUI/Objects/GitRemoteSaveResult.cs new file mode 100644 index 00000000000..3db851af398 --- /dev/null +++ b/GitUI/Objects/GitRemoteSaveResult.cs @@ -0,0 +1,24 @@ +namespace GitUI.Objects +{ + /// + /// Represents a result of operation. + /// + public class GitRemoteSaveResult + { + public GitRemoteSaveResult(string message, bool shouldUpdateRemote) + { + UserMessage = message; + ShouldUpdateRemote = shouldUpdateRemote; + } + + /// + /// Indicates whether the "remote update" is desirable after the save operation. + /// + public bool ShouldUpdateRemote { get; private set; } + + /// + /// Gets the output of the save operation (if any). + /// + public string UserMessage { get; private set; } + } +} \ No newline at end of file diff --git a/GitUI/Properties/Resources.Designer.cs b/GitUI/Properties/Resources.Designer.cs index 1c9c636361e..38866ed05fa 100644 --- a/GitUI/Properties/Resources.Designer.cs +++ b/GitUI/Properties/Resources.Designer.cs @@ -739,6 +739,16 @@ internal partial class Resources } } + /// + /// Looks up a localized resource of type System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Icon_86 { + get { + object obj = ResourceManager.GetObject("Icon_86", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/GitUI/Properties/Resources.resx b/GitUI/Properties/Resources.resx index 5926c7415c0..b8aeecb1af9 100644 --- a/GitUI/Properties/Resources.resx +++ b/GitUI/Properties/Resources.resx @@ -681,4 +681,7 @@ Alexander Eifler, Marcelo Ghelman, ghanique, olshevskiy87 ..\Resources\Icons\IconShowFirstParent.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a - \ No newline at end of file + + ..\Resources\Icons\86.png;System.Drawing.Bitmap, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a + + diff --git a/GitUI/Resources/Icons/86.png b/GitUI/Resources/Icons/86.png new file mode 100644 index 0000000000000000000000000000000000000000..f606a1b4e20def5563868151398207e244457b51 GIT binary patch literal 435 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Ea{HEjtmSN`?>!lvI6;x#X;^) z4C~IxyaaL-l0AZa85pWm85kOx85n;42hu?CQUeBtR|yOZRx=nF#PcV`A9Vw&WlQpQ zcVYMsf(!O8p9~b?EbxddW?Gfos2HyXV%?ZV!JOe`xrzYR-L%m*4JjPgu)jF55B7&i$9mIW%ouI0 zjK5D7{hS+ron_y%i~di=Yq)a4+;W~JTk>u=nwBcU!1aQm`TDeF3~P$l1^kbH!1-*Z zL3&F}j0n)pswJ)wB`Jv|saDBFsX&Us$iUE8*T6*Az&ymrz{=FZ%G4CdwK6c6KDVk1 eMMG|WN@iLmZVk^495MrHVDNPHb6Mw<&;$T Local branch name - - Delete - - Load SSH key @@ -5273,15 +5269,11 @@ Nothing to rebase. Default merge with - - New - - Prune remote branches - + PuTTY SSH @@ -5294,7 +5286,7 @@ Nothing to rebase. - Save + Save changes @@ -5309,8 +5301,8 @@ Nothing to rebase. Update all remote branch info - - Delete + + Message @@ -5351,6 +5343,14 @@ Value has been reset to empty value. Private key (*.ppk) + + Create new remote + + + + Edit remote details + + No SSH key file entered @@ -5363,10 +5363,6 @@ Value has been reset to empty value. Url needed - - Close - - Separate Push Url @@ -5375,7 +5371,7 @@ Value has been reset to empty value. Name - + Details diff --git a/GitUI/UserControls/RemotesComboboxControl.cs b/GitUI/UserControls/RemotesComboboxControl.cs index 6199bd3234e..3ca14e9d723 100644 --- a/GitUI/UserControls/RemotesComboboxControl.cs +++ b/GitUI/UserControls/RemotesComboboxControl.cs @@ -1,4 +1,5 @@ using System; +using GitUI.Objects; namespace GitUI.UserControls { @@ -11,7 +12,7 @@ public RemotesComboboxControl() AllowMultiselect = false; } - public string SelectedRemote { get { return (string)comboBoxRemotes.Text; } set { comboBoxRemotes.Text = value; } } + public string SelectedRemote { get { return comboBoxRemotes.Text; } set { comboBoxRemotes.Text = value; } } bool _allowMultiselect; public bool AllowMultiselect @@ -35,7 +36,8 @@ private void RemotesComboboxControl_Load(object sender, EventArgs e) return; } - comboBoxRemotes.DataSource = Module.GetRemotes(); + var gitRemoteController = new GitRemoteController(Module); + comboBoxRemotes.DataSource = gitRemoteController.Remotes; } } } diff --git a/Plugins/GitUIPluginInterfaces/GitUIPluginInterfaces.csproj b/Plugins/GitUIPluginInterfaces/GitUIPluginInterfaces.csproj index 635b8698b1e..95019ae5883 100644 --- a/Plugins/GitUIPluginInterfaces/GitUIPluginInterfaces.csproj +++ b/Plugins/GitUIPluginInterfaces/GitUIPluginInterfaces.csproj @@ -59,6 +59,9 @@ ..\..\FxCopRules.ruleset + + ..\..\ResourceManager\bin\Debug\GitCommands.dll + diff --git a/Plugins/GitUIPluginInterfaces/IGitModule.cs b/Plugins/GitUIPluginInterfaces/IGitModule.cs index 2598031dccc..990e8775455 100644 --- a/Plugins/GitUIPluginInterfaces/IGitModule.cs +++ b/Plugins/GitUIPluginInterfaces/IGitModule.cs @@ -2,12 +2,25 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; +using GitCommands; +using GitCommands.Settings; namespace GitUIPluginInterfaces { /// Provides manipulation with git module. public interface IGitModule { + ConfigFileSettings LocalConfigFile { get; } + + string AddRemote(string name, string path); + IList GetRefs(bool tags = true, bool branches = true); + IEnumerable GetSettings(string setting); + IList GetTree(string id, bool full); + string RemoveRemote(string name); + string RenameRemote(string name, string newName); + void SetSetting(string setting, string value); + void UnsetSetting(string setting); + /// /// Run git command, console window is hidden, redirect output /// @@ -57,7 +70,7 @@ public interface IGitModule IGitModule GetSubmodule(string submoduleName); - string[] GetRemotes(bool allowEmpty); + string[] GetRemotes(bool allowEmpty = true); string GetSetting(string setting); diff --git a/ResourceManager/GitExtensionsFormBase.cs b/ResourceManager/GitExtensionsFormBase.cs index 2ab799c6d89..231c24f6b0a 100644 --- a/ResourceManager/GitExtensionsFormBase.cs +++ b/ResourceManager/GitExtensionsFormBase.cs @@ -15,6 +15,13 @@ public class GitExtensionsFormBase : Form, ITranslate /// Creates a new indicating position restore. public GitExtensionsFormBase() { + this.SetStyle( + ControlStyles.AllPaintingInWmPaint | + ControlStyles.UserPaint | + ControlStyles.DoubleBuffer | + ControlStyles.OptimizedDoubleBuffer, + true); + SetFont(); ShowInTaskbar = Application.OpenForms.Count <= 0; @@ -22,12 +29,24 @@ public GitExtensionsFormBase() Load += GitExtensionsFormLoad; } + + protected override CreateParams CreateParams + { + get + { + var cp = base.CreateParams; + cp.ExStyle |= 0x02000000; // Turn on WS_EX_COMPOSITED + return cp; + } + } + /// Gets or sets a value that specifies if the hotkeys are used protected bool HotkeysEnabled { get; set; } /// Gets or sets the hotkeys protected IEnumerable Hotkeys { get; set; } + /// Overridden: Checks if a hotkey wants to handle the key before letting the message propagate protected override bool ProcessCmdKey(ref Message msg, Keys keyData) {