Skip to content

Commit

Permalink
Merge pull request #71 from christianhelle/download-nswag
Browse files Browse the repository at this point in the history
Download NSwag CLI on-demand
  • Loading branch information
christianhelle authored Dec 17, 2019
2 parents 3838bce + e9018f0 commit 8f116eb
Show file tree
Hide file tree
Showing 13 changed files with 131 additions and 30 deletions.
28 changes: 13 additions & 15 deletions src/ApiClientCodeGen.Core/DependencyDownloader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,21 @@ namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core
{
public static class DependencyDownloader
{
public static void InstallAutoRest()
{
Trace.WriteLine("AutoRest not installed. Attempting to install through NPM");
public static void InstallAutoRest() => InstallNpmPackage("autorest");

var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var programFiles64 = programFiles.Replace(" (x86)", newValue: string.Empty);
public static void InstallNSwag() => InstallNpmPackage("nswag");

var npmCommand = Path.Combine(programFiles, "nodejs\\npm.cmd");
if (!File.Exists(npmCommand))
{
npmCommand = Path.Combine(programFiles64, "nodejs\\npm.cmd");
if (!File.Exists(npmCommand))
throw new InvalidOperationException("Unable to find NPM. Please install Node.js");
}

new ProcessLauncher().Start(npmCommand, "install -g autorest");
Trace.WriteLine("AutoRest installed successfully through NPM");
private static void InstallNpmPackage(string packageName)
{
Trace.WriteLine($"Attempting to install {packageName} through NPM");

var processLauncher = new ProcessLauncher();
var npmPath = NpmHelper.GetNpmPath();
processLauncher.Start(
npmPath,
$"install -g {packageName}");

Trace.WriteLine($"{packageName} installed successfully through NPM");
}

public static string InstallOpenApiGenerator(string path = null)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public string GenerateCode(IProgressReporter pGenerateProgress)
Trace.WriteLine(command + " does not exist! Retrying with default NSwag.exe path");
command = PathProvider.GetNSwagPath();
if (!File.Exists(command))
throw new InvalidOperationException("NSwag not installed. Please install NSwagStudio");
DependencyDownloader.InstallNSwag();
}

TryRemoveSwaggerJsonSpec(nswagStudioFile);
Expand Down
8 changes: 6 additions & 2 deletions src/ApiClientCodeGen.Core/Generators/ProcessLauncher.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Diagnostics;
using System.Text;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators
{
Expand All @@ -11,15 +12,18 @@ public interface IProcessLauncher
public class ProcessLauncher : IProcessLauncher
{
public void Start(string command, string arguments)
=> Start(command, arguments, o => Trace.WriteLine(o), e => Trace.WriteLine(e));

public void Start(string command, string arguments, Action<string> onOutputData, Action<string> onErrorData)
{
Trace.WriteLine("Executing:");
Trace.WriteLine($"{command} {arguments}");

var processInfo = new ProcessStartInfo(command, arguments);
using (var process = new Process { StartInfo = processInfo })
{
process.OutputDataReceived += (s, e) => Trace.WriteLine(e.Data);
process.ErrorDataReceived += (s, e) => Trace.WriteLine(e.Data);
process.OutputDataReceived += (s, e) => onOutputData?.Invoke(e.Data);
process.ErrorDataReceived += (s, e) => onErrorData?.Invoke(e.Data);
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = true;
process.StartInfo.RedirectStandardInput = true;
Expand Down
52 changes: 52 additions & 0 deletions src/ApiClientCodeGen.Core/NpmHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
using System;
using System.Diagnostics;
using System.IO;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core.Generators;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core
{
public static class NpmHelper
{
public static string GetNpmPath()
{
var programFiles = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles);
var programFiles64 = programFiles.Replace(" (x86)", newValue: String.Empty);

var npmCommand = Path.Combine(programFiles, "nodejs\\npm.cmd");
if (File.Exists(npmCommand))
return npmCommand;

npmCommand = Path.Combine(programFiles64, "nodejs\\npm.cmd");
if (!File.Exists(npmCommand))
throw new InvalidOperationException("Unable to find NPM. Please install Node.js");

return npmCommand;
}

public static string GetPrefixPath()
=> TryGetNpmPrefixPathFromNpmConfig() ??
Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"npm");

private static string TryGetNpmPrefixPathFromNpmConfig()
{
try
{
var npm = GetNpmPath();
string prefix = null;
new ProcessLauncher().Start(
npm,
"config get prefix",
o => prefix += o,
e => Trace.WriteLine(e));
return prefix;
}
catch (Exception e)
{
Trace.TraceError(e.ToString());
return null;
}
}
}
}
15 changes: 10 additions & 5 deletions src/ApiClientCodeGen.Core/Options/General/PathProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ public static string GetJavaPath()
try
{
var javaHome = Environment.GetEnvironmentVariable("JAVA_HOME");
var javaExe = Path.Combine(javaHome, "bin\\java.exe");
var javaExe = Path.Combine(javaHome ?? throw new InvalidOperationException(), "bin\\java.exe");
return javaExe;
}
catch (Exception e)
Expand All @@ -35,16 +35,21 @@ public static string GetNpmPath()
npmCommand = Path.Combine(programFiles64, "nodejs\\npm.cmd");
return !File.Exists(npmCommand) ? null : npmCommand;
}

public static string GetNSwagPath()
public static string GetNSwagStudioPath()
=> Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86),
"Rico Suter\\NSwagStudio\\Win\\NSwag.exe");

public static string GetNSwagPath()
=> Path.Combine(
NpmHelper.GetPrefixPath(),
"nswag.cmd");

public static string GetAutoRestPath()
=> Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
"npm\\autorest.cmd");
NpmHelper.GetPrefixPath(),
"autorest.cmd");

