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

Commit

Permalink
Check if the clone target directory already exists.
Browse files Browse the repository at this point in the history
And show a validation error if it doesn't. Fixes #360.
  • Loading branch information
grokys authored and Jasmine committed Jun 20, 2016
1 parent 849500c commit 6f7adfb
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 1 deletion.
44 changes: 43 additions & 1 deletion src/GitHub.App/ViewModels/RepositoryCloneViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,11 @@
using System.ComponentModel.Composition;
using System.Diagnostics;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Reactive;
using System.Reactive.Linq;
using System.Text.RegularExpressions;
using System.Windows.Input;
using GitHub.App;
using GitHub.Exports;
Expand Down Expand Up @@ -80,7 +83,17 @@ public RepositoryCloneViewModel(
signalReset: filterResetSignal
);

BaseRepositoryPathValidator = this.CreateBaseRepositoryPathValidator();
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,
Expand Down Expand Up @@ -140,6 +153,35 @@ IObservable<Unit> OnCloneRepository(object state)
});
}

bool IsAlreadyRepoAtPath(string baseRepositoryPath)
{
bool isAlreadyRepoAtPath = false;

if (SelectedRepository != null)
{
var validationResult = BaseRepositoryPathValidator.ValidationResult;
if (validationResult != null && validationResult.IsValid)
{
string potentialPath = Path.Combine(baseRepositoryPath, SelectedRepository.Name);
isAlreadyRepoAtPath = IsGitRepo(potentialPath);
}
}

return isAlreadyRepoAtPath;
}

bool IsGitRepo(string path)
{
try
{
return operatingSystem.File.Exists(Path.Combine(path, ".git", "HEAD"));
}
catch (PathTooLongException)
{
return false;
}
}

/// <summary>
/// Path to clone repositories into
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Threading.Tasks;
using GitHub.Models;
using GitHub.Services;
using GitHub.Validation;
using GitHub.ViewModels;
using NSubstitute;
using Rothko;
Expand Down Expand Up @@ -196,6 +197,33 @@ public void IsTrueIfLoadingReposFails()
}
}

public class TheBaseRepositoryPathValidator
{
[Fact]
public void IsInvalidWhenDestinationRepositoryExists()
{
var repo = Substitute.For<IRepositoryModel>();
repo.Name.Returns("bar");
var repositoryHost = Substitute.For<IRepositoryHost>();
repositoryHost.ModelService.GetRepositories().Returns(Observable.Return(new[] { repo }));
var cloneService = Substitute.For<IRepositoryCloneService>();
var os = Substitute.For<IOperatingSystem>();
var files = Substitute.For<IFileFacade>();
os.File.Returns(files);
files.Exists(@"c:\foo\bar\.git\HEAD").Returns(true);
var vm = new RepositoryCloneViewModel(
repositoryHost,
cloneService,
os,
Substitute.For<INotificationService>());

vm.BaseRepositoryPath = @"c:\foo";
vm.SelectedRepository = repo;

Assert.Equal(ValidationStatus.Invalid, vm.BaseRepositoryPathValidator.ValidationResult.Status);
}
}

public class TheCloneCommand : TestBaseClass
{
[Fact]
Expand Down

0 comments on commit 6f7adfb

Please sign in to comment.