diff --git a/source/Cosmos.Build.Builder/CosmosBuildDefinition.cs b/source/Cosmos.Build.Builder/CosmosBuildDefinition.cs index e0d091908..9293f1ca3 100644 --- a/source/Cosmos.Build.Builder/CosmosBuildDefinition.cs +++ b/source/Cosmos.Build.Builder/CosmosBuildDefinition.cs @@ -16,6 +16,8 @@ namespace Cosmos.Build.Builder private IMSBuildService _msBuildService; private ISetupInstance2 _visualStudioInstance; + private readonly string _cosmosDir; + public CosmosBuildDefinition( IInnoSetupService innoSetupService, IMSBuildService msBuildService, @@ -24,10 +26,18 @@ namespace Cosmos.Build.Builder _innoSetupService = innoSetupService; _msBuildService = msBuildService; _visualStudioInstance = visualStudioInstance; + + _cosmosDir = Path.GetFullPath(Directory.GetCurrentDirectory()); + + if (!Directory.Exists(Path.Combine(_cosmosDir, "source", "Cosmos.Build.Builder"))) + { + _cosmosDir = Path.GetFullPath(Path.Combine(_cosmosDir, "..", "..", "..", "..", "..")); + } } public IEnumerable GetDependencies() { + yield return new ReposDependency(_cosmosDir); yield return new VisualStudioDependency(_visualStudioInstance); yield return new VisualStudioWorkloadsDependency(_visualStudioInstance); yield return new InnoSetupDependency(_innoSetupService); @@ -59,24 +69,17 @@ namespace Cosmos.Build.Builder } } - var cosmosDir = Path.GetFullPath(Directory.GetCurrentDirectory()); + var il2cpuDir = Path.GetFullPath(Path.Combine(_cosmosDir, "..", "IL2CPU")); + var xsharpDir = Path.GetFullPath(Path.Combine(_cosmosDir, "..", "XSharp")); - if (!Directory.Exists(Path.Combine(cosmosDir, "source", "Cosmos.Build.Builder"))) - { - cosmosDir = Path.GetFullPath(Path.Combine(cosmosDir, "..", "..", "..", "..", "..")); - } - - var il2cpuDir = Path.GetFullPath(Path.Combine(cosmosDir, "..", "IL2CPU")); - var xsharpDir = Path.GetFullPath(Path.Combine(cosmosDir, "..", "XSharp")); - - var cosmosSourceDir = Path.Combine(cosmosDir, "source"); + var cosmosSourceDir = Path.Combine(_cosmosDir, "source"); var il2cpuSourceDir = Path.Combine(il2cpuDir, "source"); - var buildSlnPath = Path.Combine(cosmosDir, "Build.sln"); + var buildSlnPath = Path.Combine(_cosmosDir, "Build.sln"); var il2cpuSlnPath = Path.Combine(il2cpuDir, "IL2CPU.sln"); var xsharpSlnPath = Path.Combine(xsharpDir, "XSharp.sln"); - var vsipDir = Path.Combine(cosmosDir, "Build", "VSIP"); + var vsipDir = Path.Combine(_cosmosDir, "Build", "VSIP"); if (Directory.Exists(vsipDir)) { @@ -136,7 +139,7 @@ namespace Cosmos.Build.Builder yield return new PackTask(_msBuildService, projectPath, packagesDir); } - var cosmosSetupDir = Path.Combine(cosmosDir, "setup"); + var cosmosSetupDir = Path.Combine(_cosmosDir, "setup"); // Create Setup @@ -159,7 +162,7 @@ namespace Cosmos.Build.Builder using (var xKey = Microsoft.Win32.Registry.CurrentUser.CreateSubKey(@"Software\Cosmos")) { - xKey.SetValue("DevKit", cosmosDir); + xKey.SetValue("DevKit", _cosmosDir); } // Launch VS @@ -169,7 +172,7 @@ namespace Cosmos.Build.Builder var vsInstance = _visualStudioInstance; var vsPath = Path.Combine(vsInstance.GetInstallationPath(), "Common7", "IDE", "devenv.exe"); - var kernelSlnPath = Path.Combine(cosmosDir, "Kernel.sln"); + var kernelSlnPath = Path.Combine(_cosmosDir, "Kernel.sln"); yield return new StartProcessTask(vsPath, kernelSlnPath, "Visual Studio (Kernel.sln)"); } diff --git a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs index 3e08f8c5d..c1bade0ec 100644 --- a/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/InnoSetupDependency.cs @@ -47,6 +47,11 @@ namespace Cosmos.Build.Builder.Dependencies var process = Process.Start(setupFilePath); await Task.Run((Action)process.WaitForExit, cancellationToken).ConfigureAwait(false); + + if (process.ExitCode != 0) + { + throw new Exception("The process failed to execute!"); + } } } } diff --git a/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs new file mode 100644 index 000000000..4728438aa --- /dev/null +++ b/source/Cosmos.Build.Builder/Dependencies/ReposDependency.cs @@ -0,0 +1,90 @@ +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net.Http; +using System.Threading; +using System.Threading.Tasks; + +namespace Cosmos.Build.Builder.Dependencies +{ + internal class ReposDependency : IDependency + { + public string Name => "Repos: IL2CPU and XSharp"; + + private readonly string _cosmosDir; + private readonly IEnumerable _repos; + + public ReposDependency(string cosmosDir) + { + _cosmosDir = cosmosDir; + + _repos = new List() + { + new Repo( + Path.GetFullPath(Path.Combine(cosmosDir, "..", "IL2CPU")), + "https://github.com/CosmosOS/IL2CPU"), + new Repo( + Path.GetFullPath(Path.Combine(cosmosDir, "..", "XSharp")), + "https://github.com/CosmosOS/XSharp") + }; + } + + public Task IsInstalledAsync(CancellationToken cancellationToken) + { + return Task.FromResult(_repos.All(r => Directory.Exists(r.LocalPath))); + } + + public Task InstallAsync(CancellationToken cancellationToken) + { + var usesGit = Directory.Exists(Path.Combine(_cosmosDir, ".git")); + return Task.WhenAll(_repos + .Where(r => !Directory.Exists(r.LocalPath)) + .Select(r => DownloadRepoAsync(r, usesGit, cancellationToken))); + } + + private async Task DownloadRepoAsync(Repo repo, bool useGit, CancellationToken cancellationToken) + { + if (useGit) + { + var process = Process.Start("git", $"clone \"{repo.Url}.git\" \"{repo.LocalPath}\""); + await Task.Run((Action)process.WaitForExit).ConfigureAwait(false); + + if (process.ExitCode != 0) + { + throw new Exception("The process failed to execute!"); + } + } + else + { + using (var httpClient = new HttpClient()) + { + var uri = new Uri(new Uri($"{repo.Url}/"), "archive/master.zip"); + var httpMessage = await httpClient.GetAsync(uri, cancellationToken).ConfigureAwait(false); + + var zipStream = await httpMessage.Content.ReadAsStreamAsync().ConfigureAwait(false); + var zipArchive = new ZipArchive(zipStream); + + var tempPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString()); + + zipArchive.ExtractToDirectory(tempPath); + Directory.Move(Directory.GetFileSystemEntries(tempPath).Single(), repo.LocalPath); + } + } + } + + private class Repo + { + public string LocalPath { get; } + public string Url { get; } + + public Repo(string localPath, string url) + { + LocalPath = localPath; + Url = url; + } + } + } +} diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs index 4dd233b00..6594b3f2e 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioDependency.cs @@ -32,7 +32,7 @@ namespace Cosmos.Build.Builder.Dependencies return Task.FromResult(false); } - public Task InstallAsync(CancellationToken cancellationToken) + public async Task InstallAsync(CancellationToken cancellationToken) { var vsInstallerPath = Environment.ExpandEnvironmentVariables( @"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vs_installershell.exe"); @@ -41,7 +41,12 @@ namespace Cosmos.Build.Builder.Dependencies var args = $"update --passive --norestart --wait --installPath \"{vsInstancePath}\""; var process = Process.Start(vsInstallerPath, args); - return Task.Run((Action)process.WaitForExit, cancellationToken); + await Task.Run((Action)process.WaitForExit, cancellationToken).ConfigureAwait(false); + + if (process.ExitCode != 0) + { + throw new Exception("The process failed to execute!"); + } } } } diff --git a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs index d5c3ee54b..e07c63a90 100644 --- a/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs +++ b/source/Cosmos.Build.Builder/Dependencies/VisualStudioWorkloadsDependency.cs @@ -33,7 +33,7 @@ namespace Cosmos.Build.Builder.Dependencies return Task.FromResult(RequiredPackages.All(p => IsPackageInstalled(p))); } - public Task InstallAsync(CancellationToken cancellationToken) + public async Task InstallAsync(CancellationToken cancellationToken) { var vsInstallerPath = Environment.ExpandEnvironmentVariables( @"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vs_installershell.exe"); @@ -52,7 +52,12 @@ namespace Cosmos.Build.Builder.Dependencies } var process = Process.Start(vsInstallerPath, args); - return Task.Run((Action)process.WaitForExit, cancellationToken); + await Task.Run((Action)process.WaitForExit, cancellationToken).ConfigureAwait(false); + + if (process.ExitCode != 0) + { + throw new Exception("The process failed to execute!"); + } } private bool IsPackageInstalled(string packageId) =>