2024-03-17 18:37:06 -07:00
|
|
|
|
using System;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.IO;
|
|
|
|
|
using System.Text.Json.Serialization;
|
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
using Avalonia.Collections;
|
|
|
|
|
using Avalonia.Controls;
|
2024-04-05 22:14:22 -07:00
|
|
|
|
using Avalonia.Media;
|
|
|
|
|
using Avalonia.Media.Imaging;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
using Avalonia.Threading;
|
|
|
|
|
|
|
|
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
|
|
|
|
|
|
|
|
namespace SourceGit.ViewModels
|
|
|
|
|
{
|
|
|
|
|
public class Repository : ObservableObject, Models.IRepository
|
|
|
|
|
{
|
|
|
|
|
public string FullPath
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _fullpath;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (value != null)
|
|
|
|
|
{
|
2024-02-29 21:40:12 -08:00
|
|
|
|
var normalized = value.Replace('\\', '/');
|
|
|
|
|
SetProperty(ref _fullpath, normalized);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-02-29 21:40:12 -08:00
|
|
|
|
SetProperty(ref _fullpath, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public string GitDir
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _gitDir;
|
|
|
|
|
set => SetProperty(ref _gitDir, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 00:36:49 -07:00
|
|
|
|
public bool PreferRebaseInsteadOfMerge
|
|
|
|
|
{
|
|
|
|
|
get;
|
|
|
|
|
set;
|
|
|
|
|
} = true;
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public AvaloniaList<string> Filters
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get;
|
2024-02-06 01:52:16 -08:00
|
|
|
|
set;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
} = new AvaloniaList<string>();
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public AvaloniaList<string> CommitMessages
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get;
|
2024-02-06 01:52:16 -08:00
|
|
|
|
set;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
} = new AvaloniaList<string>();
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public int SelectedViewIndex
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _selectedViewIndex;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (SetProperty(ref _selectedViewIndex, value))
|
|
|
|
|
{
|
|
|
|
|
switch (value)
|
|
|
|
|
{
|
|
|
|
|
case 1:
|
|
|
|
|
SelectedView = _workingCopy;
|
|
|
|
|
break;
|
|
|
|
|
case 2:
|
|
|
|
|
SelectedView = _stashesPage;
|
|
|
|
|
break;
|
|
|
|
|
default:
|
|
|
|
|
SelectedView = _histories;
|
|
|
|
|
break;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public object SelectedView
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _selectedView;
|
|
|
|
|
set => SetProperty(ref _selectedView, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-13 20:47:56 -07:00
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public string SearchBranchFilter
|
|
|
|
|
{
|
|
|
|
|
get => _searchBranchFilter;
|
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (SetProperty(ref _searchBranchFilter, value))
|
|
|
|
|
{
|
|
|
|
|
var builder = BuildBranchTree(_branches, _remotes);
|
|
|
|
|
LocalBranchTrees = builder.Locals;
|
|
|
|
|
RemoteBranchTrees = builder.Remotes;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public List<Models.Remote> Remotes
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _remotes;
|
|
|
|
|
private set => SetProperty(ref _remotes, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public List<Models.Branch> Branches
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _branches;
|
|
|
|
|
private set => SetProperty(ref _branches, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-05-13 20:47:56 -07:00
|
|
|
|
public List<BranchTreeNode> LocalBranchTrees
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _localBranchTrees;
|
|
|
|
|
private set => SetProperty(ref _localBranchTrees, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-05-13 20:47:56 -07:00
|
|
|
|
public List<BranchTreeNode> RemoteBranchTrees
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _remoteBranchTrees;
|
|
|
|
|
private set => SetProperty(ref _remoteBranchTrees, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public List<Models.Tag> Tags
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _tags;
|
|
|
|
|
private set => SetProperty(ref _tags, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public List<string> Submodules
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _submodules;
|
|
|
|
|
private set => SetProperty(ref _submodules, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public int WorkingCopyChangesCount
|
|
|
|
|
{
|
2024-02-21 19:05:20 -08:00
|
|
|
|
get => _workingCopy == null ? 0 : _workingCopy.Count;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public int StashesCount
|
|
|
|
|
{
|
2024-02-21 19:05:20 -08:00
|
|
|
|
get => _stashesPage == null ? 0 : _stashesPage.Count;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public bool IncludeUntracked
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _includeUntracked;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (SetProperty(ref _includeUntracked, value))
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Task.Run(RefreshWorkingCopyChanges);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public bool IsSearching
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _isSearching;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
set
|
|
|
|
|
{
|
|
|
|
|
if (SetProperty(ref _isSearching, value))
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
SearchedCommits = new List<Models.Commit>();
|
|
|
|
|
SearchCommitFilter = string.Empty;
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (value)
|
|
|
|
|
SelectedViewIndex = 0;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-07 03:43:37 -07:00
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public int SearchCommitFilterType
|
|
|
|
|
{
|
|
|
|
|
get => _searchCommitFilterType;
|
|
|
|
|
set => SetProperty(ref _searchCommitFilterType, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public string SearchCommitFilter
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _searchCommitFilter;
|
|
|
|
|
set => SetProperty(ref _searchCommitFilter, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public List<Models.Commit> SearchedCommits
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
get => _searchedCommits;
|
|
|
|
|
set => SetProperty(ref _searchedCommits, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-20 20:40:17 -07:00
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public bool IsTagGroupExpanded
|
|
|
|
|
{
|
|
|
|
|
get => _isTagGroupExpanded;
|
|
|
|
|
set => SetProperty(ref _isTagGroupExpanded, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public bool IsSubmoduleGroupExpanded
|
|
|
|
|
{
|
|
|
|
|
get => _isSubmoduleGroupExpanded;
|
|
|
|
|
set => SetProperty(ref _isSubmoduleGroupExpanded, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-01 06:27:08 -07:00
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public InProgressContext InProgressContext
|
|
|
|
|
{
|
|
|
|
|
get => _inProgressContext;
|
|
|
|
|
private set => SetProperty(ref _inProgressContext, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
[JsonIgnore]
|
|
|
|
|
public bool HasUnsolvedConflicts
|
|
|
|
|
{
|
|
|
|
|
get => _hasUnsolvedConflicts;
|
|
|
|
|
private set => SetProperty(ref _hasUnsolvedConflicts, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-15 01:17:29 -07:00
|
|
|
|
[JsonIgnore]
|
2024-05-10 01:04:03 -07:00
|
|
|
|
public Models.Commit SearchResultSelectedCommit
|
|
|
|
|
{
|
|
|
|
|
get => _searchResultSelectedCommit;
|
|
|
|
|
set => SetProperty(ref _searchResultSelectedCommit, value);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Open()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_watcher = new Models.Watcher(this);
|
|
|
|
|
_histories = new Histories(this);
|
|
|
|
|
_workingCopy = new WorkingCopy(this);
|
|
|
|
|
_stashesPage = new StashesPage(this);
|
|
|
|
|
_selectedView = _histories;
|
|
|
|
|
_selectedViewIndex = 0;
|
2024-04-01 06:27:08 -07:00
|
|
|
|
_inProgressContext = null;
|
|
|
|
|
_hasUnsolvedConflicts = false;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-04-27 19:19:12 -07:00
|
|
|
|
RefreshAll();
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Close()
|
|
|
|
|
{
|
2024-02-20 02:27:59 -08:00
|
|
|
|
SelectedView = 0.0; // Do NOT modify. Used to remove exists widgets for GC.Collect
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_watcher.Dispose();
|
2024-02-20 02:27:59 -08:00
|
|
|
|
_histories.Cleanup();
|
|
|
|
|
_workingCopy.Cleanup();
|
|
|
|
|
_stashesPage.Cleanup();
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_watcher = null;
|
|
|
|
|
_histories = null;
|
|
|
|
|
_workingCopy = null;
|
|
|
|
|
_stashesPage = null;
|
|
|
|
|
_isSearching = false;
|
|
|
|
|
_searchCommitFilter = string.Empty;
|
|
|
|
|
|
2024-03-20 20:40:17 -07:00
|
|
|
|
_isTagGroupExpanded = false;
|
|
|
|
|
_isSubmoduleGroupExpanded = false;
|
|
|
|
|
|
2024-04-01 06:27:08 -07:00
|
|
|
|
_inProgressContext = null;
|
|
|
|
|
_hasUnsolvedConflicts = false;
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
_remotes.Clear();
|
|
|
|
|
_branches.Clear();
|
|
|
|
|
_localBranchTrees.Clear();
|
|
|
|
|
_remoteBranchTrees.Clear();
|
|
|
|
|
_tags.Clear();
|
|
|
|
|
_submodules.Clear();
|
|
|
|
|
_searchedCommits.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-27 19:19:12 -07:00
|
|
|
|
public void RefreshAll()
|
|
|
|
|
{
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshBranches();
|
|
|
|
|
RefreshTags();
|
|
|
|
|
RefreshCommits();
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
Task.Run(RefreshSubmodules);
|
|
|
|
|
Task.Run(RefreshWorkingCopyChanges);
|
|
|
|
|
Task.Run(RefreshStashes);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void OpenInFileManager()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Native.OS.OpenInFileManager(_fullpath);
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-05 22:14:22 -07:00
|
|
|
|
public void OpenInTerminal()
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-04-05 22:14:22 -07:00
|
|
|
|
Native.OS.OpenTerminal(_fullpath);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
2024-03-28 02:42:13 -07:00
|
|
|
|
|
2024-04-08 02:39:52 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForExternalTools()
|
2024-03-27 22:49:32 -07:00
|
|
|
|
{
|
2024-04-08 02:39:52 -07:00
|
|
|
|
var tools = Native.OS.ExternalTools;
|
|
|
|
|
if (tools.Count == 0)
|
2024-04-05 22:14:22 -07:00
|
|
|
|
{
|
|
|
|
|
App.RaiseException(_fullpath, "No available external editors found!");
|
|
|
|
|
return null;
|
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-04-05 22:14:22 -07:00
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
|
|
|
|
RenderOptions.SetBitmapInterpolationMode(menu, BitmapInterpolationMode.HighQuality);
|
|
|
|
|
|
2024-04-08 02:39:52 -07:00
|
|
|
|
foreach (var tool in tools)
|
2024-04-05 22:14:22 -07:00
|
|
|
|
{
|
2024-04-08 02:39:52 -07:00
|
|
|
|
var dupTool = tool;
|
2024-04-09 00:00:52 -07:00
|
|
|
|
|
2024-04-05 22:14:22 -07:00
|
|
|
|
var item = new MenuItem();
|
2024-04-08 02:39:52 -07:00
|
|
|
|
item.Header = App.Text("Repository.OpenIn", dupTool.Name);
|
2024-04-09 00:00:52 -07:00
|
|
|
|
item.Icon = new Image { Width = 16, Height = 16, Source = dupTool.IconImage };
|
2024-04-05 22:14:22 -07:00
|
|
|
|
item.Click += (o, e) =>
|
|
|
|
|
{
|
2024-04-08 02:39:52 -07:00
|
|
|
|
dupTool.Open(_fullpath);
|
2024-04-05 22:14:22 -07:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(item);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return menu;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Fetch()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (Remotes.Count == 0)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PopupHost.ShowPopup(new Fetch(this));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Pull()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (Remotes.Count == 0)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PopupHost.ShowPopup(new Pull(this, null));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Push()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (Remotes.Count == 0)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.RaiseException(_fullpath, "No remotes added to this repository!!!");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (Branches.Find(x => x.IsCurrent) == null)
|
2024-05-29 06:31:46 -07:00
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
App.RaiseException(_fullpath, "Can NOT found current branch!!!");
|
2024-05-29 06:31:46 -07:00
|
|
|
|
return;
|
|
|
|
|
}
|
2024-05-29 18:53:07 -07:00
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
PopupHost.ShowPopup(new Push(this, null));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void ApplyPatch()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
PopupHost.ShowPopup(new Apply(this));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void Cleanup()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
PopupHost.ShowAndStartPopup(new Cleanup(this));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void OpenConfigure()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
PopupHost.ShowPopup(new RepositoryConfigure(this));
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-18 03:27:57 -07:00
|
|
|
|
public void ClearHistoriesFilter()
|
|
|
|
|
{
|
|
|
|
|
Filters.Clear();
|
|
|
|
|
|
|
|
|
|
Task.Run(() =>
|
|
|
|
|
{
|
|
|
|
|
RefreshBranches();
|
|
|
|
|
RefreshTags();
|
|
|
|
|
RefreshCommits();
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void ClearSearchCommitFilter()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
SearchCommitFilter = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void StartSearchCommits()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_histories == null)
|
|
|
|
|
return;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
|
|
|
|
var visible = new List<Models.Commit>();
|
2024-06-07 03:43:37 -07:00
|
|
|
|
|
|
|
|
|
if (_searchCommitFilterType == 0)
|
|
|
|
|
{
|
|
|
|
|
foreach (var c in _histories.Commits)
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-06-07 03:43:37 -07:00
|
|
|
|
if (c.SHA.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase)
|
2024-06-07 21:19:48 -07:00
|
|
|
|
|| c.Subject.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase)
|
2024-06-07 03:43:37 -07:00
|
|
|
|
|| c.Author.Name.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase)
|
|
|
|
|
|| c.Committer.Name.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase)
|
|
|
|
|
|| c.Author.Email.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase)
|
|
|
|
|
|| c.Committer.Email.Contains(_searchCommitFilter, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
{
|
|
|
|
|
visible.Add(c);
|
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-07 03:43:37 -07:00
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
visible = new Commands.QueryCommits(FullPath, $"-1000 -- \"{_searchCommitFilter}\"", false).Result();
|
2024-06-13 18:46:30 -07:00
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
|
|
|
|
SearchedCommits = visible;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-13 20:47:56 -07:00
|
|
|
|
public void ClearSearchBranchFilter()
|
|
|
|
|
{
|
|
|
|
|
SearchBranchFilter = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void SetWatcherEnabled(bool enabled)
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_watcher != null)
|
|
|
|
|
_watcher.SetEnabled(enabled);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void MarkBranchesDirtyManually()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_watcher != null)
|
|
|
|
|
_watcher.MarkBranchDirtyManually();
|
2024-03-07 17:57:29 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void MarkWorkingCopyDirtyManually()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_watcher != null)
|
|
|
|
|
_watcher.MarkWorkingCopyDirtyManually();
|
2024-03-07 17:57:29 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void NavigateToCommit(string sha)
|
|
|
|
|
{
|
|
|
|
|
if (_histories != null)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
SelectedViewIndex = 0;
|
|
|
|
|
_histories.NavigateTo(sha);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-04-02 05:54:19 -07:00
|
|
|
|
public void NavigateToCurrentHead()
|
|
|
|
|
{
|
|
|
|
|
var cur = Branches.Find(x => x.IsCurrent);
|
|
|
|
|
if (cur != null)
|
|
|
|
|
NavigateToCommit(cur.Head);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void UpdateFilter(string filter, bool toggle)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var changed = false;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (toggle)
|
|
|
|
|
{
|
|
|
|
|
if (!Filters.Contains(filter))
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Filters.Add(filter);
|
|
|
|
|
changed = true;
|
|
|
|
|
}
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
changed = Filters.Remove(filter);
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (changed)
|
|
|
|
|
Task.Run(RefreshCommits);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void StashAll()
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var changes = new List<Models.Change>();
|
|
|
|
|
changes.AddRange(_workingCopy.Unstaged);
|
|
|
|
|
changes.AddRange(_workingCopy.Staged);
|
|
|
|
|
PopupHost.ShowPopup(new StashChanges(this, changes, true));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void GotoResolve()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_workingCopy != null)
|
|
|
|
|
SelectedViewIndex = 1;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public async void ContinueMerge()
|
|
|
|
|
{
|
2024-04-01 06:27:08 -07:00
|
|
|
|
if (_inProgressContext != null)
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-04-01 06:27:08 -07:00
|
|
|
|
SetWatcherEnabled(false);
|
|
|
|
|
var succ = await Task.Run(_inProgressContext.Continue);
|
|
|
|
|
if (succ && _workingCopy != null)
|
|
|
|
|
{
|
|
|
|
|
_workingCopy.CommitMessage = string.Empty;
|
|
|
|
|
}
|
|
|
|
|
SetWatcherEnabled(true);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-03-07 17:57:29 -08:00
|
|
|
|
MarkWorkingCopyDirtyManually();
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public async void AbortMerge()
|
|
|
|
|
{
|
2024-04-01 06:27:08 -07:00
|
|
|
|
if (_inProgressContext != null)
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-04-01 06:27:08 -07:00
|
|
|
|
SetWatcherEnabled(false);
|
2024-04-28 18:30:37 -07:00
|
|
|
|
var succ = await Task.Run(_inProgressContext.Abort);
|
|
|
|
|
if (succ && _workingCopy != null)
|
|
|
|
|
{
|
|
|
|
|
_workingCopy.CommitMessage = string.Empty;
|
|
|
|
|
}
|
2024-04-01 06:27:08 -07:00
|
|
|
|
SetWatcherEnabled(true);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-03-07 17:57:29 -08:00
|
|
|
|
MarkWorkingCopyDirtyManually();
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshBranches()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var branches = new Commands.QueryBranches(FullPath).Result();
|
|
|
|
|
var remotes = new Commands.QueryRemotes(FullPath).Result();
|
2024-05-13 20:47:56 -07:00
|
|
|
|
var builder = BuildBranchTree(branches, remotes);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Remotes = remotes;
|
|
|
|
|
Branches = branches;
|
|
|
|
|
LocalBranchTrees = builder.Locals;
|
|
|
|
|
RemoteBranchTrees = builder.Remotes;
|
|
|
|
|
|
2024-05-30 00:13:59 -07:00
|
|
|
|
if (_workingCopy != null)
|
|
|
|
|
{
|
|
|
|
|
var cur = Branches.Find(x => x.IsCurrent);
|
|
|
|
|
_workingCopy.CanCommitWithPush = cur != null && !string.IsNullOrEmpty(cur.Upstream);
|
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshTags()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var tags = new Commands.QueryTags(FullPath).Result();
|
2024-03-31 01:54:29 -07:00
|
|
|
|
foreach (var tag in tags)
|
|
|
|
|
tag.IsFiltered = Filters.Contains(tag.Name);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Tags = tags;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshCommits()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Dispatcher.UIThread.Invoke(() => _histories.IsLoading = true);
|
|
|
|
|
|
|
|
|
|
var limits = $"-{Preference.Instance.MaxHistoryCommits} ";
|
|
|
|
|
var validFilters = new List<string>();
|
2024-03-17 18:37:06 -07:00
|
|
|
|
foreach (var filter in Filters)
|
|
|
|
|
{
|
|
|
|
|
if (filter.StartsWith("refs/", StringComparison.Ordinal))
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_branches.FindIndex(x => x.FullName == filter) >= 0)
|
|
|
|
|
validFilters.Add(filter);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_tags.FindIndex(t => t.Name == filter) >= 0)
|
|
|
|
|
validFilters.Add(filter);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
2024-06-18 03:27:57 -07:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (validFilters.Count > 0)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
limits += string.Join(" ", validFilters);
|
2024-06-18 03:27:57 -07:00
|
|
|
|
|
|
|
|
|
if (Filters.Count != validFilters.Count)
|
|
|
|
|
{
|
|
|
|
|
Dispatcher.UIThread.Post(() =>
|
|
|
|
|
{
|
|
|
|
|
Filters.Clear();
|
|
|
|
|
Filters.AddRange(validFilters);
|
|
|
|
|
});
|
|
|
|
|
}
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
limits += "--branches --remotes --tags";
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var commits = new Commands.QueryCommits(FullPath, limits).Result();
|
2024-06-06 05:25:16 -07:00
|
|
|
|
var graph = Models.CommitGraph.Parse(commits, 8);
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
|
|
|
|
if (_histories != null)
|
|
|
|
|
{
|
2024-02-20 20:26:09 -08:00
|
|
|
|
_histories.IsLoading = false;
|
|
|
|
|
_histories.Commits = commits;
|
2024-06-06 05:25:16 -07:00
|
|
|
|
_histories.Graph = graph;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshSubmodules()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var submodules = new Commands.QuerySubmodules(FullPath).Result();
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Submodules = submodules;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshWorkingCopyChanges()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var changes = new Commands.QueryLocalChanges(FullPath, _includeUntracked).Result();
|
2024-04-02 01:23:47 -07:00
|
|
|
|
if (_workingCopy == null)
|
|
|
|
|
return;
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var hasUnsolvedConflict = _workingCopy.SetData(changes);
|
2024-04-01 06:27:08 -07:00
|
|
|
|
var inProgress = null as InProgressContext;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
|
|
|
|
var rebaseMergeFolder = Path.Combine(_gitDir, "rebase-merge");
|
2024-04-01 06:27:08 -07:00
|
|
|
|
var rebaseApplyFolder = Path.Combine(_gitDir, "rebase-apply");
|
|
|
|
|
if (File.Exists(Path.Combine(_gitDir, "CHERRY_PICK_HEAD")))
|
|
|
|
|
{
|
|
|
|
|
inProgress = new CherryPickInProgress(_fullpath);
|
|
|
|
|
}
|
|
|
|
|
else if (File.Exists(Path.Combine(_gitDir, "REBASE_HEAD")) && Directory.Exists(rebaseMergeFolder))
|
|
|
|
|
{
|
|
|
|
|
inProgress = new RebaseInProgress(this);
|
|
|
|
|
}
|
|
|
|
|
else if (File.Exists(Path.Combine(_gitDir, "REVERT_HEAD")))
|
|
|
|
|
{
|
|
|
|
|
inProgress = new RevertInProgress(_fullpath);
|
|
|
|
|
}
|
|
|
|
|
else if (File.Exists(Path.Combine(_gitDir, "MERGE_HEAD")))
|
|
|
|
|
{
|
|
|
|
|
inProgress = new MergeInProgress(_fullpath);
|
|
|
|
|
}
|
|
|
|
|
else
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (Directory.Exists(rebaseMergeFolder))
|
|
|
|
|
Directory.Delete(rebaseMergeFolder, true);
|
2024-04-01 06:27:08 -07:00
|
|
|
|
|
|
|
|
|
if (Directory.Exists(rebaseApplyFolder))
|
|
|
|
|
Directory.Delete(rebaseApplyFolder, true);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2024-04-01 06:27:08 -07:00
|
|
|
|
InProgressContext = inProgress;
|
|
|
|
|
HasUnsolvedConflicts = hasUnsolvedConflict;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
OnPropertyChanged(nameof(WorkingCopyChangesCount));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void RefreshStashes()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var stashes = new Commands.QueryStashes(FullPath).Result();
|
2024-03-17 18:37:06 -07:00
|
|
|
|
Dispatcher.UIThread.Invoke(() =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (_stashesPage != null)
|
|
|
|
|
_stashesPage.Stashes = stashes;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
OnPropertyChanged(nameof(StashesCount));
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void CreateNewBranch()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var current = Branches.Find(x => x.IsCurrent);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (current == null)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateBranch(this, current));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-05-29 01:42:47 -07:00
|
|
|
|
public void CheckoutBranch(Models.Branch branch)
|
2024-04-29 02:22:22 -07:00
|
|
|
|
{
|
|
|
|
|
if (!PopupHost.CanCreatePopup())
|
|
|
|
|
return;
|
|
|
|
|
|
2024-05-29 01:42:47 -07:00
|
|
|
|
if (branch.IsLocal)
|
|
|
|
|
{
|
|
|
|
|
if (WorkingCopyChangesCount > 0)
|
|
|
|
|
PopupHost.ShowPopup(new Checkout(this, branch.Name));
|
|
|
|
|
else
|
|
|
|
|
PopupHost.ShowAndStartPopup(new Checkout(this, branch.Name));
|
|
|
|
|
}
|
2024-04-29 02:22:22 -07:00
|
|
|
|
else
|
2024-05-29 01:42:47 -07:00
|
|
|
|
{
|
|
|
|
|
foreach (var b in Branches)
|
|
|
|
|
{
|
|
|
|
|
if (b.IsLocal && b.Upstream == branch.FullName)
|
|
|
|
|
{
|
|
|
|
|
if (!b.IsCurrent)
|
|
|
|
|
CheckoutBranch(b);
|
|
|
|
|
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
PopupHost.ShowPopup(new CreateBranch(this, branch));
|
|
|
|
|
}
|
2024-04-29 02:22:22 -07:00
|
|
|
|
}
|
2024-05-29 01:42:47 -07:00
|
|
|
|
|
2024-05-24 04:15:12 -07:00
|
|
|
|
public void DeleteMultipleBranches(List<Models.Branch> branches, bool isLocal)
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteMultipleBranches(this, branches, isLocal));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void CreateNewTag()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var current = Branches.Find(x => x.IsCurrent);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (current == null)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.RaiseException(_fullpath, "Git do not hold any branch until you do first commit.");
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateTag(this, current));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void AddRemote()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new AddRemote(this));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public void AddSubmodule()
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new AddSubmodule(this));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-03 20:36:00 -07:00
|
|
|
|
public void UpdateSubmodules()
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new UpdateSubmodules(this));
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForGitFlow()
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
|
|
|
|
|
2024-06-14 21:44:35 -07:00
|
|
|
|
var isGitFlowEnabled = Commands.GitFlow.IsEnabled(_fullpath, _branches);
|
|
|
|
|
if (isGitFlowEnabled)
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var startFeature = new MenuItem();
|
|
|
|
|
startFeature.Header = App.Text("GitFlow.StartFeature");
|
2024-04-15 00:07:07 -07:00
|
|
|
|
startFeature.Icon = App.CreateMenuIcon("Icons.GitFlow.Feature");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
startFeature.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
2024-06-14 21:44:35 -07:00
|
|
|
|
PopupHost.ShowPopup(new GitFlowStart(this, "feature"));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var startRelease = new MenuItem();
|
|
|
|
|
startRelease.Header = App.Text("GitFlow.StartRelease");
|
2024-04-15 00:07:07 -07:00
|
|
|
|
startRelease.Icon = App.CreateMenuIcon("Icons.GitFlow.Release");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
startRelease.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
2024-06-14 21:44:35 -07:00
|
|
|
|
PopupHost.ShowPopup(new GitFlowStart(this, "release"));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var startHotfix = new MenuItem();
|
|
|
|
|
startHotfix.Header = App.Text("GitFlow.StartHotfix");
|
2024-04-15 00:07:07 -07:00
|
|
|
|
startHotfix.Icon = App.CreateMenuIcon("Icons.GitFlow.Hotfix");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
startHotfix.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
2024-06-14 21:44:35 -07:00
|
|
|
|
PopupHost.ShowPopup(new GitFlowStart(this, "hotfix"));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(startFeature);
|
|
|
|
|
menu.Items.Add(startRelease);
|
|
|
|
|
menu.Items.Add(startHotfix);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var init = new MenuItem();
|
|
|
|
|
init.Header = App.Text("GitFlow.Init");
|
2024-06-17 03:25:57 -07:00
|
|
|
|
init.Icon = App.CreateMenuIcon("Icons.Init");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
init.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new InitGitFlow(this));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(init);
|
|
|
|
|
}
|
|
|
|
|
return menu;
|
2024-06-17 03:25:57 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public ContextMenu CreateContextMenuForGitLFS()
|
|
|
|
|
{
|
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
menu.Placement = PlacementMode.BottomEdgeAlignedLeft;
|
|
|
|
|
|
|
|
|
|
var lfs = new Commands.LFS(_fullpath);
|
|
|
|
|
if (lfs.IsEnabled())
|
|
|
|
|
{
|
2024-06-17 23:14:13 -07:00
|
|
|
|
var addPattern = new MenuItem();
|
|
|
|
|
addPattern.Header = App.Text("GitLFS.AddTrackPattern");
|
|
|
|
|
addPattern.Icon = App.CreateMenuIcon("Icons.File.Add");
|
|
|
|
|
addPattern.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new LFSTrackCustomPattern(this));
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(addPattern);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
2024-06-17 03:25:57 -07:00
|
|
|
|
var fetch = new MenuItem();
|
|
|
|
|
fetch.Header = App.Text("GitLFS.Fetch");
|
|
|
|
|
fetch.Icon = App.CreateMenuIcon("Icons.Fetch");
|
|
|
|
|
fetch.IsEnabled = Remotes.Count > 0;
|
|
|
|
|
fetch.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
{
|
|
|
|
|
if (Remotes.Count == 1)
|
|
|
|
|
PopupHost.ShowAndStartPopup(new LFSFetch(this));
|
|
|
|
|
else
|
|
|
|
|
PopupHost.ShowPopup(new LFSFetch(this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(fetch);
|
|
|
|
|
|
|
|
|
|
var pull = new MenuItem();
|
|
|
|
|
pull.Header = App.Text("GitLFS.Pull");
|
|
|
|
|
pull.Icon = App.CreateMenuIcon("Icons.Pull");
|
|
|
|
|
pull.IsEnabled = Remotes.Count > 0;
|
|
|
|
|
pull.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
{
|
|
|
|
|
if (Remotes.Count == 1)
|
|
|
|
|
PopupHost.ShowAndStartPopup(new LFSPull(this));
|
|
|
|
|
else
|
|
|
|
|
PopupHost.ShowPopup(new LFSPull(this));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(pull);
|
|
|
|
|
|
|
|
|
|
var prune = new MenuItem();
|
|
|
|
|
prune.Header = App.Text("GitLFS.Prune");
|
|
|
|
|
prune.Icon = App.CreateMenuIcon("Icons.Clean");
|
|
|
|
|
prune.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new LFSPrune(this));
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(prune);
|
|
|
|
|
|
|
|
|
|
var locks = new MenuItem();
|
|
|
|
|
locks.Header = App.Text("GitLFS.Locks");
|
|
|
|
|
locks.Icon = App.CreateMenuIcon("Icons.Lock");
|
|
|
|
|
locks.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
var dialog = new Views.LFSLocks() { DataContext = new LFSLocks(_fullpath) };
|
|
|
|
|
dialog.Show(App.GetTopLevel() as Window);
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(locks);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var install = new MenuItem();
|
|
|
|
|
install.Header = App.Text("GitLFS.Install");
|
|
|
|
|
install.Icon = App.CreateMenuIcon("Icons.Init");
|
|
|
|
|
install.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
var succ = new Commands.LFS(_fullpath).Install();
|
|
|
|
|
if (succ)
|
|
|
|
|
App.SendNotification(_fullpath, $"LFS enabled successfully!");
|
|
|
|
|
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(install);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return menu;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForLocalBranch(Models.Branch branch)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
|
|
|
|
|
var push = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
push.Header = new Views.NameHighlightedTextBlock("BranchCM.Push", branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
push.Icon = App.CreateMenuIcon("Icons.Push");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
push.IsEnabled = Remotes.Count > 0;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
push.Click += (_, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Push(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (branch.IsCurrent)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var discard = new MenuItem();
|
|
|
|
|
discard.Header = App.Text("BranchCM.DiscardAll");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
discard.Icon = App.CreateMenuIcon("Icons.Undo");
|
2024-03-01 03:12:22 -08:00
|
|
|
|
discard.IsEnabled = _workingCopy.Count > 0;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
discard.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Discard(this));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(discard);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (!string.IsNullOrEmpty(branch.Upstream))
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var upstream = branch.Upstream.Substring(13);
|
|
|
|
|
var fastForward = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
fastForward.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new Merge(this, upstream, branch.Name));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var pull = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
pull.Header = new Views.NameHighlightedTextBlock("BranchCM.Pull", upstream);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
pull.Icon = App.CreateMenuIcon("Icons.Pull");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
pull.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Pull(this, null));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(fastForward);
|
|
|
|
|
menu.Items.Add(pull);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(push);
|
2024-06-11 00:30:06 -07:00
|
|
|
|
|
|
|
|
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
|
|
|
|
if (compareWithBranch != null)
|
|
|
|
|
{
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(compareWithBranch);
|
|
|
|
|
}
|
2024-03-17 18:37:06 -07:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var current = Branches.Find(x => x.IsCurrent);
|
|
|
|
|
|
|
|
|
|
var checkout = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
checkout.Icon = App.CreateMenuIcon("Icons.Check");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
checkout.Click += (o, e) =>
|
|
|
|
|
{
|
2024-05-29 01:42:47 -07:00
|
|
|
|
CheckoutBranch(branch);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(checkout);
|
|
|
|
|
|
|
|
|
|
var upstream = Branches.Find(x => x.FullName == branch.Upstream);
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (upstream != null)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var fastForward = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", $"{upstream.Remote}/{upstream.Name}");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
fastForward.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new FastForwardWithoutCheckout(this, branch, upstream));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(fastForward);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(push);
|
|
|
|
|
|
|
|
|
|
var merge = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", branch.Name, current.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
merge.Icon = App.CreateMenuIcon("Icons.Merge");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
merge.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Merge(this, branch.Name, current.Name));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var rebase = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", current.Name, branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
rebase.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Rebase(this, current, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(merge);
|
|
|
|
|
menu.Items.Add(rebase);
|
2024-05-27 02:21:28 -07:00
|
|
|
|
|
2024-05-27 06:05:15 -07:00
|
|
|
|
if (WorkingCopyChangesCount > 0)
|
|
|
|
|
{
|
|
|
|
|
var compareWithWorktree = new MenuItem();
|
|
|
|
|
compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree");
|
|
|
|
|
compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
|
|
|
compareWithWorktree.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
SearchResultSelectedCommit = null;
|
|
|
|
|
|
|
|
|
|
if (_histories != null)
|
|
|
|
|
{
|
|
|
|
|
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
|
|
|
|
_histories.AutoSelectedCommit = null;
|
|
|
|
|
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
|
|
|
|
}
|
|
|
|
|
};
|
2024-06-11 00:30:06 -07:00
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
2024-05-27 06:05:15 -07:00
|
|
|
|
menu.Items.Add(compareWithWorktree);
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
|
|
|
|
if (compareWithBranch != null)
|
|
|
|
|
{
|
|
|
|
|
if (WorkingCopyChangesCount == 0)
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(compareWithBranch);
|
2024-06-13 18:46:30 -07:00
|
|
|
|
}
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-14 21:44:35 -07:00
|
|
|
|
var detect = Commands.GitFlow.DetectType(_fullpath, _branches, branch.Name);
|
|
|
|
|
if (detect.IsGitFlowBranch)
|
2024-03-17 18:37:06 -07:00
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var finish = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
finish.Header = new Views.NameHighlightedTextBlock("BranchCM.Finish", branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
finish.Icon = App.CreateMenuIcon("Icons.Flow");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
finish.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
2024-06-14 21:44:35 -07:00
|
|
|
|
PopupHost.ShowPopup(new GitFlowFinish(this, branch, detect.Type, detect.Prefix));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(finish);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var rename = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
rename.Header = new Views.NameHighlightedTextBlock("BranchCM.Rename", branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
rename.Icon = App.CreateMenuIcon("Icons.Rename");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
rename.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new RenameBranch(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var delete = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", branch.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
delete.Icon = App.CreateMenuIcon("Icons.Clear");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
delete.IsEnabled = !branch.IsCurrent;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
delete.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteBranch(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var createBranch = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
createBranch.Icon = App.CreateMenuIcon("Icons.Branch.Add");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
createBranch.Header = App.Text("CreateBranch");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
createBranch.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateBranch(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var createTag = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
createTag.Icon = App.CreateMenuIcon("Icons.Tag.Add");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
createTag.Header = App.Text("CreateTag");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
createTag.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateTag(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(rename);
|
|
|
|
|
menu.Items.Add(delete);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(createBranch);
|
|
|
|
|
menu.Items.Add(createTag);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
|
|
|
|
var remoteBranches = new List<Models.Branch>();
|
2024-03-17 18:37:06 -07:00
|
|
|
|
foreach (var b in Branches)
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (!b.IsLocal)
|
|
|
|
|
remoteBranches.Add(b);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (remoteBranches.Count > 0)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var tracking = new MenuItem();
|
|
|
|
|
tracking.Header = App.Text("BranchCM.Tracking");
|
2024-06-17 23:55:22 -07:00
|
|
|
|
tracking.Icon = App.CreateMenuIcon("Icons.Track");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
foreach (var b in remoteBranches)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var upstream = b.FullName.Replace("refs/remotes/", "");
|
|
|
|
|
var target = new MenuItem();
|
|
|
|
|
target.Header = upstream;
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (branch.Upstream == b.FullName)
|
|
|
|
|
target.Icon = App.CreateMenuIcon("Icons.Check");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
target.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (Commands.Branch.SetUpstream(_fullpath, branch.Name, upstream))
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Task.Run(RefreshBranches);
|
|
|
|
|
}
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
tracking.Items.Add(target);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var unsetUpstream = new MenuItem();
|
|
|
|
|
unsetUpstream.Header = App.Text("BranchCM.UnsetUpstream");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
unsetUpstream.Click += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
if (Commands.Branch.SetUpstream(_fullpath, branch.Name, string.Empty))
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
Task.Run(RefreshBranches);
|
|
|
|
|
}
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
tracking.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
tracking.Items.Add(unsetUpstream);
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(tracking);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var archive = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
archive.Icon = App.CreateMenuIcon("Icons.Archive");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
archive.Header = App.Text("Archive");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
archive.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Archive(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(archive);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
|
|
|
|
var copy = new MenuItem();
|
|
|
|
|
copy.Header = App.Text("BranchCM.CopyName");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
copy.Click += (o, e) =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.CopyText(branch.Name);
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(copy);
|
|
|
|
|
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForRemote(Models.Remote remote)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
|
2024-06-17 05:31:54 -07:00
|
|
|
|
if (remote.TryGetVisitURL(out string visitURL))
|
|
|
|
|
{
|
|
|
|
|
var visit = new MenuItem();
|
|
|
|
|
visit.Header = App.Text("RemoteCM.OpenInBrowser");
|
|
|
|
|
visit.Icon = App.CreateMenuIcon("Icons.OpenWith");
|
|
|
|
|
visit.Click += (o, e) =>
|
|
|
|
|
{
|
|
|
|
|
Native.OS.OpenBrowser(visitURL);
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(visit);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var fetch = new MenuItem();
|
|
|
|
|
fetch.Header = App.Text("RemoteCM.Fetch");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
fetch.Icon = App.CreateMenuIcon("Icons.Fetch");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
fetch.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new Fetch(this, remote));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var prune = new MenuItem();
|
|
|
|
|
prune.Header = App.Text("RemoteCM.Prune");
|
2024-06-17 04:44:54 -07:00
|
|
|
|
prune.Icon = App.CreateMenuIcon("Icons.Clean");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
prune.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowAndStartPopup(new PruneRemote(this, remote));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var edit = new MenuItem();
|
|
|
|
|
edit.Header = App.Text("RemoteCM.Edit");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
edit.Icon = App.CreateMenuIcon("Icons.Edit");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
edit.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new EditRemote(this, remote));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var delete = new MenuItem();
|
|
|
|
|
delete.Header = App.Text("RemoteCM.Delete");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
delete.Icon = App.CreateMenuIcon("Icons.Clear");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
delete.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteRemote(this, remote));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var copy = new MenuItem();
|
|
|
|
|
copy.Header = App.Text("RemoteCM.CopyURL");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
copy.Click += (o, e) =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.CopyText(remote.URL);
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(fetch);
|
|
|
|
|
menu.Items.Add(prune);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(edit);
|
|
|
|
|
menu.Items.Add(delete);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(copy);
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForRemoteBranch(Models.Branch branch)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
var current = Branches.Find(x => x.IsCurrent);
|
|
|
|
|
|
|
|
|
|
var checkout = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
checkout.Header = new Views.NameHighlightedTextBlock("BranchCM.Checkout", $"{branch.Remote}/{branch.Name}");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
checkout.Icon = App.CreateMenuIcon("Icons.Check");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
checkout.Click += (o, e) =>
|
|
|
|
|
{
|
2024-05-29 01:42:47 -07:00
|
|
|
|
CheckoutBranch(branch);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(checkout);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
if (current != null)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var pull = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
pull.Header = new Views.NameHighlightedTextBlock("BranchCM.PullInto", $"{branch.Remote}/{branch.Name}", current.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
pull.Icon = App.CreateMenuIcon("Icons.Pull");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
pull.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Pull(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var merge = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
merge.Header = new Views.NameHighlightedTextBlock("BranchCM.Merge", $"{branch.Remote}/{branch.Name}", current.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
merge.Icon = App.CreateMenuIcon("Icons.Merge");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
merge.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Merge(this, $"{branch.Remote}/{branch.Name}", current.Name));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var rebase = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
rebase.Header = new Views.NameHighlightedTextBlock("BranchCM.Rebase", current.Name, $"{branch.Remote}/{branch.Name}");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
rebase.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Rebase(this, current, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(pull);
|
|
|
|
|
menu.Items.Add(merge);
|
|
|
|
|
menu.Items.Add(rebase);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
2024-06-11 00:30:06 -07:00
|
|
|
|
}
|
2024-05-27 02:21:28 -07:00
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
var hasCompare = false;
|
|
|
|
|
if (WorkingCopyChangesCount > 0)
|
|
|
|
|
{
|
|
|
|
|
var compareWithWorktree = new MenuItem();
|
|
|
|
|
compareWithWorktree.Header = App.Text("BranchCM.CompareWithWorktree");
|
|
|
|
|
compareWithWorktree.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
|
|
|
compareWithWorktree.Click += (o, e) =>
|
2024-05-27 02:21:28 -07:00
|
|
|
|
{
|
2024-06-11 00:30:06 -07:00
|
|
|
|
SearchResultSelectedCommit = null;
|
2024-05-27 06:05:15 -07:00
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
if (_histories != null)
|
2024-05-27 06:05:15 -07:00
|
|
|
|
{
|
2024-06-11 00:30:06 -07:00
|
|
|
|
var target = new Commands.QuerySingleCommit(FullPath, branch.Head).Result();
|
|
|
|
|
_histories.AutoSelectedCommit = null;
|
|
|
|
|
_histories.DetailContext = new RevisionCompare(FullPath, target, null);
|
2024-05-27 06:05:15 -07:00
|
|
|
|
}
|
2024-06-11 00:30:06 -07:00
|
|
|
|
};
|
|
|
|
|
menu.Items.Add(compareWithWorktree);
|
|
|
|
|
hasCompare = true;
|
|
|
|
|
}
|
2024-05-27 06:05:15 -07:00
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
var compareWithBranch = CreateMenuItemToCompareBranches(branch);
|
|
|
|
|
if (compareWithBranch != null)
|
|
|
|
|
{
|
|
|
|
|
menu.Items.Add(compareWithBranch);
|
|
|
|
|
hasCompare = true;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
if (hasCompare)
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var delete = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
delete.Header = new Views.NameHighlightedTextBlock("BranchCM.Delete", $"{branch.Remote}/{branch.Name}");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
delete.Icon = App.CreateMenuIcon("Icons.Clear");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
delete.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteBranch(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var createBranch = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
createBranch.Icon = App.CreateMenuIcon("Icons.Branch.Add");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
createBranch.Header = App.Text("CreateBranch");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
createBranch.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateBranch(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var createTag = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
createTag.Icon = App.CreateMenuIcon("Icons.Tag.Add");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
createTag.Header = App.Text("CreateTag");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
createTag.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateTag(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var archive = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
archive.Icon = App.CreateMenuIcon("Icons.Archive");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
archive.Header = App.Text("Archive");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
archive.Click += (o, e) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Archive(this, branch));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var copy = new MenuItem();
|
|
|
|
|
copy.Header = App.Text("BranchCM.CopyName");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
copy.Click += (o, e) =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.CopyText(branch.Remote + "/" + branch.Name);
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
menu.Items.Add(delete);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(createBranch);
|
|
|
|
|
menu.Items.Add(createTag);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(archive);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(copy);
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForTag(Models.Tag tag)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var createBranch = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
createBranch.Icon = App.CreateMenuIcon("Icons.Branch.Add");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
createBranch.Header = App.Text("CreateBranch");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
createBranch.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new CreateBranch(this, tag));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var pushTag = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
pushTag.Header = new Views.NameHighlightedTextBlock("TagCM.Push", tag.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
pushTag.Icon = App.CreateMenuIcon("Icons.Push");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
pushTag.IsEnabled = Remotes.Count > 0;
|
2024-03-17 18:37:06 -07:00
|
|
|
|
pushTag.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new PushTag(this, tag));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var deleteTag = new MenuItem();
|
2024-02-28 02:55:23 -08:00
|
|
|
|
deleteTag.Header = new Views.NameHighlightedTextBlock("TagCM.Delete", tag.Name);
|
2024-02-27 02:26:05 -08:00
|
|
|
|
deleteTag.Icon = App.CreateMenuIcon("Icons.Clear");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
deleteTag.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteTag(this, tag));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var archive = new MenuItem();
|
2024-02-27 02:26:05 -08:00
|
|
|
|
archive.Icon = App.CreateMenuIcon("Icons.Archive");
|
2024-02-05 23:08:37 -08:00
|
|
|
|
archive.Header = App.Text("Archive");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
archive.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new Archive(this, tag));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var copy = new MenuItem();
|
|
|
|
|
copy.Header = App.Text("TagCM.Copy");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
copy.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.CopyText(tag.Name);
|
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
menu.Items.Add(createBranch);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(pushTag);
|
|
|
|
|
menu.Items.Add(deleteTag);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(archive);
|
|
|
|
|
menu.Items.Add(new MenuItem() { Header = "-" });
|
|
|
|
|
menu.Items.Add(copy);
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-19 11:24:33 -07:00
|
|
|
|
public void OpenSubmodule(string submodule)
|
|
|
|
|
{
|
|
|
|
|
var root = Path.GetFullPath(Path.Combine(_fullpath, submodule));
|
|
|
|
|
var gitDir = new Commands.QueryGitDir(root).Result();
|
|
|
|
|
var repo = Preference.AddRepository(root, gitDir);
|
|
|
|
|
|
|
|
|
|
var node = new RepositoryNode()
|
|
|
|
|
{
|
|
|
|
|
Id = repo.FullPath,
|
|
|
|
|
Name = Path.GetFileName(repo.FullPath),
|
|
|
|
|
Bookmark = 0,
|
|
|
|
|
IsRepository = true,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var launcher = App.GetTopLevel().DataContext as Launcher;
|
|
|
|
|
if (launcher != null)
|
|
|
|
|
{
|
|
|
|
|
launcher.OpenRepositoryInTab(node, null);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-03-17 18:37:06 -07:00
|
|
|
|
public ContextMenu CreateContextMenuForSubmodule(string submodule)
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
var open = new MenuItem();
|
|
|
|
|
open.Header = App.Text("Submodule.Open");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
open.Icon = App.CreateMenuIcon("Icons.Folder.Open");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
open.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-06-19 11:24:33 -07:00
|
|
|
|
OpenSubmodule(submodule);
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var copy = new MenuItem();
|
|
|
|
|
copy.Header = App.Text("Submodule.CopyPath");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
copy.Icon = App.CreateMenuIcon("Icons.Copy");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
copy.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-02-05 23:08:37 -08:00
|
|
|
|
App.CopyText(submodule);
|
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var rm = new MenuItem();
|
|
|
|
|
rm.Header = App.Text("Submodule.Remove");
|
2024-02-27 02:26:05 -08:00
|
|
|
|
rm.Icon = App.CreateMenuIcon("Icons.Clear");
|
2024-03-17 18:37:06 -07:00
|
|
|
|
rm.Click += (o, ev) =>
|
|
|
|
|
{
|
2024-03-31 01:54:29 -07:00
|
|
|
|
if (PopupHost.CanCreatePopup())
|
|
|
|
|
PopupHost.ShowPopup(new DeleteSubmodule(this, submodule));
|
2024-02-05 23:08:37 -08:00
|
|
|
|
ev.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
var menu = new ContextMenu();
|
|
|
|
|
menu.Items.Add(open);
|
|
|
|
|
menu.Items.Add(copy);
|
|
|
|
|
menu.Items.Add(rm);
|
|
|
|
|
return menu;
|
|
|
|
|
}
|
|
|
|
|
|
2024-06-11 00:30:06 -07:00
|
|
|
|
private MenuItem CreateMenuItemToCompareBranches(Models.Branch branch)
|
|
|
|
|
{
|
|
|
|
|
if (Branches.Count == 1)
|
|
|
|
|
return null;
|
|
|
|
|
|
|
|
|
|
var compare = new MenuItem();
|
|
|
|
|
compare.Header = App.Text("BranchCM.CompareWithBranch");
|
|
|
|
|
compare.Icon = App.CreateMenuIcon("Icons.Compare");
|
|
|
|
|
|
|
|
|
|
foreach (var b in Branches)
|
|
|
|
|
{
|
|
|
|
|
if (b.FullName != branch.FullName)
|
|
|
|
|
{
|
|
|
|
|
var dup = b;
|
|
|
|
|
var target = new MenuItem();
|
|
|
|
|
target.Header = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
|
|
|
|
|
target.Icon = App.CreateMenuIcon(b.IsCurrent ? "Icons.Check" : "Icons.Branch");
|
|
|
|
|
target.Click += (_, e) =>
|
|
|
|
|
{
|
|
|
|
|
var wnd = new Views.BranchCompare()
|
|
|
|
|
{
|
|
|
|
|
DataContext = new BranchCompare(FullPath, branch, dup)
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
wnd.Show(App.GetTopLevel() as Window);
|
|
|
|
|
e.Handled = true;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
compare.Items.Add(target);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return compare;
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-13 20:47:56 -07:00
|
|
|
|
private BranchTreeNode.Builder BuildBranchTree(List<Models.Branch> branches, List<Models.Remote> remotes)
|
|
|
|
|
{
|
|
|
|
|
var builder = new BranchTreeNode.Builder();
|
|
|
|
|
builder.SetFilters(Filters);
|
|
|
|
|
|
|
|
|
|
if (string.IsNullOrEmpty(_searchBranchFilter))
|
|
|
|
|
{
|
|
|
|
|
builder.CollectExpandedNodes(_localBranchTrees, true);
|
|
|
|
|
builder.CollectExpandedNodes(_remoteBranchTrees, false);
|
|
|
|
|
builder.Run(branches, remotes, false);
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
var visibles = new List<Models.Branch>();
|
|
|
|
|
foreach (var b in branches)
|
|
|
|
|
{
|
|
|
|
|
if (b.FullName.Contains(_searchBranchFilter, StringComparison.OrdinalIgnoreCase))
|
|
|
|
|
visibles.Add(b);
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-14 03:50:36 -07:00
|
|
|
|
builder.Run(visibles, remotes, visibles.Count <= 20);
|
2024-05-13 20:47:56 -07:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return builder;
|
|
|
|
|
}
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private string _fullpath = string.Empty;
|
|
|
|
|
private string _gitDir = string.Empty;
|
|
|
|
|
|
|
|
|
|
private Models.Watcher _watcher = null;
|
|
|
|
|
private Histories _histories = null;
|
|
|
|
|
private WorkingCopy _workingCopy = null;
|
|
|
|
|
private StashesPage _stashesPage = null;
|
|
|
|
|
private int _selectedViewIndex = 0;
|
|
|
|
|
private object _selectedView = null;
|
|
|
|
|
|
|
|
|
|
private bool _isSearching = false;
|
2024-06-07 03:43:37 -07:00
|
|
|
|
private int _searchCommitFilterType = 0;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private string _searchCommitFilter = string.Empty;
|
|
|
|
|
private List<Models.Commit> _searchedCommits = new List<Models.Commit>();
|
|
|
|
|
|
2024-03-20 20:40:17 -07:00
|
|
|
|
private bool _isTagGroupExpanded = false;
|
|
|
|
|
private bool _isSubmoduleGroupExpanded = false;
|
|
|
|
|
|
2024-05-13 20:47:56 -07:00
|
|
|
|
private string _searchBranchFilter = string.Empty;
|
|
|
|
|
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private List<Models.Remote> _remotes = new List<Models.Remote>();
|
|
|
|
|
private List<Models.Branch> _branches = new List<Models.Branch>();
|
2024-05-13 20:47:56 -07:00
|
|
|
|
private List<BranchTreeNode> _localBranchTrees = new List<BranchTreeNode>();
|
|
|
|
|
private List<BranchTreeNode> _remoteBranchTrees = new List<BranchTreeNode>();
|
2024-02-05 23:08:37 -08:00
|
|
|
|
private List<Models.Tag> _tags = new List<Models.Tag>();
|
|
|
|
|
private List<string> _submodules = new List<string>();
|
|
|
|
|
private bool _includeUntracked = true;
|
2024-04-01 06:27:08 -07:00
|
|
|
|
|
|
|
|
|
private InProgressContext _inProgressContext = null;
|
|
|
|
|
private bool _hasUnsolvedConflicts = false;
|
2024-05-10 01:04:03 -07:00
|
|
|
|
private Models.Commit _searchResultSelectedCommit = null;
|
2024-02-05 23:08:37 -08:00
|
|
|
|
}
|
2024-03-31 01:54:29 -07:00
|
|
|
|
}
|