public PullRequestListViewModel( IRepositoryHost repositoryHost, ILocalRepositoryModel repository, IPackageSettings settings) { this.repositoryHost = repositoryHost; this.repository = repository; this.settings = settings; Title = Resources.PullRequestsNavigationItemText; this.listSettings = settings.UIState .GetOrCreateRepositoryState(repository.CloneUrl) .PullRequests; States = new List <PullRequestState> { new PullRequestState { IsOpen = true, Name = "Open" }, new PullRequestState { IsOpen = false, Name = "Closed" }, new PullRequestState { Name = "All" } }; trackingAuthors = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAssignees = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAuthors.Subscribe(); trackingAssignees.Subscribe(); Authors = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor)); Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee)); PullRequests = new TrackingCollection <IPullRequestModel>(); pullRequests.Comparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; pullRequests.NewerComparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; this.WhenAny(x => x.SelectedState, x => x.Value) .Where(x => PullRequests != null) .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor)); this.WhenAny(x => x.SelectedAssignee, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor)); this.WhenAny(x => x.SelectedAuthor, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a)); SelectedState = States.FirstOrDefault(x => x.Name == listSettings.SelectedState) ?? States[0]; OpenPullRequest = ReactiveCommand.Create(); OpenPullRequest.Subscribe(DoOpenPullRequest); CreatePullRequest = ReactiveCommand.Create(); CreatePullRequest.Subscribe(_ => DoCreatePullRequest()); }
public GistCreationViewModel( IRepositoryHost repositoryHost, ISelectedTextProvider selectedTextProvider, IGistPublishService gistPublishService, IUsageTracker usageTracker) { Title = Resources.CreateGistTitle; apiClient = repositoryHost.ApiClient; this.gistPublishService = gistPublishService; this.usageTracker = usageTracker; FileName = VisualStudio.Services.GetFileNameFromActiveDocument() ?? Resources.DefaultGistFileName; SelectedText = selectedTextProvider.GetSelectedText(); // This class is only instantiated after we are logged into to a github account, so we should be safe to grab the first one here as the defaut. account = repositoryHost.ModelService.GetAccounts() .FirstAsync() .Select(a => a.First()) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Account); var canCreateGist = this.WhenAny( x => x.FileName, fileName => !String.IsNullOrEmpty(fileName.Value)); CreateGist = ReactiveCommand.CreateAsyncObservable(canCreateGist, OnCreateGist); }
public GistCreationViewModel( IRepositoryHost repositoryHost, ISelectedTextProvider selectedTextProvider, IGistPublishService gistPublishService) { Title = Resources.CreateGistTitle; apiClient = repositoryHost.ApiClient; this.gistPublishService = gistPublishService; FileName = VisualStudio.Services.GetFileNameFromActiveDocument() ?? Resources.DefaultGistFileName; SelectedText = selectedTextProvider.GetSelectedText(); // This class is only instantiated after we are logged into to a github account, so we should be safe to grab the first one here as the defaut. account = repositoryHost.ModelService.GetAccounts() .FirstAsync() .Select(a => a.First()) .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Account); var canCreateGist = this.WhenAny( x => x.FileName, fileName => !String.IsNullOrEmpty(fileName.Value)); CreateGist = ReactiveCommand.CreateAsyncObservable(canCreateGist, OnCreateGist); }
async Task <IPullRequestModel> PushAndCreatePR(IRepositoryHost host, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, IBranch sourceBranch, IBranch targetBranch, string title, string body) { var repo = await Task.Run(() => gitService.GetRepository(sourceRepository.LocalPath)); var remote = await gitClient.GetHttpRemote(repo, "origin"); await gitClient.Push(repo, sourceBranch.Name, remote.Name); if (!repo.Branches[sourceBranch.Name].IsTracking) { await gitClient.SetTrackingBranch(repo, sourceBranch.Name, remote.Name); } // delay things a bit to avoid a race between pushing a new branch and creating a PR on it if (!Splat.ModeDetector.Current.InUnitTestRunner().GetValueOrDefault()) { await Task.Delay(TimeSpan.FromSeconds(5)); } var ret = await host.ModelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body); usageTracker.IncrementUpstreamPullRequestCount(); return(ret); }
public StartPageCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem) { this.operatingSystem = operatingSystem; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); var baseRepositoryPath = this.WhenAny( x => x.BaseRepositoryPath, x => x.SelectedRepository, (x, y) => x.Value); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.Create(canCloneObservable); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; }
public IObservable <Unit> LogOut(IRepositoryHost host) { Guard.ArgumentNotNull(host, nameof(host)); var address = host.Address; var isDotCom = HostAddress.GitHubDotComHostAddress == address; return(host.LogOut() .ObserveOn(RxApp.MainThreadScheduler) .Do(result => { // reset the logged out host property to null // it'll know what to do if (isDotCom) { GitHubHost = null; } else { EnterpriseHost = null; } connectionManager.RemoveConnection(address); RepositoryHostFactory.Remove(host); })); }
public PullRequestListViewModel( IRepositoryHost repositoryHost, ILocalRepositoryModel repository, IPackageSettings settings) { this.repositoryHost = repositoryHost; this.repository = repository; this.settings = settings; this.listSettings = settings.UIState .GetOrCreateRepositoryState(repository.CloneUrl) .PullRequests; openPullRequestCommand = ReactiveCommand.Create(); openPullRequestCommand.Subscribe(_ => { VisualStudio.Services.DefaultExportProvider.GetExportedValue <IVisualStudioBrowser>().OpenUrl(repositoryHost.Address.WebUri); }); States = new List <PullRequestState> { new PullRequestState { IsOpen = true, Name = "Open" }, new PullRequestState { IsOpen = false, Name = "Closed" }, new PullRequestState { Name = "All" } }; trackingAuthors = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAssignees = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAuthors.Subscribe(); trackingAssignees.Subscribe(); Authors = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor)); Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee)); PullRequests = new TrackingCollection <IPullRequestModel>(); pullRequests.Comparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; pullRequests.NewerComparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; this.WhenAny(x => x.SelectedState, x => x.Value) .Where(x => PullRequests != null) .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor)); this.WhenAny(x => x.SelectedAssignee, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor)); this.WhenAny(x => x.SelectedAuthor, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a)); SelectedState = States.FirstOrDefault(x => x.Name == listSettings.SelectedState) ?? States[0]; }
public RepositoryCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem, INotificationService notificationService, IUsageTracker usageTracker) { this.repositoryHost = repositoryHost; this.cloneService = cloneService; this.operatingSystem = operatingSystem; this.notificationService = notificationService; this.usageTracker = usageTracker; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); Repositories = new TrackingCollection<IRemoteRepositoryModel>(); repositories.ProcessingDelay = TimeSpan.Zero; repositories.Comparer = OrderedComparer<IRemoteRepositoryModel>.OrderBy(x => x.Owner).ThenBy(x => x.Name).Compare; repositories.Filter = FilterRepository; repositories.NewerComparer = OrderedComparer<IRemoteRepositoryModel>.OrderByDescending(x => x.UpdatedAt).Compare; filterTextIsEnabled = this.WhenAny(x => x.IsLoading, loading => loading.Value || repositories.UnfilteredCount > 0 && !LoadingFailed) .ToProperty(this, x => x.FilterTextIsEnabled); this.WhenAny(x => x.IsLoading, x => x.LoadingFailed, (loading, failed) => !loading.Value && !failed.Value && repositories.UnfilteredCount == 0) .Subscribe(x => NoRepositoriesFound = x); this.WhenAny(x => x.FilterText, x => x.Value) .DistinctUntilChanged(StringComparer.OrdinalIgnoreCase) .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler) .Subscribe(_ => repositories.Filter = FilterRepository); var baseRepositoryPath = this.WhenAny( x => x.BaseRepositoryPath, x => x.SelectedRepository, (x, y) => x.Value); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.CreateAsyncObservable(canCloneObservable, OnCloneRepository); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; NoRepositoriesFound = true; }
public RepositoryCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem, INotificationService notificationService) { this.repositoryHost = repositoryHost; this.cloneService = cloneService; this.operatingSystem = operatingSystem; this.notificationService = notificationService; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); Repositories = new ReactiveList <IRepositoryModel>(); loadRepositoriesCommand = ReactiveCommand.CreateAsyncObservable(OnLoadRepositories); isLoading = this.WhenAny(x => x.LoadingFailed, x => x.Value) .CombineLatest(loadRepositoriesCommand.IsExecuting, (failed, loading) => !failed && loading) .ToProperty(this, x => x.IsLoading); loadRepositoriesCommand.Subscribe(Repositories.AddRange); filterTextIsEnabled = this.WhenAny(x => x.Repositories.Count, x => x.Value > 0) .ToProperty(this, x => x.FilterTextIsEnabled); noRepositoriesFound = this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed , (any, loading, failed) => !any.Value && !loading.Value && !failed.Value) .ToProperty(this, x => x.NoRepositoriesFound); var filterResetSignal = this.WhenAny(x => x.FilterText, x => x.Value) .DistinctUntilChanged(StringComparer.OrdinalIgnoreCase) .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler); FilteredRepositories = Repositories.CreateDerivedCollection( x => x, filter: FilterRepository, signalReset: filterResetSignal ); var baseRepositoryPath = this.WhenAny( x => x.BaseRepositoryPath, x => x.SelectedRepository, (x, y) => x.Value); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath) .IfNullOrEmpty("Please enter a repository path") .IfTrue(x => x.Length > 200, "Path too long") .IfContainsInvalidPathChars("Path contains invalid characters") .IfPathNotRooted("Please enter a valid path") .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.CreateAsyncObservable(canCloneObservable, OnCloneRepository); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; }
public PullRequestListViewModel(IRepositoryHost repositoryHost, ISimpleRepositoryModel repository) { this.repositoryHost = repositoryHost; this.repository = repository; openPullRequestCommand = ReactiveCommand.Create(); openPullRequestCommand.Subscribe(_ => { VisualStudio.Services.DefaultExportProvider.GetExportedValue <IVisualStudioBrowser>().OpenUrl(repositoryHost.Address.WebUri); }); States = new List <PullRequestState> { new PullRequestState { IsOpen = true, Name = "Open" }, new PullRequestState { IsOpen = false, Name = "Closed" }, new PullRequestState { Name = "All" } }; SelectedState = States[0]; this.WhenAny(x => x.SelectedState, x => x.Value) .Where(x => PullRequests != null) .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor)); this.WhenAny(x => x.SelectedAssignee, x => x.Value) .Where(x => PullRequests != null) .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor)); this.WhenAny(x => x.SelectedAuthor, x => x.Value) .Where(x => PullRequests != null) .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a)); trackingAuthors = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAssignees = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAuthors.Subscribe(); trackingAssignees.Subscribe(); Authors = trackingAuthors.CreateListenerCollection(new List <IAccount> { EmptyUser }); Assignees = trackingAssignees.CreateListenerCollection(new List <IAccount> { EmptyUser }); PullRequests = new TrackingCollection <IPullRequestModel>(); pullRequests.Comparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; pullRequests.Filter = (pr, i, l) => pr.IsOpen; pullRequests.NewerComparer = OrderedComparer <IPullRequestModel> .OrderByDescending(x => x.UpdatedAt).Compare; }
protected IConnection SetupConnection(IServiceProvider provider, IRepositoryHosts hosts, IRepositoryHost host) { var connection = provider.GetConnection(); connection.Login().Returns(Observable.Return(connection)); hosts.LookupHost(connection.HostAddress).Returns(host); host.IsLoggedIn.Returns(true); return(connection); }
public PullRequestListViewModel( IRepositoryHost repositoryHost, ILocalRepositoryModel repository, IPackageSettings settings) { this.repositoryHost = repositoryHost; this.repository = repository; this.settings = settings; Title = Resources.PullRequestsNavigationItemText; this.listSettings = settings.UIState .GetOrCreateRepositoryState(repository.CloneUrl) .PullRequests; openPullRequestCommand = ReactiveCommand.Create(); openPullRequestCommand.Subscribe(_ => { VisualStudio.Services.DefaultExportProvider.GetExportedValue<IVisualStudioBrowser>().OpenUrl(repositoryHost.Address.WebUri); }); States = new List<PullRequestState> { new PullRequestState { IsOpen = true, Name = "Open" }, new PullRequestState { IsOpen = false, Name = "Closed" }, new PullRequestState { Name = "All" } }; trackingAuthors = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(), OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare); trackingAssignees = new TrackingCollection<IAccount>(Observable.Empty<IAccount>(), OrderedComparer<IAccount>.OrderByDescending(x => x.Login).Compare); trackingAuthors.Subscribe(); trackingAssignees.Subscribe(); Authors = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor)); Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee)); PullRequests = new TrackingCollection<IPullRequestModel>(); pullRequests.Comparer = OrderedComparer<IPullRequestModel>.OrderByDescending(x => x.UpdatedAt).Compare; pullRequests.NewerComparer = OrderedComparer<IPullRequestModel>.OrderByDescending(x => x.UpdatedAt).Compare; this.WhenAny(x => x.SelectedState, x => x.Value) .Where(x => PullRequests != null) .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor)); this.WhenAny(x => x.SelectedAssignee, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor)); this.WhenAny(x => x.SelectedAuthor, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser && IsLoaded) .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a)); SelectedState = States.FirstOrDefault(x => x.Name == listSettings.SelectedState) ?? States[0]; }
static RepositoryCloneViewModel GetVM(IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem os, INotificationService notificationService, IUsageTracker usageTracker) { var vm = new RepositoryCloneViewModel( repositoryHost, cloneService, os); vm.Initialize(null); return(vm); }
static RepositoryCloneViewModel GetVM(IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem os, INotificationService notificationService, IUsageTracker usageTracker) { var vm = new RepositoryCloneViewModel( repositoryHost, cloneService, os, notificationService, usageTracker); vm.Initialize(null); return vm; }
public RepositoryCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem, IVSServices vsServices) { this.repositoryHost = repositoryHost; this.cloneService = cloneService; this.operatingSystem = operatingSystem; this.vsServices = vsServices; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); Repositories = new ReactiveList <IRepositoryModel>(); loadRepositoriesCommand = ReactiveCommand.CreateAsyncObservable(OnLoadRepositories); isLoading = this.WhenAny(x => x.LoadingFailed, x => x.Value) .CombineLatest(loadRepositoriesCommand.IsExecuting, (failed, loading) => !failed && loading) .ToProperty(this, x => x.IsLoading); loadRepositoriesCommand.Subscribe(Repositories.AddRange); filterTextIsEnabled = this.WhenAny(x => x.Repositories.Count, x => x.Value > 0) .ToProperty(this, x => x.FilterTextIsEnabled); noRepositoriesFound = this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed , (any, loading, failed) => !any.Value && !loading.Value && !failed.Value) .ToProperty(this, x => x.NoRepositoriesFound); var filterResetSignal = this.WhenAny(x => x.FilterText, x => x.Value) .DistinctUntilChanged(StringComparer.OrdinalIgnoreCase) .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler); FilteredRepositories = Repositories.CreateDerivedCollection( x => x, filter: FilterRepository, signalReset: filterResetSignal ); BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator(); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.CreateAsyncObservable(canCloneObservable, OnCloneRepository); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; }
public RepositoryCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem, INotificationService notificationService) { this.repositoryHost = repositoryHost; this.cloneService = cloneService; this.operatingSystem = operatingSystem; this.notificationService = notificationService; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); Repositories = new ReactiveList<IRepositoryModel>(); loadRepositoriesCommand = ReactiveCommand.CreateAsyncObservable(OnLoadRepositories); isLoading = this.WhenAny(x => x.LoadingFailed, x => x.Value) .CombineLatest(loadRepositoriesCommand.IsExecuting, (failed, loading) => !failed && loading) .ToProperty(this, x => x.IsLoading); loadRepositoriesCommand.Subscribe(Repositories.AddRange); filterTextIsEnabled = this.WhenAny(x => x.Repositories.Count, x => x.Value > 0) .ToProperty(this, x => x.FilterTextIsEnabled); noRepositoriesFound = this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed , (any, loading, failed) => !any.Value && !loading.Value && !failed.Value) .ToProperty(this, x => x.NoRepositoriesFound); var filterResetSignal = this.WhenAny(x => x.FilterText, x => x.Value) .DistinctUntilChanged(StringComparer.OrdinalIgnoreCase) .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler); FilteredRepositories = Repositories.CreateDerivedCollection( x => x, filter: FilterRepository, signalReset: filterResetSignal ); BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator(); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.CreateAsyncObservable(canCloneObservable, OnCloneRepository); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; }
public IObservable <IPullRequestModel> CreatePullRequest(IRepositoryHost host, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, IBranch sourceBranch, IBranch targetBranch, string title, string body ) { Extensions.Guard.ArgumentNotNull(host, nameof(host)); Extensions.Guard.ArgumentNotNull(sourceRepository, nameof(sourceRepository)); Extensions.Guard.ArgumentNotNull(targetRepository, nameof(targetRepository)); Extensions.Guard.ArgumentNotNull(sourceBranch, nameof(sourceBranch)); Extensions.Guard.ArgumentNotNull(targetBranch, nameof(targetBranch)); Extensions.Guard.ArgumentNotNull(title, nameof(title)); Extensions.Guard.ArgumentNotNull(body, nameof(body)); return(PushAndCreatePR(host, sourceRepository, targetRepository, sourceBranch, targetBranch, title, body).ToObservable()); }
public IObservable<IPullRequestModel> CreatePullRequest(IRepositoryHost host, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, IBranch sourceBranch, IBranch targetBranch, string title, string body ) { Extensions.Guard.ArgumentNotNull(host, nameof(host)); Extensions.Guard.ArgumentNotNull(sourceRepository, nameof(sourceRepository)); Extensions.Guard.ArgumentNotNull(targetRepository, nameof(targetRepository)); Extensions.Guard.ArgumentNotNull(sourceBranch, nameof(sourceBranch)); Extensions.Guard.ArgumentNotNull(targetBranch, nameof(targetBranch)); Extensions.Guard.ArgumentNotNull(title, nameof(title)); Extensions.Guard.ArgumentNotNull(body, nameof(body)); return PushAndCreatePR(host, sourceRepository, targetRepository, sourceBranch, targetBranch, title, body).ToObservable(); }
public IObservable <Unit> LogOut(IRepositoryHost host) { var address = host.Address; var isDotCom = HostAddress.GitHubDotComHostAddress == address; return(host.LogOut() .Do(result => { // reset the logged out host property to null // it'll know what to do if (isDotCom) { GitHubHost = null; } else { EnterpriseHost = null; } connectionManager.RemoveConnection(address); RepositoryHostFactory.Remove(host); })); }
public StartPageCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem, INotificationService notificationService, IUsageTracker usageTracker) { this.cloneService = cloneService; this.operatingSystem = operatingSystem; this.notificationService = notificationService; this.usageTracker = usageTracker; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); var baseRepositoryPath = this.WhenAny( x => x.BaseRepositoryPath, x => x.SelectedRepository, (x, y) => x.Value); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.CreateAsyncObservable(canCloneObservable, OnCloneRepository); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; }
public void CreatePullRequestAllArgsMandatory() { var serviceProvider = Substitutes.ServiceProvider; var service = new PullRequestService(Substitute.For <IGitClient>(), serviceProvider.GetGitService(), serviceProvider.GetOperatingSystem(), Substitute.For <IUsageTracker>()); IRepositoryHost host = null; ILocalRepositoryModel sourceRepo = null; ILocalRepositoryModel targetRepo = null; string title = null; string body = null; IBranch source = null; IBranch target = null; Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); host = serviceProvider.GetRepositoryHosts().GitHubHost; Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); sourceRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path"); Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); targetRepo = new LocalRepositoryModel("name", new GitHub.Primitives.UriString("http://github.com/github/stuff"), "c:\\path"); Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); title = "a title"; Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); body = "a body"; Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); source = new BranchModel("source", sourceRepo); Assert.Throws <ArgumentNullException>(() => service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body)); target = new BranchModel("target", targetRepo); var pr = service.CreatePullRequest(host, sourceRepo, targetRepo, source, target, title, body); Assert.NotNull(pr); }
public PullRequestCreationViewModel(IRepositoryHost repositoryHost, ILocalRepositoryModel activeRepo, IPullRequestService service, INotificationService notifications) { Extensions.Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost)); Extensions.Guard.ArgumentNotNull(activeRepo, nameof(activeRepo)); Extensions.Guard.ArgumentNotNull(service, nameof(service)); Extensions.Guard.ArgumentNotNull(notifications, nameof(notifications)); this.repositoryHost = repositoryHost; var obs = repositoryHost.ApiClient.GetRepository(activeRepo.Owner, activeRepo.Name) .Select(r => new RemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); SourceBranch = activeRepo.CurrentBranch; service.GetPullRequestTemplate(activeRepo) .Subscribe(x => Description = x ?? String.Empty, () => Description = Description ?? String.Empty); this.WhenAnyValue(x => x.Branches) .WhereNotNull() .Where(_ => TargetBranch != null) .Subscribe(x => { if (!x.Any(t => t.Equals(TargetBranch))) TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; }); SetupValidators(); var whenAnyValidationResultChanges = this.WhenAny( x => x.TitleValidator.ValidationResult, x => x.BranchValidator.ValidationResult, x => x.IsBusy, (x, y, z) => (x.Value?.IsValid ?? false) && (y.Value?.IsValid ?? false) && !z.Value); this.WhenAny(x => x.BranchValidator.ValidationResult, x => x.GetValue()) .WhereNotNull() .Where(x => !x.IsValid && x.DisplayValidationError) .Subscribe(x => notifications.ShowError(BranchValidator.ValidationResult.Message)); createPullRequest = ReactiveCommand.CreateAsyncObservable(whenAnyValidationResultChanges, _ => service .CreatePullRequest(repositoryHost, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty) .Catch<IPullRequestModel, Exception>(ex => { log.Error(ex); //TODO:Will need a uniform solution to HTTP exception message handling var apiException = ex as ApiValidationException; var error = apiException?.ApiError?.Errors?.FirstOrDefault(); notifications.ShowError(error?.Message ?? ex.Message); return Observable.Empty<IPullRequestModel>(); })) .OnExecuteCompleted(pr => { notifications.ShowMessage(String.Format(CultureInfo.CurrentCulture, Resources.PRCreatedUpstream, SourceBranch.DisplayName, TargetBranch.Repository.Owner + "/" + TargetBranch.Repository.Name + "#" + pr.Number, TargetBranch.Repository.CloneUrl.ToRepositoryUrl().Append("pull/" + pr.Number))); }); isExecuting = CreatePullRequest.IsExecuting.ToProperty(this, x => x.IsExecuting); this.WhenAnyValue(x => x.Initialized, x => x.GitHubRepository, x => x.Description, x => x.IsExecuting) .Select(x => !(x.Item1 && x.Item2 != null && x.Item3 != null && !x.Item4)) .Subscribe(x => IsBusy = x); }
public PullRequestCreationViewModel(IRepositoryHost repositoryHost, ISimpleRepositoryModel activeRepo, IPullRequestService service, INotificationService notifications) { Extensions.Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost)); Extensions.Guard.ArgumentNotNull(activeRepo, nameof(activeRepo)); Extensions.Guard.ArgumentNotNull(service, nameof(service)); Extensions.Guard.ArgumentNotNull(notifications, nameof(notifications)); this.repositoryHost = repositoryHost; var obs = repositoryHost.ApiClient.GetRepository(activeRepo.Owner, activeRepo.Name) .Select(r => new RepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); SourceBranch = activeRepo.CurrentBranch; service.GetPullRequestTemplate(activeRepo) .Subscribe(x => Description = x ?? String.Empty, () => Description = Description ?? String.Empty); this.WhenAnyValue(x => x.Branches) .WhereNotNull() .Where(_ => TargetBranch != null) .Subscribe(x => { if (!x.Any(t => t.Equals(TargetBranch))) { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; } }); SetupValidators(); var whenAnyValidationResultChanges = this.WhenAny( x => x.TitleValidator.ValidationResult, x => x.BranchValidator.ValidationResult, x => x.IsBusy, (x, y, z) => (x.Value?.IsValid ?? false) && (y.Value?.IsValid ?? false) && !z.Value); this.WhenAny(x => x.BranchValidator.ValidationResult, x => x.GetValue()) .WhereNotNull() .Where(x => !x.IsValid && x.DisplayValidationError) .Subscribe(x => notifications.ShowError(BranchValidator.ValidationResult.Message)); createPullRequest = ReactiveCommand.CreateAsyncObservable(whenAnyValidationResultChanges, _ => service .CreatePullRequest(repositoryHost, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty) .Catch <IPullRequestModel, Exception>(ex => { log.Error(ex); //TODO:Will need a uniform solution to HTTP exception message handling var apiException = ex as ApiValidationException; var error = apiException?.ApiError?.Errors?.FirstOrDefault(); notifications.ShowError(error?.Message ?? ex.Message); return(Observable.Empty <IPullRequestModel>()); })) .OnExecuteCompleted(pr => { notifications.ShowMessage(String.Format(CultureInfo.CurrentCulture, Resources.PRCreatedUpstream, TargetBranch.Id, TargetBranch.Repository.CloneUrl.ToRepositoryUrl().Append("pull/" + pr.Number))); }); isExecuting = CreatePullRequest.IsExecuting.ToProperty(this, x => x.IsExecuting); this.WhenAnyValue(x => x.Initialized, x => x.GitHubRepository, x => x.Description, x => x.IsExecuting) .Select(x => !(x.Item1 && x.Item2 != null && x.Item3 != null && !x.Item4)) .Subscribe(x => IsBusy = x); }
public ConnectionRepositoryHostMap(IRepositoryHost repositoryHost) { CurrentRepositoryHost = repositoryHost; }
public void Remove(IRepositoryHost host) { hosts.Remove(host); }
public PullRequestListViewModel( IRepositoryHost repositoryHost, ILocalRepositoryModel repository, IPackageSettings settings, IVisualStudioBrowser visualStudioBrowser) { Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost)); Guard.ArgumentNotNull(repository, nameof(repository)); Guard.ArgumentNotNull(settings, nameof(settings)); Guard.ArgumentNotNull(visualStudioBrowser, nameof(visualStudioBrowser)); constructing = true; this.repositoryHost = repositoryHost; this.localRepository = repository; this.settings = settings; this.visualStudioBrowser = visualStudioBrowser; Title = Resources.PullRequestsNavigationItemText; this.listSettings = settings.UIState .GetOrCreateRepositoryState(repository.CloneUrl) .PullRequests; States = new List <PullRequestState> { new PullRequestState { IsOpen = true, Name = "Open" }, new PullRequestState { IsOpen = false, Name = "Closed" }, new PullRequestState { Name = "All" } }; trackingAuthors = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAssignees = new TrackingCollection <IAccount>(Observable.Empty <IAccount>(), OrderedComparer <IAccount> .OrderByDescending(x => x.Login).Compare); trackingAuthors.Subscribe(); trackingAssignees.Subscribe(); Authors = trackingAuthors.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAuthor)); Assignees = trackingAssignees.CreateListenerCollection(EmptyUser, this.WhenAnyValue(x => x.SelectedAssignee)); CreatePullRequests(); this.WhenAny(x => x.SelectedState, x => x.Value) .Where(x => PullRequests != null) .Subscribe(s => UpdateFilter(s, SelectedAssignee, SelectedAuthor)); this.WhenAny(x => x.SelectedAssignee, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser) .Subscribe(a => UpdateFilter(SelectedState, a, SelectedAuthor)); this.WhenAny(x => x.SelectedAuthor, x => x.Value) .Where(x => PullRequests != null && x != EmptyUser) .Subscribe(a => UpdateFilter(SelectedState, SelectedAssignee, a)); this.WhenAnyValue(x => x.SelectedRepository) .Skip(1) .Subscribe(_ => ResetAndLoad()); SelectedState = States.FirstOrDefault(x => x.Name == listSettings.SelectedState) ?? States[0]; OpenPullRequest = ReactiveCommand.Create(); OpenPullRequest.Subscribe(DoOpenPullRequest); CreatePullRequest = ReactiveCommand.Create(); CreatePullRequest.Subscribe(_ => DoCreatePullRequest()); OpenPullRequestOnGitHub = ReactiveCommand.Create(); OpenPullRequestOnGitHub.Subscribe(x => DoOpenPullRequestOnGitHub((int)x)); constructing = false; }
public PullRequestCreationViewModel(IRepositoryHost repositoryHost, ILocalRepositoryModel activeRepo, IPullRequestService service, INotificationService notifications) { Extensions.Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost)); Extensions.Guard.ArgumentNotNull(activeRepo, nameof(activeRepo)); Extensions.Guard.ArgumentNotNull(service, nameof(service)); Extensions.Guard.ArgumentNotNull(notifications, nameof(notifications)); this.repositoryHost = repositoryHost; activeLocalRepo = activeRepo; var obs = repositoryHost.ApiClient.GetRepository(activeRepo.Owner, activeRepo.Name) .Select(r => new RemoteRepositoryModel(r)) .PublishLast(); disposables.Add(obs.Connect()); githubObs = obs; githubRepository = githubObs.ToProperty(this, x => x.GitHubRepository); this.WhenAnyValue(x => x.GitHubRepository) .WhereNotNull() .Subscribe(r => { TargetBranch = r.IsFork ? r.Parent.DefaultBranch : r.DefaultBranch; }); SourceBranch = activeRepo.CurrentBranch; this.WhenAnyValue(x => x.Branches) .WhereNotNull() .Where(_ => TargetBranch != null) .Subscribe(x => { if (!x.Any(t => t.Equals(TargetBranch))) { TargetBranch = GitHubRepository.IsFork ? GitHubRepository.Parent.DefaultBranch : GitHubRepository.DefaultBranch; } }); SetupValidators(); var uniqueCommits = this.WhenAnyValue( x => x.SourceBranch, x => x.TargetBranch) .Where(x => x.Item1 != null && x.Item2 != null) .Select(branches => { var baseBranch = branches.Item1.Name; var compareBranch = branches.Item2.Name; // We only need to get max two commits for what we're trying to achieve here. // If there's no commits we want to block creation of the PR, if there's one commits // we wan't to use its commit message as the PR title/body and finally if there's more // than one we'll use the branch name for the title. return(service.GetMessagesForUniqueCommits(activeRepo, baseBranch, compareBranch, maxCommits: 2) .Catch <IReadOnlyList <CommitMessage>, Exception>(ex => { log.Warning(ex, "Could not load unique commits"); return Observable.Empty <IReadOnlyList <CommitMessage> >(); })); }) .Switch() .ObserveOn(RxApp.MainThreadScheduler) .Replay(1) .RefCount(); var whenAnyValidationResultChanges = this.WhenAny( x => x.TitleValidator.ValidationResult, x => x.BranchValidator.ValidationResult, x => x.IsBusy, (x, y, z) => (x.Value?.IsValid ?? false) && (y.Value?.IsValid ?? false) && !z.Value); this.WhenAny(x => x.BranchValidator.ValidationResult, x => x.GetValue()) .WhereNotNull() .Where(x => !x.IsValid && x.DisplayValidationError) .Subscribe(x => notifications.ShowError(BranchValidator.ValidationResult.Message)); CreatePullRequest = ReactiveCommand.CreateAsyncObservable(whenAnyValidationResultChanges, _ => service .CreatePullRequest(repositoryHost, activeRepo, TargetBranch.Repository, SourceBranch, TargetBranch, PRTitle, Description ?? String.Empty) .Catch <IPullRequestModel, Exception>(ex => { log.Error(ex, "Error creating pull request"); //TODO:Will need a uniform solution to HTTP exception message handling var apiException = ex as ApiValidationException; var error = apiException?.ApiError?.Errors?.FirstOrDefault(); notifications.ShowError(error?.Message ?? ex.Message); return(Observable.Empty <IPullRequestModel>()); })) .OnExecuteCompleted(pr => { notifications.ShowMessage(String.Format(CultureInfo.CurrentCulture, Resources.PRCreatedUpstream, SourceBranch.DisplayName, TargetBranch.Repository.Owner + "/" + TargetBranch.Repository.Name + "#" + pr.Number, TargetBranch.Repository.CloneUrl.ToRepositoryUrl().Append("pull/" + pr.Number))); }); isExecuting = CreatePullRequest.IsExecuting.ToProperty(this, x => x.IsExecuting); this.WhenAnyValue(x => x.Initialized, x => x.GitHubRepository, x => x.Description, x => x.IsExecuting) .Select(x => !(x.Item1 && x.Item2 != null && x.Item3 != null && !x.Item4)) .Subscribe(x => IsBusy = x); Observable.CombineLatest( this.WhenAnyValue(x => x.SourceBranch), uniqueCommits, service.GetPullRequestTemplate(activeRepo).DefaultIfEmpty(string.Empty), (compare, commits, template) => new { compare, commits, template }) .Subscribe(x => { var prTitle = string.Empty; var prDescription = string.Empty; if (x.commits.Count == 1) { prTitle = x.commits[0].Summary; prDescription = x.commits[0].Details; } else { prTitle = x.compare.Name.Humanize(); } if (!string.IsNullOrWhiteSpace(x.template)) { if (!string.IsNullOrEmpty(prDescription)) { prDescription += "\n\n"; } prDescription += x.template; } PRTitle = prTitle; Description = prDescription; }); }
public RepositoryCreationViewModel( IRepositoryHost repositoryHost, IOperatingSystem operatingSystem, IRepositoryCreationService repositoryCreationService, IAvatarProvider avatarProvider) { this.repositoryHost = repositoryHost; this.operatingSystem = operatingSystem; this.repositoryCreationService = repositoryCreationService; Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, repositoryHost.Title); SelectedGitIgnoreTemplate = GitIgnoreItem.None; SelectedLicense = LicenseItem.None; accounts = repositoryHost.ModelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] {})); this.WhenAny(x => x.Accounts, x => x.Value) .WhereNotNull() .Where(accts => accts.Any()) .Subscribe(accts => { var selectedAccount = accts.FirstOrDefault(); if (selectedAccount != null) { SelectedAccount = accts.FirstOrDefault(); } }); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator(); var nonNullRepositoryName = this.WhenAny( x => x.RepositoryName, x => x.BaseRepositoryPath, (x, y) => x.Value) .WhereNotNull(); RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .IfNullOrEmpty(Resources.RepositoryNameValidatorEmpty) .IfTrue(x => x.Length > 100, Resources.RepositoryNameValidatorTooLong) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .Add(repoName => { var parsedReference = GetSafeRepositoryName(repoName); return(parsedReference != repoName ? String.Format(CultureInfo.CurrentCulture, Resources.SafeRepositoryNameWarning, parsedReference) : null); }); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); CreateRepository = InitializeCreateRepositoryCommand(); canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting, (canKeep, publishing) => canKeep && !publishing) .ToProperty(this, x => x.CanKeepPrivate); isCreating = CreateRepository.IsExecuting .ToProperty(this, x => x.IsCreating); gitIgnoreTemplates = repositoryHost.ModelService.GetGitIgnoreTemplates() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.GitIgnoreTemplates, initialValue: new GitIgnoreItem[] { }); this.WhenAny(x => x.GitIgnoreTemplates, x => x.Value) .WhereNotNull() .Where(ignores => ignores.Any()) .Subscribe(ignores => { SelectedGitIgnoreTemplate = ignores.FirstOrDefault( template => template.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)); }); licenses = repositoryHost.ModelService.GetLicenses() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.Licenses, initialValue: new LicenseItem[] { }); BaseRepositoryPath = repositoryCreationService.DefaultClonePath; }
public RepositoryCreationViewModel( IRepositoryHost repositoryHost, IOperatingSystem operatingSystem, IRepositoryCreationService repositoryCreationService, IUsageTracker usageTracker) { this.repositoryHost = repositoryHost; this.operatingSystem = operatingSystem; this.repositoryCreationService = repositoryCreationService; this.usageTracker = usageTracker; Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, repositoryHost.Title); SelectedGitIgnoreTemplate = GitIgnoreItem.None; SelectedLicense = LicenseItem.None; accounts = repositoryHost.ModelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection <IAccount>(new IAccount[] {})); this.WhenAny(x => x.Accounts, x => x.Value) .Select(accts => accts?.FirstOrDefault()) .WhereNotNull() .Subscribe(a => SelectedAccount = a); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(this.WhenAny(x => x.BaseRepositoryPath, x => x.Value)) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid); var nonNullRepositoryName = this.WhenAny( x => x.RepositoryName, x => x.BaseRepositoryPath, (x, y) => x.Value) .WhereNotNull(); RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .IfNullOrEmpty(Resources.RepositoryNameValidatorEmpty) .IfTrue(x => x.Length > 100, Resources.RepositoryNameValidatorTooLong) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .Add(repoName => { var parsedReference = GetSafeRepositoryName(repoName); return(parsedReference != repoName ? String.Format(CultureInfo.CurrentCulture, Resources.SafeRepositoryNameWarning, parsedReference) : null); }); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); CreateRepository = InitializeCreateRepositoryCommand(); canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting, (canKeep, publishing) => canKeep && !publishing) .ToProperty(this, x => x.CanKeepPrivate); isCreating = CreateRepository.IsExecuting .ToProperty(this, x => x.IsCreating); GitIgnoreTemplates = TrackingCollection.CreateListenerCollectionAndRun( repositoryHost.ModelService.GetGitIgnoreTemplates(), new[] { GitIgnoreItem.None }, OrderedComparer <GitIgnoreItem> .OrderByDescending(item => GitIgnoreItem.IsRecommended(item.Name)).Compare, x => { if (x.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)) { SelectedGitIgnoreTemplate = x; } }); Licenses = TrackingCollection.CreateListenerCollectionAndRun( repositoryHost.ModelService.GetLicenses(), new[] { LicenseItem.None }, OrderedComparer <LicenseItem> .OrderByDescending(item => LicenseItem.IsRecommended(item.Name)).Compare); BaseRepositoryPath = repositoryCreationService.DefaultClonePath; }
public RepositoryCloneViewModel( IRepositoryHost repositoryHost, IRepositoryCloneService cloneService, IOperatingSystem operatingSystem) { Guard.ArgumentNotNull(repositoryHost, nameof(repositoryHost)); Guard.ArgumentNotNull(cloneService, nameof(cloneService)); Guard.ArgumentNotNull(operatingSystem, nameof(operatingSystem)); this.repositoryHost = repositoryHost; this.operatingSystem = operatingSystem; Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, repositoryHost.Title); Repositories = new TrackingCollection <IRemoteRepositoryModel>(); repositories.ProcessingDelay = TimeSpan.Zero; repositories.Comparer = OrderedComparer <IRemoteRepositoryModel> .OrderBy(x => x.Owner).ThenBy(x => x.Name).Compare; repositories.Filter = FilterRepository; repositories.NewerComparer = OrderedComparer <IRemoteRepositoryModel> .OrderByDescending(x => x.UpdatedAt).Compare; filterTextIsEnabled = this.WhenAny(x => x.IsBusy, loading => loading.Value || repositories.UnfilteredCount > 0 && !LoadingFailed) .ToProperty(this, x => x.FilterTextIsEnabled); this.WhenAny( x => x.repositories.UnfilteredCount, x => x.IsBusy, x => x.LoadingFailed, (unfilteredCount, loading, failed) => { if (loading.Value) { return(false); } if (failed.Value) { return(false); } return(unfilteredCount.Value == 0); }) .Subscribe(x => { NoRepositoriesFound = x; }); this.WhenAny(x => x.FilterText, x => x.Value) .DistinctUntilChanged(StringComparer.OrdinalIgnoreCase) .Throttle(TimeSpan.FromMilliseconds(100), RxApp.MainThreadScheduler) .Subscribe(_ => repositories.Filter = FilterRepository); var baseRepositoryPath = this.WhenAny( x => x.BaseRepositoryPath, x => x.SelectedRepository, (x, y) => x.Value); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); var canCloneObservable = this.WhenAny( x => x.SelectedRepository, x => x.BaseRepositoryPathValidator.ValidationResult.IsValid, (x, y) => x.Value != null && y.Value); canClone = canCloneObservable.ToProperty(this, x => x.CanClone); CloneCommand = ReactiveCommand.Create(canCloneObservable); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); BaseRepositoryPath = cloneService.DefaultClonePath; NoRepositoriesFound = true; }
public RepositoryCreationViewModel( IRepositoryHost repositoryHost, IOperatingSystem operatingSystem, IRepositoryCreationService repositoryCreationService, IUsageTracker usageTracker) { this.repositoryHost = repositoryHost; this.operatingSystem = operatingSystem; this.repositoryCreationService = repositoryCreationService; this.usageTracker = usageTracker; Title = string.Format(CultureInfo.CurrentCulture, Resources.CreateTitle, repositoryHost.Title); SelectedGitIgnoreTemplate = GitIgnoreItem.None; SelectedLicense = LicenseItem.None; accounts = repositoryHost.ModelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection<IAccount>(new IAccount[] {})); this.WhenAny(x => x.Accounts, x => x.Value) .Select(accts => accts?.FirstOrDefault()) .WhereNotNull() .Subscribe(a => SelectedAccount = a); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(this.WhenAny(x => x.BaseRepositoryPath, x => x.Value)) .IfNullOrEmpty(Resources.RepositoryCreationClonePathEmpty) .IfTrue(x => x.Length > 200, Resources.RepositoryCreationClonePathTooLong) .IfContainsInvalidPathChars(Resources.RepositoryCreationClonePathInvalidCharacters) .IfPathNotRooted(Resources.RepositoryCreationClonePathInvalid); var nonNullRepositoryName = this.WhenAny( x => x.RepositoryName, x => x.BaseRepositoryPath, (x, y) => x.Value) .WhereNotNull(); RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .IfNullOrEmpty(Resources.RepositoryNameValidatorEmpty) .IfTrue(x => x.Length > 100, Resources.RepositoryNameValidatorTooLong) .IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists); SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .Add(repoName => { var parsedReference = GetSafeRepositoryName(repoName); return parsedReference != repoName ? String.Format(CultureInfo.CurrentCulture, Resources.SafeRepositoryNameWarning, parsedReference) : null; }); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); CreateRepository = InitializeCreateRepositoryCommand(); canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting, (canKeep, publishing) => canKeep && !publishing) .ToProperty(this, x => x.CanKeepPrivate); isCreating = CreateRepository.IsExecuting .ToProperty(this, x => x.IsCreating); GitIgnoreTemplates = TrackingCollection.CreateListenerCollectionAndRun( repositoryHost.ModelService.GetGitIgnoreTemplates(), new[] { GitIgnoreItem.None }, OrderedComparer<GitIgnoreItem>.OrderByDescending(item => GitIgnoreItem.IsRecommended(item.Name)).Compare, x => { if (x.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)) SelectedGitIgnoreTemplate = x; }); Licenses = TrackingCollection.CreateListenerCollectionAndRun( repositoryHost.ModelService.GetLicenses(), new[] { LicenseItem.None }, OrderedComparer<LicenseItem>.OrderByDescending(item => LicenseItem.IsRecommended(item.Name)).Compare); BaseRepositoryPath = repositoryCreationService.DefaultClonePath; }
public RepositoryCreationViewModel( IRepositoryHost repositoryHost, IOperatingSystem operatingSystem, IRepositoryCreationService repositoryCreationService, IAvatarProvider avatarProvider) { this.repositoryHost = repositoryHost; this.operatingSystem = operatingSystem; this.repositoryCreationService = repositoryCreationService; Title = string.Format(CultureInfo.CurrentCulture, "Create a {0} Repository", repositoryHost.Title); SelectedGitIgnoreTemplate = GitIgnoreItem.None; SelectedLicense = LicenseItem.None; accounts = repositoryHost.ModelService.GetAccounts() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, vm => vm.Accounts, initialValue: new ReadOnlyCollection<IAccount>(new IAccount[] {})); this.WhenAny(x => x.Accounts, x => x.Value) .WhereNotNull() .Where(accts => accts.Any()) .Subscribe(accts => { var selectedAccount = accts.FirstOrDefault(); if (selectedAccount != null) { SelectedAccount = accts.FirstOrDefault(); } }); browseForDirectoryCommand.Subscribe(_ => ShowBrowseForDirectoryDialog()); BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator(); var nonNullRepositoryName = this.WhenAny( x => x.RepositoryName, x => x.BaseRepositoryPath, (x, y) => x.Value) .WhereNotNull(); RepositoryNameValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .IfNullOrEmpty("Please enter a repository name") .IfTrue(x => x.Length > 100, "Repository name must be fewer than 100 characters") .IfTrue(IsAlreadyRepoAtPath, "Repository with same name already exists at this location"); SafeRepositoryNameWarningValidator = ReactivePropertyValidator.ForObservable(nonNullRepositoryName) .Add(repoName => { var parsedReference = GetSafeRepositoryName(repoName); return parsedReference != repoName ? "Will be created as " + parsedReference : null; }); this.WhenAny(x => x.BaseRepositoryPathValidator.ValidationResult, x => x.Value) .Subscribe(); CreateRepository = InitializeCreateRepositoryCommand(); canKeepPrivate = CanKeepPrivateObservable.CombineLatest(CreateRepository.IsExecuting, (canKeep, publishing) => canKeep && !publishing) .ToProperty(this, x => x.CanKeepPrivate); isCreating = CreateRepository.IsExecuting .ToProperty(this, x => x.IsCreating); gitIgnoreTemplates = repositoryHost.ModelService.GetGitIgnoreTemplates() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.GitIgnoreTemplates, initialValue: new GitIgnoreItem[] { }); this.WhenAny(x => x.GitIgnoreTemplates, x => x.Value) .WhereNotNull() .Where(ignores => ignores.Any()) .Subscribe(ignores => { SelectedGitIgnoreTemplate = ignores.FirstOrDefault( template => template.Name.Equals("VisualStudio", StringComparison.OrdinalIgnoreCase)); }); licenses = repositoryHost.ModelService.GetLicenses() .ObserveOn(RxApp.MainThreadScheduler) .ToProperty(this, x => x.Licenses, initialValue: new LicenseItem[] { }); BaseRepositoryPath = repositoryCreationService.DefaultClonePath; }
async Task<IPullRequestModel> PushAndCreatePR(IRepositoryHost host, ILocalRepositoryModel sourceRepository, IRepositoryModel targetRepository, IBranch sourceBranch, IBranch targetBranch, string title, string body) { var repo = await Task.Run(() => gitService.GetRepository(sourceRepository.LocalPath)); var remote = await gitClient.GetHttpRemote(repo, "origin"); await gitClient.Push(repo, sourceBranch.Name, remote.Name); if (!repo.Branches[sourceBranch.Name].IsTracking) await gitClient.SetTrackingBranch(repo, sourceBranch.Name, remote.Name); // delay things a bit to avoid a race between pushing a new branch and creating a PR on it if (!Splat.ModeDetector.Current.InUnitTestRunner().GetValueOrDefault()) await Task.Delay(TimeSpan.FromSeconds(5)); var ret = await host.ModelService.CreatePullRequest(sourceRepository, targetRepository, sourceBranch, targetBranch, title, body); await usageTracker.IncrementUpstreamPullRequestCount(); return ret; }
public IObservable<Unit> LogOut(IRepositoryHost host) { var address = host.Address; var isDotCom = HostAddress.GitHubDotComHostAddress == address; return host.LogOut() .Do(result => { // reset the logged out host property to null // it'll know what to do if (isDotCom) GitHubHost = null; else EnterpriseHost = null; connectionManager.RemoveConnection(address); disposables.Remove(host); }); }