This repository was archived by the owner on Jun 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 1.2k
Expand file tree
/
Copy pathRepositoryRecloneViewModel.cs
More file actions
162 lines (137 loc) · 5.87 KB
/
RepositoryRecloneViewModel.cs
File metadata and controls
162 lines (137 loc) · 5.87 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
using System;
using System.ComponentModel.Composition;
using System.Globalization;
using System.IO;
using System.Reactive;
using System.Reactive.Linq;
using System.Threading.Tasks;
using System.Windows.Input;
using GitHub.App;
using GitHub.Extensions;
using GitHub.Logging;
using GitHub.Models;
using GitHub.Services;
using GitHub.Validation;
using ReactiveUI;
using Rothko;
using Serilog;
namespace GitHub.ViewModels.Dialog
{
[Export(typeof(IRepositoryRecloneViewModel))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class RepositoryRecloneViewModel : ViewModelBase, IRepositoryRecloneViewModel
{
static readonly ILogger log = LogManager.ForContext<RepositoryRecloneViewModel>();
readonly IOperatingSystem operatingSystem;
readonly ReactiveCommand<Unit, Unit> browseForDirectoryCommand = ReactiveCommand.Create(() => { });
readonly ObservableAsPropertyHelper<bool> canClone;
string baseRepositoryPath;
[ImportingConstructor]
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;
}
public Task InitializeAsync(IConnection connection)
{
Title = string.Format(CultureInfo.CurrentCulture, Resources.CloneTitle, connection.HostAddress.Title);
return Task.CompletedTask;
}
bool IsAlreadyRepoAtPath(string path)
{
Guard.ArgumentNotNull(path, nameof(path));
bool isAlreadyRepoAtPath = false;
if (SelectedRepository != null)
{
string potentialPath = Path.Combine(path, SelectedRepository.Name);
isAlreadyRepoAtPath = operatingSystem.Directory.Exists(potentialPath);
}
return isAlreadyRepoAtPath;
}
IObservable<Unit> ShowBrowseForDirectoryDialog()
{
return Observable.Start(() =>
{
// We store this in a local variable to prevent it changing underneath us while the
// folder dialog is open.
var localBaseRepositoryPath = BaseRepositoryPath;
var browseResult = operatingSystem.Dialog.BrowseForDirectory(localBaseRepositoryPath, Resources.BrowseForDirectory);
if (!browseResult.Success)
return;
var directory = browseResult.DirectoryPath ?? localBaseRepositoryPath;
try
{
BaseRepositoryPath = directory;
}
catch (Exception e)
{
// TODO: We really should limit this to exceptions we know how to handle.
log.Error(e, "Failed to set base repository path. localBaseRepositoryPath = {0} BaseRepositoryPath = {1} Chosen directory = {2}",
localBaseRepositoryPath ?? "(null)", BaseRepositoryPath ?? "(null)", directory ?? "(null)");
}
}, RxApp.MainThreadScheduler);
}
/// <summary>
/// Gets the dialog title.
/// </summary>
public string Title { get; private set; }
/// <summary>
/// Path to clone repositories into
/// </summary>
public string BaseRepositoryPath
{
get { return baseRepositoryPath; }
set { this.RaiseAndSetIfChanged(ref baseRepositoryPath, value); }
}
/// <summary>
/// Signals that the user clicked the clone button.
/// </summary>
public ReactiveCommand<Unit, Unit> CloneCommand { get; private set; }
RepositoryModel selectedRepository;
/// <summary>
/// Selected repository to clone
/// </summary>
public RepositoryModel SelectedRepository
{
get { return selectedRepository; }
set { this.RaiseAndSetIfChanged(ref selectedRepository, value); }
}
public ICommand BrowseForDirectory
{
get { return browseForDirectoryCommand; }
}
public bool CanClone
{
get { return canClone.Value; }
}
public ReactivePropertyValidator<string> BaseRepositoryPathValidator
{
get;
private set;
}
public IObservable<object> Done => CloneCommand.Select(_ => BaseRepositoryPath);
}
}