Merge branch 'master' into fixes/823-pr-list-crash

This commit is contained in:
Jasmine Greenaway 2017-02-15 11:01:39 -05:00 коммит произвёл GitHub
Родитель d858c11cb6 577223630f
Коммит 2935efe9e9
10 изменённых файлов: 211 добавлений и 22 удалений

3
install.cmd Normal file
Просмотреть файл

@ -0,0 +1,3 @@
@set PATH=%ProgramFiles(x86)%\Microsoft Visual Studio 14.0\Common7\IDE;%PATH%
vsixinstaller /q /u:"c3d3dc68-c977-411f-b3e8-03b0dccf7dfc"
vsixinstaller "%cd%\build\Debug\GitHub.VisualStudio.vsix"

Просмотреть файл

@ -244,6 +244,10 @@
<Project>{08dd4305-7787-4823-a53f-4d0f725a07f3}</Project>
<Name>Octokit</Name>
</ProjectReference>
<ProjectReference Include="..\..\submodules\Rothko\src\Rothko.csproj">
<Project>{4A84E568-CA86-4510-8CD0-90D3EF9B65F9}</Project>
<Name>Rothko</Name>
</ProjectReference>
<ProjectReference Include="..\GitHub.Extensions\GitHub.Extensions.csproj">
<Project>{6afe2e2d-6db0-4430-a2ea-f5f5388d2f78}</Project>
<Name>GitHub.Extensions</Name>

Просмотреть файл

@ -10,5 +10,6 @@ namespace GitHub.Services
void ActivityLogMessage(string message);
void ActivityLogWarning(string message);
void ActivityLogError(string message);
bool TryOpenRepository(string directory);
}
}

Просмотреть файл

@ -4,7 +4,6 @@ using EnvDTE80;
using GitHub.Info;
using GitHub.Primitives;
using GitHub.Services;
using LibGit2Sharp;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.ComponentModelHost;
using Microsoft.VisualStudio.Shell.Interop;

Просмотреть файл

