コード例 #1
0
 RepositoryCloneViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     IRepositoryCloneService repositoryCloneService,
     IOperatingSystem operatingSystem,
     INotificationService notificationService)
     : this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, notificationService)
 { }
コード例 #2
0
ファイル: Substitutes.cs プロジェクト: nulltoken/VisualStudio
 /// <summary>
 /// This returns a service provider with everything mocked except for 
 /// RepositoryCloneService and RepositoryCreationService, which are real
 /// instances.
 /// </summary>
 /// <param name="cloneService"></param>
 /// <param name="creationService"></param>
 /// <returns></returns>
 public static IServiceProvider GetServiceProvider(
     IRepositoryCloneService cloneService = null,
     IRepositoryCreationService creationService = null,
     IAvatarProvider avatarProvider = null)
 {
     var ret = Substitute.For<IServiceProvider, IUIProvider>();
     var os = OperatingSystem;
     var git = IGitRepositoriesExt;
     var vs = IVSServices;
     var clone = cloneService ?? new RepositoryCloneService(os, vs);
     var create = creationService ?? new RepositoryCreationService(clone);
     var hosts = RepositoryHosts;
     var exports = ExportFactoryProvider;
     var connection = Connection;
     var connectionManager = ConnectionManager;
     var twoFactorChallengeHandler = TwoFactorChallengeHandler;
     avatarProvider = avatarProvider ?? Substitute.For<IAvatarProvider>();
     ret.GetService(typeof(IGitRepositoriesExt)).Returns(git);
     ret.GetService(typeof(IVSServices)).Returns(vs);
     ret.GetService(typeof(IOperatingSystem)).Returns(os);
     ret.GetService(typeof(IRepositoryCloneService)).Returns(clone);
     ret.GetService(typeof(IRepositoryCreationService)).Returns(create);
     ret.GetService(typeof(IRepositoryHosts)).Returns(hosts);
     ret.GetService(typeof(IExportFactoryProvider)).Returns(exports);
     ret.GetService(typeof(IConnection)).Returns(connection);
     ret.GetService(typeof(IConnectionManager)).Returns(connectionManager);
     ret.GetService(typeof(IAvatarProvider)).Returns(avatarProvider);
     ret.GetService(typeof(ITwoFactorChallengeHandler)).Returns(twoFactorChallengeHandler);
     return ret;
 }
コード例 #3
0
        /// <summary>
        /// This returns a service provider with everything mocked except for
        /// RepositoryCloneService and RepositoryCreationService, which are real
        /// instances.
        /// </summary>
        /// <param name="cloneService"></param>
        /// <param name="creationService"></param>
        /// <returns></returns>
        public static IServiceProvider GetServiceProvider(
            IRepositoryCloneService cloneService       = null,
            IRepositoryCreationService creationService = null,
            IAvatarProvider avatarProvider             = null)
        {
            var ret = Substitute.For <IServiceProvider, IUIProvider>();

            var gitservice = IGitService;
            var cm         = Substitute.For <SComponentModel, IComponentModel>();
            var cc         = new CompositionContainer(CompositionOptions.IsThreadSafe | CompositionOptions.DisableSilentRejection);

            cc.ComposeExportedValue(gitservice);
            ((IComponentModel)cm).DefaultExportProvider.Returns(cc);
            ret.GetService(typeof(SComponentModel)).Returns(cm);

            var os     = OperatingSystem;
            var vs     = IVSServices;
            var clone  = cloneService ?? new RepositoryCloneService(os, vs);
            var create = creationService ?? new RepositoryCreationService(clone);

            avatarProvider = avatarProvider ?? Substitute.For <IAvatarProvider>();
            ret.GetService(typeof(IGitRepositoriesExt)).Returns(IGitRepositoriesExt);
            ret.GetService(typeof(IGitService)).Returns(gitservice);
            ret.GetService(typeof(IVSServices)).Returns(vs);
            ret.GetService(typeof(IOperatingSystem)).Returns(os);
            ret.GetService(typeof(IRepositoryCloneService)).Returns(clone);
            ret.GetService(typeof(IRepositoryCreationService)).Returns(create);
            ret.GetService(typeof(IRepositoryHosts)).Returns(RepositoryHosts);
            ret.GetService(typeof(IExportFactoryProvider)).Returns(ExportFactoryProvider);
            ret.GetService(typeof(IConnection)).Returns(Connection);
            ret.GetService(typeof(IConnectionManager)).Returns(ConnectionManager);
            ret.GetService(typeof(IAvatarProvider)).Returns(avatarProvider);
            ret.GetService(typeof(ITwoFactorChallengeHandler)).Returns(TwoFactorChallengeHandler);
            return(ret);
        }
