This repository has been archived on 2023-02-02. You can view files and clone it, but cannot push or open issues or pull requests.
mfgames-nitride-cil/src/Nitride.Javascript/InstallYarn.cs
Dylan R. E. Moonfire 78054ee2a7 feat: initial release
2021-09-07 00:15:45 -05:00

111 lines
3.5 KiB
C#

using System;
using System.Collections.Generic;
using System.Diagnostics;
using Gallium;
using Serilog;
using Zio;
namespace Nitride.Javascript
{
/// <summary>
/// Installs Yarn in a given directory if it is missing. If the
/// `node_modules` is already there, this step is skipped unless
/// ForceInstall is set to true.
/// </summary>
[WithProperties]
public partial class InstallYarn : INitrideOperation
{
private readonly IFileSystem fileSystem;
private readonly ILogger logger;
public InstallYarn(ILogger logger, IFileSystem fileSystem)
{
this.fileSystem = fileSystem;
this.logger = logger.ForContext<InstallYarn>();
this.Directory = "/";
}
/// <summary>
/// Gets or sets the directory that the install should be run from. This
/// is typically the same file as the package.json and the yarn.lock.
/// </summary>
public UPath? Directory { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the install should be
/// forced.
/// </summary>
public bool ForceInstall { get; set; }
/// <inheritdoc />
public IEnumerable<Entity> Run(IEnumerable<Entity> input)
{
// Make sure we have a sane value.
if (!this.Directory.HasValue)
{
throw new InvalidOperationException(
nameof(InstallYarn)
+ ".Directory was not set before Run() was called.");
}
// Make sure the directory exists in case we are the first.
UPath directory = this.Directory.Value;
if (!this.fileSystem.DirectoryExists(directory))
{
this.logger.Information("Creating directory {Path}", directory);
this.fileSystem.CreateDirectory(directory);
}
// Check to see if the directory exists.
UPath modulesPath = directory / "node_modules";
bool exists = this.fileSystem.DirectoryExists(modulesPath);
if (exists)
{
if (!this.ForceInstall)
{
this.logger.Debug(
"{Path} already exists, skipping",
modulesPath);
return input;
}
this.logger.Information(
"{Path} already exists, forcing installation",
modulesPath);
this.fileSystem.DeleteDirectory(modulesPath, true);
}
// Run Yarn install on the directory. Sadly, Yarn doesn't understand
// a C# abstraction layer, so we need the "real" path to work with
// these operations.
string realPath = this.fileSystem
.ConvertPathToInternal(directory);
// Run the install.
string command = YarnHelper.GetYarnCommand();
var start = new ProcessStartInfo
{
FileName = command,
Arguments = "install",
WorkingDirectory = realPath,
RedirectStandardOutput = true,
};
Process process = Process.Start(start);
if (process == null)
{
throw new InvalidOperationException(
"Cannot start yarn install");
}
process.WaitForExit();
// We are done, so just pass our input on.
return input;
}
}
}