using System; using System.Collections.Generic; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Threading; namespace SourceGit.UI { /// /// Git push dialog /// public partial class Push : UserControl { private Git.Repository repo = null; /// /// Constructor. /// /// Opened repository. /// Prefered push branch. public Push(Git.Repository opened, Git.Branch prefer) { repo = opened; InitializeComponent(); SetContent(prefer); } /// /// Show push dialog. /// /// /// public static void Show(Git.Repository repo, Git.Branch prefer = null) { PopupManager.Show(new Push(repo, prefer)); } /// /// Show push and start directly. /// /// public static void StartDirectly(Git.Repository repo) { var current = repo.CurrentBranch(); if (current == null || string.IsNullOrEmpty(current.Upstream)) { App.RaiseError("Current branch has no tracked upstream"); return; } var push = new Push(repo, current); PopupManager.Show(push); PopupManager.Lock(); var upstream = current.Upstream.Substring(13); var remoteIdx = upstream.IndexOf('/'); var remote = upstream.Substring(0, remoteIdx); var remoteBranch = upstream.Substring(remoteIdx + 1); push.status.Visibility = Visibility.Visible; DoubleAnimation anim = new DoubleAnimation(0, 360, TimeSpan.FromSeconds(1)); anim.RepeatBehavior = RepeatBehavior.Forever; push.statusIcon.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, anim); Task.Run(() => { repo.Push(remote, current.Name, remoteBranch, msg => push.Dispatcher.Invoke(() => push.statusMsg.Content = msg)); push.Dispatcher.Invoke(() => { push.status.Visibility = Visibility.Collapsed; push.statusIcon.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, null); PopupManager.Close(true); }); }); } /// /// Set content. /// private void SetContent(Git.Branch prefer) { var allBranches = repo.Branches(); var localBranches = new List(); foreach (var b in allBranches) { if (b.IsLocal) { localBranches.Add(b); if (b.IsCurrent && prefer == null) prefer = b; } } combLocalBranches.ItemsSource = localBranches; combLocalBranches.SelectedItem = prefer; } /// /// Start push. /// /// /// private async void Start(object sender, RoutedEventArgs e) { var localBranch = combLocalBranches.SelectedItem as Git.Branch; var remote = combRemotes.SelectedItem as string; var remoteBranch = combRemoteBranches.SelectedItem as string; var track = string.IsNullOrEmpty(localBranch.Upstream); var tags = chkTags.IsChecked == true; var force = chkForce.IsChecked == true; remoteBranch = remoteBranch.Substring($"{remote}/".Length); if (remoteBranch.Contains(" (new)")) { remoteBranch = remoteBranch.Substring(0, remoteBranch.Length - 6); } PopupManager.Lock(); status.Visibility = Visibility.Visible; DoubleAnimation anim = new DoubleAnimation(0, 360, TimeSpan.FromSeconds(1)); anim.RepeatBehavior = RepeatBehavior.Forever; statusIcon.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, anim); await Task.Run(() => repo.Push(remote, localBranch.Name, remoteBranch, msg => Dispatcher.Invoke(() => statusMsg.Content = msg), tags, track, force)); status.Visibility = Visibility.Collapsed; statusIcon.RenderTransform.BeginAnimation(RotateTransform.AngleProperty, null); PopupManager.Close(true); } /// /// Cancel. /// /// /// private void Cancel(object sender, RoutedEventArgs e) { PopupManager.Close(); } /// /// Local branch selection changed. /// /// /// private void LocalBranchesSelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count != 1) return; var current = e.AddedItems[0] as Git.Branch; var allRemotes = repo.Remotes(); var remoteNames = new List(); foreach (var r in allRemotes) remoteNames.Add(r.Name); combRemotes.ItemsSource = null; combRemotes.ItemsSource = remoteNames; if (!string.IsNullOrEmpty(current.Upstream)) { var upstream = current.Upstream.Substring("refs/remotes/".Length); combRemotes.SelectedItem = upstream.Substring(0, upstream.IndexOf('/')); } else { combRemotes.SelectedIndex = 0; } } /// /// Remote selection changed. /// /// /// private void RemotesSelectionChanged(object sender, SelectionChangedEventArgs e) { if (e.AddedItems.Count != 1) return; var remote = e.AddedItems[0] as string; var allBranches = repo.Branches(); var branches = new List(); combRemoteBranches.ItemsSource = null; foreach (var b in allBranches) { if (!b.IsLocal && b.Remote == remote) { branches.Add(b.Name); } } var current = combLocalBranches.SelectedItem as Git.Branch; if (string.IsNullOrEmpty(current.Upstream)) { var newBranch = $"{remote}/{current.Name} (new)"; branches.Add(newBranch); combRemoteBranches.ItemsSource = branches; combRemoteBranches.SelectedItem = newBranch; } else if (current.Upstream.StartsWith($"refs/remotes/{remote}", StringComparison.Ordinal)) { combRemoteBranches.ItemsSource = branches; combRemoteBranches.SelectedItem = current.Upstream.Substring("refs/remotes/".Length); } else { var match = $"{remote}/{current.Name}"; foreach (var b in branches) { if (b == match) { combRemoteBranches.ItemsSource = branches; combRemoteBranches.SelectedItem = b; return; } } var newBranch = $"{remote}/{current.Name} (new)"; branches.Add(newBranch); combRemoteBranches.ItemsSource = branches; combRemoteBranches.SelectedItem = newBranch; } } } }