コード例 #4
0
 public StartPageCloneViewModel(
     IGlobalConnection connection,
     IRepositoryCloneService cloneService,
     IOperatingSystem operatingSystem)
     : this(connection.Get(), cloneService, operatingSystem)
 {
 }
コード例 #5
0
 RepositoryCloneViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     IRepositoryCloneService repositoryCloneService,
     IOperatingSystem operatingSystem,
     IVSServices vsServices)
     : this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, vsServices)
 { }
コード例 #6
0
        static RepositoryCloneViewModel CreateTarget(
            IOperatingSystem os = null,
            IConnectionManager connectionManager     = null,
            IRepositoryCloneService service          = null,
            IUsageService usageService               = null,
            IUsageTracker usageTracker               = null,
            IRepositorySelectViewModel gitHubTab     = null,
            IRepositorySelectViewModel enterpriseTab = null,
            IGitService gitService         = null,
            IRepositoryUrlViewModel urlTab = null,
            string defaultClonePath        = defaultPath)
        {
            os = os ?? Substitute.For <IOperatingSystem>();
            connectionManager = connectionManager ?? CreateConnectionManager("https://github.com");
            service           = service ?? CreateRepositoryCloneService(defaultClonePath);
            usageService      = usageService ?? CreateUsageService();
            usageTracker      = usageTracker ?? Substitute.For <IUsageTracker>();
            gitHubTab         = gitHubTab ?? CreateSelectViewModel();
            enterpriseTab     = enterpriseTab ?? CreateSelectViewModel();
            gitService        = gitService ?? CreateGitService(true, "https://github.com/owner/repo");
            urlTab            = urlTab ?? CreateRepositoryUrlViewModel();

            return(new RepositoryCloneViewModel(
                       os,
                       connectionManager,
                       service,
                       gitService,
                       usageService,
                       usageTracker,
                       gitHubTab,
                       enterpriseTab,
                       urlTab));
        }
コード例 #7
0
 RepositoryCloneViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     IRepositoryCloneService repositoryCloneService,
     IOperatingSystem operatingSystem)
     : this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem)
 {
 }
コード例 #8
0
        /// <summary>
        /// This returns a service provider with everything mocked except for
        /// RepositoryCloneService and RepositoryCreationService, which are real
        /// instances.
        /// </summary>
        /// <param name="cloneService"></param>
        /// <param name="creationService"></param>
        /// <returns></returns>
        public static IServiceProvider GetServiceProvider(
            IRepositoryCloneService cloneService       = null,
            IRepositoryCreationService creationService = null,
            IAvatarProvider avatarProvider             = null)
        {
            var ret                       = Substitute.For <IServiceProvider, IUIProvider>();
            var os                        = OperatingSystem;
            var git                       = IGitRepositoriesExt;
            var vs                        = IVSServices;
            var clone                     = cloneService ?? new RepositoryCloneService(os, vs);
            var create                    = creationService ?? new RepositoryCreationService(clone);
            var hosts                     = RepositoryHosts;
            var exports                   = ExportFactoryProvider;
            var connection                = Connection;
            var connectionManager         = ConnectionManager;
            var twoFactorChallengeHandler = TwoFactorChallengeHandler;

            avatarProvider = avatarProvider ?? Substitute.For <IAvatarProvider>();
            ret.GetService(typeof(IGitRepositoriesExt)).Returns(git);
            ret.GetService(typeof(IVSServices)).Returns(vs);
            ret.GetService(typeof(IOperatingSystem)).Returns(os);
            ret.GetService(typeof(IRepositoryCloneService)).Returns(clone);
            ret.GetService(typeof(IRepositoryCreationService)).Returns(create);
            ret.GetService(typeof(IRepositoryHosts)).Returns(hosts);
            ret.GetService(typeof(IExportFactoryProvider)).Returns(exports);
            ret.GetService(typeof(IConnection)).Returns(connection);
            ret.GetService(typeof(IConnectionManager)).Returns(connectionManager);
            ret.GetService(typeof(IAvatarProvider)).Returns(avatarProvider);
            ret.GetService(typeof(ITwoFactorChallengeHandler)).Returns(twoFactorChallengeHandler);
            return(ret);
        }
