using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using System.Threading.Tasks; namespace SourceGit.ViewModels { public class Pull : Popup { public List Remotes => _repo.Remotes; public Models.Branch Current { get; } public bool HasSpecifiedRemoteBranch { get; private set; } public Models.Remote SelectedRemote { get => _selectedRemote; set { if (SetProperty(ref _selectedRemote, value)) PostRemoteSelected(); } } public List RemoteBranches { get => _remoteBranches; private set => SetProperty(ref _remoteBranches, value); } [Required(ErrorMessage = "Remote branch to pull is required!!!")] public Models.Branch SelectedBranch { get => _selectedBranch; set => SetProperty(ref _selectedBranch, value, true); } public bool HasLocalChanges { get => _repo.LocalChangesCount > 0; } public Models.DealWithLocalChanges DealWithLocalChanges { get; set; } = Models.DealWithLocalChanges.DoNothing; public bool UseRebase { get => _repo.UIStates.PreferRebaseInsteadOfMerge; set => _repo.UIStates.PreferRebaseInsteadOfMerge = value; } public Pull(Repository repo, Models.Branch specifiedRemoteBranch) { _repo = repo; Current = repo.CurrentBranch; if (specifiedRemoteBranch != null) { _selectedRemote = repo.Remotes.Find(x => x.Name == specifiedRemoteBranch.Remote); _selectedBranch = specifiedRemoteBranch; var branches = new List(); foreach (var branch in _repo.Branches) { if (branch.Remote == specifiedRemoteBranch.Remote) branches.Add(branch); } _remoteBranches = branches; HasSpecifiedRemoteBranch = true; } else { Models.Remote autoSelectedRemote = null; if (!string.IsNullOrEmpty(Current.Upstream)) { var remoteNameEndIdx = Current.Upstream.IndexOf('/', 13); if (remoteNameEndIdx > 0) { var remoteName = Current.Upstream.Substring(13, remoteNameEndIdx - 13); autoSelectedRemote = _repo.Remotes.Find(x => x.Name == remoteName); } } if (autoSelectedRemote == null) { Models.Remote remote = null; if (!string.IsNullOrEmpty(_repo.Settings.DefaultRemote)) remote = _repo.Remotes.Find(x => x.Name == _repo.Settings.DefaultRemote); _selectedRemote = remote ?? _repo.Remotes[0]; } else { _selectedRemote = autoSelectedRemote; } PostRemoteSelected(); HasSpecifiedRemoteBranch = false; } } public override async Task Sure() { using var lockWatcher = _repo.LockWatcher(); var log = _repo.CreateLog("Pull"); Use(log); var changes = await new Commands.CountLocalChanges(_repo.FullPath, false).GetResultAsync(); var needPopStash = false; if (changes > 0) { if (DealWithLocalChanges == Models.DealWithLocalChanges.DoNothing) { // Do nothing, just let the pull command fail and show the error to user } else if (DealWithLocalChanges == Models.DealWithLocalChanges.StashAndReapply) { var succ = await new Commands.Stash(_repo.FullPath).Use(log).PushAsync("PULL_AUTO_STASH", false); if (!succ) { log.Complete(); _repo.MarkWorkingCopyDirtyManually(); return false; } needPopStash = true; } else { await Commands.Discard.AllAsync(_repo.FullPath, true, false, false, log); } } bool rs = await new Commands.Pull( _repo.FullPath, _selectedRemote.Name, !string.IsNullOrEmpty(Current.Upstream) && Current.Upstream.Equals(_selectedBranch.FullName) ? string.Empty : _selectedBranch.Name, UseRebase).Use(log).RunAsync(); if (rs) { await _repo.AutoUpdateSubmodulesAsync(log); if (needPopStash) await new Commands.Stash(_repo.FullPath).Use(log).PopAsync("stash@{0}"); } log.Complete(); if (_repo.SelectedViewIndex == 0) { var head = await new Commands.QueryRevisionByRefName(_repo.FullPath, "HEAD").GetResultAsync(); _repo.NavigateToCommit(head, true); } return rs; } private void PostRemoteSelected() { var remoteName = _selectedRemote.Name; var branches = new List(); foreach (var branch in _repo.Branches) { if (branch.Remote == remoteName) branches.Add(branch); } RemoteBranches = branches; var autoSelectedBranch = false; if (!string.IsNullOrEmpty(Current.Upstream) && Current.Upstream.StartsWith($"refs/remotes/{remoteName}/", System.StringComparison.Ordinal)) { foreach (var branch in branches) { if (Current.Upstream == branch.FullName) { SelectedBranch = branch; autoSelectedBranch = true; break; } } } if (!autoSelectedBranch) { foreach (var branch in branches) { if (Current.Name == branch.Name) { SelectedBranch = branch; autoSelectedBranch = true; break; } } } if (!autoSelectedBranch) SelectedBranch = null; } private readonly Repository _repo = null; private Models.Remote _selectedRemote = null; private List _remoteBranches = null; private Models.Branch _selectedBranch = null; } }