PageRenderTime 55ms CodeModel.GetById 25ms RepoModel.GetById 0ms app.codeStats 0ms

/GitUI/CommandsDialogs/FormPull.cs

https://github.com/qgppl/gitextensions
C# | 876 lines | 720 code | 134 blank | 22 comment | 129 complexity | e2be0e1b298e04cbb462b38ae4a9a0b0 MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Diagnostics;
  5. using System.IO;
  6. using System.Linq;
  7. using System.Text.RegularExpressions;
  8. using System.Windows.Forms;
  9. using GitCommands;
  10. using GitCommands.Config;
  11. using GitCommands.Repository;
  12. using GitUI.Objects;
  13. using GitUI.Properties;
  14. using GitUI.Script;
  15. using GitUI.UserControls;
  16. using GitUIPluginInterfaces;
  17. using ResourceManager;
  18. namespace GitUI.CommandsDialogs
  19. {
  20. public partial class FormPull : GitModuleForm
  21. {
  22. #region Translation
  23. private readonly TranslationString _areYouSureYouWantToRebaseMerge =
  24. new TranslationString("The current commit is a merge." + Environment.NewLine +
  25. "Are you sure you want to rebase this merge?");
  26. private readonly TranslationString _areYouSureYouWantToRebaseMergeCaption =
  27. new TranslationString("Rebase merge commit?");
  28. private readonly TranslationString _allMergeConflictSolvedQuestion =
  29. new TranslationString("Are all merge conflicts solved? Do you want to commit?");
  30. private readonly TranslationString _allMergeConflictSolvedQuestionCaption =
  31. new TranslationString("Conflicts solved");
  32. private readonly TranslationString _applyShashedItemsAgain =
  33. new TranslationString("Apply stashed items to working directory again?");
  34. private readonly TranslationString _applyShashedItemsAgainCaption =
  35. new TranslationString("Auto stash");
  36. private readonly TranslationString _fetchAllBranchesCanOnlyWithFetch =
  37. new TranslationString("You can only fetch all remote branches (*) without merge or rebase." +
  38. Environment.NewLine + "If you want to fetch all remote branches, choose fetch." +
  39. Environment.NewLine +
  40. "If you want to fetch and merge a branch, choose a specific branch.");
  41. private readonly TranslationString _selectRemoteRepository =
  42. new TranslationString("Please select a remote repository");
  43. private readonly TranslationString _selectSourceDirectory =
  44. new TranslationString("Please select a source directory");
  45. private readonly TranslationString _questionInitSubmodules =
  46. new TranslationString("The pulled has submodules configured." + Environment.NewLine +
  47. "Do you want to initialize the submodules?" + Environment.NewLine +
  48. "This will initialize and update all submodules recursive.");
  49. private readonly TranslationString _questionInitSubmodulesCaption =
  50. new TranslationString("Submodules");
  51. private readonly TranslationString _notOnBranchMainInstruction = new TranslationString("You are not working on a branch");
  52. private readonly TranslationString _notOnBranch = new TranslationString("You cannot \"pull\" when git head detached." +
  53. Environment.NewLine + "" + Environment.NewLine + "Do you want to continue?");
  54. private readonly TranslationString _notOnBranchButtons = new TranslationString("Checkout branch|Continue");
  55. private readonly TranslationString _notOnBranchCaption = new TranslationString("Not on a branch");
  56. private readonly TranslationString _noRemoteBranch = new TranslationString("You didn't specify a remote branch");
  57. private readonly TranslationString _noRemoteBranchMainInstruction = new TranslationString(
  58. "You asked to pull from the remote '{0}'," + Environment.NewLine +
  59. "but did not specify a remote branch." + Environment.NewLine +
  60. "Because this is not the default configured remote for your local branch," + Environment.NewLine +
  61. "you must specify a remote branch.");
  62. private readonly TranslationString _noRemoteBranchForFetchMainInstruction = new TranslationString(
  63. "You asked to fetch from the remote '{0}'," + Environment.NewLine +
  64. "but did not specify a remote branch." + Environment.NewLine +
  65. "Because this is not the current branch, you must specify a remote branch.");
  66. private readonly TranslationString _noRemoteBranchButtons = new TranslationString("Pull from {0}|Cancel");
  67. private readonly TranslationString _noRemoteBranchForFetchButtons = new TranslationString("Fetch from {0}|Cancel");
  68. private readonly TranslationString _noRemoteBranchCaption = new TranslationString("Remote branch not specified");
  69. private readonly TranslationString _dontShowAgain = new TranslationString("Don't show me this message again.");
  70. private readonly TranslationString _pruneBranchesCaption = new TranslationString("Pull was rejected");
  71. private readonly TranslationString _pruneBranchesMainInstruction = new TranslationString("Remote branch no longer exist");
  72. private readonly TranslationString _pruneBranchesBranch =
  73. new TranslationString("Do you want deletes all stale remote-tracking branches?");
  74. private readonly TranslationString _pruneBranchesButtons = new TranslationString("Deletes stale branches|Cancel");
  75. private readonly TranslationString _pruneFromCaption = new TranslationString("Prune remote branches from {0}");
  76. private readonly TranslationString _hoverShowImageLabelText = new TranslationString("Hover to see scenario when fast forward is possible.");
  77. #endregion
  78. public bool ErrorOccurred { get; private set; }
  79. private IList<IGitRef> _heads;
  80. private string _branch;
  81. private bool _bInternalUpdate;
  82. private const string AllRemotes = "[ All ]";
  83. private readonly IGitRemoteController _gitRemoteController;
  84. private FormPull()
  85. : this(null, null, null)
  86. { }
  87. public FormPull(GitUICommands aCommands, string defaultRemoteBranch, string defaultRemote)
  88. : base(aCommands)
  89. {
  90. InitializeComponent();
  91. Translate();
  92. helpImageDisplayUserControl1.Visible = !AppSettings.DontShowHelpImages;
  93. helpImageDisplayUserControl1.IsOnHoverShowImage2NoticeText = _hoverShowImageLabelText.Text;
  94. if (aCommands != null)
  95. {
  96. _gitRemoteController = new GitRemoteController(Module);
  97. Init(defaultRemote);
  98. }
  99. Merge.Checked = AppSettings.FormPullAction == AppSettings.PullAction.Merge;
  100. Rebase.Checked = AppSettings.FormPullAction == AppSettings.PullAction.Rebase;
  101. Fetch.Checked = AppSettings.FormPullAction == AppSettings.PullAction.Fetch;
  102. localBranch.Enabled = Fetch.Checked;
  103. AutoStash.Checked = AppSettings.AutoStash;
  104. ErrorOccurred = false;
  105. if (!string.IsNullOrEmpty(defaultRemoteBranch))
  106. {
  107. Branches.Text = defaultRemoteBranch;
  108. }
  109. // If this repo is shallow, show an option to Unshallow
  110. if (aCommands != null)
  111. {
  112. // Detect by presence of the shallow file, not 100% sure it's the best way, but it's created upon shallow cloning and removed upon unshallowing
  113. bool isRepoShallow = File.Exists(Path.Combine(aCommands.Module.GetGitDirectory(), "shallow"));
  114. if (isRepoShallow)
  115. Unshallow.Visible = true;
  116. }
  117. }
  118. private void Init(string defaultRemote)
  119. {
  120. _branch = Module.GetSelectedBranch();
  121. localBranch.Text = _branch;
  122. BindRemotesDropDown(defaultRemote);
  123. }
  124. private void BindRemotesDropDown(string selectedRemoteName)
  125. {
  126. // refresh registered git remotes
  127. _gitRemoteController.LoadRemotes();
  128. _NO_TRANSLATE_Remotes.Sorted = false;
  129. _NO_TRANSLATE_Remotes.DataSource = new[] { new GitRemote { Name = AllRemotes } }.Union(_gitRemoteController.Remotes).ToList();
  130. _NO_TRANSLATE_Remotes.DisplayMember = "Name";
  131. _NO_TRANSLATE_Remotes.SelectedIndex = -1;
  132. ComboBoxHelper.ResizeComboBoxDropDownWidth(_NO_TRANSLATE_Remotes, AppSettings.BranchDropDownMinWidth, AppSettings.BranchDropDownMaxWidth);
  133. if (selectedRemoteName.IsNullOrEmpty())
  134. {
  135. selectedRemoteName = Module.GetSetting(string.Format(SettingKeyString.BranchRemote, _branch));
  136. }
  137. var currentBranchRemote = _gitRemoteController.Remotes.FirstOrDefault(x => x.Name.Equals(selectedRemoteName, StringComparison.OrdinalIgnoreCase));
  138. if (currentBranchRemote != null)
  139. {
  140. _NO_TRANSLATE_Remotes.SelectedItem = currentBranchRemote;
  141. }
  142. else if (_gitRemoteController.Remotes.Any())
  143. {
  144. // we couldn't find the default assigned remote for the selected branch
  145. // it is usually gets mapped via FormRemotes -> "default pull behavior" tab
  146. // so pick the default user remote
  147. _NO_TRANSLATE_Remotes.SelectedIndex = 1;
  148. }
  149. else
  150. {
  151. _NO_TRANSLATE_Remotes.SelectedIndex = 0;
  152. }
  153. }
  154. public DialogResult PullAndShowDialogWhenFailed(IWin32Window owner)
  155. {
  156. DialogResult result = PullChanges(owner);
  157. if (result == DialogResult.No)
  158. result = ShowDialog(owner);
  159. else
  160. Close();
  161. return result;
  162. }
  163. private void MergetoolClick(object sender, EventArgs e)
  164. {
  165. Module.RunExternalCmdShowConsole(AppSettings.GitCommand, "mergetool");
  166. if (MessageBox.Show(this, _allMergeConflictSolvedQuestion.Text, _allMergeConflictSolvedQuestionCaption.Text,
  167. MessageBoxButtons.YesNo) != DialogResult.Yes)
  168. return;
  169. UICommands.StartCommitDialog(this);
  170. }
  171. private void BranchesDropDown(object sender, EventArgs e)
  172. {
  173. if ((PullFromUrl.Checked && string.IsNullOrEmpty(comboBoxPullSource.Text)) &&
  174. (PullFromRemote.Checked && string.IsNullOrEmpty(_NO_TRANSLATE_Remotes.Text)))
  175. {
  176. Branches.DataSource = null;
  177. return;
  178. }
  179. Cursor.Current = Cursors.WaitCursor;
  180. LoadPuttyKey();
  181. if (_heads == null)
  182. {
  183. if (PullFromUrl.Checked)
  184. {
  185. _heads = Module.GetRefs(false, true);
  186. }
  187. else
  188. {
  189. // The line below is the most reliable way to get a list containing
  190. // all remote branches but it is also the slowest.
  191. // Heads = GitCommands.GitCommands.GetRemoteHeads(Remotes.Text, false, true);
  192. // The code below is a quick way to get a list contains all remote branches.
  193. // It only returns the heads that are already known to the repository. This
  194. // doesn't return heads that are new on the server. This can be updated using
  195. // update branch info in the manage remotes dialog.
  196. _heads = new List<IGitRef>();
  197. foreach (var head in Module.GetRefs(true, true))
  198. {
  199. if (!head.IsRemote ||
  200. !head.Name.StartsWith(_NO_TRANSLATE_Remotes.Text, StringComparison.CurrentCultureIgnoreCase))
  201. continue;
  202. _heads.Insert(0, head);
  203. }
  204. }
  205. }
  206. Branches.DisplayMember = "LocalName";
  207. //_heads.Insert(0, GitHead.AllHeads); --> disable this because it is only for expert users
  208. _heads.Insert(0, GitRef.NoHead(Module));
  209. Branches.DataSource = _heads;
  210. ComboBoxHelper.ResizeComboBoxDropDownWidth(Branches, AppSettings.BranchDropDownMinWidth, AppSettings.BranchDropDownMaxWidth);
  211. Cursor.Current = Cursors.Default;
  212. }
  213. private void PullClick(object sender, EventArgs e)
  214. {
  215. DialogResult dialogResult = PullChanges(this);
  216. if (dialogResult != DialogResult.No)
  217. {
  218. DialogResult = dialogResult;
  219. Close();
  220. }
  221. }
  222. private bool AskIfSubmodulesShouldBeInitialized()
  223. {
  224. return MessageBox.Show(this, _questionInitSubmodules.Text, _questionInitSubmodulesCaption.Text,
  225. MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.Yes;
  226. }
  227. private bool InitModules()
  228. {
  229. if (!File.Exists(Module.WorkingDir + ".gitmodules"))
  230. return false;
  231. if (!IsSubmodulesInitialized())
  232. {
  233. if (AskIfSubmodulesShouldBeInitialized())
  234. {
  235. UICommands.StartUpdateSubmodulesDialog(this);
  236. }
  237. return true;
  238. }
  239. return false;
  240. }
  241. private void CheckMergeConflictsOnError(IWin32Window owner)
  242. {
  243. // Rebase failed -> special 'rebase' merge conflict
  244. if (Rebase.Checked && Module.InTheMiddleOfRebase())
  245. {
  246. UICommands.StartRebaseDialog(owner, null);
  247. }
  248. else if (Module.InTheMiddleOfAction())
  249. {
  250. MergeConflictHandler.HandleMergeConflicts(UICommands, owner);
  251. }
  252. }
  253. private void PopStash(IWin32Window owner)
  254. {
  255. if (ErrorOccurred || Module.InTheMiddleOfAction())
  256. return;
  257. bool? messageBoxResult = AppSettings.AutoPopStashAfterPull;
  258. if (messageBoxResult == null)
  259. {
  260. DialogResult res = PSTaskDialog.cTaskDialog.MessageBox(
  261. owner,
  262. _applyShashedItemsAgainCaption.Text,
  263. "",
  264. _applyShashedItemsAgain.Text,
  265. "",
  266. "",
  267. _dontShowAgain.Text,
  268. PSTaskDialog.eTaskDialogButtons.YesNo,
  269. PSTaskDialog.eSysIcons.Question,
  270. PSTaskDialog.eSysIcons.Question);
  271. messageBoxResult = (res == DialogResult.Yes);
  272. if (PSTaskDialog.cTaskDialog.VerificationChecked)
  273. AppSettings.AutoPopStashAfterPull = messageBoxResult;
  274. }
  275. if ((bool)messageBoxResult)
  276. {
  277. UICommands.StashPop(this);
  278. }
  279. }
  280. public DialogResult PullChanges(IWin32Window owner)
  281. {
  282. if (!ShouldPullChanges())
  283. return DialogResult.No;
  284. UpdateSettingsDuringPull();
  285. DialogResult dr = ShouldRebaseMergeCommit();
  286. if (dr != DialogResult.Yes)
  287. return dr;
  288. if (!Fetch.Checked && Branches.Text.IsNullOrWhiteSpace() && Module.IsDetachedHead())
  289. {
  290. int idx = PSTaskDialog.cTaskDialog.ShowCommandBox(owner,
  291. _notOnBranchCaption.Text,
  292. _notOnBranchMainInstruction.Text,
  293. _notOnBranch.Text,
  294. _notOnBranchButtons.Text,
  295. true);
  296. switch (idx)
  297. {
  298. case 0:
  299. if (!UICommands.StartCheckoutBranch(owner, new[] { "" }))
  300. return DialogResult.Cancel;
  301. break;
  302. case -1:
  303. return DialogResult.Cancel;
  304. }
  305. }
  306. if (PullFromUrl.Checked && Directory.Exists(comboBoxPullSource.Text))
  307. Repositories.RepositoryHistory.AddMostRecentRepository(comboBoxPullSource.Text);
  308. var source = CalculateSource();
  309. string curLocalBranch;
  310. string curRemoteBranch;
  311. if (!CalculateLocalBranch(source, out curLocalBranch, out curRemoteBranch))
  312. return DialogResult.No;
  313. ScriptManager.RunEventScripts(this, ScriptEvent.BeforePull);
  314. var stashed = CalculateStashedValue(owner);
  315. using (FormProcess process = CreateFormProcess(source, curLocalBranch, curRemoteBranch))
  316. {
  317. ShowProcessDialogBox(owner, source, process);
  318. try
  319. {
  320. bool aborted = process != null && process.DialogResult == DialogResult.Abort;
  321. if (!aborted && !Fetch.Checked)
  322. {
  323. if (!ErrorOccurred)
  324. {
  325. if (!InitModules())
  326. UICommands.UpdateSubmodules(owner);
  327. }
  328. else
  329. CheckMergeConflictsOnError(owner);
  330. }
  331. }
  332. finally
  333. {
  334. if (stashed)
  335. PopStash(owner);
  336. ScriptManager.RunEventScripts(this, ScriptEvent.AfterPull);
  337. }
  338. return DialogResult.OK;
  339. }
  340. }
  341. private bool ShouldPullChanges()
  342. {
  343. if (PullFromUrl.Checked && string.IsNullOrEmpty(comboBoxPullSource.Text))
  344. {
  345. MessageBox.Show(this, _selectSourceDirectory.Text);
  346. return false;
  347. }
  348. if (PullFromRemote.Checked && string.IsNullOrEmpty(_NO_TRANSLATE_Remotes.Text) && !IsPullAll())
  349. {
  350. MessageBox.Show(this, _selectRemoteRepository.Text);
  351. return false;
  352. }
  353. if (!Fetch.Checked && Branches.Text == @"*")
  354. {
  355. MessageBox.Show(this, _fetchAllBranchesCanOnlyWithFetch.Text);
  356. return false;
  357. }
  358. return true;
  359. }
  360. private DialogResult ShouldRebaseMergeCommit()
  361. {
  362. DialogResult dialogResult;
  363. //ask only if exists commit not pushed to remote yet
  364. if (Rebase.Checked && PullFromRemote.Checked && MergeCommitExists())
  365. {
  366. dialogResult = MessageBox.Show(this, _areYouSureYouWantToRebaseMerge.Text,
  367. _areYouSureYouWantToRebaseMergeCaption.Text,
  368. MessageBoxButtons.YesNoCancel);
  369. }
  370. else
  371. dialogResult = DialogResult.Yes;
  372. return dialogResult;
  373. }
  374. private void ShowProcessDialogBox(IWin32Window owner, string source, FormProcess process)
  375. {
  376. if (process == null)
  377. return;
  378. if (!IsPullAll())
  379. process.Remote = source;
  380. process.ShowDialog(owner);
  381. ErrorOccurred = process.ErrorOccurred();
  382. }
  383. private bool CalculateStashedValue(IWin32Window owner)
  384. {
  385. if (!Fetch.Checked && AutoStash.Checked && !Module.IsBareRepository() &&
  386. Module.GitStatus(UntrackedFilesMode.No, IgnoreSubmodulesMode.Default).Count > 0)
  387. {
  388. UICommands.StashSave(owner, AppSettings.IncludeUntrackedFilesInAutoStash);
  389. return true;
  390. }
  391. return false;
  392. }
  393. private bool IsSubmodulesInitialized()
  394. {
  395. // Fast submodules check
  396. var submodules = Module.GetSubmodulesLocalPaths();
  397. foreach (var submoduleName in submodules)
  398. {
  399. GitModule submodule = Module.GetSubmodule(submoduleName);
  400. if (!submodule.IsValidGitWorkingDir())
  401. return false;
  402. }
  403. return true;
  404. }
  405. private FormProcess CreateFormProcess(string source, string curLocalBranch, string curRemoteBranch)
  406. {
  407. if (Fetch.Checked)
  408. {
  409. return new FormRemoteProcess(Module, Module.FetchCmd(source, curRemoteBranch, curLocalBranch, GetTagsArg(), Unshallow.Checked));
  410. }
  411. Debug.Assert(Merge.Checked || Rebase.Checked);
  412. return new FormRemoteProcess(Module, Module.PullCmd(source, curRemoteBranch, curLocalBranch, Rebase.Checked, GetTagsArg(), Unshallow.Checked))
  413. {
  414. HandleOnExitCallback = HandlePullOnExit
  415. };
  416. }
  417. private bool HandlePullOnExit(ref bool isError, FormProcess form)
  418. {
  419. if (!isError)
  420. return false;
  421. if (!PullFromRemote.Checked || string.IsNullOrEmpty(_NO_TRANSLATE_Remotes.Text))
  422. return false;
  423. //auto pull only if current branch was rejected
  424. Regex isRefRemoved = new Regex(@"Your configuration specifies to .* the ref '.*'[\r]?\nfrom the remote, but no such ref was fetched.");
  425. if (isRefRemoved.IsMatch(form.GetOutputString()))
  426. {
  427. int idx = PSTaskDialog.cTaskDialog.ShowCommandBox(form,
  428. _pruneBranchesCaption.Text,
  429. _pruneBranchesMainInstruction.Text,
  430. _pruneBranchesBranch.Text,
  431. _pruneBranchesButtons.Text,
  432. true);
  433. if (idx == 0)
  434. {
  435. string remote = _NO_TRANSLATE_Remotes.Text;
  436. string pruneCmd = "remote prune " + remote;
  437. using (var formPrune = new FormRemoteProcess(Module, pruneCmd)
  438. {
  439. Remote = remote,
  440. Text = string.Format(_pruneFromCaption.Text, remote)
  441. })
  442. {
  443. formPrune.ShowDialog(form);
  444. }
  445. }
  446. }
  447. return false;
  448. }
  449. private bool? GetTagsArg()
  450. {
  451. return AllTags.Checked ? true : NoTags.Checked ? false : (bool?)null;
  452. }
  453. private bool CalculateLocalBranch(string remote, out string curLocalBranch, out string curRemoteBranch)
  454. {
  455. if (IsPullAll())
  456. {
  457. curLocalBranch = null;
  458. curRemoteBranch = null;
  459. return true;
  460. }
  461. curRemoteBranch = Branches.Text;
  462. if (GitModule.IsDetachedHead(_branch))
  463. {
  464. curLocalBranch = null;
  465. return true;
  466. }
  467. var currentBranchRemote = new Lazy<string>(() => Module.GetSetting(string.Format(SettingKeyString.BranchRemote, localBranch.Text)));
  468. if (_branch == localBranch.Text)
  469. {
  470. if (remote.Equals(currentBranchRemote.Value) || currentBranchRemote.Value.IsNullOrEmpty())
  471. {
  472. curLocalBranch = Branches.Text.IsNullOrEmpty() ? null : _branch;
  473. }
  474. else
  475. {
  476. curLocalBranch = localBranch.Text;
  477. }
  478. }
  479. else
  480. {
  481. curLocalBranch = localBranch.Text;
  482. }
  483. if (Branches.Text.IsNullOrEmpty() && !curLocalBranch.IsNullOrEmpty()
  484. && !remote.Equals(currentBranchRemote.Value) && !Fetch.Checked)
  485. {
  486. int idx = PSTaskDialog.cTaskDialog.ShowCommandBox(this,
  487. _noRemoteBranchCaption.Text,
  488. _noRemoteBranch.Text,
  489. string.Format(_noRemoteBranchMainInstruction.Text, remote),
  490. string.Format(_noRemoteBranchButtons.Text, remote + "/" + curLocalBranch),
  491. false);
  492. switch (idx)
  493. {
  494. case 0:
  495. curRemoteBranch = curLocalBranch;
  496. return true;
  497. default:
  498. return false;
  499. }
  500. }
  501. if (Branches.Text.IsNullOrEmpty() && !curLocalBranch.IsNullOrEmpty()
  502. && Fetch.Checked)
  503. {
  504. //if local branch eq to current branch and remote branch is not specified
  505. //then run fetch with no refspec
  506. if (_branch == curLocalBranch)
  507. {
  508. curLocalBranch = null;
  509. return true;
  510. }
  511. int idx = PSTaskDialog.cTaskDialog.ShowCommandBox(this,
  512. _noRemoteBranchCaption.Text,
  513. _noRemoteBranch.Text,
  514. string.Format(_noRemoteBranchForFetchMainInstruction.Text, remote),
  515. string.Format(_noRemoteBranchForFetchButtons.Text, remote + "/" + curLocalBranch),
  516. false);
  517. switch (idx)
  518. {
  519. case 0:
  520. curRemoteBranch = curLocalBranch;
  521. return true;
  522. default:
  523. return false;
  524. }
  525. }
  526. return true;
  527. }
  528. private string CalculateSource()
  529. {
  530. if (PullFromUrl.Checked)
  531. return comboBoxPullSource.Text;
  532. LoadPuttyKey();
  533. return IsPullAll() ? "--all" : _NO_TRANSLATE_Remotes.Text;
  534. }
  535. private bool MergeCommitExists()
  536. {
  537. return Module.ExistsMergeCommit(CalculateRemoteBranchName(), _branch);
  538. }
  539. private string CalculateRemoteBranchName()
  540. {
  541. string remoteBranchName = CalculateRemoteBranchNameBasedOnBranchesText();
  542. if (remoteBranchName.IsNullOrEmpty())
  543. return remoteBranchName;
  544. else
  545. return _NO_TRANSLATE_Remotes.Text + "/" + remoteBranchName;
  546. }
  547. private string CalculateRemoteBranchNameBasedOnBranchesText()
  548. {
  549. if (!Branches.Text.IsNullOrEmpty())
  550. {
  551. return Branches.Text;
  552. }
  553. string remoteBranchName = Module.GetSetting(string.Format("branch.{0}.merge", _branch));
  554. if (!remoteBranchName.IsNullOrEmpty())
  555. remoteBranchName = Module.RunGitCmd(string.Format("name-rev --name-only \"{0}\"", remoteBranchName)).Trim();
  556. return remoteBranchName;
  557. }
  558. private void UpdateSettingsDuringPull()
  559. {
  560. if (Merge.Checked)
  561. AppSettings.FormPullAction = AppSettings.PullAction.Merge;
  562. if (Rebase.Checked)
  563. AppSettings.FormPullAction = AppSettings.PullAction.Rebase;
  564. if (Fetch.Checked)
  565. AppSettings.FormPullAction = AppSettings.PullAction.Fetch;
  566. AppSettings.AutoStash = AutoStash.Checked;
  567. }
  568. private IEnumerable<string> GetSelectedRemotes()
  569. {
  570. if (PullFromUrl.Checked)
  571. {
  572. yield break;
  573. }
  574. if (IsPullAll())
  575. {
  576. IEnumerable<string> remotes = (IEnumerable<string>)_NO_TRANSLATE_Remotes.DataSource;
  577. foreach (var r in remotes)
  578. {
  579. if (!r.IsNullOrWhiteSpace() && !r.Equals(AllRemotes))
  580. yield return r;
  581. }
  582. }
  583. else
  584. {
  585. if (!_NO_TRANSLATE_Remotes.Text.IsNullOrWhiteSpace())
  586. {
  587. yield return _NO_TRANSLATE_Remotes.Text;
  588. }
  589. }
  590. }
  591. private void LoadPuttyKey()
  592. {
  593. if (!GitCommandHelpers.Plink())
  594. return;
  595. if (File.Exists(AppSettings.Pageant))
  596. {
  597. HashSet<string> files = new HashSet<string>(PathUtil.CreatePathEqualityComparer());
  598. foreach (var remote in GetSelectedRemotes())
  599. {
  600. var sshKeyFile = Module.GetPuttyKeyFileForRemote(remote);
  601. if (!string.IsNullOrEmpty(sshKeyFile))
  602. files.Add(sshKeyFile);
  603. }
  604. foreach (var sshKeyFile in files)
  605. if (File.Exists(sshKeyFile))
  606. GitModule.StartPageantWithKey(sshKeyFile);
  607. }
  608. else
  609. MessageBoxes.PAgentNotFound(this);
  610. }
  611. private void FormPullLoad(object sender, EventArgs e)
  612. {
  613. _NO_TRANSLATE_Remotes.Select();
  614. Text = string.Format("Pull ({0})", Module.WorkingDir);
  615. }
  616. private void FillPullSourceDropDown()
  617. {
  618. comboBoxPullSource.DataSource = Repositories.RemoteRepositoryHistory.Repositories;
  619. comboBoxPullSource.DisplayMember = "Path";
  620. }
  621. private void StashClick(object sender, EventArgs e)
  622. {
  623. UICommands.StartStashDialog(this);
  624. }
  625. private void PullFromRemoteCheckedChanged(object sender, EventArgs e)
  626. {
  627. if (!PullFromRemote.Checked)
  628. {
  629. return;
  630. }
  631. ResetRemoteHeads();
  632. comboBoxPullSource.Enabled = false;
  633. folderBrowserButton1.Enabled = false;
  634. _NO_TRANSLATE_Remotes.Enabled = true;
  635. AddRemote.Enabled = true;
  636. Merge.Enabled = !IsPullAll();
  637. Rebase.Enabled = !IsPullAll();
  638. }
  639. private bool IsPullAll()
  640. {
  641. return _NO_TRANSLATE_Remotes.Text.Equals(AllRemotes, StringComparison.InvariantCultureIgnoreCase);
  642. }
  643. public void SetForFetchAll()
  644. {
  645. _NO_TRANSLATE_Remotes.Text = AllRemotes;
  646. }
  647. private void PullFromUrlCheckedChanged(object sender, EventArgs e)
  648. {
  649. if (!PullFromUrl.Checked)
  650. {
  651. return;
  652. }
  653. ResetRemoteHeads();
  654. comboBoxPullSource.Enabled = true;
  655. folderBrowserButton1.Enabled = true;
  656. _NO_TRANSLATE_Remotes.Enabled = false;
  657. AddRemote.Enabled = false;
  658. Merge.Enabled = true;
  659. Rebase.Enabled = true;
  660. FillPullSourceDropDown();
  661. }
  662. private void AddRemoteClick(object sender, EventArgs e)
  663. {
  664. if (IsPullAll())
  665. {
  666. UICommands.StartRemotesDialog(this);
  667. }
  668. else
  669. {
  670. var selectedRemote = _NO_TRANSLATE_Remotes.Text;
  671. UICommands.StartRemotesDialog(this, selectedRemote);
  672. }
  673. _bInternalUpdate = true;
  674. string origText = _NO_TRANSLATE_Remotes.Text;
  675. BindRemotesDropDown(origText);
  676. _bInternalUpdate = false;
  677. }
  678. private void MergeCheckedChanged(object sender, EventArgs e)
  679. {
  680. localBranch.Enabled = false;
  681. localBranch.Text = _branch;
  682. helpImageDisplayUserControl1.Image1 = Resources.HelpPullMerge;
  683. helpImageDisplayUserControl1.Image2 = Resources.HelpPullMergeFastForward;
  684. helpImageDisplayUserControl1.IsOnHoverShowImage2 = true;
  685. AllTags.Enabled = false;
  686. if (AllTags.Checked)
  687. ReachableTags.Checked = true;
  688. }
  689. private void RebaseCheckedChanged(object sender, EventArgs e)
  690. {
  691. localBranch.Enabled = false;
  692. localBranch.Text = _branch;
  693. helpImageDisplayUserControl1.Image1 = Resources.HelpPullRebase;
  694. helpImageDisplayUserControl1.IsOnHoverShowImage2 = false;
  695. AllTags.Enabled = false;
  696. if (AllTags.Checked)
  697. ReachableTags.Checked = true;
  698. }
  699. private void FetchCheckedChanged(object sender, EventArgs e)
  700. {
  701. localBranch.Enabled = true;
  702. helpImageDisplayUserControl1.Image1 = Resources.HelpPullFetch;
  703. helpImageDisplayUserControl1.IsOnHoverShowImage2 = false;
  704. AllTags.Enabled = true;
  705. }
  706. private void PullSourceValidating(object sender, CancelEventArgs e)
  707. {
  708. ResetRemoteHeads();
  709. }
  710. private void Remotes_TextChanged(object sender, EventArgs e)
  711. {
  712. if (!_bInternalUpdate)
  713. {
  714. RemotesValidating(null, null);
  715. }
  716. }
  717. private void RemotesValidating(object sender, CancelEventArgs e)
  718. {
  719. ResetRemoteHeads();
  720. // update the text box of the Remote Url combobox to show the URL of selected remote
  721. comboBoxPullSource.Text = Module.GetPathSetting(
  722. string.Format(SettingKeyString.RemoteUrl, _NO_TRANSLATE_Remotes.Text));
  723. // update merge options radio buttons
  724. Merge.Enabled = !IsPullAll();
  725. Rebase.Enabled = !IsPullAll();
  726. if (IsPullAll())
  727. {
  728. Fetch.Checked = true;
  729. }
  730. }
  731. private void ResetRemoteHeads()
  732. {
  733. Branches.DataSource = null;
  734. _heads = null;
  735. }
  736. private void localBranch_Leave(object sender, EventArgs e)
  737. {
  738. if (!_branch.Equals(localBranch.Text.Trim()) && Branches.Text.IsNullOrWhiteSpace())
  739. Branches.Text = localBranch.Text;
  740. }
  741. }
  742. }