コード例 #9
0
        /// <summary>
        /// This returns a service provider with everything mocked except for 
        /// RepositoryCloneService and RepositoryCreationService, which are real
        /// instances.
        /// </summary>
        /// <param name="cloneService"></param>
        /// <param name="creationService"></param>
        /// <returns></returns>
        public static IServiceProvider GetServiceProvider(
            IRepositoryCloneService cloneService = null,
            IRepositoryCreationService creationService = null,
            IAvatarProvider avatarProvider = null)
        {
            var ret = Substitute.For<IServiceProvider, IUIProvider>();

            var gitservice = IGitService;
            var cm = Substitute.For<SComponentModel, IComponentModel>();
            var cc = new CompositionContainer(CompositionOptions.IsThreadSafe | CompositionOptions.DisableSilentRejection);
            cc.ComposeExportedValue(gitservice);
            ((IComponentModel)cm).DefaultExportProvider.Returns(cc);
            ret.GetService(typeof(SComponentModel)).Returns(cm);

            var os = OperatingSystem;
            var vs = IVSServices;
            var clone = cloneService ?? new RepositoryCloneService(os, vs);
            var create = creationService ?? new RepositoryCreationService(clone);
            avatarProvider = avatarProvider ?? Substitute.For<IAvatarProvider>();
            ret.GetService(typeof(IGitRepositoriesExt)).Returns(IGitRepositoriesExt);
            ret.GetService(typeof(IGitService)).Returns(gitservice);
            ret.GetService(typeof(IVSServices)).Returns(vs);
            ret.GetService(typeof(IOperatingSystem)).Returns(os);
            ret.GetService(typeof(IRepositoryCloneService)).Returns(clone);
            ret.GetService(typeof(IRepositoryCreationService)).Returns(create);
            ret.GetService(typeof(IRepositoryHosts)).Returns(RepositoryHosts);
            ret.GetService(typeof(IExportFactoryProvider)).Returns(ExportFactoryProvider);
            ret.GetService(typeof(IConnection)).Returns(Connection);
            ret.GetService(typeof(IConnectionManager)).Returns(ConnectionManager);
            ret.GetService(typeof(IAvatarProvider)).Returns(avatarProvider);
            ret.GetService(typeof(ITwoFactorChallengeHandler)).Returns(TwoFactorChallengeHandler);
            return ret;
        }
コード例 #10
0
        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 RepositoryRecloneViewModel(
            IRepositoryCloneService cloneService,
            IOperatingSystem operatingSystem)
        {
            Guard.ArgumentNotNull(cloneService, nameof(cloneService));
            Guard.ArgumentNotNull(operatingSystem, nameof(operatingSystem));

            this.operatingSystem = operatingSystem;

            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;
        }
コード例 #12
0
        public GitHubConnectSection(IGitHubServiceProvider serviceProvider,
                                    ISimpleApiClientFactory apiFactory,
                                    ITeamExplorerServiceHolder holder,
                                    IConnectionManager manager,
                                    IPackageSettings packageSettings,
                                    IVSServices vsServices,
                                    IRepositoryCloneService cloneService,
                                    IDialogService dialogService,
                                    int index)
            : base(serviceProvider, apiFactory, holder, manager)
        {
            Title        = "GitHub";
            IsEnabled    = true;
            IsVisible    = false;
            LoggedIn     = false;
            sectionIndex = index;

            this.packageSettings = packageSettings;
            this.vsServices      = vsServices;
            this.cloneService    = cloneService;
            this.dialogService   = dialogService;

            Clone = CreateAsyncCommandHack(DoClone);

            connectionManager.Connections.CollectionChanged += RefreshConnections;
            PropertyChanged += OnPropertyChange;
            UpdateConnection();
        }
コード例 #13
0
        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;
        }
コード例 #14
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;
        }
コード例 #15
0
 public RepositoryCloneViewModel(
     IGlobalConnection connection,
     IModelServiceFactory modelServiceFactory,
     IRepositoryCloneService cloneService,
     IOperatingSystem operatingSystem)
     : this(connection.Get(), modelServiceFactory, cloneService, operatingSystem)
 {
 }