public static string GetSwaggerCodegenPath()
=> Path.Combine(
Expand Down
2 changes: 2 additions & 0 deletions src/ApiClientCodeGen.Tests/ApiClientCodeGen.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@
<None Include="Converters\CSharpToVisualBasicLanguageConverterTests.cs" />
<Compile Include="CustomTool\SingleFileCodeGeneratorTests.cs" />
<Compile Include="CustomTool\TestSingleFileCodeGenerator.cs" />
<Compile Include="DependencyDownloaderTests.cs" />
<Compile Include="Extensions\GetDependenciesTests.cs" />
<Compile Include="Extensions\GetSupportedCodeGeneratorTests.cs" />
<Compile Include="Extensions\OpenApiDocumentExtensionsTests.cs" />
Expand All @@ -78,6 +79,7 @@
<Compile Include="Generators\Swagger\SwaggerCSharpCodeGeneratorExceptionTests.cs" />
<Compile Include="Generators\Swagger\SwaggerCSharpCodeGeneratorTests.cs" />
<Compile Include="GlobalSuppressions.cs" />
<Compile Include="NpmHelperTests.cs" />
<Compile Include="NuGet\PackageDependencyTests.cs" />
<Compile Include="NuGet\SupportedCodeGeneratorExtensionsTests.cs" />
<Compile Include="NuGet\PackageDependencyListProviderTests.cs" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.IntegrationTests
namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Tests
{
[TestClass]
public class DependencyDownloaderTests
Expand All @@ -27,5 +27,11 @@ public void InstallAutoRest_Returns_Path()
=> new Action(DependencyDownloader.InstallAutoRest)
.Should()
.NotThrow();

[TestMethod]
public void InstallNSwag_Returns_Path()
=> new Action(DependencyDownloader.InstallNSwag)
.Should()
.NotThrow();
}
}
35 changes: 35 additions & 0 deletions src/ApiClientCodeGen.Tests/NpmHelperTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using System.IO;
using ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Core;
using FluentAssertions;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace ChristianHelle.DeveloperTools.CodeGenerators.ApiClient.Tests
{
[TestClass]
public class NpmHelperTests
{
[TestMethod]
public void Can_GetNpmPath()
=> NpmHelper.GetNpmPath()
.Should()
.NotBeNullOrWhiteSpace();

[TestMethod]
public void FileExists_GetNpmPath()
=> File.Exists(NpmHelper.GetNpmPath())
.Should()
.BeTrue();

[TestMethod]
public void Can_GetNpmPrefixPath()
=> NpmHelper.GetPrefixPath()
.Should()
.NotBeNullOrWhiteSpace();

[TestMethod]
public void DirectoryExists_GetNpmPrefixPath()
=> Directory.Exists(NpmHelper.GetPrefixPath())
.Should()
.BeTrue();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public void NSwagPath_NotNullOrWhiteSpace()

[TestMethod]
public void NSwagPath_Reads_From_Options()
=> sut.NSwagPath.Should().Be(PathProvider.GetNSwagPath());
=> sut.NSwagPath.Should().Be(PathProvider.GetNSwagStudioPath());

[TestMethod]
public void SwaggerCodegenPath_NotNullOrWhiteSpace()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public CustomPathOptions(IGeneralOptions options = null)
{
JavaPath = PathProvider.GetJavaPath();
NpmPath = PathProvider.GetNpmPath();
NSwagPath = PathProvider.GetNSwagPath();
NSwagPath = PathProvider.GetNSwagStudioPath();
SwaggerCodegenPath = PathProvider.GetSwaggerCodegenPath();
OpenApiGeneratorPath = PathProvider.GetOpenApiGeneratorPath();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ public GeneralOptionPage()
{
JavaPath = PathProvider.GetJavaPath();
NpmPath = PathProvider.GetNpmPath();
NSwagPath = PathProvider.GetNSwagPath();
NSwagPath = PathProvider.GetNSwagStudioPath();
}

[Category("File Paths")]
Expand All @@ -31,7 +31,7 @@ public GeneralOptionPage()

[Category("File Paths")]
[DisplayName("NSwag Path")]
[Description("Full path to nswag.exe")]
[Description("Full path to NSwag.exe (Installs from NPM if not found)")]
public string NSwagPath { get; set; }

[Category("File Paths")]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
<Compile Include="CustomTool\CSharpSingleFileCodeGenerator.cs" />
<None Include="CustomTool\VisualBasicSingleFileCodeGeneratorTests.cs" />
<None Include="CustomTool\VisualBasicSingleFileCodeGenerator.cs" />
<Compile Include="DependencyDownloaderTests.cs" />
<Compile Include="Generators\NSwagStudioCodeGeneratorBuildTests.cs" />
<Compile Include="GlobalSuppressions.cs" />
<None Include="VisualBasic\AutoRestVisualBasicCodeGeneratorTests.cs" />
Expand Down

0 comments on commit 8f116eb

Please sign in to comment.