PageRenderTime 31ms CodeModel.GetById 39ms RepoModel.GetById 0ms app.codeStats 1ms

/GitUI/GitUICommands.cs

https://github.com/qgppl/gitextensions
C# | 2267 lines | 1802 code | 409 blank | 56 comment | 139 complexity | af248561c9d899bbbd0876a47b49c7f6 MD5 | raw file
Possible License(s): GPL-3.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Drawing;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Windows.Forms;
  7. using GitCommands;
  8. using GitCommands.Settings;
  9. using GitUI.CommandsDialogs;
  10. using GitUI.CommandsDialogs.RepoHosting;
  11. using GitUI.CommandsDialogs.SettingsDialog;
  12. using GitUIPluginInterfaces;
  13. using GitUIPluginInterfaces.RepositoryHosts;
  14. using Gravatar;
  15. using JetBrains.Annotations;
  16. using Settings = GitCommands.AppSettings;
  17. namespace GitUI
  18. {
  19. /// <summary>Contains methods to invoke GitEx forms, dialogs, etc.</summary>
  20. public sealed class GitUICommands : IGitUICommands
  21. {
  22. public GitUICommands(GitModule module)
  23. {
  24. Module = module;
  25. RepoChangedNotifier = new ActionNotifier(
  26. () => InvokeEvent(null, PostRepositoryChanged));
  27. }
  28. public GitUICommands(string workingDir)
  29. : this(new GitModule(workingDir)) { }
  30. #region IGitUICommands Members
  31. public event GitUIEventHandler PreBrowse;
  32. public event GitUIEventHandler PostBrowse;
  33. public event GitUIEventHandler PreDeleteBranch;
  34. public event GitUIPostActionEventHandler PostDeleteBranch;
  35. public event GitUIEventHandler PreCheckoutRevision;
  36. public event GitUIPostActionEventHandler PostCheckoutRevision;
  37. public event GitUIEventHandler PreCheckoutBranch;
  38. public event GitUIPostActionEventHandler PostCheckoutBranch;
  39. public event GitUIEventHandler PreFileHistory;
  40. public event GitUIPostActionEventHandler PostFileHistory;
  41. public event GitUIEventHandler PreCompareRevisions;
  42. public event GitUIPostActionEventHandler PostCompareRevisions;
  43. public event GitUIEventHandler PreAddFiles;
  44. public event GitUIPostActionEventHandler PostAddFiles;
  45. public event GitUIEventHandler PreCreateBranch;
  46. public event GitUIPostActionEventHandler PostCreateBranch;
  47. public event GitUIEventHandler PreClone;
  48. public event GitUIPostActionEventHandler PostClone;
  49. public event GitUIEventHandler PreSvnClone;
  50. public event GitUIPostActionEventHandler PostSvnClone;
  51. public event GitUIEventHandler PreCommit;
  52. public event GitUIPostActionEventHandler PostCommit;
  53. public event GitUIEventHandler PreSvnDcommit;
  54. public event GitUIPostActionEventHandler PostSvnDcommit;
  55. public event GitUIEventHandler PreSvnRebase;
  56. public event GitUIPostActionEventHandler PostSvnRebase;
  57. public event GitUIEventHandler PreSvnFetch;
  58. public event GitUIPostActionEventHandler PostSvnFetch;
  59. public event GitUIEventHandler PreInitialize;
  60. public event GitUIPostActionEventHandler PostInitialize;
  61. public event GitUIEventHandler PrePush;
  62. public event GitUIPostActionEventHandler PostPush;
  63. public event GitUIEventHandler PrePull;
  64. public event GitUIPostActionEventHandler PostPull;
  65. public event GitUIEventHandler PreViewPatch;
  66. public event GitUIPostActionEventHandler PostViewPatch;
  67. public event GitUIEventHandler PreApplyPatch;
  68. public event GitUIPostActionEventHandler PostApplyPatch;
  69. public event GitUIEventHandler PreFormatPatch;
  70. public event GitUIPostActionEventHandler PostFormatPatch;
  71. public event GitUIEventHandler PreStash;
  72. public event GitUIPostActionEventHandler PostStash;
  73. public event GitUIEventHandler PreResolveConflicts;
  74. public event GitUIPostActionEventHandler PostResolveConflicts;
  75. public event GitUIEventHandler PreCherryPick;
  76. public event GitUIPostActionEventHandler PostCherryPick;
  77. public event GitUIEventHandler PreRevertCommit;
  78. public event GitUIPostActionEventHandler PostRevertCommit;
  79. public event GitUIEventHandler PreMergeBranch;
  80. public event GitUIPostActionEventHandler PostMergeBranch;
  81. public event GitUIEventHandler PreCreateTag;
  82. public event GitUIPostActionEventHandler PostCreateTag;
  83. public event GitUIEventHandler PreDeleteTag;
  84. public event GitUIPostActionEventHandler PostDeleteTag;
  85. public event GitUIEventHandler PreEditGitIgnore;
  86. public event GitUIPostActionEventHandler PostEditGitIgnore;
  87. public event GitUIEventHandler PreSettings;
  88. public event GitUIPostActionEventHandler PostSettings;
  89. public event GitUIEventHandler PreArchive;
  90. public event GitUIPostActionEventHandler PostArchive;
  91. public event GitUIEventHandler PreMailMap;
  92. public event GitUIPostActionEventHandler PostMailMap;
  93. public event GitUIEventHandler PreVerifyDatabase;
  94. public event GitUIPostActionEventHandler PostVerifyDatabase;
  95. public event GitUIEventHandler PreRemotes;
  96. public event GitUIPostActionEventHandler PostRemotes;
  97. public event GitUIEventHandler PreRebase;
  98. public event GitUIPostActionEventHandler PostRebase;
  99. public event GitUIEventHandler PreRename;
  100. public event GitUIPostActionEventHandler PostRename;
  101. public event GitUIEventHandler PreSubmodulesEdit;
  102. public event GitUIPostActionEventHandler PostSubmodulesEdit;
  103. public event GitUIEventHandler PreUpdateSubmodules;
  104. public event GitUIPostActionEventHandler PostUpdateSubmodules;
  105. public event GitUIEventHandler PreSyncSubmodules;
  106. public event GitUIPostActionEventHandler PostSyncSubmodules;
  107. public event GitUIEventHandler PreBlame;
  108. public event GitUIPostActionEventHandler PostBlame;
  109. public event GitUIEventHandler PreEditGitAttributes;
  110. public event GitUIPostActionEventHandler PostEditGitAttributes;
  111. public event GitUIEventHandler PreBrowseInitialize;
  112. public event GitUIEventHandler PostBrowseInitialize;
  113. public event GitUIEventHandler PreSparseWorkingCopy;
  114. public event GitUIPostActionEventHandler PostSparseWorkingCopy;
  115. /// <summary>
  116. /// listeners for changes being made to repository
  117. /// </summary>
  118. public event GitUIEventHandler PostRepositoryChanged;
  119. public event GitUIEventHandler PostRegisterPlugin;
  120. public ILockableNotifier RepoChangedNotifier { get; private set; }
  121. public IBrowseRepo BrowseRepo { get; set; }
  122. #endregion
  123. public string GitCommand(string arguments)
  124. {
  125. return Module.RunGitCmd(arguments);
  126. }
  127. public string CommandLineCommand(string cmd, string arguments)
  128. {
  129. return Module.RunCmd(cmd, arguments);
  130. }
  131. private bool RequiresValidWorkingDir(object owner)
  132. {
  133. if (!Module.IsValidGitWorkingDir())
  134. {
  135. MessageBoxes.NotValidGitDirectory(owner as IWin32Window);
  136. return false;
  137. }
  138. return true;
  139. }
  140. private bool RequiredValidGitSvnWorikingDir(object owner)
  141. {
  142. if (!RequiresValidWorkingDir(owner))
  143. return false;
  144. if (!GitSvnCommandHelpers.ValidSvnWorkingDir(Module))
  145. {
  146. MessageBoxes.NotValidGitSVNDirectory(owner as IWin32Window);
  147. return false;
  148. }
  149. if (!GitSvnCommandHelpers.CheckRefsRemoteSvn(Module))
  150. {
  151. MessageBoxes.UnableGetSVNInformation(owner as IWin32Window);
  152. return false;
  153. }
  154. return true;
  155. }
  156. public void CacheAvatar(string email)
  157. {
  158. FallBackService gravatarFallBack = FallBackService.Identicon;
  159. try
  160. {
  161. gravatarFallBack =
  162. (FallBackService)Enum.Parse(typeof(FallBackService), Settings.GravatarFallbackService);
  163. }
  164. catch
  165. {
  166. Settings.GravatarFallbackService = gravatarFallBack.ToString();
  167. }
  168. GravatarService.CacheImage(email + ".png", email, Settings.AuthorImageSize,
  169. gravatarFallBack);
  170. }
  171. public Icon FormIcon { get { return GitExtensionsForm.ApplicationIcon; } }
  172. public bool StartBatchFileProcessDialog(object owner, string batchFile)
  173. {
  174. string tempFileName = Path.ChangeExtension(Path.GetTempFileName(), ".cmd");
  175. using (var writer = new StreamWriter(tempFileName))
  176. {
  177. writer.WriteLine("@prompt $G");
  178. writer.Write(batchFile);
  179. }
  180. FormProcess.ShowDialog(owner as IWin32Window, Module, "cmd.exe", "/C \"" + tempFileName + "\"");
  181. File.Delete(tempFileName);
  182. return true;
  183. }
  184. public bool StartBatchFileProcessDialog(string batchFile)
  185. {
  186. return StartBatchFileProcessDialog(null, batchFile);
  187. }
  188. public bool StartCommandLineProcessDialog(GitCommand cmd, IWin32Window parentForm)
  189. {
  190. bool executed;
  191. if (cmd.AccessesRemote())
  192. executed = FormRemoteProcess.ShowDialog(parentForm, Module, cmd.ToLine());
  193. else
  194. executed = FormProcess.ShowDialog(parentForm, Module, cmd.ToLine());
  195. if (executed && cmd.ChangesRepoState())
  196. RepoChangedNotifier.Notify();
  197. return executed;
  198. }
  199. public bool StartCommandLineProcessDialog(object owner, string command, string arguments)
  200. {
  201. FormProcess.ShowDialog(owner as IWin32Window, Module, command, arguments);
  202. return true;
  203. }
  204. public bool StartCommandLineProcessDialog(string command, string arguments)
  205. {
  206. return StartCommandLineProcessDialog(null, command, arguments);
  207. }
  208. public bool StartGitCommandProcessDialog(IWin32Window owner, string arguments)
  209. {
  210. FormProcess.ShowDialog(owner, Module, arguments);
  211. return true;
  212. }
  213. public bool StartGitCommandProcessDialog(string arguments)
  214. {
  215. return StartGitCommandProcessDialog(null, arguments);
  216. }
  217. public bool StartBrowseDialog()
  218. {
  219. return StartBrowseDialog("");
  220. }
  221. public bool StartDeleteBranchDialog(IWin32Window owner, string branch)
  222. {
  223. return DoActionOnRepo(owner, true, false, PreDeleteBranch, PostDeleteBranch, () =>
  224. {
  225. using (var form = new FormDeleteBranch(this, branch))
  226. form.ShowDialog(owner);
  227. return true;
  228. }
  229. );
  230. }
  231. public bool StartDeleteBranchDialog(string branch)
  232. {
  233. return StartDeleteBranchDialog(null, branch);
  234. }
  235. public bool StartCheckoutRevisionDialog(IWin32Window owner, string revision = null)
  236. {
  237. return DoActionOnRepo(owner, true, true, PreCheckoutRevision, PostCheckoutRevision, () =>
  238. {
  239. using (var form = new FormCheckoutRevision(this))
  240. {
  241. form.SetRevision(revision);
  242. return form.ShowDialog(owner) == DialogResult.OK;
  243. }
  244. }
  245. );
  246. }
  247. public bool StartCheckoutRevisionDialog()
  248. {
  249. return StartCheckoutRevisionDialog(null);
  250. }
  251. public bool StashSave(IWin32Window owner, bool includeUntrackedFiles, bool keepIndex = false, string message = "")
  252. {
  253. Func<bool> action = () =>
  254. {
  255. var arguments = GitCommandHelpers.StashSaveCmd(includeUntrackedFiles, keepIndex, message);
  256. FormProcess.ShowDialog(owner, Module, arguments);
  257. return true;
  258. };
  259. return DoActionOnRepo(owner, true, true, null, null, action);
  260. }
  261. public bool StashPop(IWin32Window owner)
  262. {
  263. Func<bool> action = () =>
  264. {
  265. FormProcess.ShowDialog(owner, Module, "stash pop");
  266. MergeConflictHandler.HandleMergeConflicts(this, owner, false, false);
  267. return true;
  268. };
  269. return DoActionOnRepo(owner, true, true, null, null, action);
  270. }
  271. /// <summary>Creates and checks out a new branch starting from the commit at which the stash was originally created.
  272. /// Applies the changes recorded in the stash to the new working directory and index.</summary>
  273. public bool StashBranch(IWin32Window owner, string branchName, string stash = null)
  274. {
  275. Func<bool> action = () =>
  276. {
  277. FormProcess.ShowDialog(owner, Module, "stash branch " + branchName.Quote().Combine(" ", stash.QuoteNE()));
  278. return true;
  279. };
  280. return DoActionOnRepo(owner, true, true, null, null, action);
  281. }
  282. public bool StashDrop(IWin32Window owner, string stashName)
  283. {
  284. Func<bool> action = () =>
  285. {
  286. FormProcess.ShowDialog(owner, Module, "stash drop " + stashName.Quote());
  287. return true;
  288. };
  289. return DoActionOnRepo(owner, true, true, null, null, action);
  290. }
  291. public bool StashApply(IWin32Window owner, string stashName)
  292. {
  293. Func<bool> action = () =>
  294. {
  295. FormProcess.ShowDialog(owner, Module, "stash apply " + stashName.Quote());
  296. MergeConflictHandler.HandleMergeConflicts(this, owner, false, false);
  297. return true;
  298. };
  299. return DoActionOnRepo(owner, true, true, null, null, action);
  300. }
  301. public void InvokeEventOnClose(Form form, GitUIEventHandler ev)
  302. {
  303. form.FormClosed += (object o, FormClosedEventArgs ea) =>
  304. {
  305. InvokeEvent(form == null ? null : form.Owner, ev);
  306. };
  307. }
  308. public void ShowModelessForm(IWin32Window owner, bool requiresValidWorkingDir,
  309. GitUIEventHandler preEvent, GitUIPostActionEventHandler postEvent, Func<Form> provideForm)
  310. {
  311. if (requiresValidWorkingDir && !RequiresValidWorkingDir(owner))
  312. return;
  313. if (!InvokeEvent(owner, preEvent))
  314. return;
  315. Form form = provideForm();
  316. FormClosedEventHandler formClosed = null;
  317. formClosed = (sender, e) =>
  318. {
  319. form.FormClosed -= formClosed;
  320. InvokePostEvent(owner, true, postEvent);
  321. };
  322. form.FormClosed += formClosed;
  323. form.ShowInTaskbar = true;
  324. if (Application.OpenForms.Count > 0)
  325. form.Show();
  326. else
  327. form.ShowDialog();
  328. }
  329. /// <summary>
  330. ///
  331. /// </summary>
  332. /// <param name="requiresValidWorkingDir">If action requires valid working directory</param>
  333. /// <param name="owner">Owner window</param>
  334. /// <param name="changesRepo">if successfully done action changes repo state</param>
  335. /// <param name="preEvent">Event invoked before performing action</param>
  336. /// <param name="postEvent">Event invoked after performing action</param>
  337. /// <param name="action">Action to do. Return true to indicate that the action was successfully done.</param>
  338. /// <returns>true if action was successfully done, false otherwise</returns>
  339. public bool DoActionOnRepo(IWin32Window owner, bool requiresValidWorkingDir, bool changesRepo,
  340. GitUIEventHandler preEvent, GitUIPostActionEventHandler postEvent, Func<bool> action)
  341. {
  342. bool actionDone = false;
  343. RepoChangedNotifier.Lock();
  344. try
  345. {
  346. if (requiresValidWorkingDir && !RequiresValidWorkingDir(owner))
  347. return false;
  348. if (!InvokeEvent(owner, preEvent))
  349. return false;
  350. try
  351. {
  352. actionDone = action();
  353. }
  354. finally
  355. {
  356. InvokePostEvent(owner, actionDone, postEvent);
  357. }
  358. }
  359. finally
  360. {
  361. RepoChangedNotifier.UnLock(changesRepo && actionDone);
  362. }
  363. return actionDone;
  364. }
  365. public void DoActionOnRepo(Action action)
  366. {
  367. Func<bool> fnc = () =>
  368. {
  369. action();
  370. return true;
  371. };
  372. DoActionOnRepo(null, false, false, null, null, fnc);
  373. }
  374. public bool DoActionOnRepo(Func<bool> action)
  375. {
  376. return DoActionOnRepo(null, false, true, null, null, action);
  377. }
  378. #region Checkout
  379. public bool StartCheckoutBranch(IWin32Window owner, string branch, bool remote, string[] containRevisons)
  380. {
  381. return DoActionOnRepo(owner, true, true, PreCheckoutBranch, PostCheckoutBranch, () =>
  382. {
  383. using (var form = new FormCheckoutBranch(this, branch, remote, containRevisons))
  384. return form.DoDefaultActionOrShow(owner) != DialogResult.Cancel;
  385. }
  386. );
  387. }
  388. public bool StartCheckoutBranch(IWin32Window owner, string branch, bool remote)
  389. {
  390. return StartCheckoutBranch(owner, branch, remote, null);
  391. }
  392. public bool StartCheckoutBranch(IWin32Window owner, string[] containRevisons)
  393. {
  394. return StartCheckoutBranch(owner, "", false, containRevisons);
  395. }
  396. public bool StartCheckoutBranch(IWin32Window owner)
  397. {
  398. return StartCheckoutBranch(owner, "", false, null);
  399. }
  400. public bool StartCheckoutBranch(string branch, bool remote)
  401. {
  402. return StartCheckoutBranch(null, branch, remote, null);
  403. }
  404. public bool StartCheckoutBranch()
  405. {
  406. return StartCheckoutBranch(null, "", false, null);
  407. }
  408. public bool StartCheckoutRemoteBranch(IWin32Window owner, string branch)
  409. {
  410. return StartCheckoutBranch(owner, branch, true);
  411. }
  412. #endregion Checkout
  413. public bool StartCompareRevisionsDialog(IWin32Window owner)
  414. {
  415. Func<bool> action = () =>
  416. {
  417. using (var form = new FormLog(this))
  418. {
  419. return form.ShowDialog(owner) == DialogResult.OK;
  420. }
  421. };
  422. return DoActionOnRepo(owner, true, true, PreCompareRevisions, PostCompareRevisions, action);
  423. }
  424. public bool StartCompareRevisionsDialog()
  425. {
  426. return StartCompareRevisionsDialog(null);
  427. }
  428. public bool StartAddFilesDialog(IWin32Window owner, string addFiles)
  429. {
  430. return DoActionOnRepo(owner, true, true, PreAddFiles, PostAddFiles, () =>
  431. {
  432. using (var form = new FormAddFiles(this, addFiles))
  433. form.ShowDialog(owner);
  434. return true;
  435. }
  436. );
  437. }
  438. public bool StartAddFilesDialog(IWin32Window owner)
  439. {
  440. return StartAddFilesDialog(owner, null);
  441. }
  442. public bool StartAddFilesDialog(string addFiles)
  443. {
  444. return StartAddFilesDialog(null, addFiles);
  445. }
  446. public bool StartAddFilesDialog()
  447. {
  448. return StartAddFilesDialog(null, null);
  449. }
  450. public bool StartCreateBranchDialog(IWin32Window owner, GitRevision revision)
  451. {
  452. Func<bool> action = () =>
  453. {
  454. using (var form = new FormCreateBranch(this, revision))
  455. {
  456. return form.ShowDialog(owner) == DialogResult.OK;
  457. }
  458. };
  459. return DoActionOnRepo(owner, true, true, PreCreateBranch, PostCreateBranch, action);
  460. }
  461. public bool StartCreateBranchDialog()
  462. {
  463. return StartCreateBranchDialog(null, null);
  464. }
  465. public bool StartCloneDialog(IWin32Window owner, string url, bool openedFromProtocolHandler, EventHandler<GitModuleEventArgs> GitModuleChanged)
  466. {
  467. Func<bool> action = () =>
  468. {
  469. using (var form = new FormClone(this, url, openedFromProtocolHandler, GitModuleChanged))
  470. form.ShowDialog(owner);
  471. return true;
  472. };
  473. return DoActionOnRepo(owner, false, false, PreClone, PostClone, action);
  474. }
  475. public bool StartCloneDialog(IWin32Window owner, string url, EventHandler<GitModuleEventArgs> GitModuleChanged)
  476. {
  477. return StartCloneDialog(owner, url, false, GitModuleChanged);
  478. }
  479. public bool StartCloneDialog(IWin32Window owner, string url)
  480. {
  481. return StartCloneDialog(owner, url, false, null);
  482. }
  483. public bool StartCloneDialog(IWin32Window owner)
  484. {
  485. return StartCloneDialog(owner, null, false, null);
  486. }
  487. public bool StartCloneDialog(string url)
  488. {
  489. return StartCloneDialog(null, url, false, null);
  490. }
  491. public bool StartCloneDialog()
  492. {
  493. return StartCloneDialog(null, null, false, null);
  494. }
  495. public bool StartSvnCloneDialog(IWin32Window owner, EventHandler<GitModuleEventArgs> GitModuleChanged)
  496. {
  497. Func<bool> action = () =>
  498. {
  499. using (var form = new FormSvnClone(this, GitModuleChanged))
  500. form.ShowDialog(owner);
  501. return true;
  502. };
  503. return DoActionOnRepo(owner, false, false, PreSvnClone, PostSvnClone, action);
  504. }
  505. public bool StartSvnCloneDialog()
  506. {
  507. return StartSvnCloneDialog(null, null);
  508. }
  509. public void StartCleanupRepositoryDialog(IWin32Window owner = null, string path = null)
  510. {
  511. using (var form = new FormCleanupRepository(this))
  512. {
  513. form.SetPathArgument(path);
  514. form.ShowDialog(owner);
  515. }
  516. }
  517. public bool StartSquashCommitDialog(IWin32Window owner, GitRevision revision)
  518. {
  519. Func<bool> action = () =>
  520. {
  521. using (var form = new FormCommit(this, CommitKind.Squash, revision))
  522. {
  523. form.ShowDialog(owner);
  524. }
  525. return true;
  526. };
  527. return DoActionOnRepo(action);
  528. }
  529. public bool StartFixupCommitDialog(IWin32Window owner, GitRevision revision)
  530. {
  531. Func<bool> action = () =>
  532. {
  533. using (var form = new FormCommit(this, CommitKind.Fixup, revision))
  534. {
  535. form.ShowDialog(owner);
  536. }
  537. return true;
  538. };
  539. return DoActionOnRepo(action);
  540. }
  541. public bool StartCommitDialog(IWin32Window owner, bool showOnlyWhenChanges)
  542. {
  543. Func<bool> action = () =>
  544. {
  545. using (var form = new FormCommit(this))
  546. {
  547. if (showOnlyWhenChanges)
  548. form.ShowDialogWhenChanges(owner);
  549. else
  550. form.ShowDialog(owner);
  551. }
  552. return true;
  553. };
  554. return DoActionOnRepo(owner, true, false, PreCommit, PostCommit, action);
  555. }
  556. public bool StartCommitDialog(IWin32Window owner)
  557. {
  558. return StartCommitDialog(owner, false);
  559. }
  560. public bool StartCommitDialog(bool showOnlyWhenChanges)
  561. {
  562. return StartCommitDialog(null, showOnlyWhenChanges);
  563. }
  564. public bool StartCommitDialog()
  565. {
  566. return StartCommitDialog(null, false);
  567. }
  568. public bool StartSvnDcommitDialog(IWin32Window owner)
  569. {
  570. if (!RequiredValidGitSvnWorikingDir(owner))
  571. return false;
  572. Func<bool> action = () =>
  573. {
  574. return FormProcess.ShowDialog(owner, Module, Settings.GitCommand, GitSvnCommandHelpers.DcommitCmd());
  575. };
  576. return DoActionOnRepo(owner, true, true, PreSvnDcommit, PostSvnDcommit, action);
  577. }
  578. public bool StartSvnDcommitDialog()
  579. {
  580. return StartSvnDcommitDialog(null);
  581. }
  582. public bool StartSvnRebaseDialog(IWin32Window owner)
  583. {
  584. if (!RequiredValidGitSvnWorikingDir(owner))
  585. return false;
  586. Func<bool> action = () =>
  587. {
  588. FormProcess.ShowDialog(owner, Module, Settings.GitCommand, GitSvnCommandHelpers.RebaseCmd());
  589. return true;
  590. };
  591. return DoActionOnRepo(owner, true, true, PreSvnRebase, PostSvnRebase, action);
  592. }
  593. public bool StartSvnRebaseDialog()
  594. {
  595. return StartSvnRebaseDialog(null);
  596. }
  597. public bool StartSvnFetchDialog(IWin32Window owner)
  598. {
  599. if (!RequiredValidGitSvnWorikingDir(owner))
  600. return false;
  601. Func<bool> action = () =>
  602. {
  603. return FormProcess.ShowDialog(owner, Module, Settings.GitCommand, GitSvnCommandHelpers.FetchCmd());
  604. };
  605. return DoActionOnRepo(owner, true, true, PreSvnFetch, PostSvnFetch, action);
  606. }
  607. public bool StartSvnFetchDialog()
  608. {
  609. return StartSvnFetchDialog(null);
  610. }
  611. public bool StartInitializeDialog(IWin32Window owner, EventHandler<GitModuleEventArgs> GitModuleChanged)
  612. {
  613. return StartInitializeDialog(owner, null, GitModuleChanged);
  614. }
  615. public bool StartInitializeDialog()
  616. {
  617. return StartInitializeDialog((IWin32Window)null, null);
  618. }
  619. public bool StartInitializeDialog(IWin32Window owner, string dir, EventHandler<GitModuleEventArgs> GitModuleChanged)
  620. {
  621. Func<bool> action = () =>
  622. {
  623. if (dir == null)
  624. dir = Module.IsValidGitWorkingDir() ? Module.WorkingDir : string.Empty;
  625. using (var frm = new FormInit(dir, GitModuleChanged)) frm.ShowDialog(owner);
  626. return true;
  627. };
  628. return DoActionOnRepo(owner, false, true, PreInitialize, PostInitialize, action);
  629. }
  630. public bool StartInitializeDialog(string dir)
  631. {
  632. return StartInitializeDialog(null, dir, null);
  633. }
  634. /// <summary>
  635. /// Starts pull dialog
  636. /// </summary>
  637. /// <param name="owner">An implementation of IWin32Window that will own the modal dialog box.</param>
  638. /// <param name="pullOnShow"></param>
  639. /// <param name="pullCompleted">true if pull completed with no errors</param>
  640. /// <returns>if revision grid should be refreshed</returns>
  641. public bool StartPullDialog(IWin32Window owner, bool pullOnShow, string remoteBranch, string remote, out bool pullCompleted, bool fetchAll)
  642. {
  643. var pulled = false;
  644. Func<bool> action = () =>
  645. {
  646. using (FormPull formPull = new FormPull(this, remoteBranch, remote))
  647. {
  648. if (fetchAll)
  649. formPull.SetForFetchAll();
  650. DialogResult dlgResult;
  651. if (pullOnShow)
  652. dlgResult = formPull.PullAndShowDialogWhenFailed(owner);
  653. else
  654. dlgResult = formPull.ShowDialog(owner);
  655. if (dlgResult == DialogResult.OK)
  656. {
  657. pulled = !formPull.ErrorOccurred;
  658. }
  659. return dlgResult == DialogResult.OK;
  660. }
  661. };
  662. bool done = DoActionOnRepo(owner, true, true, PrePull, PostPull, action);
  663. pullCompleted = pulled;
  664. return done;
  665. }
  666. public bool StartPullDialog(IWin32Window owner, bool pullOnShow, out bool pullCompleted, bool fetchAll)
  667. {
  668. return StartPullDialog(owner, pullOnShow, null, null, out pullCompleted, fetchAll);
  669. }
  670. public bool StartPullDialog(IWin32Window owner, bool pullOnShow, out bool pullCompleted)
  671. {
  672. return StartPullDialog(owner, pullOnShow, out pullCompleted, false);
  673. }
  674. public bool StartPullDialog(IWin32Window owner, bool pullOnShow)
  675. {
  676. bool errorOccurred;
  677. return StartPullDialog(owner, pullOnShow, out errorOccurred, false);
  678. }
  679. public bool StartPullDialog(bool pullOnShow, out bool pullCompleted)
  680. {
  681. return StartPullDialog(null, pullOnShow, out pullCompleted, false);
  682. }
  683. public bool StartPullDialog(bool pullOnShow, string remoteBranch, out bool pullCompleted)
  684. {
  685. return StartPullDialog(null, pullOnShow, remoteBranch, null, out pullCompleted, false);
  686. }
  687. public bool StartPullDialog(bool pullOnShow)
  688. {
  689. return StartPullDialog(pullOnShow, null);
  690. }
  691. public bool StartPullDialog(bool pullOnShow, string remoteBranch)
  692. {
  693. bool errorOccurred;
  694. return StartPullDialog(pullOnShow, remoteBranch, out errorOccurred);
  695. }
  696. public bool StartPullDialog(IWin32Window owner)
  697. {
  698. bool errorOccurred;
  699. return StartPullDialog(owner, false, out errorOccurred, false);
  700. }
  701. public bool StartPullDialog()
  702. {
  703. return StartPullDialog(false);
  704. }
  705. public bool StartViewPatchDialog(IWin32Window owner, string patchFile)
  706. {
  707. Func<bool> action = () =>
  708. {
  709. using (var viewPatch = new FormViewPatch(this))
  710. {
  711. if (!String.IsNullOrEmpty(patchFile))
  712. viewPatch.LoadPatch(patchFile);
  713. viewPatch.ShowDialog(owner);
  714. }
  715. return true;
  716. };
  717. return DoActionOnRepo(owner, false, false, PreViewPatch, PostViewPatch, action);
  718. }
  719. public bool StartViewPatchDialog(string patchFile)
  720. {
  721. return StartViewPatchDialog(null, patchFile);
  722. }
  723. public bool StartViewPatchDialog(IWin32Window owner)
  724. {
  725. return StartViewPatchDialog(owner, null);
  726. }
  727. public bool StartViewPatchDialog()
  728. {
  729. return StartViewPatchDialog(null, null);
  730. }
  731. public bool StartSparseWorkingCopyDialog()
  732. {
  733. return StartSparseWorkingCopyDialog(null);
  734. }
  735. public bool StartSparseWorkingCopyDialog([CanBeNull] IWin32Window owner)
  736. {
  737. Func<bool> action = () =>
  738. {
  739. using(var form = new FormSparseWorkingCopy(this))
  740. form.ShowDialog(owner);
  741. return true;
  742. };
  743. return DoActionOnRepo(owner, true, false, PreSparseWorkingCopy, PostSparseWorkingCopy, action);
  744. }
  745. public bool StartFormatPatchDialog(IWin32Window owner)
  746. {
  747. Func<bool> action = () =>
  748. {
  749. using (var form = new FormFormatPatch(this))
  750. form.ShowDialog(owner);
  751. return true;
  752. };
  753. return DoActionOnRepo(owner, true, false, PreFormatPatch, PostFormatPatch, action);
  754. }
  755. public bool StartFormatPatchDialog()
  756. {
  757. return StartFormatPatchDialog(null);
  758. }
  759. public bool StartStashDialog(IWin32Window owner)
  760. {
  761. Func<bool> action = () =>
  762. {
  763. using (var form = new FormStash(this))
  764. form.ShowDialog(owner);
  765. return true;
  766. };
  767. return DoActionOnRepo(owner, true, false, PreStash, PostStash, action);
  768. }
  769. public bool StartStashDialog()
  770. {
  771. return StartStashDialog(null);
  772. }
  773. public bool StartResetChangesDialog(IWin32Window owner)
  774. {
  775. var unstagedFiles = Module.GetUnstagedFiles();
  776. return StartResetChangesDialog(owner, unstagedFiles, false);
  777. }
  778. public bool StartResetChangesDialog(IWin32Window owner, IEnumerable<GitItemStatus> unstagedFiles, bool onlyUnstaged)
  779. {
  780. // Show a form asking the user if they want to reset the changes.
  781. FormResetChanges.ActionEnum resetAction = FormResetChanges.ShowResetDialog(owner, unstagedFiles.Any(item => !item.IsNew), unstagedFiles.Any(item => item.IsNew));
  782. if (resetAction == FormResetChanges.ActionEnum.Cancel)
  783. {
  784. return false;
  785. }
  786. Func<bool> action = () =>
  787. {
  788. if (onlyUnstaged)
  789. Module.RunGitCmd("checkout -- .");
  790. else
  791. // Reset all changes.
  792. Module.ResetHard("");
  793. if (resetAction == FormResetChanges.ActionEnum.ResetAndDelete)
  794. Module.RunGitCmd("clean -df");
  795. return true;
  796. };
  797. return DoActionOnRepo(owner, true, true, null, null, action);
  798. }
  799. public bool StartResetChangesDialog(IWin32Window owner, string fileName)
  800. {
  801. // Show a form asking the user if they want to reset the changes.
  802. FormResetChanges.ActionEnum resetAction = FormResetChanges.ShowResetDialog(owner, true, false);
  803. if (resetAction == FormResetChanges.ActionEnum.Cancel)
  804. {
  805. return false;
  806. }
  807. Cursor.Current = Cursors.WaitCursor;
  808. // Reset all changes.
  809. Module.ResetFile(fileName);
  810. // Also delete new files, if requested.
  811. if (resetAction == FormResetChanges.ActionEnum.ResetAndDelete)
  812. {
  813. try
  814. {
  815. string path = Path.Combine(Module.WorkingDir, fileName);
  816. if (File.Exists(path))
  817. File.Delete(path);
  818. else
  819. Directory.Delete(path, true);
  820. }
  821. catch (System.IO.IOException) { }
  822. catch (System.UnauthorizedAccessException) { }
  823. }
  824. Cursor.Current = Cursors.Default;
  825. return true;
  826. }
  827. public bool StartResetChangesDialog(string fileName)
  828. {
  829. return StartResetChangesDialog(null, fileName);
  830. }
  831. public bool StartResetChangesDialog()
  832. {
  833. return StartResetChangesDialog((IWin32Window) null);
  834. }
  835. public bool StartRevertCommitDialog(IWin32Window owner, GitRevision revision)
  836. {
  837. Func<bool> action = () =>
  838. {
  839. using (var form = new FormRevertCommit(this, revision))
  840. {
  841. return form.ShowDialog(owner) == DialogResult.OK;
  842. }
  843. };
  844. return DoActionOnRepo(owner, true, true, PreRevertCommit, PostRevertCommit, action);
  845. }
  846. public bool StartResolveConflictsDialog(IWin32Window owner, bool offerCommit)
  847. {
  848. Func<bool> action = () =>
  849. {
  850. using (var form = new FormResolveConflicts(this, offerCommit))
  851. form.ShowDialog(owner);
  852. return true;
  853. };
  854. return DoActionOnRepo(owner, true, true, PreResolveConflicts, PostResolveConflicts, action);
  855. }
  856. public bool StartResolveConflictsDialog(IWin32Window owner)
  857. {
  858. return StartResolveConflictsDialog(owner, true);
  859. }
  860. public bool StartResolveConflictsDialog(bool offerCommit)
  861. {
  862. return StartResolveConflictsDialog(null, offerCommit);
  863. }
  864. public bool StartResolveConflictsDialog()
  865. {
  866. return StartResolveConflictsDialog(null, true);
  867. }
  868. public bool StartCherryPickDialog(IWin32Window owner, GitRevision revision)
  869. {
  870. Func<bool> action = () =>
  871. {
  872. using (var form = new FormCherryPick(this, revision))
  873. {
  874. return form.ShowDialog(owner) == DialogResult.OK;
  875. }
  876. };
  877. return DoActionOnRepo(owner, true, true, PreCherryPick, PostCherryPick, action);
  878. }
  879. [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2202:Do not dispose objects multiple times", Justification = "It seems that all prevForm variable values are different so there is not a double dispose here. However the logic is better to be rewritten")]
  880. public bool StartCherryPickDialog(IWin32Window owner, IEnumerable<GitRevision> revisions)
  881. {
  882. if (revisions == null)
  883. throw new ArgumentNullException("revisions");
  884. Func<bool> action = () =>
  885. {
  886. FormCherryPick prevForm = null;
  887. try
  888. {
  889. bool repoChanged = false;
  890. foreach (var r in revisions)
  891. {
  892. var frm = new FormCherryPick(this, r);
  893. if (prevForm != null)
  894. {
  895. frm.CopyOptions(prevForm);
  896. prevForm.Dispose();
  897. }
  898. prevForm = frm;
  899. if (frm.ShowDialog(owner) == DialogResult.OK)
  900. repoChanged = true;
  901. else
  902. return repoChanged;
  903. }
  904. return repoChanged;
  905. }
  906. finally
  907. {
  908. if (prevForm != null)
  909. {
  910. prevForm.Dispose();
  911. }
  912. }
  913. };
  914. return DoActionOnRepo(owner, true, true, PreCherryPick, PostCherryPick, action);
  915. }
  916. public bool StartCherryPickDialog(IWin32Window owner)
  917. {
  918. return StartCherryPickDialog(owner, (GitRevision)null);
  919. }
  920. public bool StartCherryPickDialog()
  921. {
  922. return StartCherryPickDialog(null);
  923. }
  924. /// <summary>Start Merge dialog, using the specified branch.</summary>
  925. /// <param name="owner">Owner of the dialog.</param>
  926. /// <param name="branch">Branch to merge into the current branch.</param>
  927. public bool StartMergeBranchDialog(IWin32Window owner, string branch)
  928. {
  929. Func<bool> action = () =>
  930. {
  931. using (var form = new FormMergeBranch(this, branch))
  932. form.ShowDialog(owner);
  933. return true;
  934. };
  935. return DoActionOnRepo(owner, true, false, PreMergeBranch, PostMergeBranch, action);
  936. }
  937. /// <summary>Start Merge dialog, using the specified branch.</summary>
  938. /// <param name="branch">Branch to merge into the current branch.</param>
  939. public bool StartMergeBranchDialog(string branch)
  940. {
  941. return StartMergeBranchDialog(null, branch);
  942. }
  943. public bool StartCreateTagDialog(IWin32Window owner)
  944. {
  945. Func<bool> action = () =>
  946. {
  947. using (var form = new FormCreateTag(this, null))
  948. {
  949. return form.ShowDialog(owner) == DialogResult.OK;
  950. }
  951. };
  952. return DoActionOnRepo(owner, true, true, PreCreateTag, PostCreateTag, action);
  953. }
  954. public bool StartCreateTagDialog()
  955. {
  956. return StartCreateTagDialog(null);
  957. }
  958. public bool StartDeleteTagDialog(IWin32Window owner, string tag)
  959. {
  960. Func<bool> action = () =>
  961. {
  962. using (var form = new FormDeleteTag(this, tag))
  963. {
  964. return form.ShowDialog(owner) == DialogResult.OK;
  965. }
  966. };
  967. return DoActionOnRepo(owner, true, true, PreDeleteTag, PostDeleteTag, action);
  968. }
  969. public bool StartDeleteTagDialog(string tag)
  970. {
  971. return StartDeleteTagDialog(null, tag);
  972. }
  973. public bool StartDeleteTagDialog()
  974. {
  975. return StartDeleteTagDialog(null, "");
  976. }
  977. public bool StartEditGitIgnoreDialog(IWin32Window owner)
  978. {
  979. Func<bool> action = () =>
  980. {
  981. using (var form = new FormGitIgnore(this))
  982. form.ShowDialog(owner);
  983. return true;
  984. };
  985. return DoActionOnRepo(owner, true, false, PreEditGitIgnore, PostEditGitIgnore, action);
  986. }
  987. public bool StartEditGitIgnoreDialog()
  988. {
  989. return StartEditGitIgnoreDialog(null);
  990. }
  991. public bool StartAddToGitIgnoreDialog(IWin32Window owner, params string[] filePattern)
  992. {
  993. Func<bool> action = () =>
  994. {
  995. using (var frm = new FormAddToGitIgnore(this, filePattern))
  996. frm.ShowDialog(owner);
  997. return true;
  998. };
  999. return DoActionOnRepo(owner, true, false, PreEditGitIgnore, PostEditGitIgnore, action);
  1000. }
  1001. public bool StartSettingsDialog(IWin32Window owner, SettingsPageReference initialPage = null)
  1002. {
  1003. Func<bool> action = () =>
  1004. {
  1005. FormSettings.ShowSettingsDialog(this, owner, initialPage);
  1006. return true;
  1007. };
  1008. return DoActionOnRepo(owner, false, true, PreSettings, PostSettings, action);
  1009. }
  1010. public bool StartSettingsDialog()
  1011. {
  1012. return StartSettingsDialog(null, null);
  1013. }
  1014. public bool StartSettingsDialog(IGitPlugin gitPlugin)
  1015. {
  1016. // TODO: how to pass the main dialog as owner of the SettingsDialog (first parameter):
  1017. return StartSettingsDialog(null, new SettingsPageReferenceByPlugin(gitPlugin));
  1018. }
  1019. /// <summary>
  1020. /// Open the archive dialog
  1021. /// </summary>
  1022. /// <param name="owner"></param>
  1023. /// <param name="revision">Revision to create an archive from</param>
  1024. /// <param name="revision2">Revision for differencial archive </param>
  1025. /// <param name="path">Files path for archive</param>
  1026. /// <returns></returns>
  1027. public bool StartArchiveDialog(IWin32Window owner = null, GitRevision revision = null, GitRevision revision2 = null, string path = null)
  1028. {
  1029. return DoActionOnRepo(owner, true, false, PreArchive, PostArchive, () =>
  1030. {
  1031. using (var form = new FormArchive(this))
  1032. {
  1033. form.SelectedRevision = revision;
  1034. form.SetDiffSelectedRevision(revision2);
  1035. form.SetPathArgument(path);
  1036. form.ShowDialog(owner);
  1037. }
  1038. return true;
  1039. }
  1040. );
  1041. }
  1042. public bool StartArchiveDialog()
  1043. {
  1044. return StartArchiveDialog(null);
  1045. }
  1046. public bool StartMailMapDialog(IWin32Window owner)
  1047. {
  1048. Func<bool> action = () =>
  1049. {
  1050. using (var form = new FormMailMap(this))
  1051. form.ShowDialog(owner);
  1052. return true;
  1053. };
  1054. return DoActionOnRepo(owner, true, false, PreMailMap, PostMailMap, action);
  1055. }
  1056. public bool StartMailMapDialog()
  1057. {
  1058. return StartMailMapDialog(null);
  1059. }
  1060. public bool StartVerifyDatabaseDialog(IWin32Window owner)
  1061. {
  1062. Func<bool> action = () =>
  1063. {
  1064. using (var form = new FormVerify(this))
  1065. form.ShowDialog(owner);
  1066. return true;
  1067. };
  1068. //TODO: move Notify to FormVerify and friends
  1069. return DoActionOnRepo(owner, true, true, PreVerifyDatabase, PostVerifyDatabase, action);
  1070. }
  1071. public bool StartVerifyDatabaseDialog()
  1072. {
  1073. return StartVerifyDatabaseDialog(null);
  1074. }
  1075. /// <summary>
  1076. ///
  1077. /// </summary>
  1078. /// <param name="owner"></param>
  1079. /// <param name="preselectRemote">makes the FormRemotes initialially select the given remote</param>
  1080. /// <returns></returns>
  1081. public bool StartRemotesDialog(IWin32Window owner, string preselectRemote)
  1082. {
  1083. Func<bool> action = () =>
  1084. {
  1085. using (var form = new FormRemotes(this))
  1086. {
  1087. form.PreselectRemoteOnLoad = preselectRemote;
  1088. form.ShowDialog(owner);
  1089. }
  1090. return true;
  1091. };
  1092. return DoActionOnRepo(owner, true, true, PreRemotes, PostRemotes, action);
  1093. }
  1094. public bool StartRemotesDialog(IWin32Window owner)
  1095. {
  1096. return StartRemotesDialog(owner, null);
  1097. }
  1098. public bool StartRemotesDialog()
  1099. {
  1100. return StartRemotesDialog(null);
  1101. }
  1102. public bool StartRebaseDialog(IWin32Window owner, string branch)
  1103. {
  1104. return StartRebaseDialog(owner, string.Empty, null, branch);
  1105. }
  1106. public bool StartRebaseDialog(IWin32Window owner, string from, string to, string onto)
  1107. {
  1108. Func<bool> action = () =>
  1109. {
  1110. using (var form = new FormRebase(this, from, to, onto))
  1111. form.ShowDialog(owner);
  1112. return true;
  1113. };
  1114. return DoActionOnRepo(owner, true, true, PreRebase, PostRebase, action);
  1115. }
  1116. public bool StartRebaseDialog(string branch)
  1117. {
  1118. return StartRebaseDialog(null, branch);
  1119. }
  1120. public bool StartRenameDialog(string branch)
  1121. {
  1122. return StartRenameDialog(null, branch);
  1123. }
  1124. public bool StartRenameDialog(IWin32Window owner, string branch)
  1125. {
  1126. Func<bool> action = () =>
  1127. {
  1128. using (var form = new FormRenameBranch(this, branch))
  1129. {
  1130. return form.ShowDialog(owner) == DialogResult.OK;
  1131. }
  1132. };
  1133. return DoActionOnRepo(owner, true, true, PreRename, PostRename, action);
  1134. }
  1135. public bool StartSubmodulesDialog(IWin32Window owner)
  1136. {
  1137. Func<bool> action = () =>
  1138. {
  1139. using (var form = new FormSubmodules(this))
  1140. form.ShowDialog(owner);
  1141. return true;
  1142. };
  1143. return DoActionOnRepo(owner, true, true, PreSubmodulesEdit, PostSubmodulesEdit, action);
  1144. }
  1145. public bool StartSubmodulesDialog()
  1146. {
  1147. return StartSubmodulesDialog(null);
  1148. }
  1149. public bool StartUpdateSubmodulesDialog(IWin32Window owner)
  1150. {
  1151. Func<bool> action = () =>
  1152. {
  1153. return FormProcess.ShowDialog(owner, Module, GitCommandHelpers.SubmoduleUpdateCmd(""));
  1154. };
  1155. return DoActionOnRepo(owner, true, true, PreUpdateSubmodules, PostUpdateSubmodules, action);
  1156. }
  1157. public bool StartUpdateSubmodulesDialog()
  1158. {
  1159. return StartUpdateSubmodulesDialog(null);
  1160. }
  1161. public bool StartSyncSubmodulesDialog(IWin32Window owner)
  1162. {
  1163. Func<bool> action = () =>
  1164. {
  1165. return FormProcess.ShowDialog(owner, Module, GitCommandHelpers.SubmoduleSyncCmd(""));
  1166. };
  1167. return DoActionOnRepo(owner, true, true, PreSyncSubmodules, PostSyncSubmodules, action);
  1168. }
  1169. public bool StartSyncSubmodulesDialog()
  1170. {
  1171. return StartSyncSubmodulesDialog(null);
  1172. }
  1173. public void UpdateSubmodules(IWin32Window win)
  1174. {
  1175. if (!Module.HasSubmodules())
  1176. return;
  1177. var updateSubmodules = AppSettings.UpdateSubmodulesOnCheckout ?? MessageBoxes.ConfirmUpdateSubmodules(win);
  1178. if (updateSubmodules)
  1179. StartUpdateSubmodulesDialog(win);
  1180. }
  1181. public bool StartPluginSettingsDialog(IWin32Window owner)
  1182. {
  1183. return StartSettingsDialog(owner, PluginsSettingsGroup.GetPageReference());
  1184. }
  1185. public bool StartPluginSettingsDialog()
  1186. {
  1187. return StartPluginSettingsDialog(null);
  1188. }
  1189. public bool StartRepoSettingsDialog(IWin32Window owner)
  1190. {
  1191. return StartSettingsDialog(owner, GitUI.CommandsDialogs.SettingsDialog.Pages.GitConfigSettingsPage.GetPageReference());
  1192. }
  1193. public bool StartBrowseDialog(IWin32Window owner, string filter)
  1194. {
  1195. if (!InvokeEvent(owner, PreBrowse))
  1196. return false;
  1197. var form = new FormBrowse(this, filter);
  1198. if (Application.MessageLoop)
  1199. {
  1200. form.Show();
  1201. }
  1202. else
  1203. {
  1204. Application.Run(form);
  1205. }
  1206. InvokeEvent(owner, PostBrowse);
  1207. return true;
  1208. }
  1209. public bool StartBrowseDialog(string filter)
  1210. {
  1211. return StartBrowseDialog(null, filter);
  1212. }
  1213. public void StartFileHistoryDialog(IWin32Window owner, string fileName, GitRevision revision, bool filterByRevision, bool showBlame)
  1214. {
  1215. Func<Form> provideForm = () =>
  1216. {
  1217. var form = new FormFileHistory(this, fileName, revision, filterByRevision);
  1218. if (showBlame)
  1219. form.SelectBlameTab();
  1220. return form;
  1221. };
  1222. ShowModelessForm(owner, true, PreFileHistory, PostFileHistory, provideForm);
  1223. }
  1224. public void StartFileHistoryDialog(IWin32Window owner, string fileName, GitRevision revision, bool filterByRevision)
  1225. {
  1226. StartFileHistoryDialog(owner, fileName, revision, filterByRevision, false);
  1227. }
  1228. public void StartFileHistoryDialog(IWin32Window owner, string fileName, GitRevision revision)
  1229. {
  1230. StartFileHistoryDialog(owner, fileName, revision, false);
  1231. }
  1232. public void StartFileHistoryDialog(IWin32Window owner, string fileName)
  1233. {
  1234. StartFileHistoryDialog(owner, fileName, null, false);
  1235. }
  1236. public void StartFileHistoryDialog(string fileName, GitRevision revision)
  1237. {
  1238. StartFileHistoryDialog(null, fileName, revision, false);
  1239. }
  1240. public void StartFileHistoryDialog(string fileName)
  1241. {
  1242. StartFileHistoryDialog(fileName, null);
  1243. }
  1244. public bool StartPushDialog()
  1245. {
  1246. return StartPushDialog(false);
  1247. }
  1248. public bool StartPushDialog(IWin32Window owner, bool pushOnShow, out bool pushCompleted)
  1249. {
  1250. bool pushed = false;
  1251. Func<bool> action = () =>
  1252. {
  1253. using (var form = new FormPush(this))
  1254. {
  1255. DialogResult dlgResult;
  1256. if (pushOnShow)
  1257. dlgResult = form.PushAndShowDialogWhenFailed(owner);
  1258. else
  1259. dlgResult = form.ShowDialog(owner);
  1260. if (dlgResult == DialogResult.OK)
  1261. pushed = !form.ErrorOccurred;
  1262. return dlgResult == DialogResult.OK;
  1263. }
  1264. };
  1265. bool done = DoActionOnRepo(owner, true, true, PrePush, PostPush, action);
  1266. pushCompleted = pushed;
  1267. return done;
  1268. }
  1269. public bool StartPushDialog(IWin32Window owner, bool pushOnShow)
  1270. {
  1271. bool pushCompleted;
  1272. return StartPushDialog(owner, pushOnShow, out pushCompleted);
  1273. }
  1274. public bool StartPushDialog(bool pushOnShow)
  1275. {
  1276. return StartPushDialog(null, pushOnShow);
  1277. }
  1278. public bool StartApplyPatchDialog(IWin32Window owner, string patchFile)
  1279. {
  1280. return DoActionOnRepo(owner, true, false, PreApplyPatch, PostApplyPatch, () =>
  1281. {
  1282. using (var form = new FormApplyPatch(this))
  1283. {
  1284. if (Directory.Exists(patchFile))
  1285. form.SetPatchDir(patchFile);
  1286. else
  1287. form.SetPatchFile(patchFile);
  1288. form.ShowDialog(owner);
  1289. return true;
  1290. }
  1291. }
  1292. );
  1293. }
  1294. public bool StartApplyPatchDialog(string patchFile)
  1295. {
  1296. return StartApplyPatchDialog(null, patchFile);
  1297. }
  1298. public bool StartApplyPatchDialog(IWin32Window owner)
  1299. {
  1300. return StartApplyPatchDialog(owner, null);
  1301. }
  1302. public bool StartApplyPatchDialog()
  1303. {
  1304. return StartApplyPatchDialog(null, null);
  1305. }
  1306. public bool StartEditGitAttributesDialog(IWin32Window owner)
  1307. {
  1308. Func<bool> action = () =>
  1309. {
  1310. using (var form = new FormGitAttributes(this))
  1311. {
  1312. form.ShowDialog(owner);
  1313. }
  1314. return true;
  1315. };
  1316. return DoActionOnRepo(owner, true, false, PreEditGitAttributes, PostEditGitAttributes, action);
  1317. }
  1318. public bool StartEditGitAttributesDialog()
  1319. {
  1320. return StartEditGitAttributesDialog(null);
  1321. }
  1322. private bool InvokeEvent(IWin32Window ownerForm, GitUIEventHandler gitUIEventHandler)
  1323. {
  1324. return InvokeEvent(this, ownerForm, gitUIEventHandler);
  1325. }
  1326. public GitModule Module { get; private set; }
  1327. public IGitModule GitModule
  1328. {
  1329. get
  1330. {
  1331. return Module;
  1332. }
  1333. }
  1334. private void InvokePostEvent(IWin32Window ownerForm, bool actionDone, GitUIPostActionEventHandler gitUIEventHandler)
  1335. {
  1336. if (gitUIEventHandler != null)
  1337. {
  1338. var e = new GitUIPostActionEventArgs(ownerForm, this, actionDone);
  1339. gitUIEventHandler(this, e);
  1340. }
  1341. }
  1342. internal bool InvokeEvent(object sender, IWin32Window ownerForm, GitUIEventHandler gitUIEventHandler)
  1343. {
  1344. try
  1345. {
  1346. var e = new GitUIEventArgs(ownerForm, this);
  1347. if (gitUIEventHandler != null)
  1348. gitUIEventHandler(sender, e);
  1349. return !e.Cancel;
  1350. }
  1351. catch (Exception ex)
  1352. {
  1353. MessageBox.Show(ex.Message, "Exception");
  1354. }
  1355. return true;
  1356. }
  1357. public bool StartBlameDialog(IWin32Window owner, string fileName)
  1358. {
  1359. return StartBlameDialog(owner, fileName, null);
  1360. }
  1361. private bool StartBlameDialog(IWin32Window owner, string fileName, GitRevision revision)
  1362. {
  1363. return DoActionOnRepo(owner, true, false, PreBlame, PostBlame, () =>
  1364. {
  1365. using (var frm = new FormBlame(this, fileName, revision))
  1366. frm.ShowDialog(owner);
  1367. return true;
  1368. }
  1369. );
  1370. }
  1371. public bool StartBlameDialog(string fileName)
  1372. {
  1373. return StartBlameDialog(null, fileName, null);
  1374. }
  1375. private bool StartBlameDialog(string fileName, GitRevision revision)
  1376. {
  1377. return StartBlameDialog(null, fileName, revision);
  1378. }
  1379. private void WrapRepoHostingCall(string name, IRepositoryHostPlugin gitHoster,
  1380. Action<IRepositoryHostPlugin> call)
  1381. {
  1382. if (!gitHoster.ConfigurationOk)
  1383. {
  1384. var eventArgs = new GitUIEventArgs(null, this);
  1385. gitHoster.Execute(eventArgs);
  1386. }
  1387. if (gitHoster.ConfigurationOk)
  1388. {
  1389. try
  1390. {
  1391. call(gitHoster);
  1392. }
  1393. catch (Exception ex)
  1394. {
  1395. MessageBox.Show(
  1396. string.Format("ERROR: {0} failed. Message: {1}\r\n\r\n{2}", name, ex.Message, ex.StackTrace),
  1397. "Error! :(");
  1398. }
  1399. }
  1400. }
  1401. public void StartCloneForkFromHoster(IWin32Window owner, IRepositoryHostPlugin gitHoster, EventHandler<GitModuleEventArgs> GitModuleChanged)
  1402. {
  1403. WrapRepoHostingCall("View pull requests", gitHoster, gh =>
  1404. {
  1405. using (var frm = new ForkAndCloneForm(gitHoster, GitModuleChanged)) frm.ShowDialog(owner);
  1406. });
  1407. }
  1408. internal void StartPullRequestsDialog(IWin32Window owner, IRepositoryHostPlugin gitHoster)
  1409. {
  1410. WrapRepoHostingCall("View pull requests", gitHoster,
  1411. gh =>
  1412. {
  1413. var frm = new ViewPullRequestsForm(this, gitHoster) {ShowInTaskbar = true};
  1414. frm.Show();
  1415. });
  1416. }
  1417. internal void StartPullRequestsDialog(IRepositoryHostPlugin gitHoster)
  1418. {
  1419. StartPullRequestsDialog(null, gitHoster);
  1420. }
  1421. public void StartCreatePullRequest(IWin32Window owner)
  1422. {
  1423. List<IRepositoryHostPlugin> relevantHosts =
  1424. (from gh in RepoHosts.GitHosters where gh.GitModuleIsRelevantToMe(Module) select gh).ToList();
  1425. if (relevantHosts.Count == 0)
  1426. MessageBox.Show(owner, "Could not find any repo hosts for current working directory");
  1427. else if (relevantHosts.Count == 1)
  1428. StartCreatePullRequest(owner, relevantHosts.First());
  1429. else
  1430. MessageBox.Show("StartCreatePullRequest:Selection not implemented!");
  1431. }
  1432. public void StartCreatePullRequest()
  1433. {
  1434. StartCreatePullRequest((IRepositoryHostPlugin)null);
  1435. }
  1436. public void StartCreatePullRequest(IWin32Window owner, IRepositoryHostPlugin gitHoster)
  1437. {
  1438. StartCreatePullRequest(owner, gitHoster, null, null);
  1439. }
  1440. public void StartCreatePullRequest(IRepositoryHostPlugin gitHoster)
  1441. {
  1442. StartCreatePullRequest(null, gitHoster, null, null);
  1443. }
  1444. public void StartCreatePullRequest(IRepositoryHostPlugin gitHoster, string chooseRemote, string chooseBranch)
  1445. {
  1446. StartCreatePullRequest(null, gitHoster, chooseRemote, chooseBranch);
  1447. }
  1448. public void StartCreatePullRequest(IWin32Window owner, IRepositoryHostPlugin gitHoster, string chooseRemote, string chooseBranch)
  1449. {
  1450. WrapRepoHostingCall("Create pull request", gitHoster,
  1451. gh =>
  1452. {
  1453. CreatePullRequestForm form = new CreatePullRequestForm(this, gitHoster, chooseRemote, chooseBranch);
  1454. form.ShowInTaskbar = true;
  1455. form.Show();
  1456. });
  1457. }
  1458. public void RunCommand(string[] args)
  1459. {
  1460. var arguments = InitializeArguments(args);
  1461. if (args.Length <= 1)
  1462. return;
  1463. var command = args[1];
  1464. if (command.Equals("blame") && args.Length <= 2)
  1465. {
  1466. MessageBox.Show("Cannot open blame, there is no file selected.", "Blame");
  1467. return;
  1468. }
  1469. if (command.Equals("difftool") && args.Length <= 2)
  1470. {
  1471. MessageBox.Show("Cannot open difftool, there is no file selected.", "Difftool");
  1472. return;
  1473. }
  1474. if (command.Equals("filehistory") && args.Length <= 2)
  1475. {
  1476. MessageBox.Show("Cannot open file history, there is no file selected.", "File history");
  1477. return;
  1478. }
  1479. if (command.Equals("fileeditor") && args.Length <= 2)
  1480. {
  1481. MessageBox.Show("Cannot open file editor, there is no file selected.", "File editor");
  1482. return;
  1483. }
  1484. if (command.Equals("revert") && args.Length <= 2)
  1485. {
  1486. MessageBox.Show("Cannot open revert, there is no file selected.", "Revert");
  1487. return;
  1488. }
  1489. RunCommandBasedOnArgument(args, arguments);
  1490. }
  1491. // Please update FormCommandlineHelp if you add or change commands
  1492. private void RunCommandBasedOnArgument(string[] args, Dictionary<string, string> arguments)
  1493. {
  1494. switch (args[1])
  1495. {
  1496. case "about":
  1497. var frm = new AboutBox();
  1498. frm.StartPosition = FormStartPosition.CenterScreen;
  1499. Application.Run(frm);
  1500. return;
  1501. case "add":
  1502. case "addfiles":
  1503. StartAddFilesDialog(args.Length == 3 ? args[2] : ".");
  1504. return;
  1505. case "apply": // [filename]
  1506. case "applypatch":
  1507. StartApplyPatchDialog(args.Length == 3 ? args[2] : "");
  1508. return;
  1509. case "blame": // filename
  1510. RunBlameCommand(args);
  1511. return;
  1512. case "branch":
  1513. StartCreateBranchDialog();
  1514. return;
  1515. case "browse": // [path] [-filter]
  1516. RunBrowseCommand(args);
  1517. return;
  1518. case "checkout":
  1519. case "checkoutbranch":
  1520. StartCheckoutBranch();
  1521. return;
  1522. case "checkoutrevision":
  1523. StartCheckoutRevisionDialog();
  1524. return;
  1525. case "cherry":
  1526. StartCherryPickDialog();
  1527. return;
  1528. case "cleanup":
  1529. StartCleanupRepositoryDialog();
  1530. return;
  1531. case "clone": // [path]
  1532. RunCloneCommand(args);
  1533. return;
  1534. case "commit": // [--quiet]
  1535. Commit(arguments);
  1536. return;
  1537. case "difftool": // filename
  1538. Module.OpenWithDifftool(args[2]);
  1539. return;
  1540. case "filehistory": // filename
  1541. if (Module.WorkingDir.TrimEnd('\\') == Path.GetFullPath(args[2]) && Module.SuperprojectModule != null)
  1542. Module = Module.SuperprojectModule;
  1543. RunFileHistoryCommand(args);
  1544. return;
  1545. case "fileeditor": // filename
  1546. if (!StartFileEditorDialog(args[2]))
  1547. System.Environment.ExitCode = -1;
  1548. return;
  1549. case "formatpatch":
  1550. StartFormatPatchDialog();
  1551. return;
  1552. case "gitbash":
  1553. Module.RunBash();
  1554. return;
  1555. case "gitignore":
  1556. StartEditGitIgnoreDialog();
  1557. return;
  1558. case "init": // [path]
  1559. RunInitCommand(args);
  1560. return;
  1561. case "merge": // [--branch name]
  1562. RunMergeCommand(arguments);
  1563. return;
  1564. case "mergeconflicts": // [--quiet]
  1565. case "mergetool":
  1566. RunMergeToolOrConflictCommand(arguments);
  1567. return;
  1568. case "openrepo": // [path]
  1569. RunOpenRepoCommand(args);
  1570. return;
  1571. case "pull": // [--rebase] [--merge] [--fetch] [--quiet] [--remotebranch name]
  1572. Pull(arguments);
  1573. return;
  1574. case "push": // [--quiet]
  1575. Push(arguments);
  1576. return;
  1577. case "rebase": // [--branch name]
  1578. RunRebaseCommand(arguments);
  1579. return;
  1580. case "remotes":
  1581. StartRemotesDialog();
  1582. return;
  1583. case "revert":
  1584. case "reset":
  1585. StartResetChangesDialog(args.Length == 3 ? args[2] : "");
  1586. return;
  1587. case "searchfile":
  1588. RunSearchFileCommand();
  1589. return;
  1590. case "settings":
  1591. StartSettingsDialog();
  1592. return;
  1593. case "stash":
  1594. StartStashDialog();
  1595. return;
  1596. case "synchronize": // [--rebase] [--merge] [--fetch] [--quiet]
  1597. RunSynchronizeCommand(arguments);
  1598. return;
  1599. case "tag":
  1600. StartCreateTagDialog();
  1601. return;
  1602. case "viewdiff":
  1603. StartCompareRevisionsDialog();
  1604. return;
  1605. case "viewpatch": // [filename]
  1606. StartViewPatchDialog(args.Length == 3 ? args[2] : "");
  1607. return;
  1608. case "uninstall":
  1609. Uninstall();
  1610. return;
  1611. default:
  1612. if (args[1].StartsWith("git://") || args[1].StartsWith("http://") || args[1].StartsWith("https://"))
  1613. {
  1614. StartCloneDialog(null, args[1], true, null);
  1615. return;
  1616. }
  1617. if (args[1].StartsWith("github-windows://openRepo/"))
  1618. {
  1619. StartCloneDialog(null, args[1].Replace("github-windows://openRepo/", ""), true, null);
  1620. return;
  1621. }
  1622. break;
  1623. }
  1624. var frmCmdLine = new FormCommandlineHelp();
  1625. frmCmdLine.StartPosition = FormStartPosition.CenterScreen;
  1626. Application.Run(frmCmdLine);
  1627. }
  1628. private void Uninstall()
  1629. {
  1630. var configFileGlobalSettings = ConfigFileSettings.CreateGlobal(false);
  1631. var coreEditor = configFileGlobalSettings.GetValue("core.editor");
  1632. if (coreEditor.ToLowerInvariant().Contains(AppSettings.GetInstallDir().ToPosixPath().ToLowerInvariant()))
  1633. {
  1634. configFileGlobalSettings.SetValue("core.editor", "");
  1635. }
  1636. configFileGlobalSettings.Save();
  1637. }
  1638. private void RunMergeCommand(Dictionary<string, string> arguments)
  1639. {
  1640. string branch = null;
  1641. if (arguments.ContainsKey("branch"))
  1642. branch = arguments["branch"];
  1643. StartMergeBranchDialog(branch);
  1644. }
  1645. private void RunSearchFileCommand()
  1646. {
  1647. var searchWindow = new SearchWindow<string>(FindFileMatches);
  1648. Application.Run(searchWindow);
  1649. if (searchWindow.SelectedItem != null)
  1650. //We need to return the file that has been found, the visual studio plugin uses the return value
  1651. //to open the selected file.
  1652. Console.WriteLine(Path.Combine(Module.WorkingDir, searchWindow.SelectedItem));
  1653. }
  1654. private void RunBrowseCommand(string[] args)
  1655. {
  1656. StartBrowseDialog(GetParameterOrEmptyStringAsDefault(args, "-filter"));
  1657. }
  1658. private static string GetParameterOrEmptyStringAsDefault(string[] args, string paramName)
  1659. {
  1660. for (int i = 2; i < args.Length; i++)
  1661. {
  1662. string arg = args[i];
  1663. if (arg.StartsWith(paramName + "="))
  1664. {
  1665. return arg.Replace(paramName + "=", "");
  1666. }
  1667. }
  1668. return string.Empty;
  1669. }
  1670. private void RunOpenRepoCommand(string[] args)
  1671. {
  1672. GitUICommands c = this;
  1673. if (args.Length > 2)
  1674. {
  1675. if (File.Exists(args[2]))
  1676. {
  1677. string path = File.ReadAllText(args[2]).Trim().Split(new char[] { '\n' }, 1).FirstOrDefault();
  1678. if (Directory.Exists(path))
  1679. {
  1680. c = new GitUICommands(path);
  1681. }
  1682. }
  1683. }
  1684. c.StartBrowseDialog(GetParameterOrEmptyStringAsDefault(args, "-filter"));
  1685. }
  1686. private void RunSynchronizeCommand(Dictionary<string, string> arguments)
  1687. {
  1688. Commit(arguments);
  1689. Pull(arguments);
  1690. Push(arguments);
  1691. }
  1692. private void RunRebaseCommand(Dictionary<string, string> arguments)
  1693. {
  1694. string branch = null;
  1695. if (arguments.ContainsKey("branch"))
  1696. branch = arguments["branch"];
  1697. StartRebaseDialog(branch);
  1698. }
  1699. public bool StartFileEditorDialog(string filename, bool showWarning = false)
  1700. {
  1701. using (var formEditor = new FormEditor(this, filename, showWarning))
  1702. return formEditor.ShowDialog() != DialogResult.Cancel;
  1703. }
  1704. private void RunFileHistoryCommand(string[] args)
  1705. {
  1706. //Remove working directory from filename. This is to prevent filenames that are too
  1707. //long while there is room left when the workingdir was not in the path.
  1708. string fileHistoryFileName = String.IsNullOrEmpty(Module.WorkingDir) ? args[2] :
  1709. args[2].Replace(Module.WorkingDir, "").ToPosixPath();
  1710. StartFileHistoryDialog(fileHistoryFileName);
  1711. }
  1712. private void RunCloneCommand(string[] args)
  1713. {
  1714. if (args.Length > 2)
  1715. StartCloneDialog(args[2]);
  1716. else
  1717. StartCloneDialog();
  1718. }
  1719. private void RunInitCommand(string[] args)
  1720. {
  1721. if (args.Length > 2)
  1722. StartInitializeDialog(args[2]);
  1723. else
  1724. StartInitializeDialog();
  1725. }
  1726. private void RunBlameCommand(string[] args)
  1727. {
  1728. // Remove working directory from filename. This is to prevent filenames that are too
  1729. // long while there is room left when the workingdir was not in the path.
  1730. string filenameFromBlame = args[2].Replace(Module.WorkingDir, "").ToPosixPath();
  1731. StartBlameDialog(filenameFromBlame);
  1732. }
  1733. private void RunMergeToolOrConflictCommand(Dictionary<string, string> arguments)
  1734. {
  1735. if (!arguments.ContainsKey("quiet") || Module.InTheMiddleOfConflictedMerge())
  1736. StartResolveConflictsDialog();
  1737. }
  1738. private static Dictionary<string, string> InitializeArguments(string[] args)
  1739. {
  1740. Dictionary<string, string> arguments = new Dictionary<string, string>();
  1741. for (int i = 2; i < args.Length; i++)
  1742. {
  1743. if (args[i].StartsWith("--") && i + 1 < args.Length && !args[i + 1].StartsWith("--"))
  1744. arguments.Add(args[i].TrimStart('-'), args[++i]);
  1745. else if (args[i].StartsWith("--"))
  1746. arguments.Add(args[i].TrimStart('-'), null);
  1747. }
  1748. return arguments;
  1749. }
  1750. private IList<string> FindFileMatches(string name)
  1751. {
  1752. var candidates = Module.GetFullTree("HEAD");
  1753. string nameAsLower = name.ToLower();
  1754. return candidates.Where(fileName => fileName.ToLower().Contains(nameAsLower)).ToList();
  1755. }
  1756. private void Commit(Dictionary<string, string> arguments)
  1757. {
  1758. StartCommitDialog(arguments.ContainsKey("quiet"));
  1759. }
  1760. private void Push(Dictionary<string, string> arguments)
  1761. {
  1762. StartPushDialog(arguments.ContainsKey("quiet"));
  1763. }
  1764. private void Pull(Dictionary<string, string> arguments)
  1765. {
  1766. UpdateSettingsBasedOnArguments(arguments);
  1767. string remoteBranch = null;
  1768. if (arguments.ContainsKey("remotebranch"))
  1769. remoteBranch = arguments["remotebranch"];
  1770. StartPullDialog(arguments.ContainsKey("quiet"), remoteBranch);
  1771. }
  1772. private static void UpdateSettingsBasedOnArguments(Dictionary<string, string> arguments)
  1773. {
  1774. if (arguments.ContainsKey("merge"))
  1775. Settings.FormPullAction = Settings.PullAction.Merge;
  1776. if (arguments.ContainsKey("rebase"))
  1777. Settings.FormPullAction = Settings.PullAction.Rebase;
  1778. if (arguments.ContainsKey("fetch"))
  1779. Settings.FormPullAction = Settings.PullAction.Fetch;
  1780. if (arguments.ContainsKey("autostash"))
  1781. Settings.AutoStash = true;
  1782. }
  1783. internal void RaisePreBrowseInitialize(IWin32Window owner)
  1784. {
  1785. InvokeEvent(owner, PreBrowseInitialize);
  1786. }
  1787. internal void RaisePostBrowseInitialize(IWin32Window owner)
  1788. {
  1789. InvokeEvent(owner, PostBrowseInitialize);
  1790. }
  1791. internal void RaisePostRegisterPlugin(IWin32Window owner)
  1792. {
  1793. InvokeEvent(owner, PostRegisterPlugin);
  1794. }
  1795. public void BrowseGoToRef(string refName, bool showNoRevisionMsg)
  1796. {
  1797. if (BrowseRepo != null)
  1798. BrowseRepo.GoToRef(refName, showNoRevisionMsg);
  1799. }
  1800. public IGitRemoteCommand CreateRemoteCommand()
  1801. {
  1802. return new GitRemoteCommand(Module);
  1803. }
  1804. private class GitRemoteCommand : IGitRemoteCommand
  1805. {
  1806. public object OwnerForm { get; set; }
  1807. public string Remote { get; set; }
  1808. public string Title { get; set; }
  1809. public string CommandText { get; set; }
  1810. public bool ErrorOccurred { get; private set; }
  1811. public string CommandOutput { get; private set; }
  1812. public readonly GitModule Module;
  1813. public event GitRemoteCommandCompletedEventHandler Completed;
  1814. internal GitRemoteCommand(GitModule aModule)
  1815. {
  1816. Module = aModule;
  1817. }
  1818. public void Execute()
  1819. {
  1820. if (CommandText == null)
  1821. throw new InvalidOperationException("CommandText is required");
  1822. using (var form = new FormRemoteProcess(Module, CommandText))
  1823. {
  1824. if (Title != null)
  1825. form.Text = Title;
  1826. if (Remote != null)
  1827. form.Remote = Remote;
  1828. form.HandleOnExitCallback = HandleOnExit;
  1829. form.ShowDialog(OwnerForm as IWin32Window);
  1830. ErrorOccurred = form.ErrorOccurred();
  1831. CommandOutput = form.GetOutputString();
  1832. }
  1833. }
  1834. private bool HandleOnExit(ref bool isError, FormProcess form)
  1835. {
  1836. CommandOutput = form.GetOutputString();
  1837. var e = new GitRemoteCommandCompletedEventArgs(this, isError, false);
  1838. if (Completed != null)
  1839. Completed(form, e);
  1840. isError = e.IsError;
  1841. return e.Handled;
  1842. }
  1843. }
  1844. public override bool Equals(object obj)
  1845. {
  1846. GitUICommands other = obj as GitUICommands;
  1847. return (other != null) && Equals(other);
  1848. }
  1849. bool Equals(GitUICommands other)
  1850. {
  1851. return Equals(Module, other.Module);
  1852. }
  1853. public override int GetHashCode()
  1854. {
  1855. return Module.GetHashCode();
  1856. }
  1857. }
  1858. }