コード例 #16
0
 StartPageCloneViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     IRepositoryCloneService repositoryCloneService,
     IOperatingSystem operatingSystem,
     INotificationService notificationService,
     IUsageTracker usageTracker)
     : this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, notificationService, usageTracker)
 { }
コード例 #17
0
 RepositoryCloneViewModel(
     IConnectionRepositoryHostMap connectionRepositoryHostMap,
     IRepositoryCloneService repositoryCloneService,
     IOperatingSystem operatingSystem,
     INotificationService notificationService,
     IUsageTracker usageTracker)
     : this(connectionRepositoryHostMap.CurrentRepositoryHost, repositoryCloneService, operatingSystem, notificationService, usageTracker)
 {
 }
コード例 #18
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);
    }
コード例 #19
0
 public GitHubConnectSection1(IGitHubServiceProvider serviceProvider,
                              ISimpleApiClientFactory apiFactory,
                              ITeamExplorerServiceHolder holder,
                              IConnectionManager manager,
                              IPackageSettings settings,
                              IVSServices vsServices,
                              IRepositoryCloneService cloneService,
                              IDialogService dialogService)
     : base(serviceProvider, apiFactory, holder, manager, settings, vsServices, cloneService, dialogService, 1)
 {
 }
コード例 #20
0
        public RepositorySelectViewModel(IRepositoryCloneService service)
        {
            Guard.ArgumentNotNull(service, nameof(service));

            this.service = service;

            repository = this.WhenAnyValue(x => x.SelectedItem)
                         .Select(CreateRepository)
                         .ToProperty(this, x => x.Repository);
            this.WhenAnyValue(x => x.Filter).Subscribe(_ => ItemsView?.Refresh());
        }
コード例 #21
0
        public RepositoryCloneViewModel(
            IOperatingSystem os,
            IConnectionManager connectionManager,
            IRepositoryCloneService service,
            IGitService gitService,
            IUsageTracker usageTracker,
            IDialogService dialogService,
            IRepositorySelectViewModel gitHubTab,
            IRepositorySelectViewModel enterpriseTab)
        {
            this.os = os;
            this.connectionManager = connectionManager;
            this.service           = service;
            this.gitService        = gitService;
            this.usageTracker      = usageTracker;
            this.dialogService     = dialogService;

            GitHubTab     = gitHubTab;
            EnterpriseTab = enterpriseTab;
            tabs          = new IRepositoryCloneTabViewModel[] { GitHubTab, EnterpriseTab };

            var repository = this.WhenAnyValue(x => x.SelectedTabIndex)
                             .SelectMany(x => tabs[x].WhenAnyValue(tab => tab.Repository));

            Path = service.DefaultClonePath;
            repository.Subscribe(x => UpdatePath(x));

            pathWarning = Observable.CombineLatest(
                repository,
                this.WhenAnyValue(x => x.Path),
                ValidatePathWarning)
                          .ToProperty(this, x => x.PathWarning);

            var canClone = Observable.CombineLatest(
                repository, this.WhenAnyValue(x => x.Path),
                (repo, path) => repo != null && !service.DestinationFileExists(path) &&
                (!service.DestinationDirectoryExists(path) || service.DestinationDirectoryEmpty(path)));

            var canOpen = Observable.CombineLatest(
                repository, this.WhenAnyValue(x => x.Path),
                (repo, path) => repo != null && !service.DestinationFileExists(path) && service.DestinationDirectoryExists(path) &&
                !service.DestinationDirectoryEmpty(path));

            Browse = ReactiveCommand.Create(() => BrowseForDirectory());
            Clone  = ReactiveCommand.CreateFromObservable(
                () => repository.Select(x => new CloneDialogResult(Path, x?.CloneUrl)),
                canClone);
            Open = ReactiveCommand.CreateFromObservable(
                () => repository.Select(x => new CloneDialogResult(Path, x?.CloneUrl)),
                canOpen);

            LoginAsDifferentUser = ReactiveCommand.CreateFromTask(LoginAsDifferentUserAsync);
        }
コード例 #22
0
 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;
 }
コード例 #23
0
        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;
        }
コード例 #24
0
        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;
        }
