Skip to content

Commit

Permalink
SolutionRun utilizes dotnet run
Browse files Browse the repository at this point in the history
Removes lots of extra wiring needed for path to exe features
  • Loading branch information
Noggog committed Oct 11, 2020
1 parent 79bdac2 commit 68208d0
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 133 deletions.
3 changes: 1 addition & 2 deletions Synthesis.Bethesda.Execution/CLI/RunPatcherPipeline.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,8 +83,7 @@ public static async Task Run(RunPatcherPipelineInstructions run, IRunReporter? r
SolutionPatcherSettings sln => new SolutionPatcherRun(
nickname: sln.Nickname,
pathToSln: sln.SolutionPath,
pathToProj: Path.Combine(Path.GetDirectoryName(sln.SolutionPath)!, sln.ProjectSubpath),
pathToExe: null),
pathToProj: Path.Combine(Path.GetDirectoryName(sln.SolutionPath)!, sln.ProjectSubpath)),
GithubPatcherSettings git => new GitPatcherRun(
settings: git,
localDir: GitPatcherRun.RunnerRepoDirectory(profile.ID, git.ID)),
Expand Down
3 changes: 1 addition & 2 deletions Synthesis.Bethesda.Execution/Patcher Runs/GitPatcherRun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,8 +63,7 @@ public async Task Prep(GameRelease release, CancellationToken? cancel = null)
SolutionRun = new SolutionPatcherRun(
_settings.Nickname,
pathToSln: Path.Combine(_localDir, pathToSln),
pathToProj: pathToProj,
pathToExe: null);
pathToProj: pathToProj);
using var outputSub = SolutionRun.Output.Subscribe(this._output);
using var errSub = SolutionRun.Error.Subscribe(this._error);
await SolutionRun.Prep(release, cancel).ConfigureAwait(false);
Expand Down
87 changes: 21 additions & 66 deletions Synthesis.Bethesda.Execution/Patcher Runs/SolutionPatcherRun.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
using Buildalyzer;
using Buildalyzer.Environment;
using CommandLine;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Emit;
using Microsoft.CodeAnalysis.MSBuild;
using Mutagen.Bethesda;
using Mutagen.Bethesda.Synthesis.CLI;
using Noggog;
using Noggog.Utility;
using Synthesis.Bethesda.Execution.Patchers;
Expand All @@ -26,8 +28,6 @@ public class SolutionPatcherRun : IPatcherRun
public string Name { get; }
public string PathToSolution { get; }
public string PathToProject { get; }
public string? PathToExe { get; }
public CliPatcherRun? CliRun { get; private set; }

private Subject<string> _output = new Subject<string>();
public IObservable<string> Output => _output;
Expand All @@ -38,35 +38,15 @@ public class SolutionPatcherRun : IPatcherRun
public SolutionPatcherRun(
string nickname,
string pathToSln,
string pathToProj,
string? pathToExe)
string pathToProj)
{
PathToSolution = pathToSln;
PathToProject = pathToProj;
PathToExe = pathToExe;
Name = nickname ?? $"{Path.GetFileNameWithoutExtension(pathToSln)}/{Path.GetFileNameWithoutExtension(pathToProj)}";
}

