111 lines
3.5 KiB
C#
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;
|
|
}
|
|
}
|
|
}
|