コード例 #25
0
        static GitHubContainerProvider CreateGitHubContainerProvider(IDialogService dialogService         = null,
                                                                     IRepositoryCloneService cloneService = null, IUsageTracker usageTracker = null)
        {
            dialogService = dialogService ?? Substitute.For <IDialogService>();
            cloneService  = cloneService ?? Substitute.For <IRepositoryCloneService>();
            usageTracker  = usageTracker ?? Substitute.For <IUsageTracker>();

            var sp = Substitute.For <IGitHubServiceProvider>();

            sp.GetService <IDialogService>().Returns(dialogService);
            sp.GetService <IRepositoryCloneService>().Returns(cloneService);
            sp.GetService <IUsageTracker>().Returns(usageTracker);

            var gitHubServiceProvider = new Lazy <IGitHubServiceProvider>(() => sp);

            return(new GitHubContainerProvider(gitHubServiceProvider));
        }
コード例 #26
0
    static OpenFromUrlCommand CreateOpenFromUrlCommand(
        IDialogService dialogService = null,
        IRepositoryCloneService repositoryCloneService = null,
        ITeamExplorerContext teamExplorerContext       = null,
        IGitHubContextService gitHubContextService     = null)
    {
        dialogService          = dialogService ?? Substitute.For <IDialogService>();
        repositoryCloneService = repositoryCloneService ?? Substitute.For <IRepositoryCloneService>();
        teamExplorerContext    = teamExplorerContext ?? Substitute.For <ITeamExplorerContext>();
        gitHubContextService   = gitHubContextService ?? Substitute.For <IGitHubContextService>();

        return(new OpenFromUrlCommand(
                   new Lazy <IDialogService>(() => dialogService),
                   new Lazy <IRepositoryCloneService>(() => repositoryCloneService),
                   new Lazy <ITeamExplorerContext>(() => teamExplorerContext),
                   new Lazy <IGitHubContextService>(() => gitHubContextService)));
    }
コード例 #27
0
    static RepositoryCloneViewModel GetVM(IModelService modelService, IRepositoryCloneService cloneService, IOperatingSystem os)
    {
        var connection = Substitute.For <IConnection>();

        connection.HostAddress.Returns(HostAddress.GitHubDotComHostAddress);
        var modelServiceFactory = Substitute.For <IModelServiceFactory>();

        modelServiceFactory.CreateAsync(connection).Returns(modelService);

        var vm = new RepositoryCloneViewModel(
            modelServiceFactory,
            cloneService,
            os);

        vm.InitializeAsync(connection).Wait();
        return(vm);
    }
コード例 #28
0
        /// <summary>
        /// This returns a service provider with everything mocked except for
        /// RepositoryCloneService and RepositoryCreationService, which are real
        /// instances.
        /// </summary>
        /// <param name="cloneService"></param>
        /// <param name="creationService"></param>
        /// <returns></returns>
        public static IGitHubServiceProvider GetServiceProvider(
            IRepositoryCloneService cloneService       = null,
            IRepositoryCreationService creationService = null,
            IAvatarProvider avatarProvider             = null)
        {
            var ret = Substitute.For <IGitHubServiceProvider, IServiceProvider>();

            var gitservice = IGitService;
            var cm         = Substitute.For <SComponentModel, IComponentModel>();
            var cc         = new CompositionContainer(CompositionOptions.IsThreadSafe | CompositionOptions.DisableSilentRejection);

            cc.ComposeExportedValue(gitservice);
            ((IComponentModel)cm).DefaultExportProvider.Returns(cc);
            ret.GetService(typeof(SComponentModel)).Returns(cm);
            Services.UnitTestServiceProvider = ret;

            var os    = OperatingSystem;
            var vsgit = IVSGitServices;
            var clone = cloneService ?? new RepositoryCloneService(os, vsgit, Substitute.For <ITeamExplorerServices>(),
                                                                   Substitute.For <IGraphQLClientFactory>(), Substitute.For <IGitHubContextService>(),
                                                                   Substitute.For <IUsageTracker>(), ret);
            var create = creationService ?? new RepositoryCreationService(clone);

            avatarProvider = avatarProvider ?? Substitute.For <IAvatarProvider>();
            ret.GetService(typeof(IGitService)).Returns(gitservice);
            ret.GetService(typeof(IVSServices)).Returns(Substitute.For <IVSServices>());
            ret.GetService(typeof(ITeamExplorerServices)).Returns(Substitute.For <ITeamExplorerServices>());
            ret.GetService(typeof(IGraphQLClientFactory)).Returns(Substitute.For <IGraphQLClientFactory>());
            ret.GetService(typeof(IGitHubContextService)).Returns(Substitute.For <IGitHubContextService>());
            ret.GetService(typeof(IVSGitExt)).Returns(Substitute.For <IVSGitExt>());
            ret.GetService(typeof(IUsageTracker)).Returns(Substitute.For <IUsageTracker>());
            ret.GetService(typeof(IVSGitServices)).Returns(vsgit);
            ret.GetService(typeof(IOperatingSystem)).Returns(os);
            ret.GetService(typeof(IRepositoryCloneService)).Returns(clone);
            ret.GetService(typeof(IRepositoryCreationService)).Returns(create);
            ret.GetService(typeof(IViewViewModelFactory)).Returns(ViewViewModelFactory);
            ret.GetService(typeof(IConnection)).Returns(Connection);
            ret.GetService(typeof(IConnectionManager)).Returns(ConnectionManager);
            ret.GetService(typeof(IAvatarProvider)).Returns(avatarProvider);
            ret.GetService(typeof(IDelegatingTwoFactorChallengeHandler)).Returns(TwoFactorChallengeHandler);
            ret.GetService(typeof(IGistPublishService)).Returns(GistPublishService);
            ret.GetService(typeof(IPullRequestService)).Returns(PullRequestService);
            return(ret);
        }