@ -1,12 +1,13 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.ComponentModel.Composition;
using System.Globalization;
using GitHub.VisualStudio;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.Shell.Interop;
using System.Linq;
using DTE = EnvDTE.DTE;
using Rothko;
namespace GitHub.Services
{
@ -16,6 +17,10 @@ namespace GitHub.Services
{
readonly IGitHubServiceProvider serviceProvider;
// Use a prefix (~$) that is defined in the default VS gitignore.
public const string TempSolutionName = "~$GitHubVSTemp$~";
[ImportingConstructor]
public VSServices(IGitHubServiceProvider serviceProvider)
{
@ -68,6 +73,73 @@ namespace GitHub.Services
}
}
/// <summary>Open a repository in Team Explorer</summary>
/// <remarks>
/// There doesn't appear to be a command that directly opens a target repo.
/// Our workaround is to create, open and delete a solution in the repo directory.
/// This triggers an event that causes the target repo to open. ;)
/// </remarks>
/// <param name="repoPath">The path to the repository to open</param>
/// <returns>True if a transient solution was successfully created in target directory (which should trigger opening of repository).</returns>
public bool TryOpenRepository(string repoPath)
{
var os = serviceProvider.TryGetService<IOperatingSystem>();
if (os == null)
{
VsOutputLogger.WriteLine("TryOpenRepository couldn't find IOperatingSystem service.");
return false;
}
var dte = serviceProvider.TryGetService<DTE>();
if (dte == null)
{
VsOutputLogger.WriteLine("TryOpenRepository couldn't find DTE service.");
return false;
}
var repoDir = os.Directory.GetDirectory(repoPath);
if(!repoDir.Exists)
{
return false;
}
bool solutionCreated = false;
try
{
dte.Solution.Create(repoPath, TempSolutionName);
solutionCreated = true;
dte.Solution.Close(false); // Don't create a .sln file when we close.
}
catch (Exception e)
{
VsOutputLogger.WriteLine("Error opening repository. {0}", e);
}
finally
{
TryCleanupSolutionUserFiles(os, repoPath, TempSolutionName);
}
return solutionCreated;
}
void TryCleanupSolutionUserFiles(IOperatingSystem os, string repoPath, string slnName)
{
var vsTempPath = Path.Combine(repoPath, ".vs", slnName);
try
{
// Clean up the dummy solution's subdirectory inside `.vs`.
var vsTempDir = os.Directory.GetDirectory(vsTempPath);
if (vsTempDir.Exists)
{
vsTempDir.Delete(true);
}
}
catch (Exception e)
{
VsOutputLogger.WriteLine("Couldn't clean up {0}. {1}", vsTempPath, e);
}
}
const string RegistryRootKey = @"Software\Microsoft\VisualStudio";
const string EnvVersionKey = "EnvVersion";
string GetVSVersion()

Просмотреть файл

@ -25,10 +25,12 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
{
public class GitHubConnectSection : TeamExplorerSectionBase, IGitHubConnectSection
{
readonly IPackageSettings packageSettings;
readonly IVSServices vsServices;
readonly int sectionIndex;
bool isCloning;
bool isCreating;
IPackageSettings packageSettings;
GitHubConnectSectionState settings;
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", "CA1823:AvoidUnusedPrivateFields")]
@ -92,6 +94,7 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
ITeamExplorerServiceHolder holder,
IConnectionManager manager,
IPackageSettings packageSettings,
IVSServices vsServices,
int index)
: base(serviceProvider, apiFactory, holder, manager)
{
@ -102,6 +105,7 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
sectionIndex = index;
this.packageSettings = packageSettings;
this.vsServices = vsServices;
connectionManager.Connections.CollectionChanged += RefreshConnections;
PropertyChanged += OnPropertyChange;
@ -344,22 +348,23 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
public bool OpenRepository()
{
var old = Repositories.FirstOrDefault(x => x.Equals(Holder.ActiveRepo));
// open the solution selection dialog when the user wants to switch to a different repo
// since there's no other way of changing the source control context in VS
if (!Equals(SelectedRepository, old))
{
if (ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(SelectedRepository.LocalPath, 1)))
var opened = vsServices.TryOpenRepository(SelectedRepository.LocalPath);
if (!opened)
{
ServiceProvider.TryGetService<ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
return true;
}
else
{
SelectedRepository = old;
return false;
// TryOpenRepository might fail because dir no longer exists. Let user find solution themselves.
opened = ErrorHandler.Succeeded(ServiceProvider.GetSolution().OpenSolutionViaDlg(SelectedRepository.LocalPath, 1));
if (!opened)
{
return false;
}
}
}
return false;
// Navigate away when we're on the correct source control contexts.
ServiceProvider.TryGetService<ITeamExplorer>()?.NavigateToPage(new Guid(TeamExplorerPageIds.Home), null);
return true;
}
void StartFlow(UIControllerFlow controllerFlow)

Просмотреть файл

@ -18,8 +18,9 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
ISimpleApiClientFactory apiFactory,
ITeamExplorerServiceHolder holder,
IConnectionManager manager,
IPackageSettings settings)
: base(serviceProvider, apiFactory, holder, manager, settings, 0)
IPackageSettings settings,
IVSServices vsServices)
: base(serviceProvider, apiFactory, holder, manager, settings, vsServices, 0)
{
}
}

Просмотреть файл

@ -18,8 +18,9 @@ namespace GitHub.VisualStudio.TeamExplorer.Connect
ISimpleApiClientFactory apiFactory,
ITeamExplorerServiceHolder holder,
IConnectionManager manager,
IPackageSettings settings)
: base(serviceProvider, apiFactory, holder, manager, settings, 1)
IPackageSettings settings,
IVSServices vsServices)
: base(serviceProvider, apiFactory, holder, manager, settings, vsServices, 1)
{
}
}

Просмотреть файл

