Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Analyze a repo for mistakes

This commit finishes the bulk of DropRepoViewModel, where we scan the
repo for errors such as bad encodings or line ending issues.
  • Loading branch information...
commit 42a0720733e912fd8eebdf80679c14d33248afe8 1 parent 4996daf
@paulcbetts paulcbetts authored
View
34 RepoRepairTool.Tests/IntegrationTestHelper.cs
@@ -0,0 +1,34 @@
+using System;
+using System.Collections.Generic;
+using System.Diagnostics;
+using System.IO;
+using System.Linq;
+
+namespace RepoRepairTool.Tests
+{
+ public static class IntegrationTestHelper
+ {
+ public static string GetPath(params string[] paths)
+ {
+ var ret = GetIntegrationTestRootDirectory();
+ return (new FileInfo(paths.Aggregate(ret, Path.Combine))).FullName;
+ }
+
+ public static string GetIntegrationTestRootDirectory()
+ {
+ // XXX: This is an evil hack, but it's okay for a unit test
+ // We can't use Assembly.Location because unit test runners love
+ // to move stuff to temp directories
+ var st = new StackFrame(true);
+ var di = new DirectoryInfo(Path.GetDirectoryName(st.GetFileName()));
+
+ return di.FullName;
+ }
+
+ public static bool SkipTestOnXPAndVista()
+ {
+ int osVersion = Environment.OSVersion.Version.Major * 100 + Environment.OSVersion.Version.Minor;
+ return (osVersion < 601);
+ }
+ }
+}
View
18 RepoRepairTool.Tests/RepoRepairTool.Tests.csproj
@@ -32,10 +32,16 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
+ <Reference Include="GitHub.Core">
+ <HintPath>..\ext\GitHub.Core.dll</HintPath>
+ </Reference>
<Reference Include="Microsoft.Reactive.Testing, Version=1.1.11111.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx_Experimental-Testing.1.1.11111\lib\Net4-Full\Microsoft.Reactive.Testing.dll</HintPath>
</Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
+ <Reference Include="Newtonsoft.Json">
+ <HintPath>..\packages\Newtonsoft.Json.4.5.5\lib\net40\Newtonsoft.Json.dll</HintPath>
+ </Reference>
<Reference Include="Ninject">
<HintPath>..\packages\Ninject.3.0.0.15\lib\net40\Ninject.dll</HintPath>
</Reference>
@@ -48,6 +54,8 @@
<Reference Include="NLog">
<HintPath>..\packages\NLog.2.0.0.2000\lib\net40\NLog.dll</HintPath>
</Reference>
+ <Reference Include="PresentationCore" />
+ <Reference Include="PresentationFramework" />
<Reference Include="ReactiveUI">
<HintPath>..\packages\reactiveui-core.3.1.2\lib\Net4\ReactiveUI.dll</HintPath>
</Reference>
@@ -74,11 +82,13 @@
<Reference Include="System.Reactive.Windows.Threading, Version=1.1.11111.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\packages\Rx_Experimental-Xaml.1.1.11111\lib\Net4\System.Reactive.Windows.Threading.dll</HintPath>
</Reference>
+ <Reference Include="System.Xaml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
+ <Reference Include="WindowsBase" />
<Reference Include="xunit">
<HintPath>..\packages\xunit.1.9.0.1566\lib\xunit.dll</HintPath>
</Reference>
@@ -87,11 +97,19 @@
</Reference>
</ItemGroup>
<ItemGroup>
+ <Compile Include="IntegrationTestHelper.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
+ <Compile Include="ViewModels\DropRepoViewModelTests.cs" />
</ItemGroup>
<ItemGroup>
<None Include="packages.config" />
</ItemGroup>
+ <ItemGroup>
+ <ProjectReference Include="..\RepoRepairTool\RepoRepairTool.csproj">
+ <Project>{B7A278AF-3730-44FE-8529-AAF1741BB8BA}</Project>
+ <Name>RepoRepairTool</Name>
+ </ProjectReference>
+ </ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<Import Project="$(SolutionDir)\.nuget\nuget.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
View
52 RepoRepairTool.Tests/ViewModels/DropRepoViewModelTests.cs
@@ -0,0 +1,52 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reactive.Linq;
+using System.Text;
+using GitHub;
+using Newtonsoft.Json;
+using ReactiveUI;
+using ReactiveUI.Xaml;
+using RepoRepairTool.ViewModels;
+using Should;
+using Xunit;
+using Xunit.Extensions;
+
+namespace RepoRepairTool.Tests.ViewModels
+{
+ public class DropRepoViewModelTests : IEnableLogger
+ {
+ [Theory]
+ [InlineData("Derp")]
+ [InlineData("C:\\Windows\\System32\\Notepad.exe")]
+ [InlineData(null)]
+ public void AnalyzeRepoWithThingsThatArentReposShouldFail(string input)
+ {
+ UserError error = null;
+
+ using(UserError.OverrideHandlersForTesting(x => { error = x; return RecoveryOptionResult.CancelOperation; })) {
+ var fixture = new DropRepoViewModel(null);
+ fixture.AnalyzeRepo.Execute(input);
+ }
+
+ error.ShouldNotBeNull();
+ }
+
+ [Fact]
+ public void ScanningOurselvesShouldReturnResults()
+ {
+ var repoRootPath = CoreUtility.FindRepositoryRoot(IntegrationTestHelper.GetIntegrationTestRootDirectory());
+
+ var fixture = new DropRepoViewModel(null);
+ fixture.AnalyzeRepo.Execute(repoRootPath);
+ fixture.AnalyzeRepo.ItemsInflight.Where(x => x == 0).First();
+
+ fixture.RepoAnalysis.ShouldNotBeNull();
+ fixture.CurrentRepoPath.ShouldEqual(repoRootPath);
+
+ this.Log().Info(JsonConvert.SerializeObject(fixture.RepoAnalysis, Formatting.Indented));
+ fixture.RepoAnalysis.Keys.Any(x => x.ToLowerInvariant().Contains("working")).ShouldBeTrue();
+ fixture.RepoAnalysis.Keys.Any(x => x.ToLowerInvariant().Contains("master")).ShouldBeTrue();
+ }
+ }
+}
View
11 RepoRepairTool/RepoRepairTool.csproj
@@ -42,6 +42,12 @@
<Reference Include="GitHub.Core">
<HintPath>..\ext\GitHub.Core.dll</HintPath>
</Reference>
+ <Reference Include="Ionic.Zip">
+ <HintPath>..\ext\Ionic.Zip.dll</HintPath>
+ </Reference>
+ <Reference Include="LibGit2Sharp">
+ <HintPath>..\ext\LibGit2Sharp.dll</HintPath>
+ </Reference>
<Reference Include="Microsoft.VisualStudio.QualityTools.UnitTestFramework, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL" />
<Reference Include="Microsoft.WindowsAPICodePack">
<HintPath>..\ext\Microsoft.WindowsAPICodePack.dll</HintPath>
@@ -79,6 +85,9 @@
<Reference Include="ReactiveUI.Xaml">
<HintPath>..\packages\reactiveui-xaml.3.1.2\lib\Net4\ReactiveUI.Xaml.dll</HintPath>
</Reference>
+ <Reference Include="RestSharp">
+ <HintPath>..\ext\RestSharp.dll</HintPath>
+ </Reference>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Interactive">
@@ -108,6 +117,7 @@
<SubType>Designer</SubType>
</ApplicationDefinition>
<Compile Include="ViewModels\AppBootstrapper.cs" />
+ <Compile Include="ViewModels\DropRepoViewModel.cs" />
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
@@ -139,6 +149,7 @@
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
+ <None Include="app.config" />
<None Include="packages.config" />
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
View
2  RepoRepairTool/ViewModels/AppBootstrapper.cs
@@ -32,7 +32,7 @@ public AppBootstrapper(IKernel kernel = null, IRoutingState router = null)
RxApp.ConfigureServiceLocator(
(t, s) => kernel.Get(t, s), (t, s) => kernel.GetAll(t, s));
- // TODO: Navigate to the first screen here
+ Router.Navigate.Execute(RxApp.GetService<IDropRepoViewModel>());
}
IKernel createStandardKernel()
View
99 RepoRepairTool/ViewModels/DropRepoViewModel.cs
@@ -0,0 +1,99 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
+using System.Reactive.Concurrency;
+using System.Reactive.Linq;
+using System.Text;
+using System.Windows;
+using GitHub;
+using GitHub.Helpers;
+using LibGit2Sharp;
+using ReactiveUI;
+using ReactiveUI.Routing;
+using ReactiveUI.Xaml;
+using GitHub.Helpers;
+
+namespace RepoRepairTool.ViewModels
+{
+ public interface IDropRepoViewModel : IRoutableViewModel
+ {
+ string CurrentRepoPath { get; }
+
+ ReactiveAsyncCommand AnalyzeRepo { get; }
+ Dictionary<string, HeuristicTreeInformation> RepoAnalysis { get; }
+
+ Visibility RepairButtonVisibility { get; }
+ ReactiveCommand RepairButton { get; }
+ }
+
+ public class DropRepoViewModel : ReactiveObject, IDropRepoViewModel
+ {
+ public ReactiveAsyncCommand AnalyzeRepo { get; protected set; }
+
+ ObservableAsPropertyHelper<string> _CurrentRepoPath;
+ public string CurrentRepoPath { get { return _CurrentRepoPath.Value; } }
+
+ ObservableAsPropertyHelper<Dictionary<string, HeuristicTreeInformation>> _RepoAnalysis;
+ public Dictionary<string, HeuristicTreeInformation> RepoAnalysis { get { return _RepoAnalysis.Value; } }
+
+ ObservableAsPropertyHelper<Visibility> _RepairButtonVisibility;
+ public Visibility RepairButtonVisibility { get { return _RepairButtonVisibility.Value; } }
+
+ public ReactiveCommand RepairButton { get; protected set; }
+
+ public string UrlPathSegment {
+ get { return "drop"; }
+ }
+
+ public IScreen HostScreen { get; protected set; }
+
+ public DropRepoViewModel(IScreen hostScreen)
+ {
+ HostScreen = hostScreen;
+
+ AnalyzeRepo = new ReactiveAsyncCommand();
+ var scanResult = AnalyzeRepo.RegisterAsyncObservable(pathObj => {
+ Repository repo;
+
+ CoreUtility.ExtractLibGit2();
+
+ try {
+ repo = new Repository((string)pathObj);
+ } catch (Exception ex) {
+ UserError.Throw("This doesn't appear to be a Git repository", ex);
+ return Observable.Empty<Tuple<string, Dictionary<string, HeuristicTreeInformation>>>();
+ }
+
+ string path = (string) pathObj;
+
+ var scanAllBranches = repo.Branches.Select(branch =>
+ Observable.Defer(() =>
+ Observable.Start(() =>
+ branch.Tip.Tree.AnalyzeRepository(true))
+ .Select(x => new { Branch = branch.Name, Result = x })))
+ .Merge(2);
+
+ var scanWorkingDirectory = Observable.Defer(() => Observable.Start(() =>
+ new { Branch = "Working Directory", Result = TreeWalkerMixin.AnalyzeRepository(
+ allFilesInDirectory(path).Select(x => Tuple.Create(x, (Stream)File.OpenRead(x))), true) }));
+
+ return scanAllBranches.Merge(scanWorkingDirectory)
+ .Aggregate(new Dictionary<string, HeuristicTreeInformation>(),
+ (acc, x) => { acc[x.Branch] = x.Result; return acc; })
+ .Select(x => Tuple.Create(path, x));
+ });
+
+ scanResult.Select(x => x != null ? x.Item1 : null).ToProperty(this, x => x.CurrentRepoPath);
+ scanResult.Select(x => x != null ? x.Item2 : null).ToProperty(this, x => x.RepoAnalysis);
+ }
+
+ IEnumerable<string> allFilesInDirectory(string rootPath)
+ {
+ var di = new DirectoryInfo(rootPath);
+ return di.GetDirectories().Where(x => x.Name != ".git")
+ .SelectMany(x => allFilesInDirectory(x.FullName))
+ .Concat(di.GetFiles().Select(x => x.FullName));
+ }
+ }
+}
View
11 RepoRepairTool/app.config
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="utf-8"?>
+<configuration>
+ <runtime>
+ <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
+ <dependentAssembly>
+ <assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
+ <bindingRedirect oldVersion="0.0.0.0-4.5.0.0" newVersion="4.5.0.0" />
+ </dependentAssembly>
+ </assemblyBinding>
+ </runtime>
+</configuration>
Please sign in to comment.
Something went wrong with that request. Please try again.