コード例 #29
0
        public RepositoryCloneViewModel(
            IOperatingSystem os,
            IConnectionManager connectionManager,
            IRepositoryCloneService service,
            IUsageService usageService,
            IUsageTracker usageTracker,
            IRepositorySelectViewModel gitHubTab,
            IRepositorySelectViewModel enterpriseTab,
            IRepositoryUrlViewModel urlTab)
        {
            this.os = os;
            this.connectionManager = connectionManager;
            this.service           = service;
            this.usageService      = usageService;
            this.usageTracker      = usageTracker;

            GitHubTab     = gitHubTab;
            EnterpriseTab = enterpriseTab;
            UrlTab        = urlTab;
            tabs          = new IRepositoryCloneTabViewModel[] { GitHubTab, EnterpriseTab, UrlTab };

            var repository = this.WhenAnyValue(x => x.SelectedTabIndex)
                             .SelectMany(x => tabs[x].WhenAnyValue(tab => tab.Repository));

            Path = service.DefaultClonePath;
            repository.Subscribe(x => UpdatePath(x));

            pathError = Observable.CombineLatest(
                repository,
                this.WhenAnyValue(x => x.Path),
                ValidatePath)
                        .ToProperty(this, x => x.PathError);

            var canClone = Observable.CombineLatest(
                repository,
                this.WhenAnyValue(x => x.PathError),
                (repo, error) => (repo, error))
                           .Select(x => x.repo != null && x.error == null);

            Browse = ReactiveCommand.Create().OnExecuteCompleted(_ => BrowseForDirectory());
            Clone  = ReactiveCommand.CreateAsyncObservable(
                canClone,
                _ => repository.Select(x => new CloneDialogResult(Path, x)));
        }
コード例 #30
0
        public RepositorySelectViewModel(IRepositoryCloneService service, IGitHubContextService gitHubContextService)
        {
            Guard.ArgumentNotNull(service, nameof(service));
            Guard.ArgumentNotNull(service, nameof(gitHubContextService));

            this.service = service;
            this.gitHubContextService = gitHubContextService;

            var selectedRepository = this.WhenAnyValue(x => x.SelectedItem)
                                     .Select(CreateRepository);

            var filterRepository = this.WhenAnyValue(x => x.Filter)
                                   .Select(f => gitHubContextService.FindContextFromUrl(f))
                                   .Select(CreateRepository);

            repository = selectedRepository
                         .Merge(filterRepository)
                         .ToProperty(this, x => x.Repository);

            this.WhenAnyValue(x => x.Filter).Subscribe(_ => ItemsView?.Refresh());
        }
