Skip to content
This repository was archived by the owner on Jun 21, 2023. It is now read-only.

Commit 6f7adfb

Browse files
grokysJasmine
authored andcommitted
Check if the clone target directory already exists.
And show a validation error if it doesn't. Fixes #360.
1 parent 849500c commit 6f7adfb

File tree

2 files changed

+71
-1
lines changed

2 files changed

+71
-1
lines changed

src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,11 @@
33
using System.ComponentModel.Composition;
44
using System.Diagnostics;
55
using System.Globalization;
6+
using System.IO;
7+
using System.Linq;
68
using System.Reactive;
79
using System.Reactive.Linq;
10+
using System.Text.RegularExpressions;
811
using System.Windows.Input;
912
using GitHub.App;
1013
using GitHub.Exports;
@@ -80,7 +83,17 @@ public RepositoryCloneViewModel(
8083
signalReset: filterResetSignal
8184
);
8285

83-
BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator();
86+
var baseRepositoryPath = this.WhenAny(
87+
x => x.BaseRepositoryPath,
88+
x => x.SelectedRepository,
89+
(x, y) => x.Value);
90+
91+
BaseRepositoryPathValidator = ReactivePropertyValidator.ForObservable(baseRepositoryPath)
92+
.IfNullOrEmpty("Please enter a repository path")
93+
.IfTrue(x => x.Length > 200, "Path too long")
94+
.IfContainsInvalidPathChars("Path contains invalid characters")
95+
.IfPathNotRooted("Please enter a valid path")
96+
.IfTrue(IsAlreadyRepoAtPath, Resources.RepositoryNameValidatorAlreadyExists);
8497

8598
var canCloneObservable = this.WhenAny(
8699
x => x.SelectedRepository,
@@ -140,6 +153,35 @@ IObservable<Unit> OnCloneRepository(object state)
140153
});
141154
}
142155

156+
bool IsAlreadyRepoAtPath(string baseRepositoryPath)
157+
{
158+
bool isAlreadyRepoAtPath = false;
159+
160+
if (SelectedRepository != null)
161+
{
162+
var validationResult = BaseRepositoryPathValidator.ValidationResult;
163+
if (validationResult != null && validationResult.IsValid)
164+
{
165+
string potentialPath = Path.Combine(baseRepositoryPath, SelectedRepository.Name);
166+
isAlreadyRepoAtPath = IsGitRepo(potentialPath);
167+
}
168+
}
169+
170+
return isAlreadyRepoAtPath;
171+
}
172+
173+
bool IsGitRepo(string path)
174+
{
175+
try
176+
{
177+
return operatingSystem.File.Exists(Path.Combine(path, ".git", "HEAD"));
178+
}
179+
catch (PathTooLongException)
180+
{
181+
return false;
182+
}
183+
}
184+
143185
/// <summary>
144186
/// Path to clone repositories into
145187
/// </summary>

src/UnitTests/GitHub.App/ViewModels/RepositoryCloneViewModelTests.cs

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using System.Threading.Tasks;
66
using GitHub.Models;
77
using GitHub.Services;
8+
using GitHub.Validation;
89
using GitHub.ViewModels;
910
using NSubstitute;
1011
using Rothko;
@@ -196,6 +197,33 @@ public void IsTrueIfLoadingReposFails()
196197
}
197198
}
198199

200+
public class TheBaseRepositoryPathValidator
201+
{
202+
[Fact]
203+
public void IsInvalidWhenDestinationRepositoryExists()
204+
{
205+
var repo = Substitute.For<IRepositoryModel>();
206+
repo.Name.Returns("bar");
207+
var repositoryHost = Substitute.For<IRepositoryHost>();
208+
repositoryHost.ModelService.GetRepositories().Returns(Observable.Return(new[] { repo }));
209+
var cloneService = Substitute.For<IRepositoryCloneService>();
210+
var os = Substitute.For<IOperatingSystem>();
211+
var files = Substitute.For<IFileFacade>();
212+
os.File.Returns(files);
213+
files.Exists(@"c:\foo\bar\.git\HEAD").Returns(true);
214+
var vm = new RepositoryCloneViewModel(
215+
repositoryHost,
216+
cloneService,
217+
os,
218+
Substitute.For<INotificationService>());
219+
220+
vm.BaseRepositoryPath = @"c:\foo";
221+
vm.SelectedRepository = repo;
222+
223+
Assert.Equal(ValidationStatus.Invalid, vm.BaseRepositoryPathValidator.ValidationResult.Status);
224+
}
225+
}
226+
199227
public class TheCloneCommand : TestBaseClass
200228
{
201229
[Fact]

0 commit comments

Comments
 (0)