From ec1f4a02013d13940f900d1bfadb5f58367a9a5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20M=C3=BCnchow?= Date: Wed, 7 Nov 2018 14:34:36 +0100 Subject: [PATCH] Added bugfix actions. --- .../GitFlow.VS.Extension.csproj | 9 + .../GitFlowBugfixesSection.cs | 56 + GitFlow.VS.Extension/GitFlowInstallSection.cs | 12 +- GitFlow.VS.Extension/Guids.cs | 7 +- GitFlow.VS.Extension/UI/BugfixesUI.xaml | 82 + GitFlow.VS.Extension/UI/BugfixesUI.xaml.cs | 25 + GitFlow.VS.Extension/UI/GitFlowActionsUI.xaml | 70 +- GitFlow.VS.Extension/UI/InitUI.xaml | 10 +- GitFlow.VS.Extension/UI/ReleasesUI.xaml.cs | 2 +- .../ViewModels/ActionViewModel.cs | 2332 ++++++++++------- .../ViewModels/BugfixesViewModel.cs | 154 ++ .../ViewModels/FeaturesViewModel.cs | 12 +- GitFlow.VS.Extension/ViewModels/InitModel.cs | 16 +- GitFlow.VS.Tests/GitFlowWrapperTests.cs | 30 +- GitFlow.VS/GitFlowRepoSettings.cs | 2 + GitFlow.VS/GitFlowWrapper.cs | 231 +- 16 files changed, 1937 insertions(+), 1113 deletions(-) create mode 100644 GitFlow.VS.Extension/GitFlowBugfixesSection.cs create mode 100644 GitFlow.VS.Extension/UI/BugfixesUI.xaml create mode 100644 GitFlow.VS.Extension/UI/BugfixesUI.xaml.cs create mode 100644 GitFlow.VS.Extension/ViewModels/BugfixesViewModel.cs diff --git a/GitFlow.VS.Extension/GitFlow.VS.Extension.csproj b/GitFlow.VS.Extension/GitFlow.VS.Extension.csproj index c4ae5b3..36efe99 100644 --- a/GitFlow.VS.Extension/GitFlow.VS.Extension.csproj +++ b/GitFlow.VS.Extension/GitFlow.VS.Extension.csproj @@ -206,6 +206,7 @@ + @@ -215,6 +216,9 @@ + + BugfixesUI.xaml + ReleasesUI.xaml @@ -231,6 +235,7 @@ InstallGitFlowUI.xaml + @@ -491,6 +496,10 @@ + + MSBuild:Compile + Designer + MSBuild:Compile Designer diff --git a/GitFlow.VS.Extension/GitFlowBugfixesSection.cs b/GitFlow.VS.Extension/GitFlowBugfixesSection.cs new file mode 100644 index 0000000..a96641b --- /dev/null +++ b/GitFlow.VS.Extension/GitFlowBugfixesSection.cs @@ -0,0 +1,56 @@ +using GitFlowVS.Extension.UI; +using GitFlowVS.Extension.ViewModels; +using Microsoft.TeamFoundation.Controls; +using TeamExplorer.Common; + +namespace GitFlowVS.Extension +{ + [TeamExplorerSection(GuidList.GitFlowBugfixesSection, GuidList.GitFlowPage, 115)] + public class GitFlowBugfixesSection : TeamExplorerBaseSection, IGitFlowSection + { + private readonly BugfixesViewModel model; + + public GitFlowBugfixesSection() + { + Title = "Current Bugfixes"; + IsVisible = false; + model = new BugfixesViewModel(this); + UpdateVisibleState(); + } + + public override void Refresh() + { + var service = GetService(); + service.Refresh(); + } + + public void UpdateVisibleState() + { + if (!GitFlowPage.GitFlowIsInstalled) + { + IsVisible = false; + return; + } + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepo.RepositoryPath, GitFlowPage.OutputWindow); + if (gf.IsInitialized) + { + if (!IsVisible) + { + SectionContent = new BugfixesUI(model); + IsVisible = true; + } + model.Update(); + } + else + { + IsVisible = false; + } + } + + public void ShowErrorNotification(string message) + { + ShowNotification(message, NotificationType.Error); + } + } +} \ No newline at end of file diff --git a/GitFlow.VS.Extension/GitFlowInstallSection.cs b/GitFlow.VS.Extension/GitFlowInstallSection.cs index afc0d1e..8532d5a 100644 --- a/GitFlow.VS.Extension/GitFlowInstallSection.cs +++ b/GitFlow.VS.Extension/GitFlowInstallSection.cs @@ -24,13 +24,13 @@ public GitFlowInstallSection() } } - private void HandleException(Exception ex) - { - Logger.Exception(ex); - ShowNotification(ex.Message, NotificationType.Error); - } + private void HandleException(Exception ex) + { + Logger.Exception(ex); + ShowNotification(ex.Message, NotificationType.Error); + } - public override void Refresh() + public override void Refresh() { var service = GetService(); service.Refresh(); diff --git a/GitFlow.VS.Extension/Guids.cs b/GitFlow.VS.Extension/Guids.cs index 62a2545..b1955ff 100644 --- a/GitFlow.VS.Extension/Guids.cs +++ b/GitFlow.VS.Extension/Guids.cs @@ -2,7 +2,7 @@ namespace GitFlowVS.Extension { - static class GuidList + internal static class GuidList { public const string GuidGitFlowVsExtensionPkgString = "19ffe08d-8c71-4125-a024-6296bd27fce8"; public const string GuidGitFlowVsExtensionCmdSetString = "9be3ffde-c8d0-4d89-824b-f310e4d05ca1"; @@ -11,9 +11,10 @@ static class GuidList public const string GitFlowPage = "1F9974CD-16C3-4AEF-AED2-0CE37988E2F1"; public const string GitFlowActionSection = "F63C9A55-E0A2-4E7C-A78B-C37512EAEE5D"; + public const string GitFlowBugfixesSection = "6E1F4634-C123-4EA1-9FB7-0F56FAC88095"; public const string GitFlowFeaturesSection = "FED30B30-AEB3-4CCA-963B-1D044A9B90E5"; public const string GitFlowInitSection = "12760882-D1DE-46FF-8965-045017C7472D"; public const string GitFlowInstallSection = "9D57DC9D-5B59-4B0B-B581-809E6C973D57"; - public const string GitFlowReleasesSection = "C75DDD57-0FD1-425D-A06F-B18F24968EA2"; - }; + public const string GitFlowReleasesSection = "C75DDD57-0FD1-425D-A06F-B18F24968EA2"; + }; } \ No newline at end of file diff --git a/GitFlow.VS.Extension/UI/BugfixesUI.xaml b/GitFlow.VS.Extension/UI/BugfixesUI.xaml new file mode 100644 index 0000000..071f7ea --- /dev/null +++ b/GitFlow.VS.Extension/UI/BugfixesUI.xaml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + No bugfixes available + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/GitFlow.VS.Extension/UI/BugfixesUI.xaml.cs b/GitFlow.VS.Extension/UI/BugfixesUI.xaml.cs new file mode 100644 index 0000000..562c488 --- /dev/null +++ b/GitFlow.VS.Extension/UI/BugfixesUI.xaml.cs @@ -0,0 +1,25 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; +using GitFlowVS.Extension.ViewModels; + +namespace GitFlowVS.Extension.UI +{ + /// + /// Interaction logic for BugfixesUI.xaml + /// + public partial class BugfixesUI : UserControl + { + public BugfixesUI(BugfixesViewModel model) + { + InitializeComponent(); + DataContext = model; + } + + private void BugfixesGrid_OnMouseDoubleClick(object sender, MouseButtonEventArgs e) + { + var model = (BugfixesViewModel)DataContext; + model.CheckoutBugfixBranch(); + } + } +} diff --git a/GitFlow.VS.Extension/UI/GitFlowActionsUI.xaml b/GitFlow.VS.Extension/UI/GitFlowActionsUI.xaml index c56156b..c349606 100644 --- a/GitFlow.VS.Extension/UI/GitFlowActionsUI.xaml +++ b/GitFlow.VS.Extension/UI/GitFlowActionsUI.xaml @@ -29,12 +29,16 @@ + + + + @@ -46,6 +50,9 @@ + + + @@ -123,7 +130,31 @@ - + + + + + + + + + + + + + + + + + + + @@ -151,8 +182,8 @@ Command="{Binding Path=CancelFinishFeatureCommand}"/> - - + + @@ -185,7 +216,7 @@ - + @@ -216,6 +247,35 @@ - + + + + + + + + + + + + + + Rebase on development branch + Delete local branch + Delete remote branch + Squash bugfix during merge + Never fast-forward during the merge + + + + + + + diff --git a/GitFlow.VS.Extension/UI/InitUI.xaml b/GitFlow.VS.Extension/UI/InitUI.xaml index 7d5e615..5362df5 100644 --- a/GitFlow.VS.Extension/UI/InitUI.xaml +++ b/GitFlow.VS.Extension/UI/InitUI.xaml @@ -50,10 +50,12 @@ Hotfix branch prefix: - Version branch prefix: - + Bugfix branch prefix: + + Version branch prefix: + - + @@ -61,7 +63,7 @@ Localization.Attributes="Text (Modifiable Readable Text)" Command="{Binding Path=CancelCommand}"/> - + diff --git a/GitFlow.VS.Extension/UI/ReleasesUI.xaml.cs b/GitFlow.VS.Extension/UI/ReleasesUI.xaml.cs index f0d36c6..b918cfe 100644 --- a/GitFlow.VS.Extension/UI/ReleasesUI.xaml.cs +++ b/GitFlow.VS.Extension/UI/ReleasesUI.xaml.cs @@ -6,7 +6,7 @@ namespace GitFlowVS.Extension.UI { /// - /// Interaction logic for FeaturesUI.xaml + /// Interaction logic for ReleasesUI.xaml /// public partial class ReleasesUI : UserControl { diff --git a/GitFlow.VS.Extension/ViewModels/ActionViewModel.cs b/GitFlow.VS.Extension/ViewModels/ActionViewModel.cs index 9c38136..c59bc5b 100644 --- a/GitFlow.VS.Extension/ViewModels/ActionViewModel.cs +++ b/GitFlow.VS.Extension/ViewModels/ActionViewModel.cs @@ -1,1012 +1,1320 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Windows; -using System.Windows.Input; -using GitFlow.VS; -using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer; - -namespace GitFlowVS.Extension.ViewModels -{ - public class ActionViewModel : ViewModelBase - { - private Visibility showStartFeature; - private Visibility showStartRelease; - private Visibility showStartHotfix; - - private Visibility showFinishFeature; - private Visibility showFinishRelease; - private Visibility showFinishHotfix; - - private string featureName; - private string releaseName; - private string hotfixName; - - private bool featureRebaseOnDevelopmentBranch; - private bool featureDeleteLocalBranch; - private bool featureDeleteRemoteBranch; - private bool featureSquash; - private bool featureNoFastForward; - private bool releaseDeleteBranch; - private string releaseTagMessage; - private bool releaseForceDeletion; - private bool releasePushChanges; - private bool releaseNoBackMerge; - private bool hotfixDeleteBranch; - private bool hotfixPushChanges; - private bool hotfixForceDeletion; - private string hotfixTagMessage; - private ListItem selectedFeature; - private bool hotfixTagMessageSelected; - private bool releaseTagMessageSelected; - private ListItem selectedHotfix; - private ListItem selectedRelease; - - public ICommand StartFeatureDropDownCommand { get; private set; } - public ICommand StartFeatureCommand { get; private set; } - public ICommand CancelStartFeatureCommand { get; private set; } - - - public ICommand StartReleaseDropDownCommand { get; private set; } - public ICommand StartReleaseCommand { get; private set; } - public ICommand CancelStartReleaseCommand { get; private set; } - - public ICommand StartHotfixDropDownCommand { get; private set; } - public ICommand StartHotfixCommand { get; private set; } - public ICommand CancelStartHotfixCommand { get; private set; } - - public ICommand FinishFeatureDropDownCommand { get; private set; } - public ICommand FinishFeatureCommand { get; private set; } - public ICommand CancelFinishFeatureCommand { get; private set; } - - - public ICommand FinishReleaseDropDownCommand { get; private set; } - public ICommand FinishReleaseCommand { get; private set; } - public ICommand CancelFinishReleaseCommand { get; private set; } - - public ICommand FinishHotfixDropDownCommand { get; private set; } - public ICommand FinishHotfixCommand { get; private set; } - public ICommand CancelFinishHotfixCommand { get; private set; } - - - public ActionViewModel(GitFlowActionSection te) - : base(te) - { - FeatureDeleteLocalBranch = true; - FeatureDeleteRemoteBranch = true; - FeatureSquash = true; - FeatureNoFastForward = true; - ReleaseDeleteBranch = true; - ReleaseTagMessageSelected = true; - ReleaseNoBackMerge = false; - HotfixDeleteBranch = true; - HotfixTagMessageSelected = true; - - ShowStartFeature = Visibility.Collapsed; - ShowStartRelease = Visibility.Collapsed; - ShowStartHotfix = Visibility.Collapsed; - - ShowFinishFeature = Visibility.Collapsed; - ShowFinishRelease = Visibility.Collapsed; - ShowFinishHotfix = Visibility.Collapsed; - - HideProgressBar(); - - StartFeatureDropDownCommand = new DropDownLinkCommand(p => StartFeatureDropDown(), p => CanShowStartFeatureDropDown()); - StartFeatureCommand = new RelayCommand(p => StartFeature(), p => CanCreateFeature); - CancelStartFeatureCommand = new RelayCommand(p => CancelStartFeature(), p => CanCancelFinishCommand()); - - StartReleaseDropDownCommand = new DropDownLinkCommand(p => StartReleaseDropDown(), p => CanShowStartReleaseDropDown()); - StartReleaseCommand = new RelayCommand(p => StartRelease(), p => CanCreateRelease); - CancelStartReleaseCommand = new RelayCommand(p => CancelStartRelease(), p => CanCancelFinishCommand()); - - StartHotfixDropDownCommand = new DropDownLinkCommand(p => StartHotfixDropDown(), p => CanShowStartHotfixDropDown()); - StartHotfixCommand = new RelayCommand(p => StartHotfix(), p => CanCreateHotfix); - CancelStartHotfixCommand = new RelayCommand(p => CancelStartHotfix(), p => CanCancelFinishCommand()); - - FinishFeatureDropDownCommand = new DropDownLinkCommand(p => FinishFeatureDropDown(), p => CanShowFinishFeatureDropDown()); - FinishFeatureCommand = new RelayCommand(p => FinishFeature(), p => CanFinishFeature); - CancelFinishFeatureCommand = new RelayCommand(p => CancelFinishFeature(), p => CanCancelFinishCommand()); - - FinishReleaseDropDownCommand = new DropDownLinkCommand(p => FinishReleaseDropDown(), p => CanShowFinishReleaseDropDown()); - FinishReleaseCommand = new RelayCommand(p => FinishRelease(), p => CanFinishRelease); - CancelFinishReleaseCommand = new RelayCommand(p => CancelFinishRelease(), p => CanCancelFinishCommand()); - - FinishHotfixDropDownCommand = new DropDownLinkCommand(p => FinishHotfixDropDown(), p => CanShowFinishHotfixDropDown()); - FinishHotfixCommand = new RelayCommand(p => FinishHotfix(), p => CanFinishHotfix); - CancelFinishHotfixCommand = new RelayCommand(p => CancelFinishHotfix(), p => CanCancelFinishCommand()); - } - - public bool CanFinishRelease - { - get { return SelectedRelease != null && CanCancelFinishCommand(); } - } - - public bool CanFinishHotfix - { - get { return SelectedHotfix != null && CanCancelFinishCommand(); } - } - - public bool CanFinishFeature - { - get { return SelectedFeature != null && CanCancelFinishCommand(); } - } - - private void CancelStartFeature() - { - ShowStartFeature = Visibility.Collapsed; - } - private void CancelStartHotfix() - { - ShowStartHotfix = Visibility.Collapsed; - } - - private void CancelStartRelease() - { - ShowStartRelease = Visibility.Collapsed; - } - - private void CancelFinishFeature() - { - ShowFinishFeature = Visibility.Collapsed; - } - private void CancelFinishHotfix() - { - ShowFinishHotfix = Visibility.Collapsed; - } - - private void CancelFinishRelease() - { - ShowFinishRelease = Visibility.Collapsed; - } - - private bool CanShowStartFeatureDropDown() - { - return true; - } - - private bool CanCancelFinishCommand() - { - return ProgressVisibility != Visibility.Visible; - } - - private bool CanShowStartHotfixDropDown() - { - return true; - } - private bool CanShowStartReleaseDropDown() - { - return true; - } - - private bool CanShowFinishFeatureDropDown() - { - return true; - } - private bool CanShowFinishHotfixDropDown() - { - return true; - } - private bool CanShowFinishReleaseDropDown() - { - return true; - } - - private void StartFeatureDropDown() - { - HideAll(); - ShowStartFeature = Visibility.Visible; - } - - private void HideAll() - { - ShowStartFeature = Visibility.Collapsed; - ShowStartRelease = Visibility.Collapsed; - ShowStartHotfix = Visibility.Collapsed; - ShowFinishFeature = Visibility.Collapsed; - ShowFinishRelease = Visibility.Collapsed; - ShowFinishHotfix = Visibility.Collapsed; - } - - private void UpdateMenus() - { - OnPropertyChanged("StartFeatureVisible"); - OnPropertyChanged("StartReleaseVisible"); - OnPropertyChanged("StartHotfixVisible"); - OnPropertyChanged("FinishFeatureVisible"); - OnPropertyChanged("FinishReleaseVisible"); - OnPropertyChanged("FinishHotfixVisible"); - - OnPropertyChanged("OtherStartFeatureVisible"); - OnPropertyChanged("OtherStartReleaseVisible"); - OnPropertyChanged("OtherStartHotfixVisible"); - OnPropertyChanged("OtherFinishFeatureVisible"); - OnPropertyChanged("OtherFinishReleaseVisible"); - OnPropertyChanged("OtherFinishHotfixVisible"); - } - - private void StartHotfixDropDown() - { - HideAll(); - ShowStartHotfix = Visibility.Visible; - - } - private void StartReleaseDropDown() - { - HideAll(); - ShowStartRelease = Visibility.Visible; - } - - private void FinishFeatureDropDown() - { - HideAll(); - ShowFinishFeature = Visibility.Visible; - } - - private void FinishHotfixDropDown() - { - HideAll(); - ShowFinishHotfix = Visibility.Visible; - } - private void FinishReleaseDropDown() - { - HideAll(); - ShowFinishRelease = Visibility.Visible; - } - - public bool CanCreateFeature - { - get { return !String.IsNullOrEmpty(FeatureName) && CanCancelFinishCommand(); } - } - - public bool CanCreateRelease - { - get - { - return !String.IsNullOrEmpty(ReleaseName) && CanCancelFinishCommand(); - } - } - - public bool CanCreateHotfix - { - get { return !String.IsNullOrEmpty(HotfixName) && CanCancelFinishCommand(); } - } - - public List AllFeatures - { - get - { - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - return gf.AllFeatures.Select(x => new ListItem {Name = x}).ToList(); - } - } - - public ListItem SelectedFeature - { - get { return selectedFeature; } - set - { - if (Equals(value, selectedFeature)) return; - selectedFeature = value; - OnPropertyChanged(); - } - } - - public List AllReleases - { - get - { - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - return gf.AllReleases.Select(x => new ListItem { Name = x }).ToList(); - } - } - - public ListItem SelectedRelease - { - get { return selectedRelease; } - set - { - if (Equals(value, selectedRelease)) return; - selectedRelease = value; - OnPropertyChanged(); - } - } - - public List AllHotfixes - { - get - { - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - return gf.AllHotfixes.Select(x => new ListItem { Name = x }).ToList(); - } - } - - - public ListItem SelectedHotfix - { - get { return selectedHotfix; } - set - { - if (Equals(value, selectedHotfix)) return; - selectedHotfix = value; - OnPropertyChanged(); - } - } - - - private void StartFeature() - { - try - { - if (String.IsNullOrEmpty(FeatureName)) - return; - - Logger.Event("StartFeature"); - DateTime start = DateTime.Now; - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - ShowProgressBar(); - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.StartFeature(FeatureName); - if (!result.Success) - { - ShowErrorMessage(result); - } - - HideProgressBar(); - FeatureName = String.Empty; - UpdateMenus(); - HideAll(); - OnPropertyChanged("AllFeatures"); - } - Logger.Metric("Duration-StartFeature", (DateTime.Now-start).Milliseconds); - } - catch (Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - - } - - private void StartRelease() - { - try - { - if (String.IsNullOrEmpty(ReleaseName)) - return; - - Logger.Event("StartRelease"); - DateTime start = DateTime.Now; - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - ShowProgressBar(); - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.StartRelease(ReleaseName); - if (!result.Success) - { - ShowErrorMessage(result); - } - HideProgressBar(); - ShowStartRelease = Visibility.Collapsed; - ReleaseName = String.Empty; - UpdateMenus(); - HideAll(); - OnPropertyChanged("AllReleases"); - } - Logger.Metric("Duration-StartRelease", (DateTime.Now - start).Milliseconds); - } - catch (Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - - } - - private void ShowErrorMessage(GitFlowCommandResult result) - { - Te.ShowErrorNotification(result.CommandOutput); - } - private void ShowErrorMessage(string message) - { - Te.ShowErrorNotification(message); - } - - private void StartHotfix() - { - try - { - if (String.IsNullOrEmpty(HotfixName)) - return; - - Logger.Event("StartHotfix"); - DateTime start = DateTime.Now; - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - ShowProgressBar(); - - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.StartHotfix(HotfixName); - if (!result.Success) - { - ShowErrorMessage(result); - } - - HideProgressBar(); - ShowStartHotfix = Visibility.Collapsed; - HotfixName = String.Empty; - UpdateMenus(); - HideAll(); - OnPropertyChanged("AllHotfixes"); - } - Logger.Metric("Duration-StartHotfix", (DateTime.Now - start).Milliseconds); - } - catch (Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - - } - - private void FinishFeature() - { - try - { - DateTime start = DateTime.Now; - - var properties = new Dictionary - { - {"RebaseOnDevelopmentBranch", FeatureRebaseOnDevelopmentBranch.ToString()}, - {"DeleteLocalBranch", FeatureDeleteLocalBranch.ToString()}, - {"DeleteRemoteBranch", FeatureDeleteRemoteBranch.ToString()}, - {"Squash", FeatureSquash.ToString()}, - {"NoFastForward", FeatureNoFastForward.ToString()} - }; - Logger.Event("FinishFeature", properties); - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - - ShowProgressBar(); - - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.FinishFeature(SelectedFeature.Name, FeatureRebaseOnDevelopmentBranch, FeatureDeleteLocalBranch, FeatureDeleteRemoteBranch, FeatureSquash, FeatureNoFastForward); - if (!result.Success) - { - ShowErrorMessage(result); - } - - HideProgressBar(); - ShowFinishFeature = Visibility.Collapsed; - UpdateMenus(); - HideAll(); - OnPropertyChanged("AllFeatures"); - Te.Refresh(); - } - - Logger.Metric("Duration-FinishFeature", (DateTime.Now - start).Milliseconds); - } - catch( Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - } - - private void FinishRelease() - { - try - { - DateTime start = DateTime.Now; - var properties = new Dictionary - { - {"TaggedRelease", (!String.IsNullOrEmpty(ReleaseTagMessage)).ToString()}, - {"DeleteBranch", ReleaseDeleteBranch.ToString()}, - {"ForceDeletion", ReleaseForceDeletion.ToString()}, - {"PushChanges", ReleasePushChanges.ToString()}, - {"NoBackMerge", ReleaseNoBackMerge.ToString()} - }; - Logger.Event("FinishRelease", properties); - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - ShowProgressBar(); - - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.FinishRelease(SelectedRelease.Name, ReleaseTagMessage, ReleaseDeleteBranch, ReleaseForceDeletion, ReleasePushChanges, ReleaseNoBackMerge); - if (!result.Success) - { - ShowErrorMessage(result); - } - - HideAll(); - HideProgressBar(); - ShowFinishRelease = Visibility.Collapsed; - OnPropertyChanged("AllReleases"); - UpdateMenus(); - } - Logger.Metric("Duration-FinishRelease", (DateTime.Now - start).Milliseconds); - } - catch (Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - } - - private void FinishHotfix() - { - try - { - DateTime start = DateTime.Now; - var properties = new Dictionary - { - {"TaggedRelease", (!String.IsNullOrEmpty(HotfixTagMessage)).ToString()}, - {"DeleteBranch", HotfixDeleteBranch.ToString()}, - {"ForceDeletion", HotfixForceDeletion.ToString()}, - {"PushChanges", HotfixPushChanges.ToString()} - }; - Logger.Event("FinishHotfix", properties); - - if (GitFlowPage.ActiveRepo != null) - { - GitFlowPage.ActiveOutputWindow(); - ShowProgressBar(); - - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - var result = gf.FinishHotfix(SelectedHotfix.Name, HotfixTagMessage, HotfixDeleteBranch, HotfixForceDeletion, HotfixPushChanges); - if (!result.Success) - { - ShowErrorMessage(result); - } - - HideAll(); - HideProgressBar(); - ShowFinishHotfix = Visibility.Collapsed; - OnPropertyChanged("AllHotfixes"); - UpdateMenus(); - } - Logger.Metric("Duration-FinishHotfix", (DateTime.Now - start).Milliseconds); - } - catch (Exception ex) - { - ShowErrorMessage(ex.ToString()); - Logger.Exception(ex); - } - - } - - public string ReleaseName - { - get { return releaseName; } - set - { - if (value == releaseName) return; - releaseName = value; - OnPropertyChanged(); - OnPropertyChanged("CanCreateRelease"); - } - } - - public string HotfixName - { - get { return hotfixName; } - set - { - if (value == hotfixName) return; - hotfixName = value; - OnPropertyChanged(); - OnPropertyChanged("CanCreateHotfix"); - } - } - - public string FeatureName - { - get { return featureName; } - set - { - if (value == featureName) return; - featureName = value; - OnPropertyChanged(); - OnPropertyChanged("CanCreateFeature"); - } - } - - public Visibility ShowStartFeature - { - get { return showStartFeature; } - set - { - if (value == showStartFeature) return; - showStartFeature = value; - OnPropertyChanged(); - } - } - - public Visibility ShowStartHotfix - { - get { return showStartHotfix; } - set - { - if (value == showStartHotfix) return; - showStartHotfix = value; - OnPropertyChanged(); - } - } - - public Visibility ShowStartRelease - { - get { return showStartRelease; } - set - { - if (value == showStartRelease) return; - showStartRelease = value; - OnPropertyChanged(); - } - } - - public Visibility ShowFinishFeature - { - get { return showFinishFeature; } - set - { - if (value == showFinishFeature) return; - showFinishFeature = value; - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - if (gf.IsOnFeatureBranch) - { - SelectedFeature = AllFeatures.First(f => f.Name == gf.CurrentBranchLeafName); - } - - OnPropertyChanged(); - } - } - - public Visibility ShowFinishHotfix - { - get { return showFinishHotfix; } - set - { - if (value == showFinishHotfix) return; - showFinishHotfix = value; - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - if (gf.IsOnHotfixBranch) - { - SelectedHotfix = AllHotfixes.First(f => f.Name == gf.CurrentBranchLeafName); - } - OnPropertyChanged(); - } - } - - public Visibility ShowFinishRelease - { - get { return showFinishRelease; } - set - { - if (value == showFinishRelease) return; - showFinishRelease = value; - - var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); - if (gf.IsOnReleaseBranch) - { - SelectedRelease = AllReleases.First(f => f.Name == gf.CurrentBranchLeafName); - } - OnPropertyChanged(); - } - } - - #region Feature - - public bool FeatureRebaseOnDevelopmentBranch - { - get { return featureRebaseOnDevelopmentBranch; } - set - { - if (value.Equals(featureRebaseOnDevelopmentBranch)) return; - featureRebaseOnDevelopmentBranch = value; - OnPropertyChanged(); - } - } - - public bool FeatureDeleteLocalBranch - { - get { return featureDeleteLocalBranch; } - set - { - if (value.Equals(featureDeleteLocalBranch)) return; - featureDeleteLocalBranch = value; - OnPropertyChanged(); - } - } - public bool FeatureDeleteRemoteBranch - { - get { return featureDeleteRemoteBranch; } - set - { - if (value.Equals(featureDeleteRemoteBranch)) return; - featureDeleteRemoteBranch = value; - OnPropertyChanged(); - } - } - - public bool FeatureSquash - { - get { return featureSquash; } - set - { - if (value.Equals(featureSquash)) return; - featureSquash = value; - OnPropertyChanged(); - } - } - - public bool FeatureNoFastForward - { - get { return featureNoFastForward; } - set - { - if (value.Equals(featureNoFastForward)) return; - featureNoFastForward = value; - OnPropertyChanged(); - } - } - - #endregion - - #region Release - - public bool HotfixTagMessageSelected - { - get { return hotfixTagMessageSelected; } - set - { - if (value.Equals(hotfixTagMessageSelected)) return; - hotfixTagMessageSelected = value; - OnPropertyChanged(); - } - } - - public bool ReleaseTagMessageSelected - { - get { return releaseTagMessageSelected; } - set - { - if (value.Equals(releaseTagMessageSelected)) return; - releaseTagMessageSelected = value; - OnPropertyChanged(); - } - } - - public string ReleaseTagMessage - { - get { return releaseTagMessage; } - set - { - if (value == releaseTagMessage) return; - releaseTagMessage = value; - OnPropertyChanged(); - } - } - - public bool ReleaseDeleteBranch - { - get { return releaseDeleteBranch; } - set - { - if (value.Equals(releaseDeleteBranch)) return; - releaseDeleteBranch = value; - OnPropertyChanged(); - } - } - - public bool ReleasePushChanges - { - get { return releasePushChanges; } - set - { - if (value.Equals(releasePushChanges)) return; - releasePushChanges = value; - OnPropertyChanged(); - } - } - - - public bool ReleaseNoBackMerge - { - get { return releaseNoBackMerge; } - set - { - if (value.Equals(releaseNoBackMerge)) return; - releaseNoBackMerge = value; - OnPropertyChanged(); - } - } - - public bool ReleaseForceDeletion - { - get { return releaseForceDeletion; } - set - { - if (value.Equals(releaseForceDeletion)) return; - releaseForceDeletion = value; - OnPropertyChanged(); - } - } - - #endregion - - #region Hotfix - - public string HotfixTagMessage - { - get { return hotfixTagMessage; } - set - { - if (value == hotfixTagMessage) return; - hotfixTagMessage = value; - OnPropertyChanged(); - } - } - - public bool HotfixForceDeletion - { - get { return hotfixForceDeletion; } - set - { - if (value.Equals(hotfixForceDeletion)) return; - hotfixForceDeletion = value; - OnPropertyChanged(); - } - } - - public bool HotfixPushChanges - { - get { return hotfixPushChanges; } - set - { - if (value.Equals(hotfixPushChanges)) return; - hotfixPushChanges = value; - OnPropertyChanged(); - } - } - - public bool HotfixDeleteBranch - { - get { return hotfixDeleteBranch; } - set - { - if (value.Equals(hotfixDeleteBranch)) return; - hotfixDeleteBranch = value; - OnPropertyChanged(); - } - } - - #endregion - - #region Visibility - - //TODO: Refactor this code and introduce BooleanToVisibility converter... - public Visibility StartFeatureVisible - { - get { return OnMainBranch(); } - } - - public Visibility OtherStartFeatureVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - public Visibility OtherStartReleaseVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - public Visibility OtherStartHotfixVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - private static Visibility OnMainBranch() - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Visible : Visibility.Collapsed; - } - - public Visibility StartReleaseVisible - { - get - { - return OnMainBranch(); - } - } - - public Visibility StartHotfixVisible - { - get { return OnMainBranch(); } - } - - public Visibility FinishHotfixVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnHotfixBranch ? Visibility.Visible : Visibility.Collapsed; - } - } - - public Visibility FinishFeatureVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnFeatureBranch ? Visibility.Visible : Visibility.Collapsed; - } - } - - public Visibility FinishReleaseVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnReleaseBranch ? Visibility.Visible : Visibility.Collapsed; - } - } - - - public Visibility OtherFinishHotfixVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnHotfixBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - public Visibility OtherFinishFeatureVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnFeatureBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - public Visibility OtherFinishReleaseVisible - { - get - { - var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); - return gf.IsOnReleaseBranch ? Visibility.Collapsed : Visibility.Visible; - } - } - - #endregion - - public void Update() - { - UpdateMenus(); - } - } -} +using System; +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using GitFlow.VS; +using Microsoft.TeamFoundation.Controls.WPF.TeamExplorer; + +namespace GitFlowVS.Extension.ViewModels +{ + public class ActionViewModel : ViewModelBase + { + private Visibility showStartFeature; + private Visibility showStartRelease; + private Visibility showStartHotfix; + private Visibility showStartBugfix; + + private Visibility showFinishFeature; + private Visibility showFinishRelease; + private Visibility showFinishHotfix; + private Visibility showFinishBugfix; + + private string featureName; + private string releaseName; + private string hotfixName; + private string bugfixName; + + private bool featureRebaseOnDevelopmentBranch; + private bool featureDeleteLocalBranch; + private bool featureDeleteRemoteBranch; + private bool featureSquash; + private bool featureNoFastForward; + private bool bugfixRebaseOnDevelopmentBranch; + private bool bugfixDeleteLocalBranch; + private bool bugfixDeleteRemoteBranch; + private bool bugfixSquash; + private bool bugfixNoFastForward; + private bool releaseDeleteBranch; + private string releaseTagMessage; + private bool releaseForceDeletion; + private bool releasePushChanges; + private bool releaseNoBackMerge; + private bool hotfixDeleteBranch; + private bool hotfixPushChanges; + private bool hotfixForceDeletion; + private string hotfixTagMessage; + private ListItem selectedFeature; + private ListItem selectedBugfix; + private bool hotfixTagMessageSelected; + private bool releaseTagMessageSelected; + private ListItem selectedHotfix; + private ListItem selectedRelease; + + public ICommand StartFeatureDropDownCommand { get; private set; } + public ICommand StartFeatureCommand { get; private set; } + public ICommand CancelStartFeatureCommand { get; private set; } + + public ICommand StartReleaseDropDownCommand { get; private set; } + public ICommand StartReleaseCommand { get; private set; } + public ICommand CancelStartReleaseCommand { get; private set; } + + public ICommand StartHotfixDropDownCommand { get; private set; } + public ICommand StartHotfixCommand { get; private set; } + public ICommand CancelStartHotfixCommand { get; private set; } + + public ICommand StartBugfixDropDownCommand { get; private set; } + public ICommand StartBugfixCommand { get; private set; } + public ICommand CancelStartBugfixCommand { get; private set; } + + public ICommand FinishFeatureDropDownCommand { get; private set; } + public ICommand FinishFeatureCommand { get; private set; } + public ICommand CancelFinishFeatureCommand { get; private set; } + + public ICommand FinishReleaseDropDownCommand { get; private set; } + public ICommand FinishReleaseCommand { get; private set; } + public ICommand CancelFinishReleaseCommand { get; private set; } + + public ICommand FinishHotfixDropDownCommand { get; private set; } + public ICommand FinishHotfixCommand { get; private set; } + public ICommand CancelFinishHotfixCommand { get; private set; } + + public ICommand FinishBugfixDropDownCommand { get; private set; } + public ICommand FinishBugfixCommand { get; private set; } + public ICommand CancelFinishBugfixCommand { get; private set; } + + public ActionViewModel(GitFlowActionSection te) + : base(te) + { + FeatureDeleteLocalBranch = true; + FeatureDeleteRemoteBranch = true; + FeatureSquash = true; + FeatureNoFastForward = true; + ReleaseDeleteBranch = true; + ReleaseTagMessageSelected = true; + ReleaseNoBackMerge = false; + HotfixDeleteBranch = true; + HotfixTagMessageSelected = true; + BugfixDeleteLocalBranch = true; + BugfixDeleteRemoteBranch = true; + BugfixSquash = true; + BugfixNoFastForward = true; + + ShowStartFeature = Visibility.Collapsed; + ShowStartRelease = Visibility.Collapsed; + ShowStartHotfix = Visibility.Collapsed; + ShowStartBugfix = Visibility.Collapsed; + + ShowFinishFeature = Visibility.Collapsed; + ShowFinishRelease = Visibility.Collapsed; + ShowFinishHotfix = Visibility.Collapsed; + ShowFinishBugfix = Visibility.Collapsed; + + HideProgressBar(); + + StartFeatureDropDownCommand = new DropDownLinkCommand(p => StartFeatureDropDown(), p => CanShowStartFeatureDropDown()); + StartFeatureCommand = new RelayCommand(p => StartFeature(), p => CanCreateFeature); + CancelStartFeatureCommand = new RelayCommand(p => CancelStartFeature(), p => CanCancelFinishCommand()); + + StartReleaseDropDownCommand = new DropDownLinkCommand(p => StartReleaseDropDown(), p => CanShowStartReleaseDropDown()); + StartReleaseCommand = new RelayCommand(p => StartRelease(), p => CanCreateRelease); + CancelStartReleaseCommand = new RelayCommand(p => CancelStartRelease(), p => CanCancelFinishCommand()); + + StartHotfixDropDownCommand = new DropDownLinkCommand(p => StartHotfixDropDown(), p => CanShowStartHotfixDropDown()); + StartHotfixCommand = new RelayCommand(p => StartHotfix(), p => CanCreateHotfix); + CancelStartHotfixCommand = new RelayCommand(p => CancelStartHotfix(), p => CanCancelFinishCommand()); + + StartBugfixDropDownCommand = new DropDownLinkCommand(p => StartBugfixDropDown(), p => CanShowStartBugfixDropDown()); + StartBugfixCommand = new RelayCommand(p => StartBugfix(), p => CanCreateBugfix); + CancelStartBugfixCommand = new RelayCommand(p => CancelStartBugfix(), p => CanCancelFinishCommand()); + + FinishFeatureDropDownCommand = new DropDownLinkCommand(p => FinishFeatureDropDown(), p => CanShowFinishFeatureDropDown()); + FinishFeatureCommand = new RelayCommand(p => FinishFeature(), p => CanFinishFeature); + CancelFinishFeatureCommand = new RelayCommand(p => CancelFinishFeature(), p => CanCancelFinishCommand()); + + FinishReleaseDropDownCommand = new DropDownLinkCommand(p => FinishReleaseDropDown(), p => CanShowFinishReleaseDropDown()); + FinishReleaseCommand = new RelayCommand(p => FinishRelease(), p => CanFinishRelease); + CancelFinishReleaseCommand = new RelayCommand(p => CancelFinishRelease(), p => CanCancelFinishCommand()); + + FinishHotfixDropDownCommand = new DropDownLinkCommand(p => FinishHotfixDropDown(), p => CanShowFinishHotfixDropDown()); + FinishHotfixCommand = new RelayCommand(p => FinishHotfix(), p => CanFinishHotfix); + CancelFinishHotfixCommand = new RelayCommand(p => CancelFinishHotfix(), p => CanCancelFinishCommand()); + + FinishBugfixDropDownCommand = new DropDownLinkCommand(p => FinishBugfixDropDown(), p => CanShowFinishBugfixDropDown()); + FinishBugfixCommand = new RelayCommand(p => FinishBugfix(), p => CanFinishBugfix); + CancelFinishBugfixCommand = new RelayCommand(p => CancelFinishBugfix(), p => CanCancelFinishCommand()); + } + + public bool CanFinishRelease + { + get { return SelectedRelease != null && CanCancelFinishCommand(); } + } + + public bool CanFinishHotfix + { + get { return SelectedHotfix != null && CanCancelFinishCommand(); } + } + + public bool CanFinishFeature + { + get { return SelectedFeature != null && CanCancelFinishCommand(); } + } + + public bool CanFinishBugfix + { + get { return SelectedBugfix != null && CanCancelFinishCommand(); } + } + + private void CancelStartFeature() + { + ShowStartFeature = Visibility.Collapsed; + } + + private void CancelStartHotfix() + { + ShowStartHotfix = Visibility.Collapsed; + } + + private void CancelStartRelease() + { + ShowStartRelease = Visibility.Collapsed; + } + + private void CancelStartBugfix() + { + ShowStartBugfix = Visibility.Collapsed; + } + + private void CancelFinishFeature() + { + ShowFinishFeature = Visibility.Collapsed; + } + + private void CancelFinishHotfix() + { + ShowFinishHotfix = Visibility.Collapsed; + } + + private void CancelFinishRelease() + { + ShowFinishRelease = Visibility.Collapsed; + } + + private void CancelFinishBugfix() + { + ShowFinishBugfix = Visibility.Collapsed; + } + + private bool CanShowStartFeatureDropDown() + { + return true; + } + + private bool CanShowStartBugfixDropDown() + { + return true; + } + + private bool CanCancelFinishCommand() + { + return ProgressVisibility != Visibility.Visible; + } + + private bool CanShowStartHotfixDropDown() + { + return true; + } + private bool CanShowStartReleaseDropDown() + { + return true; + } + + private bool CanShowFinishFeatureDropDown() + { + return true; + } + private bool CanShowFinishHotfixDropDown() + { + return true; + } + private bool CanShowFinishReleaseDropDown() + { + return true; + } + private bool CanShowFinishBugfixDropDown() + { + return true; + } + + private void StartFeatureDropDown() + { + HideAll(); + ShowStartFeature = Visibility.Visible; + } + + private void StartBugfixDropDown() + { + HideAll(); + ShowStartBugfix = Visibility.Visible; + } + + private void HideAll() + { + ShowStartFeature = Visibility.Collapsed; + ShowStartRelease = Visibility.Collapsed; + ShowStartHotfix = Visibility.Collapsed; + ShowStartBugfix = Visibility.Collapsed; + ShowFinishFeature = Visibility.Collapsed; + ShowFinishRelease = Visibility.Collapsed; + ShowFinishHotfix = Visibility.Collapsed; + ShowFinishBugfix = Visibility.Collapsed; + } + + private void UpdateMenus() + { + OnPropertyChanged("StartFeatureVisible"); + OnPropertyChanged("StartReleaseVisible"); + OnPropertyChanged("StartHotfixVisible"); + OnPropertyChanged("StartBugfixVisible"); + OnPropertyChanged("FinishFeatureVisible"); + OnPropertyChanged("FinishReleaseVisible"); + OnPropertyChanged("FinishHotfixVisible"); + OnPropertyChanged("FinishBugfixVisible"); + + OnPropertyChanged("OtherStartFeatureVisible"); + OnPropertyChanged("OtherStartReleaseVisible"); + OnPropertyChanged("OtherStartHotfixVisible"); + OnPropertyChanged("OtherStartBugfixVisible"); + OnPropertyChanged("OtherFinishFeatureVisible"); + OnPropertyChanged("OtherFinishReleaseVisible"); + OnPropertyChanged("OtherFinishHotfixVisible"); + OnPropertyChanged("OtherFinishBugfixVisible"); + } + + private void StartHotfixDropDown() + { + HideAll(); + ShowStartHotfix = Visibility.Visible; + + } + private void StartReleaseDropDown() + { + HideAll(); + ShowStartRelease = Visibility.Visible; + } + + private void FinishFeatureDropDown() + { + HideAll(); + ShowFinishFeature = Visibility.Visible; + } + + private void FinishHotfixDropDown() + { + HideAll(); + ShowFinishHotfix = Visibility.Visible; + } + + private void FinishReleaseDropDown() + { + HideAll(); + ShowFinishRelease = Visibility.Visible; + } + + private void FinishBugfixDropDown() + { + HideAll(); + ShowFinishBugfix = Visibility.Visible; + } + + public bool CanCreateFeature + { + get { return !String.IsNullOrEmpty(FeatureName) && CanCancelFinishCommand(); } + } + + public bool CanCreateRelease + { + get + { + return !String.IsNullOrEmpty(ReleaseName) && CanCancelFinishCommand(); + } + } + + public bool CanCreateHotfix + { + get { return !String.IsNullOrEmpty(HotfixName) && CanCancelFinishCommand(); } + } + + public bool CanCreateBugfix + { + get { return !String.IsNullOrEmpty(BugfixName) && CanCancelFinishCommand(); } + } + + public List AllFeatures + { + get + { + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + return gf.AllFeatures.Select(x => new ListItem {Name = x}).ToList(); + } + } + + public ListItem SelectedFeature + { + get { return selectedFeature; } + set + { + if (Equals(value, selectedFeature)) return; + selectedFeature = value; + OnPropertyChanged(); + } + } + + public List AllReleases + { + get + { + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + return gf.AllReleases.Select(x => new ListItem { Name = x }).ToList(); + } + } + + public ListItem SelectedRelease + { + get { return selectedRelease; } + set + { + if (Equals(value, selectedRelease)) return; + selectedRelease = value; + OnPropertyChanged(); + } + } + + public List AllHotfixes + { + get + { + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + return gf.AllHotfixes.Select(x => new ListItem { Name = x }).ToList(); + } + } + + public ListItem SelectedHotfix + { + get { return selectedHotfix; } + set + { + if (Equals(value, selectedHotfix)) return; + selectedHotfix = value; + OnPropertyChanged(); + } + } + + public List AllBugfixes + { + get + { + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + return gf.AllBugfixes.Select(x => new ListItem { Name = x }).ToList(); + } + } + + public ListItem SelectedBugfix + { + get { return selectedBugfix; } + set + { + if (Equals(value, selectedBugfix)) return; + selectedBugfix = value; + OnPropertyChanged(); + } + } + + private void StartFeature() + { + try + { + if (String.IsNullOrEmpty(FeatureName)) + return; + + Logger.Event("StartFeature"); + DateTime start = DateTime.Now; + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.StartFeature(FeatureName); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideProgressBar(); + FeatureName = String.Empty; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllFeatures"); + } + Logger.Metric("Duration-StartFeature", (DateTime.Now-start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + private void StartRelease() + { + try + { + if (String.IsNullOrEmpty(ReleaseName)) + return; + + Logger.Event("StartRelease"); + DateTime start = DateTime.Now; + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.StartRelease(ReleaseName); + if (!result.Success) + { + ShowErrorMessage(result); + } + HideProgressBar(); + ShowStartRelease = Visibility.Collapsed; + ReleaseName = String.Empty; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllReleases"); + } + Logger.Metric("Duration-StartRelease", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + } + + private void StartBugfix() + { + try + { + if (String.IsNullOrEmpty(BugfixName)) + return; + + Logger.Event("StartBugfix"); + DateTime start = DateTime.Now; + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.StartBugfix(BugfixName); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideProgressBar(); + BugfixName = String.Empty; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllBugfixes"); + } + Logger.Metric("Duration-StartBugfix", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + private void ShowErrorMessage(GitFlowCommandResult result) + { + Te.ShowErrorNotification(result.CommandOutput); + } + private void ShowErrorMessage(string message) + { + Te.ShowErrorNotification(message); + } + + private void StartHotfix() + { + try + { + if (String.IsNullOrEmpty(HotfixName)) + return; + + Logger.Event("StartHotfix"); + DateTime start = DateTime.Now; + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.StartHotfix(HotfixName); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideProgressBar(); + ShowStartHotfix = Visibility.Collapsed; + HotfixName = String.Empty; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllHotfixes"); + } + Logger.Metric("Duration-StartHotfix", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + private void FinishFeature() + { + try + { + DateTime start = DateTime.Now; + + var properties = new Dictionary + { + {"RebaseOnDevelopmentBranch", FeatureRebaseOnDevelopmentBranch.ToString()}, + {"DeleteLocalBranch", FeatureDeleteLocalBranch.ToString()}, + {"DeleteRemoteBranch", FeatureDeleteRemoteBranch.ToString()}, + {"Squash", FeatureSquash.ToString()}, + {"NoFastForward", FeatureNoFastForward.ToString()} + }; + Logger.Event("FinishFeature", properties); + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + + ShowProgressBar(); + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.FinishFeature(SelectedFeature.Name, FeatureRebaseOnDevelopmentBranch, FeatureDeleteLocalBranch, FeatureDeleteRemoteBranch, FeatureSquash, FeatureNoFastForward); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideProgressBar(); + ShowFinishFeature = Visibility.Collapsed; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllFeatures"); + Te.Refresh(); + } + + Logger.Metric("Duration-FinishFeature", (DateTime.Now - start).Milliseconds); + } + catch( Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + } + + private void FinishBugfix() + { + try + { + DateTime start = DateTime.Now; + + var properties = new Dictionary + { + {"RebaseOnDevelopmentBranch", BugfixRebaseOnDevelopmentBranch.ToString()}, + {"DeleteLocalBranch", BugfixDeleteLocalBranch.ToString()}, + {"DeleteRemoteBranch", BugfixDeleteRemoteBranch.ToString()}, + {"Squash", BugfixSquash.ToString()}, + {"NoFastForward", BugfixNoFastForward.ToString()} + }; + Logger.Event("FinishBugfix", properties); + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + + ShowProgressBar(); + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.FinishBugfix(SelectedBugfix.Name, BugfixRebaseOnDevelopmentBranch, BugfixDeleteLocalBranch, BugfixDeleteRemoteBranch, BugfixSquash, BugfixNoFastForward); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideProgressBar(); + ShowFinishBugfix = Visibility.Collapsed; + UpdateMenus(); + HideAll(); + OnPropertyChanged("AllBugfixes"); + Te.Refresh(); + } + + Logger.Metric("Duration-FinishBugfix", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + } + + private void FinishRelease() + { + try + { + DateTime start = DateTime.Now; + var properties = new Dictionary + { + {"TaggedRelease", (!String.IsNullOrEmpty(ReleaseTagMessage)).ToString()}, + {"DeleteBranch", ReleaseDeleteBranch.ToString()}, + {"ForceDeletion", ReleaseForceDeletion.ToString()}, + {"PushChanges", ReleasePushChanges.ToString()}, + {"NoBackMerge", ReleaseNoBackMerge.ToString()} + }; + Logger.Event("FinishRelease", properties); + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.FinishRelease(SelectedRelease.Name, ReleaseTagMessage, ReleaseDeleteBranch, ReleaseForceDeletion, ReleasePushChanges, ReleaseNoBackMerge); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideAll(); + HideProgressBar(); + ShowFinishRelease = Visibility.Collapsed; + OnPropertyChanged("AllReleases"); + UpdateMenus(); + } + Logger.Metric("Duration-FinishRelease", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + } + + private void FinishHotfix() + { + try + { + DateTime start = DateTime.Now; + var properties = new Dictionary + { + {"TaggedRelease", (!String.IsNullOrEmpty(HotfixTagMessage)).ToString()}, + {"DeleteBranch", HotfixDeleteBranch.ToString()}, + {"ForceDeletion", HotfixForceDeletion.ToString()}, + {"PushChanges", HotfixPushChanges.ToString()} + }; + Logger.Event("FinishHotfix", properties); + + if (GitFlowPage.ActiveRepo != null) + { + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.FinishHotfix(SelectedHotfix.Name, HotfixTagMessage, HotfixDeleteBranch, HotfixForceDeletion, HotfixPushChanges); + if (!result.Success) + { + ShowErrorMessage(result); + } + + HideAll(); + HideProgressBar(); + ShowFinishHotfix = Visibility.Collapsed; + OnPropertyChanged("AllHotfixes"); + UpdateMenus(); + } + Logger.Metric("Duration-FinishHotfix", (DateTime.Now - start).Milliseconds); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + public string ReleaseName + { + get { return releaseName; } + set + { + if (value == releaseName) return; + releaseName = value; + OnPropertyChanged(); + OnPropertyChanged("CanCreateRelease"); + } + } + + public string HotfixName + { + get { return hotfixName; } + set + { + if (value == hotfixName) return; + hotfixName = value; + OnPropertyChanged(); + OnPropertyChanged("CanCreateHotfix"); + } + } + + public string FeatureName + { + get { return featureName; } + set + { + if (value == featureName) return; + featureName = value; + OnPropertyChanged(); + OnPropertyChanged("CanCreateFeature"); + } + } + + public string BugfixName + { + get { return bugfixName; } + set + { + if (value == bugfixName) return; + bugfixName = value; + OnPropertyChanged(); + OnPropertyChanged("CanCreateBugfix"); + } + } + + public Visibility ShowStartFeature + { + get { return showStartFeature; } + set + { + if (value == showStartFeature) return; + showStartFeature = value; + OnPropertyChanged(); + } + } + + public Visibility ShowStartBugfix + { + get { return showStartBugfix; } + set + { + if (value == showStartBugfix) return; + showStartBugfix = value; + OnPropertyChanged(); + } + } + + public Visibility ShowStartHotfix + { + get { return showStartHotfix; } + set + { + if (value == showStartHotfix) return; + showStartHotfix = value; + OnPropertyChanged(); + } + } + + public Visibility ShowStartRelease + { + get { return showStartRelease; } + set + { + if (value == showStartRelease) return; + showStartRelease = value; + OnPropertyChanged(); + } + } + + public Visibility ShowFinishFeature + { + get { return showFinishFeature; } + set + { + if (value == showFinishFeature) return; + showFinishFeature = value; + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + if (gf.IsOnFeatureBranch) + { + SelectedFeature = AllFeatures.First(f => f.Name == gf.CurrentBranchLeafName); + } + + OnPropertyChanged(); + } + } + + public Visibility ShowFinishBugfix + { + get { return showFinishBugfix; } + set + { + if (value == showFinishBugfix) return; + showFinishBugfix = value; + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + if (gf.IsOnBugfixBranch) + { + SelectedBugfix = AllBugfixes.First(f => f.Name == gf.CurrentBranchLeafName); + } + + OnPropertyChanged(); + } + } + + public Visibility ShowFinishHotfix + { + get { return showFinishHotfix; } + set + { + if (value == showFinishHotfix) return; + showFinishHotfix = value; + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + if (gf.IsOnHotfixBranch) + { + SelectedHotfix = AllHotfixes.First(f => f.Name == gf.CurrentBranchLeafName); + } + OnPropertyChanged(); + } + } + + public Visibility ShowFinishRelease + { + get { return showFinishRelease; } + set + { + if (value == showFinishRelease) return; + showFinishRelease = value; + + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + if (gf.IsOnReleaseBranch) + { + SelectedRelease = AllReleases.First(f => f.Name == gf.CurrentBranchLeafName); + } + OnPropertyChanged(); + } + } + + #region Feature + + public bool FeatureRebaseOnDevelopmentBranch + { + get { return featureRebaseOnDevelopmentBranch; } + set + { + if (value.Equals(featureRebaseOnDevelopmentBranch)) return; + featureRebaseOnDevelopmentBranch = value; + OnPropertyChanged(); + } + } + + public bool FeatureDeleteLocalBranch + { + get { return featureDeleteLocalBranch; } + set + { + if (value.Equals(featureDeleteLocalBranch)) return; + featureDeleteLocalBranch = value; + OnPropertyChanged(); + } + } + public bool FeatureDeleteRemoteBranch + { + get { return featureDeleteRemoteBranch; } + set + { + if (value.Equals(featureDeleteRemoteBranch)) return; + featureDeleteRemoteBranch = value; + OnPropertyChanged(); + } + } + + public bool FeatureSquash + { + get { return featureSquash; } + set + { + if (value.Equals(featureSquash)) return; + featureSquash = value; + OnPropertyChanged(); + } + } + + public bool FeatureNoFastForward + { + get { return featureNoFastForward; } + set + { + if (value.Equals(featureNoFastForward)) return; + featureNoFastForward = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Release + + public bool HotfixTagMessageSelected + { + get { return hotfixTagMessageSelected; } + set + { + if (value.Equals(hotfixTagMessageSelected)) return; + hotfixTagMessageSelected = value; + OnPropertyChanged(); + } + } + + public bool ReleaseTagMessageSelected + { + get { return releaseTagMessageSelected; } + set + { + if (value.Equals(releaseTagMessageSelected)) return; + releaseTagMessageSelected = value; + OnPropertyChanged(); + } + } + + public string ReleaseTagMessage + { + get { return releaseTagMessage; } + set + { + if (value == releaseTagMessage) return; + releaseTagMessage = value; + OnPropertyChanged(); + } + } + + public bool ReleaseDeleteBranch + { + get { return releaseDeleteBranch; } + set + { + if (value.Equals(releaseDeleteBranch)) return; + releaseDeleteBranch = value; + OnPropertyChanged(); + } + } + + public bool ReleasePushChanges + { + get { return releasePushChanges; } + set + { + if (value.Equals(releasePushChanges)) return; + releasePushChanges = value; + OnPropertyChanged(); + } + } + + + public bool ReleaseNoBackMerge + { + get { return releaseNoBackMerge; } + set + { + if (value.Equals(releaseNoBackMerge)) return; + releaseNoBackMerge = value; + OnPropertyChanged(); + } + } + + public bool ReleaseForceDeletion + { + get { return releaseForceDeletion; } + set + { + if (value.Equals(releaseForceDeletion)) return; + releaseForceDeletion = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Hotfix + + public string HotfixTagMessage + { + get { return hotfixTagMessage; } + set + { + if (value == hotfixTagMessage) return; + hotfixTagMessage = value; + OnPropertyChanged(); + } + } + + public bool HotfixForceDeletion + { + get { return hotfixForceDeletion; } + set + { + if (value.Equals(hotfixForceDeletion)) return; + hotfixForceDeletion = value; + OnPropertyChanged(); + } + } + + public bool HotfixPushChanges + { + get { return hotfixPushChanges; } + set + { + if (value.Equals(hotfixPushChanges)) return; + hotfixPushChanges = value; + OnPropertyChanged(); + } + } + + public bool HotfixDeleteBranch + { + get { return hotfixDeleteBranch; } + set + { + if (value.Equals(hotfixDeleteBranch)) return; + hotfixDeleteBranch = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Bugfix + + public bool BugfixRebaseOnDevelopmentBranch + { + get { return bugfixRebaseOnDevelopmentBranch; } + set + { + if (value.Equals(bugfixRebaseOnDevelopmentBranch)) return; + bugfixRebaseOnDevelopmentBranch = value; + OnPropertyChanged(); + } + } + + public bool BugfixDeleteLocalBranch + { + get { return bugfixDeleteLocalBranch; } + set + { + if (value.Equals(bugfixDeleteLocalBranch)) return; + bugfixDeleteLocalBranch = value; + OnPropertyChanged(); + } + } + public bool BugfixDeleteRemoteBranch + { + get { return bugfixDeleteRemoteBranch; } + set + { + if (value.Equals(bugfixDeleteRemoteBranch)) return; + bugfixDeleteRemoteBranch = value; + OnPropertyChanged(); + } + } + + public bool BugfixSquash + { + get { return bugfixSquash; } + set + { + if (value.Equals(bugfixSquash)) return; + BugfixSquash = value; + OnPropertyChanged(); + } + } + + public bool bugfixNoFastForward + { + get { return bugfixNoFastForward; } + set + { + if (value.Equals(bugfixNoFastForward)) return; + bugfixNoFastForward = value; + OnPropertyChanged(); + } + } + + #endregion + + #region Visibility + + //TODO: Refactor this code and introduce BooleanToVisibility converter... + public Visibility StartFeatureVisible + { + get { return OnMainBranch(); } + } + + public Visibility OtherStartFeatureVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility StartBugfixVisible + { + get { return OnMainBranch(); } + } + + public Visibility OtherStartBugfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility OtherStartReleaseVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility OtherStartHotfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + private static Visibility OnMainBranch() + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnDevelopBranch || gf.IsOnMasterBranch ? Visibility.Visible : Visibility.Collapsed; + } + + public Visibility StartReleaseVisible + { + get + { + return OnMainBranch(); + } + } + + public Visibility StartHotfixVisible + { + get { return OnMainBranch(); } + } + + public Visibility FinishHotfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnHotfixBranch ? Visibility.Visible : Visibility.Collapsed; + } + } + + public Visibility FinishFeatureVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnFeatureBranch ? Visibility.Visible : Visibility.Collapsed; + } + } + + public Visibility FinishBugfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnBugfixBranch ? Visibility.Visible : Visibility.Collapsed; + } + } + + public Visibility FinishReleaseVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnReleaseBranch ? Visibility.Visible : Visibility.Collapsed; + } + } + + + public Visibility OtherFinishHotfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnHotfixBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility OtherFinishFeatureVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnFeatureBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility OtherFinishBugfixVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnBugfixBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + public Visibility OtherFinishReleaseVisible + { + get + { + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + return gf.IsOnReleaseBranch ? Visibility.Collapsed : Visibility.Visible; + } + } + + #endregion + + public void Update() + { + UpdateMenus(); + } + } +} diff --git a/GitFlow.VS.Extension/ViewModels/BugfixesViewModel.cs b/GitFlow.VS.Extension/ViewModels/BugfixesViewModel.cs new file mode 100644 index 0000000..7f478d4 --- /dev/null +++ b/GitFlow.VS.Extension/ViewModels/BugfixesViewModel.cs @@ -0,0 +1,154 @@ +using System.Collections.Generic; +using System.Linq; +using System.Windows; +using System.Windows.Input; +using GitFlow.VS; +using System; + +namespace GitFlowVS.Extension.ViewModels +{ + public class BugfixesViewModel : ViewModelBase + { + public ICommand PublishBugfixBranchCommand { get; private set; } + public ICommand TrackBugfixBranchCommand { get; private set; } + public ICommand CheckoutBugfixBranchCommand { get; private set; } + + public BugfixesViewModel(IGitFlowSection te) + : base(te) + { + PublishBugfixBranchCommand = new RelayCommand(p => PublishBugfixBranch(), p => CanPublishBugfixBranch); + TrackBugfixBranchCommand = new RelayCommand(p => TrackBugfixBranch(), p => CanTrackBugfixBranch); + CheckoutBugfixBranchCommand = new RelayCommand(p => CheckoutBugfixBranch(), p => CanCheckoutBugfixBranch); + + HideProgressBar(); + } + + public bool CanPublishBugfixBranch + { + get + { + return SelectedBugfix != null && !SelectedBugfix.IsRemote && !SelectedBugfix.IsTracking; + } + } + + public bool CanTrackBugfixBranch + { + get + { + return SelectedBugfix != null && SelectedBugfix.IsRemote && !SelectedBugfix.IsTracking; + } + } + + public bool CanCheckoutBugfixBranch + { + get + { + return SelectedBugfix != null && !SelectedBugfix.IsCurrentBranch && !SelectedBugfix.IsRemote; + } + } + + public void PublishBugfixBranch() + { + try + { + Logger.Event("PublishBugfixBranch"); + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.PublishBugfix(SelectedBugfix.Name); + if (!result.Success) + { + Te.ShowErrorNotification(result.CommandOutput); + } + + HideProgressBar(); + Update(); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + public void TrackBugfixBranch() + { + try + { + Logger.Event("TrackBugfixBranch"); + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.TrackBugfix(SelectedBugfix.Name); + if (!result.Success) + { + Te.ShowErrorNotification(result.CommandOutput); + } + + HideProgressBar(); + Update(); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + + } + + public void CheckoutBugfixBranch() + { + try + { + Logger.Event("CheckoutBugfixBranch"); + GitFlowPage.ActiveOutputWindow(); + ShowProgressBar(); + var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); + var result = gf.CheckoutBugfix(SelectedBugfix.Name); + if (!result.Success) + { + Te.ShowErrorNotification(result.CommandOutput); + } + + HideProgressBar(); + Update(); + } + catch (Exception ex) + { + ShowErrorMessage(ex.ToString()); + Logger.Exception(ex); + } + } + + + public List AllBugfixes + { + get + { + var gf = new GitFlowWrapper(GitFlowPage.ActiveRepoPath); + var list = gf.AllBugfixBranches.ToList(); + return list; + } + } + + public BranchItem SelectedBugfix { get; set; } + + public void Update() + { + OnPropertyChanged("AllBugfixes"); + OnPropertyChanged("NoItemsMessageVisibility"); + } + + public Visibility NoItemsMessageVisibility + { + get { return AllBugfixes.Any() ? Visibility.Collapsed : Visibility.Visible; } + + } + + private void ShowErrorMessage(string message) + { + Te.ShowErrorNotification(message); + } + } +} \ No newline at end of file diff --git a/GitFlow.VS.Extension/ViewModels/FeaturesViewModel.cs b/GitFlow.VS.Extension/ViewModels/FeaturesViewModel.cs index 58e85a8..92d4f13 100644 --- a/GitFlow.VS.Extension/ViewModels/FeaturesViewModel.cs +++ b/GitFlow.VS.Extension/ViewModels/FeaturesViewModel.cs @@ -52,8 +52,8 @@ public void PublishFeatureBranch() { try { - Logger.Event("PublishFeatureBranch"); - GitFlowPage.ActiveOutputWindow(); + Logger.Event("PublishFeatureBranch"); + GitFlowPage.ActiveOutputWindow(); ShowProgressBar(); var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); var result = gf.PublishFeature(SelectedFeature.Name); @@ -77,8 +77,8 @@ public void TrackFeatureBranch() { try { - Logger.Event("TrackFeatureBranch"); - GitFlowPage.ActiveOutputWindow(); + Logger.Event("TrackFeatureBranch"); + GitFlowPage.ActiveOutputWindow(); ShowProgressBar(); var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); var result = gf.TrackFeature(SelectedFeature.Name); @@ -102,8 +102,8 @@ public void CheckoutFeatureBranch() { try { - Logger.Event("CheckoutFeatureBranch"); - GitFlowPage.ActiveOutputWindow(); + Logger.Event("CheckoutFeatureBranch"); + GitFlowPage.ActiveOutputWindow(); ShowProgressBar(); var gf = new VsGitFlowWrapper(GitFlowPage.ActiveRepoPath, GitFlowPage.OutputWindow); var result = gf.CheckoutFeature(SelectedFeature.Name); diff --git a/GitFlow.VS.Extension/ViewModels/InitModel.cs b/GitFlow.VS.Extension/ViewModels/InitModel.cs index 17ba35e..ef37ca5 100644 --- a/GitFlow.VS.Extension/ViewModels/InitModel.cs +++ b/GitFlow.VS.Extension/ViewModels/InitModel.cs @@ -12,6 +12,7 @@ public class InitModel : ViewModelBase private string featurePrefix; private string releasePrefix; private string hotfixPrefix; + private string bugfixPrefix; private string versionTagPrefix; private Visibility initGridVisibility; @@ -36,6 +37,7 @@ private void InitializeModel() FeaturePrefix = "feature/"; ReleasePrefix = "release/"; HotfixPrefix = "hotfix/"; + bugfixPrefix = "bugfix/"; VersionTagPrefix = ""; InitGridVisibility = Visibility.Hidden; @@ -83,6 +85,7 @@ private void OnInitialize() FeatureBranch = FeaturePrefix, ReleaseBranch = ReleasePrefix, HotfixBranch = HotfixPrefix, + BugfixBranch = BugfixPrefix, VersionTag = VersionTagPrefix }); if (!result.Success) @@ -101,7 +104,7 @@ private void OnInitialize() Te.ShowErrorNotification(e.ToString()); Logger.Exception(e); } - } + } public string Master { @@ -136,6 +139,17 @@ public string FeaturePrefix } } + public string BugfixPrefix + { + get { return bugfixPrefix; } + set + { + if (value == bugfixPrefix) return; + bugfixPrefix = value; + OnPropertyChanged(); + } + } + public string ReleasePrefix { get { return releasePrefix; } diff --git a/GitFlow.VS.Tests/GitFlowWrapperTests.cs b/GitFlow.VS.Tests/GitFlowWrapperTests.cs index cd9852c..3277f41 100644 --- a/GitFlow.VS.Tests/GitFlowWrapperTests.cs +++ b/GitFlow.VS.Tests/GitFlowWrapperTests.cs @@ -138,25 +138,25 @@ public void FinishFeatureShouldRemoveIt() Assert.AreEqual(1, gf.AllFeatures.Count()); } - [TestMethod] - public void FinishFeatureKeepLocalBranch() - { - var gf = new GitFlowWrapper(sampleRepoPath); - gf.Init(new GitFlowRepoSettings()); - gf.StartFeature("X"); + [TestMethod] + public void FinishFeatureKeepLocalBranch() + { + var gf = new GitFlowWrapper(sampleRepoPath); + gf.Init(new GitFlowRepoSettings()); + gf.StartFeature("X"); - Assert.AreEqual(1, gf.AllFeatures.Count()); + Assert.AreEqual(1, gf.AllFeatures.Count()); - gf.FinishFeature("X", deleteLocalBranch: false); + gf.FinishFeature("X", deleteLocalBranch: false); - using (var repo = new Repository(sampleRepoPath)) - { - Assert.IsTrue(repo.Branches.Any(b => !b.IsRemote && b.Name == "feature/X")); - } - } + using (var repo = new Repository(sampleRepoPath)) + { + Assert.IsTrue(repo.Branches.Any(b => !b.IsRemote && b.Name == "feature/X")); + } + } - [TestMethod] + [TestMethod] public void GetAllFeatures() { var gf = new GitFlowWrapper(sampleRepoPath); @@ -287,7 +287,7 @@ public void FinishRelease() } } - [TestMethod] + [TestMethod] public void StartHotfix() { var gf = new GitFlowWrapper(sampleRepoPath); diff --git a/GitFlow.VS/GitFlowRepoSettings.cs b/GitFlow.VS/GitFlowRepoSettings.cs index 589b6b8..1da314d 100644 --- a/GitFlow.VS/GitFlowRepoSettings.cs +++ b/GitFlow.VS/GitFlowRepoSettings.cs @@ -8,6 +8,7 @@ public class GitFlowRepoSettings public string ReleaseBranch { get; set; } public string HotfixBranch { get; set; } public string SupportBranch { get; set; } + public string BugfixBranch { get; set; } public string VersionTag { get; set; } public GitFlowRepoSettings() @@ -18,6 +19,7 @@ public GitFlowRepoSettings() ReleaseBranch = "release/"; HotfixBranch = "hotfix/"; SupportBranch = "support/"; + BugfixBranch = "bugfix/"; VersionTag = ""; } } diff --git a/GitFlow.VS/GitFlowWrapper.cs b/GitFlow.VS/GitFlowWrapper.cs index 5539b6e..ea29d90 100644 --- a/GitFlow.VS/GitFlowWrapper.cs +++ b/GitFlow.VS/GitFlowWrapper.cs @@ -5,7 +5,6 @@ using System.Linq; using System.Text; using System.Text.RegularExpressions; -using System.Windows.Forms; using LibGit2Sharp; namespace GitFlow.VS @@ -57,6 +56,23 @@ public bool IsOnHotfixBranch } } + public bool IsOnBugfixBranch + { + get + { + if (!IsInitialized) + return false; + + using (var repo = new Repository(repoDirectory)) + { + var bugfixPrefix = repo.Config.Get("gitflow.prefix.bugfix"); + if (bugfixPrefix == null) + return false; + return repo.Head.Name.StartsWith(bugfixPrefix.Value); + } + } + } + public bool IsOnMasterBranch { get @@ -80,8 +96,8 @@ public bool IsInitialized { using (var repo = new Repository(repoDirectory)) { - return repo.Config.Any(c => c.Key.StartsWith("gitflow.branch.master")) && - repo.Config.Any(c => c.Key.StartsWith("gitflow.branch.develop")); + return repo.Config.Any(c => c.Key.StartsWith("gitflow.branch.master")) && + repo.Config.Any(c => c.Key.StartsWith("gitflow.branch.develop")); } } } @@ -99,6 +115,8 @@ public string CurrentStatus status = "Hotfix: " + CurrentBranchLeafName; else if (IsOnReleaseBranch) status = "Release: " + CurrentBranchLeafName; + else if (IsOnBugfixBranch) + status = "Bugfix: " + CurrentBranchLeafName; return status; } @@ -112,6 +130,51 @@ public IEnumerable AllFeatures } } + public IEnumerable AllBugfixBranches + { + get + { + if (!IsInitialized) + return new List(); + + using (var repo = new Repository(repoDirectory)) + { + var prefix = repo.Config.Get("gitflow.prefix.bugfix").Value; + var bugfixBranches = + repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix)) + .Select(c => new BranchItem + { + Author = c.Tip.Author.Name, + Name = c.Name.Replace(prefix, ""), + LastCommit = c.Tip.Author.When, + IsTracking = c.IsTracking, + IsCurrentBranch = c.IsCurrentRepositoryHead, + IsRemote = c.IsRemote, + CommitId = c.Tip.Id.ToString(), + Message = c.Tip.MessageShort + }).ToList(); + + var remoteBugfixBranches = + repo.Branches.Where(b => b.IsRemote && b.Name.Contains(prefix) + && !repo.Branches.Any(br => !br.IsRemote && br.IsTracking && br.TrackedBranch.CanonicalName == b.CanonicalName)) + .Select(c => new BranchItem + { + Author = c.Tip.Author.Name, + Name = c.Name, + LastCommit = c.Tip.Author.When, + IsTracking = c.IsTracking, + IsCurrentBranch = c.IsCurrentRepositoryHead, + IsRemote = c.IsRemote, + CommitId = c.Tip.Id.ToString(), + Message = c.Tip.MessageShort + }).ToList(); + + bugfixBranches.AddRange(remoteBugfixBranches); + return bugfixBranches; + } + } + } + public IEnumerable AllFeatureBranches { get @@ -122,12 +185,12 @@ public IEnumerable AllFeatureBranches using (var repo = new Repository(repoDirectory)) { var prefix = repo.Config.Get("gitflow.prefix.feature").Value; - var featureBranches = - repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix) ) + var featureBranches = + repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix)) .Select(c => new BranchItem { Author = c.Tip.Author.Name, - Name = c.Name.Replace(prefix,""), + Name = c.Name.Replace(prefix, ""), LastCommit = c.Tip.Author.When, IsTracking = c.IsTracking, IsCurrentBranch = c.IsCurrentRepositoryHead, @@ -138,7 +201,7 @@ public IEnumerable AllFeatureBranches var remoteFeatureBranches = repo.Branches.Where(b => b.IsRemote && b.Name.Contains(prefix) - && !repo.Branches.Any(br => !br.IsRemote && br.IsTracking && br.TrackedBranch.CanonicalName== b.CanonicalName)) + && !repo.Branches.Any(br => !br.IsRemote && br.IsTracking && br.TrackedBranch.CanonicalName == b.CanonicalName)) .Select(c => new BranchItem { Author = c.Tip.Author.Name, @@ -153,58 +216,62 @@ public IEnumerable AllFeatureBranches featureBranches.AddRange(remoteFeatureBranches); return featureBranches; - } - + } } } - public IEnumerable AllReleaseBranches - { - get - { - if (!IsInitialized) - return new List(); - - using (var repo = new Repository(repoDirectory)) - { - var prefix = repo.Config.Get("gitflow.prefix.release").Value; - var releaseBranches = - repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix)) - .Select(c => new BranchItem - { - Author = c.Tip.Author.Name, - Name = c.Name.Replace(prefix, ""), - LastCommit = c.Tip.Author.When, - IsTracking = c.IsTracking, - IsCurrentBranch = c.IsCurrentRepositoryHead, - IsRemote = c.IsRemote, - CommitId = c.Tip.Id.ToString(), - Message = c.Tip.MessageShort - }).ToList(); + public IEnumerable AllReleaseBranches + { + get + { + if (!IsInitialized) + return new List(); - return releaseBranches; - } + using (var repo = new Repository(repoDirectory)) + { + var prefix = repo.Config.Get("gitflow.prefix.release").Value; + var releaseBranches = + repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix)) + .Select(c => new BranchItem + { + Author = c.Tip.Author.Name, + Name = c.Name.Replace(prefix, ""), + LastCommit = c.Tip.Author.When, + IsTracking = c.IsTracking, + IsCurrentBranch = c.IsCurrentRepositoryHead, + IsRemote = c.IsRemote, + CommitId = c.Tip.Id.ToString(), + Message = c.Tip.MessageShort + }).ToList(); - } - } + return releaseBranches; + } + } + } - public GitFlowCommandResult PublishFeature(string featureName) + public GitFlowCommandResult PublishFeature(string featureName) { string gitArguments = "feature publish \"" + TrimBranchName(featureName) + "\""; return RunGitFlow(gitArguments); } - public GitFlowCommandResult PublishRelease(string releaseName) - { - string gitArguments = "release publish \"" + TrimBranchName(releaseName) + "\""; - return RunGitFlow(gitArguments); - } + public GitFlowCommandResult PublishBugfix(string bugfixName) + { + string gitArguments = "bugfix publish \"" + TrimBranchName(bugfixName) + "\""; + return RunGitFlow(gitArguments); + } - private string TrimBranchName(string branchName) + public GitFlowCommandResult PublishRelease(string releaseName) { - if( branchName.LastIndexOf('/') >= 0) + string gitArguments = "release publish \"" + TrimBranchName(releaseName) + "\""; + return RunGitFlow(gitArguments); + } + + private string TrimBranchName(string branchName) + { + if (branchName.LastIndexOf('/') >= 0) { - branchName = branchName.Substring(branchName.LastIndexOf('/')+1); + branchName = branchName.Substring(branchName.LastIndexOf('/') + 1); } return branchName.Trim().Replace(" ", "_"); } @@ -215,12 +282,24 @@ public GitFlowCommandResult TrackFeature(string featureName) return RunGitFlow(gitArguments); } + public GitFlowCommandResult TrackBugfix(string bugfixName) + { + string gitArguments = "bugfix track \"" + TrimBranchName(bugfixName) + "\""; + return RunGitFlow(gitArguments); + } + public GitFlowCommandResult CheckoutFeature(string featureName) { string gitArguments = "feature checkout \"" + TrimBranchName(featureName) + "\""; return RunGitFlow(gitArguments); } + public GitFlowCommandResult CheckoutBugfix(string bugfixName) + { + string gitArguments = "bugfix checkout \"" + TrimBranchName(bugfixName) + "\""; + return RunGitFlow(gitArguments); + } + public IEnumerable AllReleases { get @@ -238,6 +317,14 @@ public IEnumerable AllHotfixes } } + public IEnumerable AllBugfixes + { + get + { + return GetAllBranchesThatStartsWithConfigPrefix("gitflow.prefix.bugfix"); + } + } + public IEnumerable GetAllBranchesThatStartsWithConfigPrefix(string config) { if (!IsInitialized) @@ -250,7 +337,7 @@ public IEnumerable GetAllBranchesThatStartsWithConfigPrefix(string confi repo.Branches.Where(b => !b.IsRemote && b.Name.StartsWith(prefix)).ToList(); return gitFlowBranches.Select(b => b.Name.Replace(prefix, "")).ToList(); - } + } } public bool IsOnDevelopBranch @@ -294,7 +381,7 @@ public string CurrentBranch using (var repo = new Repository(repoDirectory)) { return repo.Head.Name; - } + } } } @@ -319,6 +406,10 @@ public string CurrentBranchLeafName { prefix = repo.Config.Get("gitflow.prefix.hotfix"); } + if (IsOnBugfixBranch) + { + prefix = repo.Config.Get("gitflow.prefix.bugfix"); + } return prefix != null ? fullBranchName.Replace(prefix.Value, "") : fullBranchName; } } @@ -342,6 +433,29 @@ public GitFlowWrapper(string repoDirectory) this.repoDirectory = repoDirectory; } + public GitFlowCommandResult StartBugfix(string bugfixName) + { + string gitArguments = "bugfix start \"" + TrimBranchName(bugfixName) + "\""; + return RunGitFlow(gitArguments); + } + + public GitFlowCommandResult FinishBugfix(string bugfixName, bool rebaseOnDevelopment = false, bool deleteLocalBranch = true, bool deleteRemoteBranch = true, bool squash = false, bool noFastForward = false) + { + string gitArguments = "bugfix finish \"" + TrimBranchName(bugfixName) + "\""; + if (rebaseOnDevelopment) + gitArguments += " -r"; + if (!deleteLocalBranch) + gitArguments += " --keeplocal"; + if (!deleteRemoteBranch) + gitArguments += " --keepremote"; + if (squash) + gitArguments += " --squash"; + if (noFastForward) + gitArguments += " --no-ff"; + + return RunGitFlow(gitArguments); + } + public GitFlowCommandResult StartFeature(string featureName) { string gitArguments = "feature start \"" + TrimBranchName(featureName) + "\""; @@ -362,9 +476,7 @@ public GitFlowCommandResult FinishFeature(string featureName, bool rebaseOnDevel if (noFastForward) gitArguments += " --no-ff"; - return RunGitFlow(gitArguments); - } public GitFlowCommandResult StartRelease(string releaseName) @@ -373,7 +485,7 @@ public GitFlowCommandResult StartRelease(string releaseName) return RunGitFlow(gitArguments); } - public GitFlowCommandResult FinishRelease(string releaseName, string tagMessage = null, bool deleteBranch = true, bool forceDeletion=false, bool pushChanges = false, bool releaseNoBackMerge = false) + public GitFlowCommandResult FinishRelease(string releaseName, string tagMessage = null, bool deleteBranch = true, bool forceDeletion = false, bool pushChanges = false, bool releaseNoBackMerge = false) { string gitArguments = "release finish \"" + TrimBranchName(releaseName) + "\""; if (!String.IsNullOrEmpty(tagMessage)) @@ -396,13 +508,12 @@ public GitFlowCommandResult FinishRelease(string releaseName, string tagMessage { gitArguments += " -p"; } - if (releaseNoBackMerge) - { - gitArguments += " -b"; - } - + if (releaseNoBackMerge) + { + gitArguments += " -b"; + } - return RunGitFlow(gitArguments); + return RunGitFlow(gitArguments); } public GitFlowCommandResult StartHotfix(string hotfixName) @@ -454,7 +565,7 @@ public GitFlowCommandResult Init(GitFlowRepoSettings settings) var sr = p.StandardOutput; while (!sr.EndOfStream) { - var inputChar = (char) sr.Read(); + var inputChar = (char)sr.Read(); input.Append(inputChar); if (StringBuilderEndsWith(input, Environment.NewLine)) { @@ -485,7 +596,7 @@ public GitFlowCommandResult Init(GitFlowRepoSettings settings) } else if (IsBugfixBranchQuery(input.ToString())) { - p.StandardInput.Write(settings.FeatureBranch + "\n"); + p.StandardInput.Write(settings.BugfixBranch + "\n"); Output.Append(input); OnCommandOutputDataReceived(new CommandOutputEventArgs(input + Environment.NewLine)); input = new StringBuilder(); @@ -537,7 +648,7 @@ public GitFlowCommandResult Init(GitFlowRepoSettings settings) private static Process CreateGitFlowProcess(string arguments, string repoDirectory) { var gitInstallationPath = GitHelper.GetGitInstallationPath(); - string pathToGit = Path.Combine(Path.Combine(gitInstallationPath,"bin\\git.exe")); + string pathToGit = Path.Combine(Path.Combine(gitInstallationPath, "bin\\git.exe")); return new Process { StartInfo = @@ -612,7 +723,7 @@ public bool IsHotfixBranchQuery(string input) public bool IsSupportBranchQuery(string input) { - var regex = new Regex(@"Support branches\? " + GitFlowDefaultValueRegExp); + var regex = new Regex(@"Support branches\? " + GitFlowDefaultValueRegExp); return MatchInput(input, regex); }