コード例 #31
0
        public GitHubConnectSection(IGitHubServiceProvider serviceProvider,
                                    ISimpleApiClientFactory apiFactory,
                                    ITeamExplorerServiceHolder holder,
                                    IConnectionManager manager,
                                    IPackageSettings packageSettings,
                                    IVSServices vsServices,
                                    IRepositoryCloneService cloneService,
                                    IDialogService dialogService,
                                    ILocalRepositories localRepositories,
                                    int index)
            : base(serviceProvider, apiFactory, holder, manager)
        {
            Guard.ArgumentNotNull(apiFactory, nameof(apiFactory));
            Guard.ArgumentNotNull(holder, nameof(holder));
            Guard.ArgumentNotNull(manager, nameof(manager));
            Guard.ArgumentNotNull(packageSettings, nameof(packageSettings));
            Guard.ArgumentNotNull(vsServices, nameof(vsServices));
            Guard.ArgumentNotNull(cloneService, nameof(cloneService));
            Guard.ArgumentNotNull(dialogService, nameof(dialogService));
            Guard.ArgumentNotNull(localRepositories, nameof(localRepositories));

            Title        = "GitHub";
            IsEnabled    = true;
            IsVisible    = false;
            LoggedIn     = false;
            sectionIndex = index;

            this.packageSettings   = packageSettings;
            this.vsServices        = vsServices;
            this.cloneService      = cloneService;
            this.dialogService     = dialogService;
            this.localRepositories = localRepositories;

            Clone = CreateAsyncCommandHack(DoClone);

            connectionManager.Connections.CollectionChanged += RefreshConnections;
            PropertyChanged += OnPropertyChange;
            UpdateConnection();
        }
コード例 #32
0
        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;
        }
コード例 #33
0
        static RepositoryCloneViewModel CreateTarget(
            IOperatingSystem os = null,
            IConnectionManager connectionManager     = null,
            IRepositoryCloneService service          = null,
            IRepositorySelectViewModel gitHubTab     = null,
            IRepositorySelectViewModel enterpriseTab = null,
            IRepositoryUrlViewModel urlTab           = null)
        {
            os = os ?? Substitute.For <IOperatingSystem>();
            connectionManager = connectionManager ?? CreateConnectionManager("https://github.com");
            service           = service ?? CreateRepositoryCloneService();
            gitHubTab         = gitHubTab ?? CreateSelectViewModel();
            enterpriseTab     = enterpriseTab ?? CreateSelectViewModel();
            urlTab            = urlTab ?? Substitute.For <IRepositoryUrlViewModel>();

            return(new RepositoryCloneViewModel(
                       os,
                       connectionManager,
                       service,
                       gitHubTab,
                       enterpriseTab,
                       urlTab));
        }
コード例 #34
0
        public RepositoryCloneViewModel(
            IConnection connection,
            IModelServiceFactory modelServiceFactory,
            IRepositoryCloneService cloneService,
            IOperatingSystem operatingSystem)
        {
            Guard.ArgumentNotNull(connection, nameof(connection));
            Guard.ArgumentNotNull(modelServiceFactory, nameof(modelServiceFactory));
            Guard.ArgumentNotNull(cloneService, nameof(cloneService));
            Guard.ArgumentNotNull(operatingSystem, nameof(operatingSystem));

            this.connection          = connection;
            this.modelServiceFactory = modelServiceFactory;
            this.operatingSystem     = operatingSystem;

            Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, connection.HostAddress.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;
        }
コード例 #35
0
 public RepositoryCreationService(IRepositoryCloneService cloneService)
 {
     this.cloneService = cloneService;
 }
コード例 #36
0
 public RepositoryCreationService(IRepositoryCloneService cloneService)
 {
     this.cloneService = cloneService;
 }
コード例 #37
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 <IRepositoryModel>();
            repositories.ProcessingDelay = TimeSpan.Zero;
            repositories.Comparer        = OrderedComparer <IRepositoryModel> .OrderBy(x => x.Owner).ThenBy(x => x.Name).Compare;

            repositories.Filter        = FilterRepository;
            repositories.NewerComparer = OrderedComparer <IRepositoryModel> .OrderByDescending(x => x.UpdatedAt).Compare;

            filterTextIsEnabled = this.WhenAny(x => x.IsLoading, x => x.Value)
                                  .Select(x => !x && repositories.UnfilteredCount > 0)
                                  .ToProperty(this, x => x.FilterTextIsEnabled);

            this.WhenAny(x => x.FilterTextIsEnabled, x => x.IsLoading, x => x.LoadingFailed
                         , (any, loading, failed) => !any.Value && !loading.Value && !failed.Value)
            .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;
        }