/GitUI/CommandsDialogs/FormBrowse.cs
C# | 3162 lines | 2883 code | 219 blank | 60 comment | 213 complexity | 0ccd660db8521343e8d6828aea17a64c MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0
Large files files are truncated, but you can click here to view the full file
- using System;
- using System.Collections.Generic;
- using System.Collections.Specialized;
- using System.Diagnostics;
- using System.Drawing;
- using System.IO;
- using System.Linq;
- using System.Net;
- using System.Reflection;
- using System.Text;
- using System.Threading;
- using System.Threading.Tasks;
- using System.Windows.Forms;
- using GitCommands;
- using GitCommands.Repository;
- using GitCommands.Utils;
- using GitUI.CommandsDialogs.BrowseDialog;
- using GitUI.CommandsDialogs.BrowseDialog.DashboardControl;
- using GitUI.Hotkey;
- using GitUI.Plugin;
- using GitUI.Properties;
- using GitUI.Script;
- using GitUIPluginInterfaces;
- using ResourceManager;
- using Settings = GitCommands.AppSettings;
- #if !__MonoCS__
- using Microsoft.WindowsAPICodePack.Taskbar;
- #endif
- namespace GitUI.CommandsDialogs
- {
- public partial class FormBrowse : GitModuleForm, IBrowseRepo
- {
- #region Translation
- private readonly TranslationString _stashCount =
- new TranslationString("{0} saved {1}");
- private readonly TranslationString _stashPlural =
- new TranslationString("stashes");
- private readonly TranslationString _stashSingular =
- new TranslationString("stash");
- private readonly TranslationString _warningMiddleOfBisect =
- new TranslationString("You are in the middle of a bisect");
- private readonly TranslationString _warningMiddleOfRebase =
- new TranslationString("You are in the middle of a rebase");
- private readonly TranslationString _warningMiddleOfPatchApply =
- new TranslationString("You are in the middle of a patch apply");
- private readonly TranslationString _hintUnresolvedMergeConflicts =
- new TranslationString("There are unresolved merge conflicts!");
- private readonly TranslationString _noBranchTitle =
- new TranslationString("no branch");
- private readonly TranslationString _noSubmodulesPresent =
- new TranslationString("No submodules");
- private readonly TranslationString _saveFileFilterCurrentFormat =
- new TranslationString("Current format");
- private readonly TranslationString _saveFileFilterAllFiles =
- new TranslationString("All files");
- private readonly TranslationString _indexLockDeleted =
- new TranslationString("index.lock deleted.");
- private readonly TranslationString _indexLockNotFound =
- new TranslationString("index.lock not found at:");
- private readonly TranslationString _errorCaption =
- new TranslationString("Error");
- private readonly TranslationString _noReposHostPluginLoaded =
- new TranslationString("No repository host plugin loaded.");
- private readonly TranslationString _noReposHostFound =
- new TranslationString("Could not find any relevant repository hosts for the currently open repository.");
- private readonly TranslationString _configureWorkingDirMenu =
- new TranslationString("Configure this menu");
- private readonly TranslationString directoryIsNotAValidRepositoryCaption =
- new TranslationString("Open");
- private readonly TranslationString directoryIsNotAValidRepository =
- new TranslationString("The selected item is not a valid git repository.\n\nDo you want to abort and remove it from the recent repositories list?");
- private readonly TranslationString _updateCurrentSubmodule =
- new TranslationString("Update current submodule");
- private readonly TranslationString _nodeNotFoundNextAvailableParentSelected =
- new TranslationString("Node not found. The next available parent node will be selected.");
- private readonly TranslationString _nodeNotFoundSelectionNotChanged =
- new TranslationString("Node not found. File tree selection was not changed.");
- #endregion
- private Dashboard _dashboard;
- private ToolStripItem _rebase;
- private ToolStripItem _bisect;
- private ToolStripItem _warning;
- #if !__MonoCS__
- private ThumbnailToolBarButton _commitButton;
- private ThumbnailToolBarButton _pushButton;
- private ThumbnailToolBarButton _pullButton;
- private bool _toolbarButtonsCreated;
- #endif
- private bool _dontUpdateOnIndexChange;
- private readonly ToolStripGitStatus _toolStripGitStatus;
- private readonly FilterRevisionsHelper _filterRevisionsHelper;
- private readonly FilterBranchHelper _filterBranchHelper;
- private const string DiffTabPageTitleBase = "Diff";
- private readonly FormBrowseMenus _formBrowseMenus;
- private readonly FormBrowseMenuCommands _formBrowseMenuCommands;
- /// <summary>
- /// For VS designer
- /// </summary>
- private FormBrowse()
- {
- InitializeComponent();
- Translate();
- }
- public FormBrowse(GitUICommands aCommands, string filter)
- : base(true, aCommands)
- {
- InitializeComponent();
- // set tab page images
- {
- var imageList = new ImageList();
- CommitInfoTabControl.ImageList = imageList;
- imageList.ColorDepth = ColorDepth.Depth8Bit;
- imageList.Images.Add(global::GitUI.Properties.Resources.IconCommit);
- imageList.Images.Add(global::GitUI.Properties.Resources.IconFileTree);
- imageList.Images.Add(global::GitUI.Properties.Resources.IconDiff);
- CommitInfoTabControl.TabPages[0].ImageIndex = 0;
- CommitInfoTabControl.TabPages[1].ImageIndex = 1;
- CommitInfoTabControl.TabPages[2].ImageIndex = 2;
- }
- RevisionGrid.UICommandsSource = this;
- Repositories.LoadRepositoryHistoryAsync();
- Task.Factory.StartNew(PluginLoader.Load)
- .ContinueWith((task) => RegisterPlugins(), TaskScheduler.FromCurrentSynchronizationContext());
- RevisionGrid.GitModuleChanged += SetGitModule;
- _filterRevisionsHelper = new FilterRevisionsHelper(toolStripTextBoxFilter, toolStripDropDownButton1, RevisionGrid, toolStripLabel2, this);
- _filterBranchHelper = new FilterBranchHelper(toolStripBranches, toolStripDropDownButton2, RevisionGrid);
- Translate();
- if (Settings.ShowGitStatusInBrowseToolbar)
- {
- _toolStripGitStatus = new ToolStripGitStatus
- {
- ImageTransparentColor = Color.Magenta
- };
- if (aCommands != null)
- _toolStripGitStatus.UICommandsSource = this;
- _toolStripGitStatus.Click += StatusClick;
- ToolStrip.Items.Insert(ToolStrip.Items.IndexOf(toolStripButton1), _toolStripGitStatus);
- ToolStrip.Items.Remove(toolStripButton1);
- _toolStripGitStatus.CommitTranslatedString = toolStripButton1.Text;
- }
- RevisionGrid.SelectionChanged += RevisionGridSelectionChanged;
- DiffText.ExtraDiffArgumentsChanged += DiffTextExtraDiffArgumentsChanged;
- _filterRevisionsHelper.SetFilter(filter);
- DiffText.SetFileLoader(getNextPatchFile);
- GitTree.ImageList = new ImageList();
- GitTree.ImageList.Images.Add(Properties.Resources.New); //File
- GitTree.ImageList.Images.Add(Properties.Resources.Folder); //Folder
- GitTree.ImageList.Images.Add(Properties.Resources.IconFolderSubmodule); //Submodule
- GitTree.MouseDown += GitTree_MouseDown;
- GitTree.MouseMove += GitTree_MouseMove;
- this.HotkeysEnabled = true;
- this.Hotkeys = HotkeySettingsManager.LoadHotkeys(HotkeySettingsName);
- this.toolPanel.SplitterDistance = this.ToolStrip.Height;
- this._dontUpdateOnIndexChange = false;
- GitUICommandsChanged += (a, oldcommands) =>
- {
- RefreshPullIcon();
- oldcommands.PostRepositoryChanged -= UICommands_PostRepositoryChanged;
- UICommands.PostRepositoryChanged += UICommands_PostRepositoryChanged;
- oldcommands.BrowseRepo = null;
- UICommands.BrowseRepo = this;
- };
- if (aCommands != null)
- {
- RefreshPullIcon();
- UICommands.PostRepositoryChanged += UICommands_PostRepositoryChanged;
- UICommands.BrowseRepo = this;
- }
- FillBuildReport(); // Ensure correct page visibility
- RevisionGrid.ShowBuildServerInfo = true;
- _formBrowseMenuCommands = new FormBrowseMenuCommands(this, RevisionGrid);
- _formBrowseMenus = new FormBrowseMenus(menuStrip1);
- RevisionGrid.MenuCommands.MenuChanged += (sender, e) => _formBrowseMenus.OnMenuCommandsPropertyChanged();
- }
- void UICommands_PostRepositoryChanged(object sender, GitUIBaseEventArgs e)
- {
- this.InvokeAsync(RefreshRevisions);
- }
- private void RefreshRevisions()
- {
- if (_dashboard == null || !_dashboard.Visible)
- {
- RevisionGrid.ForceRefreshRevisions();
- InternalInitialize(false);
- }
- }
-
- #region IBrowseRepo
- public void GoToRef(string refName, bool showNoRevisionMsg)
- {
- RevisionGrid.GoToRef(refName, showNoRevisionMsg);
- }
- #endregion
- private void ShowDashboard()
- {
- if (_dashboard == null)
- {
- _dashboard = new Dashboard();
- _dashboard.GitModuleChanged += SetGitModule;
- toolPanel.Panel2.Controls.Add(_dashboard);
- _dashboard.Dock = DockStyle.Fill;
- }
- else
- _dashboard.Refresh();
- _dashboard.Visible = true;
- _dashboard.BringToFront();
- _dashboard.ShowRecentRepositories();
- }
- private void HideDashboard()
- {
- if (_dashboard != null && _dashboard.Visible)
- _dashboard.Visible = false;
- }
- private void GitTree_AfterSelect(object sender, TreeViewEventArgs e)
- {
- var item = e.Node.Tag as GitItem;
- if (item == null)
- return;
- if (item.IsBlob)
- FileText.ViewGitItem(item.FileName, item.Guid);
- else if (item.IsCommit)
- FileText.ViewText(item.FileName,
- GitCommandHelpers.GetSubmoduleText(Module, item.FileName, item.Guid));
- else
- FileText.ViewText("", "");
- }
- private void BrowseLoad(object sender, EventArgs e)
- {
- #if !__MonoCS__
- if (EnvUtils.RunningOnWindows() && TaskbarManager.IsPlatformSupported)
- {
- TaskbarManager.Instance.ApplicationId = "GitExtensions";
- }
- #endif
- HideVariableMainMenuItems();
- RevisionGrid.Load();
- _filterBranchHelper.InitToolStripBranchFilter();
- Cursor.Current = Cursors.WaitCursor;
- InternalInitialize(false);
- RevisionGrid.Focus();
- RevisionGrid.IndexWatcher.Reset();
- RevisionGrid.IndexWatcher.Changed += _indexWatcher_Changed;
- Cursor.Current = Cursors.Default;
- try
- {
- if (Settings.PlaySpecialStartupSound)
- {
- using (var cowMoo = Resources.cow_moo)
- new System.Media.SoundPlayer(cowMoo).Play();
- }
- }
- catch // This code is just for fun, we do not want the program to crash because of it.
- {
- }
- }
- void _indexWatcher_Changed(bool indexChanged)
- {
- this.InvokeAsync(() =>
- {
- RefreshButton.Image = indexChanged && Settings.UseFastChecks && Module.IsValidGitWorkingDir()
- ? Resources.arrow_refresh_dirty
- : Resources.arrow_refresh;
- });
- }
- private bool _pluginsLoaded;
- private void LoadPluginsInPluginMenu()
- {
- if (_pluginsLoaded)
- return;
- foreach (var plugin in LoadedPlugins.Plugins)
- {
- var item = new ToolStripMenuItem { Text = plugin.Description, Tag = plugin };
- item.Click += ItemClick;
- pluginsToolStripMenuItem.DropDownItems.Insert(pluginsToolStripMenuItem.DropDownItems.Count - 2, item);
- }
- _pluginsLoaded = true;
- UpdatePluginMenu(Module.IsValidGitWorkingDir());
- }
- /// <summary>
- /// Execute plugin
- /// </summary>
- private void ItemClick(object sender, EventArgs e)
- {
- var menuItem = sender as ToolStripMenuItem;
- if (menuItem == null)
- return;
- var plugin = menuItem.Tag as IGitPlugin;
- if (plugin == null)
- return;
- var eventArgs = new GitUIEventArgs(this, UICommands);
- bool refresh = plugin.Execute(eventArgs);
- if (refresh)
- RefreshToolStripMenuItemClick(null, null);
- }
- private void UpdatePluginMenu(bool validWorkingDir)
- {
- foreach (ToolStripItem item in pluginsToolStripMenuItem.DropDownItems)
- {
- var plugin = item.Tag as IGitPluginForRepository;
- item.Enabled = plugin == null || validWorkingDir;
- }
- }
- private void RegisterPlugins()
- {
- foreach (var plugin in LoadedPlugins.Plugins)
- plugin.Register(UICommands);
- UICommands.RaisePostRegisterPlugin(this);
- }
- private void UnregisterPlugins()
- {
- foreach (var plugin in LoadedPlugins.Plugins)
- plugin.Unregister(UICommands);
- }
- /// <summary>
- /// to avoid showing menu items that should not be there during
- /// the transition from dashboard to repo browser and vice versa
- ///
- /// and reset hotkeys that are shared between mutual exclusive menu items
- /// </summary>
- private void HideVariableMainMenuItems()
- {
- dashboardToolStripMenuItem.Visible = false;
- repositoryToolStripMenuItem.Visible = false;
- commandsToolStripMenuItem.Visible = false;
- refreshToolStripMenuItem.ShortcutKeys = Keys.None;
- refreshDashboardToolStripMenuItem.ShortcutKeys = Keys.None;
- _repositoryHostsToolStripMenuItem.Visible = false;
- _formBrowseMenus.RemoveAdditionalMainMenuItems();
- menuStrip1.Refresh();
- }
- private void InternalInitialize(bool hard)
- {
- Cursor.Current = Cursors.WaitCursor;
- UICommands.RaisePreBrowseInitialize(this);
- // check for updates
- if (Settings.LastUpdateCheck.AddDays(7) < DateTime.Now)
- {
- Settings.LastUpdateCheck = DateTime.Now;
- using (var updateForm = new FormUpdates(Module.AppVersion))
- updateForm.SearchForUpdatesAndShow(Owner, false);
- }
- bool bareRepository = Module.IsBareRepository();
- bool validWorkingDir = Module.IsValidGitWorkingDir();
- bool hasWorkingDir = !string.IsNullOrEmpty(Module.WorkingDir);
- branchSelect.Text = validWorkingDir ? Module.GetSelectedBranch() : "";
- if (hasWorkingDir)
- HideDashboard();
- else
- ShowDashboard();
- toolStripButtonLevelUp.Enabled = hasWorkingDir && !bareRepository;
- CommitInfoTabControl.Visible = validWorkingDir;
- fileExplorerToolStripMenuItem.Enabled = validWorkingDir;
- manageRemoteRepositoriesToolStripMenuItem1.Enabled = validWorkingDir;
- branchSelect.Enabled = validWorkingDir;
- toolStripButton1.Enabled = validWorkingDir && !bareRepository;
- if (_toolStripGitStatus != null)
- _toolStripGitStatus.Enabled = validWorkingDir;
- toolStripButtonPull.Enabled = validWorkingDir;
- toolStripButtonPush.Enabled = validWorkingDir;
- dashboardToolStripMenuItem.Visible = !validWorkingDir;
- repositoryToolStripMenuItem.Visible = validWorkingDir;
- commandsToolStripMenuItem.Visible = validWorkingDir;
- if (validWorkingDir)
- {
- refreshToolStripMenuItem.ShortcutKeys = Keys.F5;
- }
- else
- {
- refreshDashboardToolStripMenuItem.ShortcutKeys = Keys.F5;
- }
- UpdatePluginMenu(validWorkingDir);
- gitMaintenanceToolStripMenuItem.Enabled = validWorkingDir;
- editgitignoreToolStripMenuItem1.Enabled = validWorkingDir;
- editgitattributesToolStripMenuItem.Enabled = validWorkingDir;
- editmailmapToolStripMenuItem.Enabled = validWorkingDir;
- toolStripSplitStash.Enabled = validWorkingDir && !bareRepository;
- commitcountPerUserToolStripMenuItem.Enabled = validWorkingDir;
- _createPullRequestsToolStripMenuItem.Enabled = validWorkingDir;
- _viewPullRequestsToolStripMenuItem.Enabled = validWorkingDir;
- //Only show "Repository hosts" menu item when there is at least 1 repository host plugin loaded
- _repositoryHostsToolStripMenuItem.Visible = RepoHosts.GitHosters.Count > 0;
- if (RepoHosts.GitHosters.Count == 1)
- _repositoryHostsToolStripMenuItem.Text = RepoHosts.GitHosters[0].Description;
- _filterBranchHelper.InitToolStripBranchFilter();
- if (repositoryToolStripMenuItem.Visible)
- {
- manageSubmodulesToolStripMenuItem.Enabled = !bareRepository;
- updateAllSubmodulesToolStripMenuItem.Enabled = !bareRepository;
- synchronizeAllSubmodulesToolStripMenuItem.Enabled = !bareRepository;
- editgitignoreToolStripMenuItem1.Enabled = !bareRepository;
- editgitattributesToolStripMenuItem.Enabled = !bareRepository;
- editmailmapToolStripMenuItem.Enabled = !bareRepository;
- }
- if (commandsToolStripMenuItem.Visible)
- {
- commitToolStripMenuItem.Enabled = !bareRepository;
- mergeToolStripMenuItem.Enabled = !bareRepository;
- rebaseToolStripMenuItem1.Enabled = !bareRepository;
- pullToolStripMenuItem1.Enabled = !bareRepository;
- resetToolStripMenuItem.Enabled = !bareRepository;
- cleanupToolStripMenuItem.Enabled = !bareRepository;
- stashToolStripMenuItem.Enabled = !bareRepository;
- checkoutBranchToolStripMenuItem.Enabled = !bareRepository;
- mergeBranchToolStripMenuItem.Enabled = !bareRepository;
- rebaseToolStripMenuItem.Enabled = !bareRepository;
- runMergetoolToolStripMenuItem.Enabled = !bareRepository;
- cherryPickToolStripMenuItem.Enabled = !bareRepository;
- checkoutToolStripMenuItem.Enabled = !bareRepository;
- bisectToolStripMenuItem.Enabled = !bareRepository;
- applyPatchToolStripMenuItem.Enabled = !bareRepository;
- SvnRebaseToolStripMenuItem.Enabled = !bareRepository;
- SvnDcommitToolStripMenuItem.Enabled = !bareRepository;
- }
- stashChangesToolStripMenuItem.Enabled = !bareRepository;
- gitGUIToolStripMenuItem.Enabled = !bareRepository;
- SetShortcutKeyDisplayStringsFromHotkeySettings();
- if (hard && hasWorkingDir)
- ShowRevisions();
- RefreshWorkingDirCombo();
- Text = GenerateWindowTitle(Module.WorkingDir, validWorkingDir, branchSelect.Text);
- DiffText.Font = Settings.DiffFont;
- UpdateJumplist(validWorkingDir);
- CheckForMergeConflicts();
- UpdateStashCount();
- UpdateSubmodulesList();
- // load custom user menu
- LoadUserMenu();
- if (validWorkingDir)
- {
- // add Navigate and View menu
- _formBrowseMenus.ResetMenuCommandSets();
- //// _formBrowseMenus.AddMenuCommandSet(MainMenuItem.NavigateMenu, _formBrowseMenuCommands.GetNavigateMenuCommands()); // not used at the moment
- _formBrowseMenus.AddMenuCommandSet(MainMenuItem.NavigateMenu, RevisionGrid.MenuCommands.GetNavigateMenuCommands());
- _formBrowseMenus.AddMenuCommandSet(MainMenuItem.ViewMenu, RevisionGrid.MenuCommands.GetViewMenuCommands());
- _formBrowseMenus.InsertAdditionalMainMenuItems(repositoryToolStripMenuItem);
- }
- UICommands.RaisePostBrowseInitialize(this);
- Cursor.Current = Cursors.Default;
- }
- internal Keys GetShortcutKeys(Commands cmd)
- {
- return GetShortcutKeys((int)cmd);
- }
- /// <summary>
- ///
- /// </summary>
- private void SetShortcutKeyDisplayStringsFromHotkeySettings()
- {
- gitBashToolStripMenuItem.ShortcutKeyDisplayString = GetShortcutKeys(Commands.GitBash).ToShortcutKeyDisplayString();
- commitToolStripMenuItem.ShortcutKeyDisplayString = GetShortcutKeys(Commands.Commit).ToShortcutKeyDisplayString();
- // TODO: add more
- }
- private void RefreshWorkingDirCombo()
- {
- Repository r = null;
- if (Repositories.RepositoryHistory.Repositories.Count > 0)
- r = Repositories.RepositoryHistory.Repositories[0];
- List<RecentRepoInfo> mostRecentRepos = new List<RecentRepoInfo>();
- if (r == null || !r.Path.Equals(Module.WorkingDir, StringComparison.InvariantCultureIgnoreCase))
- Repositories.AddMostRecentRepository(Module.WorkingDir);
- using (var graphics = CreateGraphics())
- {
- var splitter = new RecentRepoSplitter
- {
- measureFont = _NO_TRANSLATE_Workingdir.Font,
- graphics = graphics
- };
- splitter.SplitRecentRepos(Repositories.RepositoryHistory.Repositories, mostRecentRepos, mostRecentRepos);
- RecentRepoInfo ri = mostRecentRepos.Find((e) => e.Repo.Path.Equals(Module.WorkingDir, StringComparison.InvariantCultureIgnoreCase));
- if (ri == null)
- _NO_TRANSLATE_Workingdir.Text = Module.WorkingDir;
- else
- _NO_TRANSLATE_Workingdir.Text = ri.Caption;
- if (Settings.RecentReposComboMinWidth > 0)
- {
- _NO_TRANSLATE_Workingdir.AutoSize = false;
- var captionWidth = graphics.MeasureString(_NO_TRANSLATE_Workingdir.Text, _NO_TRANSLATE_Workingdir.Font).Width;
- captionWidth = captionWidth + _NO_TRANSLATE_Workingdir.DropDownButtonWidth + 5;
- _NO_TRANSLATE_Workingdir.Width = Math.Max(Settings.RecentReposComboMinWidth, (int)captionWidth);
- }
- else
- _NO_TRANSLATE_Workingdir.AutoSize = true;
- }
- }
- /// <summary>
- /// Returns a short name for repository.
- /// If the repository contains a description it is returned,
- /// otherwise the last part of path is returned.
- /// </summary>
- /// <param name="repositoryDir">Path to repository.</param>
- /// <returns>Short name for repository</returns>
- private static String GetRepositoryShortName(string repositoryDir)
- {
- DirectoryInfo dirInfo = new DirectoryInfo(repositoryDir);
- if (dirInfo.Exists)
- {
- string desc = ReadRepositoryDescription(repositoryDir);
- if (desc.IsNullOrEmpty())
- {
- desc = Repositories.RepositoryHistory.Repositories
- .Where(repo => repo.Path.Equals(repositoryDir, StringComparison.CurrentCultureIgnoreCase)).Select(repo => repo.Title)
- .FirstOrDefault();
- }
- return desc ?? dirInfo.Name;
- }
- return dirInfo.Name;
- }
- private void LoadUserMenu()
- {
- var scripts = ScriptManager.GetScripts().Where(script => script.Enabled
- && script.OnEvent == ScriptEvent.ShowInUserMenuBar).ToList();
- for (int i = ToolStrip.Items.Count - 1; i >= 0; i--)
- if (ToolStrip.Items[i].Tag != null &&
- ToolStrip.Items[i].Tag as String == "userscript")
- ToolStrip.Items.RemoveAt(i);
- if (scripts.Count == 0)
- return;
- ToolStripSeparator toolstripseparator = new ToolStripSeparator();
- toolstripseparator.Tag = "userscript";
- ToolStrip.Items.Add(toolstripseparator);
- foreach (ScriptInfo scriptInfo in scripts)
- {
- ToolStripButton tempButton = new ToolStripButton();
- //store scriptname
- tempButton.Text = scriptInfo.Name;
- tempButton.Tag = "userscript";
- //add handler
- tempButton.Click += UserMenu_Click;
- tempButton.Enabled = true;
- tempButton.Visible = true;
- //tempButton.Image = GitUI.Properties.Resources.bug;
- //scriptInfo.Icon = "Cow";
- tempButton.Image = scriptInfo.GetIcon();
- tempButton.DisplayStyle = ToolStripItemDisplayStyle.ImageAndText;
- //add to toolstrip
- ToolStrip.Items.Add(tempButton);
- }
- }
- private void UserMenu_Click(object sender, EventArgs e)
- {
- if (ScriptRunner.RunScript(this, Module, ((ToolStripButton)sender).Text, this.RevisionGrid))
- RevisionGrid.RefreshRevisions();
- }
- private void UpdateJumplist(bool validWorkingDir)
- {
- #if !__MonoCS__
- if (EnvUtils.RunningOnWindows() && TaskbarManager.IsPlatformSupported)
- {
- if (validWorkingDir)
- {
- string repositoryDescription = GetRepositoryShortName(Module.WorkingDir);
- string baseFolder = Path.Combine(Settings.ApplicationDataPath.Value, "Recent");
- if (!Directory.Exists(baseFolder))
- {
- Directory.CreateDirectory(baseFolder);
- }
- //Remove InvalidPathChars
- StringBuilder sb = new StringBuilder(repositoryDescription);
- foreach (char c in Path.GetInvalidFileNameChars())
- {
- sb.Replace(c, '_');
- }
- string path = Path.Combine(baseFolder, String.Format("{0}.{1}", sb, "gitext"));
- File.WriteAllText(path, Module.WorkingDir);
- JumpList.AddToRecent(path);
- var JList = JumpList.CreateJumpListForIndividualWindow(TaskbarManager.Instance.ApplicationId, Handle);
- JList.ClearAllUserTasks();
- //to control which category Recent/Frequent is displayed
- JList.KnownCategoryToDisplay = JumpListKnownCategoryType.Recent;
- JList.Refresh();
- }
- CreateOrUpdateTaskBarButtons(validWorkingDir);
- }
- #endif
- }
- #if !__MonoCS__
- private void CreateOrUpdateTaskBarButtons(bool validRepo)
- {
- if (EnvUtils.RunningOnWindows() && TaskbarManager.IsPlatformSupported)
- {
- if (!_toolbarButtonsCreated)
- {
- _commitButton = new ThumbnailToolBarButton(MakeIcon(toolStripButton1.Image, 48, true), toolStripButton1.Text);
- _commitButton.Click += ToolStripButton1Click;
- _pushButton = new ThumbnailToolBarButton(MakeIcon(toolStripButtonPush.Image, 48, true), toolStripButtonPush.Text);
- _pushButton.Click += PushToolStripMenuItemClick;
- _pullButton = new ThumbnailToolBarButton(MakeIcon(toolStripButtonPull.Image, 48, true), toolStripButtonPull.Text);
- _pullButton.Click += PullToolStripMenuItemClick;
- _toolbarButtonsCreated = true;
- ThumbnailToolBarButton[] buttons = new[] { _commitButton, _pullButton, _pushButton };
- //Call this method using reflection. This is a workaround to *not* reference WPF libraries, becuase of how the WindowsAPICodePack was implimented.
- TaskbarManager.Instance.ThumbnailToolBars.AddButtons(Handle, buttons);
- }
- _commitButton.Enabled = validRepo;
- _pushButton.Enabled = validRepo;
- _pullButton.Enabled = validRepo;
- }
- }
- #endif
- /// <summary>
- /// Converts an image into an icon. This was taken off of the interwebs.
- /// It's on a billion different sites and forum posts, so I would say its creative commons by now. -tekmaven
- /// </summary>
- /// <param name="img">The image that shall become an icon</param>
- /// <param name="size">The width and height of the icon. Standard
- /// sizes are 16x16, 32x32, 48x48, 64x64.</param>
- /// <param name="keepAspectRatio">Whether the image should be squashed into a
- /// square or whether whitespace should be put around it.</param>
- /// <returns>An icon!!</returns>
- private static Icon MakeIcon(Image img, int size, bool keepAspectRatio)
- {
- Bitmap square = new Bitmap(size, size); // create new bitmap
- Graphics g = Graphics.FromImage(square); // allow drawing to it
- int x, y, w, h; // dimensions for new image
- if (!keepAspectRatio || img.Height == img.Width)
- {
- // just fill the square
- x = y = 0; // set x and y to 0
- w = h = size; // set width and height to size
- }
- else
- {
- // work out the aspect ratio
- float r = (float)img.Width / (float)img.Height;
- // set dimensions accordingly to fit inside size^2 square
- if (r > 1)
- { // w is bigger, so divide h by r
- w = size;
- h = (int)((float)size / r);
- x = 0; y = (size - h) / 2; // center the image
- }
- else
- { // h is bigger, so multiply w by r
- w = (int)((float)size * r);
- h = size;
- y = 0; x = (size - w) / 2; // center the image
- }
- }
- // make the image shrink nicely by using HighQualityBicubic mode
- g.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
- g.DrawImage(img, x, y, w, h); // draw image with specified dimensions
- g.Flush(); // make sure all drawing operations complete before we get the icon
- // following line would work directly on any image, but then
- // it wouldn't look as nice.
- return Icon.FromHandle(square.GetHicon());
- }
- private void UpdateStashCount()
- {
- if (Settings.ShowStashCount)
- {
- AsyncLoader.DoAsync(() => Module.GetStashes().Count,
- (result) => toolStripSplitStash.Text = string.Format(_stashCount.Text, result,
- result != 1 ? _stashPlural.Text : _stashSingular.Text));
- }
- else
- {
- toolStripSplitStash.Text = string.Empty;
- }
- }
- private void CheckForMergeConflicts()
- {
- bool validWorkingDir = Module.IsValidGitWorkingDir();
- if (validWorkingDir && Module.InTheMiddleOfBisect())
- {
- if (_bisect == null)
- {
- _bisect = new WarningToolStripItem { Text = _warningMiddleOfBisect.Text };
- _bisect.Click += BisectClick;
- statusStrip.Items.Add(_bisect);
- }
- }
- else
- {
- if (_bisect != null)
- {
- _bisect.Click -= BisectClick;
- statusStrip.Items.Remove(_bisect);
- _bisect = null;
- }
- }
- if (validWorkingDir &&
- (Module.InTheMiddleOfRebase() || Module.InTheMiddleOfPatch()))
- {
- if (_rebase == null)
- {
- _rebase = new WarningToolStripItem
- {
- Text = Module.InTheMiddleOfRebase()
- ? _warningMiddleOfRebase.Text
- : _warningMiddleOfPatchApply.Text
- };
- _rebase.Click += RebaseClick;
- statusStrip.Items.Add(_rebase);
- }
- }
- else
- {
- if (_rebase != null)
- {
- _rebase.Click -= RebaseClick;
- statusStrip.Items.Remove(_rebase);
- _rebase = null;
- }
- }
- if (validWorkingDir && Module.InTheMiddleOfConflictedMerge() &&
- !Directory.Exists(Module.GetGitDirectory() + "rebase-apply\\"))
- {
- if (_warning == null)
- {
- _warning = new WarningToolStripItem { Text = _hintUnresolvedMergeConflicts.Text };
- _warning.Click += WarningClick;
- statusStrip.Items.Add(_warning);
- }
- }
- else
- {
- if (_warning != null)
- {
- _warning.Click -= WarningClick;
- statusStrip.Items.Remove(_warning);
- _warning = null;
- }
- }
- //Only show status strip when there are status items on it.
- //There is always a close (x) button, do not count first item.
- if (statusStrip.Items.Count > 1)
- statusStrip.Show();
- else
- statusStrip.Hide();
- }
- /// <summary>
- /// Generates main window title according to given repository.
- /// </summary>
- /// <param name="workingDir">Path to repository.</param>
- /// <param name="isWorkingDirValid">If the given path contains valid repository.</param>
- /// <param name="branchName">Current branch name.</param>
- private string GenerateWindowTitle(string workingDir, bool isWorkingDirValid, string branchName)
- {
- #if DEBUG
- const string defaultTitle = "Git Extensions -> DEBUG <-";
- const string repositoryTitleFormat = "{0} ({1}) - Git Extensions -> DEBUG <-";
- #else
- const string defaultTitle = "Git Extensions";
- const string repositoryTitleFormat = "{0} ({1}) - Git Extensions";
- #endif
- if (!isWorkingDirValid)
- return defaultTitle;
- string repositoryDescription = GetRepositoryShortName(workingDir);
- if (string.IsNullOrEmpty(branchName))
- branchName = _noBranchTitle.Text;
- return string.Format(repositoryTitleFormat, repositoryDescription, branchName.Trim('(', ')'));
- }
- /// <summary>
- /// Reads repository description's first line from ".git\description" file.
- /// </summary>
- /// <param name="workingDir">Path to repository.</param>
- /// <returns>If the repository has description, returns that description, else returns <c>null</c>.</returns>
- private static string ReadRepositoryDescription(string workingDir)
- {
- const string repositoryDescriptionFileName = "description";
- const string defaultDescription = "Unnamed repository; edit this file 'description' to name the repository.";
- var repositoryPath = GitModule.GetGitDirectory(workingDir);
- var repositoryDescriptionFilePath = Path.Combine(repositoryPath, repositoryDescriptionFileName);
- if (!File.Exists(repositoryDescriptionFilePath))
- return null;
- try
- {
- var repositoryDescription = File.ReadLines(repositoryDescriptionFilePath).FirstOrDefault();
- return string.Equals(repositoryDescription, defaultDescription, StringComparison.CurrentCulture)
- ? null
- : repositoryDescription;
- }
- catch (IOException)
- {
- return null;
- }
- }
- private void RebaseClick(object sender, EventArgs e)
- {
- if (Module.InTheMiddleOfRebase())
- UICommands.StartRebaseDialog(this, null);
- else
- UICommands.StartApplyPatchDialog(this);
- }
- private void ShowRevisions()
- {
- if (RevisionGrid.IndexWatcher.IndexChanged)
- {
- RevisionGrid.RefreshRevisions();
- FillFileTree();
- FillDiff();
- FillCommitInfo();
- FillBuildReport();
- }
- RevisionGrid.IndexWatcher.Reset();
- }
- //store strings to not keep references to nodes
- private readonly Stack<string> lastSelectedNodes = new Stack<string>();
- private void FillFileTree()
- {
- if (CommitInfoTabControl.SelectedTab != TreeTabPage)
- return;
- if (selectedRevisionUpdatedTargets.HasFlag(UpdateTargets.FileTree))
- return;
- selectedRevisionUpdatedTargets |= UpdateTargets.FileTree;
- try
- {
- GitTree.SuspendLayout();
- // Save state only when there is selected node
- if (GitTree.SelectedNode != null)
- {
- TreeNode node = GitTree.SelectedNode;
- FileText.SaveCurrentScrollPos();
- lastSelectedNodes.Clear();
- while (node != null)
- {
- lastSelectedNodes.Push(node.Text);
- node = node.Parent;
- }
- }
- // Refresh tree
- GitTree.Nodes.Clear();
- //restore selected file and scroll position when new selection is done
- if (RevisionGrid.GetSelectedRevisions().Count > 0)
- {
- LoadInTree(RevisionGrid.GetSelectedRevisions()[0].SubItems, GitTree.Nodes);
- //GitTree.Sort();
- TreeNode lastMatchedNode = null;
- // Load state
- var currenNodes = GitTree.Nodes;
- TreeNode matchedNode = null;
- while (lastSelectedNodes.Count > 0 && currenNodes != null)
- {
- var next = lastSelectedNodes.Pop();
- foreach (TreeNode node in currenNodes)
- {
- if (node.Text != next && next.Length != 40)
- continue;
- node.Expand();
- matchedNode = node;
- break;
- }
- if (matchedNode == null)
- currenNodes = null;
- else
- {
- lastMatchedNode = matchedNode;
- currenNodes = matchedNode.Nodes;
- }
- }
- //if there is no exact match, don't restore scroll position
- if (lastMatchedNode != matchedNode)
- FileText.ResetCurrentScrollPos();
- GitTree.SelectedNode = lastMatchedNode;
- }
- if (GitTree.SelectedNode == null)
- {
- FileText.ViewText("", "");
- }
- }
- finally
- {
- GitTree.ResumeLayout();
- }
- }
- private void FillDiff()
- {
- DiffTabPage.Text = string.Format("{0}", DiffTabPageTitleBase);
- if (CommitInfoTabControl.SelectedTab != DiffTabPage)
- {
- return;
- }
- if (selectedRevisionUpdatedTargets.HasFlag(UpdateTargets.DiffList))
- return;
- selectedRevisionUpdatedTargets |= UpdateTargets.DiffList;
- var revisions = RevisionGrid.GetSelectedRevisions();
- DiffText.SaveCurrentScrollPos();
- DiffFiles.SetDiffs(revisions);
- switch (revisions.Count)
- {
- case 0:
- DiffTabPage.Text = string.Format("{0} (no selection)", DiffTabPageTitleBase);
- break;
- case 1: // diff "parent" --> "selected revision"
- var revision = revisions[0];
- if (revision != null && revision.ParentGuids != null && revision.ParentGuids.Length != 0)
- DiffTabPage.Text = string.Format("{0} (A: parent --> B: selection)", DiffTabPageTitleBase);
- break;
- case 2: // diff "first clicked revision" --> "second clicked revision"
- bool artificialRevSelected = revisions[0].IsArtificial() || revisions[1].IsArtificial();
- if (!artificialRevSelected)
- DiffTabPage.Text = string.Format("{0} (A: first --> B: second)", DiffTabPageTitleBase);
- break;
- default: // more than 2 revisions selected => no diff
- DiffTabPage.Text = string.Format("{0} (not supported)", DiffTabPageTitleBase);
- break;
- }
- }
- private void FillCommitInfo()
- {
- if (CommitInfoTabControl.SelectedTab != CommitInfoTabPage)
- return;
- if (selectedRevisionUpdatedTargets.HasFlag(UpdateTargets.CommitInfo))
- return;
- selectedRevisionUpdatedTargets |= UpdateTargets.CommitInfo;
- if (RevisionGrid.GetSelectedRevisions().Count == 0)
- return;
- var revision = RevisionGrid.GetSelectedRevisions()[0];
-
- var children = RevisionGrid.GetRevisionChildren(revision.Guid);
- RevisionInfo.SetRevisionWithChildren(revision, children);
- }
- private BuildReportTabPageExtension BuildReportTabPageExtension;
-
- private void FillBuildReport()
- {
- if(EnvUtils.IsMonoRuntime())
- return;
- var selectedRevisions = RevisionGrid.GetSelectedRevisions();
- var revision = selectedRevisions.Count == 1 ? selectedRevisions.Single() : null;
- if (BuildReportTabPageExtension == null)
- BuildReportTabPageExtension = new BuildReportTabPageExtension(CommitInfoTabControl);
- BuildReportTabPageExtension.FillBuildReport(revision);
- }
- public void fileHistoryItem_Click(object sender, EventArgs e)
- {
- var item = GitTree.SelectedNode.Tag as GitItem;
- if (item == null)
- return;
- IList<GitRevision> revisions = RevisionGrid.GetSelectedRevisions();
- if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
- UICommands.StartFileHistoryDialog(this, item.FileName);
- else
- UICommands.StartFileHistoryDialog(this, item.FileName, revisions[0], false, false);
- }
- private void blameMenuItem_Click(object sender, EventArgs e)
- {
- var item = GitTree.SelectedNode.Tag as GitItem;
- if (item == null)
- return;
- IList<GitRevision> revisions = RevisionGrid.GetSelectedRevisions();
- if (revisions.Count == 0 || GitRevision.IsArtificial(revisions[0].Guid))
- UICommands.StartFileHistoryDialog(this, item.FileName, null, false, true);
- else
- UICommands.StartFileHistoryDialog(this, item.FileName, revisions[0], true, true);
- }
- public void FindFileOnClick(object sender, EventArgs e)
- {
- string selectedItem;
- using (var searchWindow = new SearchWindow<string>(FindFileMatches)
- {
- Owner = this
- })
- {
- searchWindow.ShowDialog(this);
- selectedItem = searchWindow.SelectedItem;
- }
- if (string.IsNullOrEmpty(selectedItem))
- {
- return;
- }
- string[] items = selectedItem.Split(new[] { '/' });
- TreeNodeCollection nodes = GitTree.Nodes;
- for (int i = 0; i < items.Length - 1; i++)
- {
- TreeNode selectedNode = Find(nodes, items[i]);
- if (selectedNode == null)
- {
- return; //Item does not exist in the tree
- }
- selectedNode.Expand();
- nodes = selectedNode.Nodes;
- }
- var lastItem = Find(nodes, items[items.Length - 1]);
- if (lastItem != null)
- {
- GitTree.SelectedNode = lastItem;
- }
- }
- private static TreeNode Find(TreeNodeCollection nodes, string label)
- {
- for (int i = 0; i < nodes.Count; i++)
- {
- if (nodes[i].Text == label)
- {
- return nodes[i];
- }
- }
- return null;
- }
- private IList<string> FindFileMatches(string name)
- {
- var candidates = Module.GetFullTree(RevisionGrid.GetSelectedRevisions()[0].TreeGuid);
- string nameAsLower = name.ToLower();
- return candidates.Where(fileName => fileName.ToLower().Contains(nameAsLower)).ToList();
- }
- private string SaveSelectedItemToTempFile()
- {
- var gitItem = GitTree.SelectedNode.Tag as GitItem;
- if (gitItem == null || !gitItem.IsBlob)
- return null;
- var fileName = gitItem.FileName;
- if (fileName.Contains("\\") && fileName.LastIndexOf("\\") < fileName.Length)
- fileName = fileName.Substring(fileName.LastIndexOf('\\') + 1);
- if (fileName.Contains("/") && fileName.LastIndexOf("/") < fileName.Length)
- fileName = fileName.Substring(fileName.LastIndexOf('/') + 1);
- fileName = (Path.GetTempPath() + fileName).ToNativePath();
- Module.SaveBlobAs(fileName, gitItem.Guid);
- return fileName;
- }
- public void OpenWithOnClick(object sender, EventArgs e)
- {
- var fileName = SaveSelectedItemToTempFile();
- if (fileName != null)
- OsShellUtil.OpenAs(fileName);
- }
- public void OpenOnClick(object sender, EventArgs e)
- {
- try
- {
- var fileName = SaveSelectedItemToTempFile();
- if (fileName != null)
- Process.Start(fileName);
- }
- catch (Exception ex)
- {
- MessageBox.Show(this, ex.Message);
- }
- }
- private void FileTreeContextMenu_Opening(object sender, System.ComponentModel.CancelEventArgs e)
- {
- var gitItem = (GitTree.SelectedNode != null) ? GitTree.SelectedNode.Tag as GitItem : null;
- var enableItems = gitItem != null && gitItem.IsBlob;
- saveAsToolStripMenuItem.Enabled = enableItems;
- openFileToolStripMenuItem.Enabled = enableItems;
- openFileWithToolStripMenuItem.Enabled = enableItems;
- openWithToolStripMenuItem.Enabled = enableItems;
- copyFilenameToClipboardToolStripMenuItem.Enabled = FormBrowseUtil.IsFileOrDirectory(FormBrowseUtil.GetFullPathFromGitItem(Module, gitItem));
- editCheckedOutFileToolStripMenuItem.Enabled = enableItems;
- }
- protected void LoadInTree(IEnumerable<IGitItem> items, TreeNodeCollection node)
- {
- var sortedItems = items.OrderBy(gi => gi, new GitFileTreeComparer());
- foreach (var item in sortedItems)
- {
- var subNode = node.Add(item.Name);
- subNode.Tag = item;
- var gitItem = item as GitItem;
- if (gitItem == null)
- subNode.Nodes.Add(new TreeNode());
- else
- {
- if (gitItem.IsTree)
- {
- subNode.ImageIndex = 1;
- subNode.SelectedImageIndex = 1;
- subNode.Nodes.Add(new TreeNode());
- …
Large files files are truncated, but you can click here to view the full file