PageRenderTime 54ms CodeModel.GetById 14ms 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

Large files files are truncated, but you can click here to view the full file

  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,

Large files files are truncated, but you can click here to view the full file