@ -1,13 +1,112 @@
using System;
using System.IO;
using System.Runtime.InteropServices;
using GitHub.Services;
using Microsoft.TeamFoundation.Git.Controls.Extensibility;
using NSubstitute;
using Xunit;
using DTE = EnvDTE.DTE;
using Rothko;
public class VSServicesTests
{
public class TheTryOpenRepositoryMethod : TestBaseClass
{
[Fact]
public void NoExceptions_ReturnsTrue()
{
var repoDir = @"x:\repo";
var target = CreateVSServices(repoDir);
var success = target.TryOpenRepository(repoDir);
Assert.True(success);
}
[Fact]
public void SolutionCreateThrows_ReturnsFalse()
{
var repoDir = @"x:\repo";
var dte = Substitute.For<DTE>();
dte.Solution.When(s => s.Create(Arg.Any<string>(), Arg.Any<string>())).Do(
ci => { throw new COMException(); });
var target = CreateVSServices(repoDir, dte: dte);
var success = target.TryOpenRepository("");
Assert.False(success);
}
[Fact]
public void RepoDirExistsFalse_ReturnFalse()
{
var repoDir = @"x:\repo";
var os = Substitute.For<IOperatingSystem>();
//var directoryInfo = Substitute.For<IDirectoryInfo>();
//directoryInfo.Exists.Returns(false);
//os.Directory.GetDirectory(repoDir).Returns(directoryInfo);
var target = CreateVSServices(null, os: os);
var success = target.TryOpenRepository(repoDir);
Assert.False(success);
}
[Fact]
public void DeleteThrowsIOException_ReturnTrue()
{
var repoDir = @"x:\repo";
var tempDir = Path.Combine(repoDir, ".vs", VSServices.TempSolutionName);
var os = Substitute.For<IOperatingSystem>();
var directoryInfo = Substitute.For<IDirectoryInfo>();
directoryInfo.Exists.Returns(true);
os.Directory.GetDirectory(tempDir).Returns(directoryInfo);
directoryInfo.When(di => di.Delete(true)).Do(
ci => { throw new IOException(); });
var target = CreateVSServices(repoDir, os: os);
var success = target.TryOpenRepository(repoDir);
Assert.True(success);
}
[Fact]
public void SolutionCreate_DeleteVsSolutionSubdir()
{
var repoDir = @"x:\repo";
var tempDir = Path.Combine(repoDir, ".vs", VSServices.TempSolutionName);
var os = Substitute.For<IOperatingSystem>();
var directoryInfo = Substitute.For<IDirectoryInfo>();
directoryInfo.Exists.Returns(true);
os.Directory.GetDirectory(tempDir).Returns(directoryInfo);
var target = CreateVSServices(repoDir, os: os);
var success = target.TryOpenRepository(repoDir);
directoryInfo.Received().Delete(true);
}
VSServices CreateVSServices(string repoDir, IOperatingSystem os = null, DTE dte = null)
{
os = os ?? Substitute.For<IOperatingSystem>();
dte = dte ?? Substitute.For<DTE>();
if (repoDir != null)
{
var directoryInfo = Substitute.For<IDirectoryInfo>();
directoryInfo.Exists.Returns(true);
os.Directory.GetDirectory(repoDir).Returns(directoryInfo);
}
var provider = Substitute.For<IGitHubServiceProvider>();
provider.TryGetService<DTE>().Returns(dte);
provider.TryGetService<IOperatingSystem>().Returns(os);
return new VSServices(provider);
}
}
public class TheCloneMethod : TestBaseClass
{
/*
[Theory]
[InlineData(true, CloneOptions.RecurseSubmodule)]
[InlineData(false, CloneOptions.None)]
@ -24,5 +123,6 @@ public class VSServicesTests
gitRepositoriesExt.Received()
.Clone("https://github.com/github/visualstudio", @"c:\fake\ghfvs", expectedCloneOptions);
}
*/
}
}

Просмотреть файл

@ -35,6 +35,9 @@
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="envdte, Version=8.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<EmbedInteropTypes>False</EmbedInteropTypes>
</Reference>
<Reference Include="LibGit2Sharp, Version=0.22.0.0, Culture=neutral, PublicKeyToken=7cbde695407f0333, processorArchitecture=MSIL">
<HintPath>..\..\packages\LibGit2Sharp.0.22.0\lib\net40\LibGit2Sharp.dll</HintPath>
<Private>True</Private>
@ -238,7 +241,7 @@
<Compile Include="GitHub.App\ViewModels\RepositoryPublishViewModelTests.cs" />
<Compile Include="GitHub.Exports.Reactive\Caches\AccountCacheItemTests.cs" />
<Compile Include="GitHub.Exports\GitServiceTests.cs" />
<None Include="GitHub.Exports\VSServicesTests.cs" />
<Compile Include="GitHub.Exports\VSServicesTests.cs" />
<Compile Include="GitHub.Exports\HostAddressTests.cs" />
<Compile Include="GitHub.Exports\LocalRepositoryModelTests.cs" />
<Compile Include="GitHub.Extensions\GuardTests.cs" />