public async Task Prep(GameRelease release, CancellationToken? cancel = null)
{
var pathToExe = PathToExe;
if (pathToExe == null)
{
_output.OnNext($"Locating path to exe based on proj path {PathToProject}");
var pathToExeGet = await GetPathToExe(PathToProject, cancel ?? CancellationToken.None);
if (pathToExeGet.Failed)
{
throw pathToExeGet.Exception ?? throw new ArgumentException("Could not find path to exe");
}
pathToExe = pathToExeGet.Value;
_output.OnNext($"Located path to exe: {pathToExe}");
}

CliRun = new CliPatcherRun(
nickname: Name,
pathToExecutable: pathToExe,
pathToExtra: Path.Combine(Path.GetDirectoryName(PathToProject), "Data"));

_output.OnNext($"Compiling");
var resp = await CompileWithDotnet(PathToProject, cancel ?? CancellationToken.None).ConfigureAwait(false);
if (!resp.Succeeded)
Expand All @@ -78,13 +58,26 @@ public async Task Prep(GameRelease release, CancellationToken? cancel = null)

public async Task Run(RunSynthesisPatcher settings, CancellationToken? cancel = null)
{
if (CliRun == null)
var internalSettings = new RunSynthesisMutagenPatcher()
{
throw new SynthesisBuildFailure("Expected CLI Run object did not exist.");
DataFolderPath = settings.DataFolderPath,
ExtraSettingsPath = Path.Combine(Path.GetDirectoryName(PathToProject), "Data"),
GameRelease = settings.GameRelease,
LoadOrderFilePath = settings.LoadOrderFilePath,
OutputPath = settings.OutputPath,
SourcePath = settings.SourcePath
};
var args = Parser.Default.FormatCommandLine(internalSettings);
using var process = ProcessWrapper.Start(
new ProcessStartInfo("dotnet", $"run --project \"{PathToProject}\" --no-build {args}"),
cancel: cancel);
using var outputSub = process.Output.Subscribe(_output);
using var errSub = process.Error.Subscribe(_error);
var result = await process.Start().ConfigureAwait(false);
if (result != 0)
{
throw new CliUnsuccessfulRunException(result, "Error running solution patcher");
}
using var outputSub = CliRun.Output.Subscribe(_output);
using var errSub = CliRun.Error.Subscribe(_error);
await CliRun.Run(settings, cancel).ConfigureAwait(false);
}

public void Dispose()
Expand Down Expand Up @@ -154,44 +147,6 @@ public static async Task<ErrorResponse> CompileWithDotnet(string url, Cancellati
return ErrorResponse.Fail(reason: firstError ?? "Unknown Error");
}

public static async Task<GetResponse<string>> GetPathToExe(string projectPath, CancellationToken cancel)
{
try
{
cancel.ThrowIfCancellationRequested();
if (!File.Exists(projectPath))
{
return GetResponse<string>.Fail("Project path does not exist.");
}

// Right now this is slow as it cleans the build results unnecessarily. Need to look into that
var manager = new AnalyzerManager();
cancel.ThrowIfCancellationRequested();
var proj = manager.GetProject(projectPath);
cancel.ThrowIfCancellationRequested();
var opt = new EnvironmentOptions();
opt.TargetsToBuild.SetTo("Build");
var build = proj.Build();
cancel.ThrowIfCancellationRequested();
var results = build.Results.ToArray();
if (results.Length != 1)
{
return GetResponse<string>.Fail("Unsupported number of build results.");
}
var result = results[0];
if (!result.Properties.TryGetValue("RunCommand", out var cmd))
{
return GetResponse<string>.Fail("Could not find executable to be run");
}

return GetResponse<string>.Succeed(cmd);
}
catch (Exception ex)
{
return GetResponse<string>.Fail(ex);
}
}

public static IEnumerable<string> AvailableProjects(string solutionPath)
{
if (!File.Exists(solutionPath)) return Enumerable.Empty<string>();
Expand Down
15 changes: 0 additions & 15 deletions Synthesis.Bethesda.GUI/ViewModels/Config/GitPatcherVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,6 @@ public class GitPatcherVM : PatcherVM
private readonly ObservableAsPropertyHelper<RunnerRepoInfo?> _RunnableData;
public RunnerRepoInfo? RunnableData => _RunnableData.Value;

private readonly ObservableAsPropertyHelper<string> _ExePath;
public string ExePath => _ExePath.Value;

public ICommand OpenGitPageCommand { get; }

public ICommand OpenGitPageToVersionCommand { get; }
Expand Down Expand Up @@ -351,17 +348,6 @@ async Task<GetResponse<RunnerRepoInfo>> Execute()
.Select(x => x.RunnableState.Succeeded ? x.Item : default(RunnerRepoInfo?))
.ToGuiProperty(this, nameof(RunnableData));

_ExePath = runnableState
.SelectReplace(async (x, cancel) =>
{
if (x.RunnableState.Failed) return string.Empty;
using var timing = Logger.Time($"locate path to exe from {x.Item.ProjPath}");
var exePath = await SolutionPatcherRun.GetPathToExe(x.Item.ProjPath, cancel);
if (exePath.Failed) return string.Empty;
return exePath.Value;
})
.ToGuiProperty<string>(this, nameof(ExePath));

_State = Observable.CombineLatest(
driverRepoInfo
.Select(x => x.ToUnit()),
Expand Down Expand Up @@ -449,7 +435,6 @@ public override PatcherRunVM ToRunner(PatchersRunVM parent)
this,
new SolutionPatcherRun(
nickname: DisplayName,
pathToExe: ExePath,
pathToSln: RunnableData.SolutionPath,
pathToProj: SelectedProjectPath.TargetPath));
}
Expand Down
49 changes: 1 addition & 48 deletions Synthesis.Bethesda.GUI/ViewModels/Config/SolutionPatcherVM.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,6 @@ public class SolutionPatcherVM : PatcherVM
[Reactive]
public string ProjectSubpath { get; set; } = string.Empty;

private readonly ObservableAsPropertyHelper<string> _PathToExe;
public string PathToExe => _PathToExe.Value;

public PathPickerVM SelectedProjectPath { get; } = new PathPickerVM()
{
ExistCheckOption = PathPickerVM.CheckOptions.On,
Expand Down Expand Up @@ -100,55 +97,12 @@ public SolutionPatcherVM(ProfileVM parent, SolutionPatcherSettings? settings = n
.Subscribe(p => SelectedProjectPath.TargetPath = p)
.DisposeWith(this);

var pathToExe = projPath
.ObserveOn(RxApp.TaskpoolScheduler)
.SelectReplaceWithIntermediate(
new ConfigurationStateVM<string>(default!)
{
IsHaltingError = false,
RunnableState = ErrorResponse.Fail("Locating exe to run.")
},
async (projectPath, cancel) =>
{
GetResponse<string> exe;
using (Log.Logger.Time($"locate path to exe from {projectPath}"))
{
exe = await SolutionPatcherRun.GetPathToExe(projectPath, cancel);
if (exe.Failed) return new ConfigurationStateVM<string>(exe.BubbleFailure<string>());
}

using (Logger.Time($"building {projectPath}"))
{
// Now we want to build, just to prep for run
var build = await SolutionPatcherRun.CompileWithDotnet(projectPath, cancel).ConfigureAwait(false);
if (build.Failed) return new ConfigurationStateVM<string>(build.BubbleFailure<string>());
}

return new ConfigurationStateVM<string>(exe);
})
.Replay(1)
.RefCount();

_PathToExe = pathToExe
.Select(r => r.Item ?? string.Empty)
.ToGuiProperty<string>(this, nameof(PathToExe));

_State = Observable.CombineLatest(
this.WhenAnyValue(x => x.SolutionPath.ErrorState),
this.WhenAnyValue(x => x.SelectedProjectPath.ErrorState),
Observable.Merge(
projPath
.Select(_ => new ConfigurationStateVM()
{
IsHaltingError = false,
RunnableState = ErrorResponse.Fail("Building")
}),
pathToExe
.Select(i => i.ToUnit())),
(sln, proj, exe) =>
(sln, proj) =>
{
if (sln.Failed) return new ConfigurationStateVM(sln);
if (exe.RunnableState.Failed) return exe;
return new ConfigurationStateVM(proj);
})
.ToGuiProperty<ConfigurationStateVM>(this, nameof(State), ConfigurationStateVM.Success);
Expand Down Expand Up @@ -279,7 +233,6 @@ public override PatcherRunVM ToRunner(PatchersRunVM parent)
new SolutionPatcherRun(
nickname: DisplayName,
pathToSln: SolutionPath.TargetPath,
pathToExe: PathToExe,
pathToProj: SelectedProjectPath.TargetPath));
}

Expand Down

0 comments on commit 68208d0

Please sign in to comment.