2017-11-27 10:45:43 -08:00
|
|
|
|
// Copyright (c) .NET Foundation and contributors. All rights reserved.
|
|
|
|
|
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
|
|
|
|
|
|
|
|
using System;
|
|
|
|
|
using System.IO;
|
2018-01-18 14:54:10 -08:00
|
|
|
|
using System.Linq;
|
2017-11-27 10:45:43 -08:00
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
using System.Text;
|
2018-01-18 14:54:10 -08:00
|
|
|
|
using System.Xml.Linq;
|
2017-11-27 10:45:43 -08:00
|
|
|
|
using Microsoft.DotNet.Cli.Utils;
|
2018-01-13 09:40:48 -08:00
|
|
|
|
using Microsoft.DotNet.Tools;
|
2017-11-27 10:45:43 -08:00
|
|
|
|
using Microsoft.Extensions.EnvironmentAbstractions;
|
|
|
|
|
|
2017-12-04 14:13:24 -08:00
|
|
|
|
namespace Microsoft.DotNet.ShellShim
|
2017-11-27 10:45:43 -08:00
|
|
|
|
{
|
|
|
|
|
public class ShellShimMaker
|
|
|
|
|
{
|
2018-01-19 13:28:13 -08:00
|
|
|
|
private const string LauncherExeResourceName = "Microsoft.DotNet.Tools.Launcher.Executable";
|
|
|
|
|
private const string LauncherConfigResourceName = "Microsoft.DotNet.Tools.Launcher.Config";
|
2018-01-18 14:54:10 -08:00
|
|
|
|
|
2017-11-27 10:45:43 -08:00
|
|
|
|
private readonly string _pathToPlaceShim;
|
|
|
|
|
|
|
|
|
|
public ShellShimMaker(string pathToPlaceShim)
|
|
|
|
|
{
|
|
|
|
|
_pathToPlaceShim =
|
|
|
|
|
pathToPlaceShim ?? throw new ArgumentNullException(nameof(pathToPlaceShim));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void CreateShim(string packageExecutablePath, string shellCommandName)
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
FilePath shimPath = GetShimPath(shellCommandName);
|
2017-11-27 10:45:43 -08:00
|
|
|
|
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
CreateConfigFile(shimPath.Value + ".config", entryPoint: packageExecutablePath, runner: "dotnet");
|
|
|
|
|
using (var shim = File.Create(shimPath.Value))
|
2018-01-19 13:28:13 -08:00
|
|
|
|
using (var exe = typeof(ShellShimMaker).Assembly.GetManifestResourceStream(LauncherExeResourceName))
|
2018-01-18 14:54:10 -08:00
|
|
|
|
{
|
|
|
|
|
exe.CopyTo(shim);
|
|
|
|
|
}
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
var packageExecutable = new FilePath(packageExecutablePath);
|
|
|
|
|
|
|
|
|
|
var script = new StringBuilder();
|
2017-11-27 10:45:43 -08:00
|
|
|
|
script.AppendLine("#!/bin/sh");
|
|
|
|
|
script.AppendLine($"dotnet {packageExecutable.ToQuotedString()} \"$@\"");
|
|
|
|
|
|
2018-01-18 14:54:10 -08:00
|
|
|
|
File.WriteAllText(shimPath.Value, script.ToString());
|
2017-11-27 10:45:43 -08:00
|
|
|
|
|
2018-01-18 14:54:10 -08:00
|
|
|
|
SetUserExecutionPermissionToShimFile(shimPath);
|
|
|
|
|
}
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void EnsureCommandNameUniqueness(string shellCommandName)
|
|
|
|
|
{
|
|
|
|
|
if (File.Exists(Path.Combine(_pathToPlaceShim, shellCommandName)))
|
|
|
|
|
{
|
|
|
|
|
throw new GracefulException(
|
2018-01-13 09:40:48 -08:00
|
|
|
|
string.Format(CommonLocalizableStrings.FailInstallToolSameName,
|
|
|
|
|
shellCommandName));
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2018-01-18 14:54:10 -08:00
|
|
|
|
internal void CreateConfigFile(string outputPath, string entryPoint, string runner)
|
|
|
|
|
{
|
|
|
|
|
XDocument config;
|
2018-01-19 13:28:13 -08:00
|
|
|
|
using (var resource = typeof(ShellShimMaker).Assembly.GetManifestResourceStream(LauncherConfigResourceName))
|
2018-01-18 14:54:10 -08:00
|
|
|
|
{
|
|
|
|
|
config = XDocument.Load(resource);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var appSettings = config.Descendants("appSettings").First();
|
|
|
|
|
appSettings.Add(new XElement("add", new XAttribute("key", "entryPoint"), new XAttribute("value", entryPoint)));
|
|
|
|
|
appSettings.Add(new XElement("add", new XAttribute("key", "runner"), new XAttribute("value", runner ?? string.Empty)));
|
|
|
|
|
config.Save(outputPath);
|
|
|
|
|
}
|
|
|
|
|
|
2017-11-27 10:45:43 -08:00
|
|
|
|
public void Remove(string shellCommandName)
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
File.Delete(GetShimPath(shellCommandName).Value);
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
|
2018-01-18 14:54:10 -08:00
|
|
|
|
private FilePath GetShimPath(string shellCommandName)
|
2017-11-27 10:45:43 -08:00
|
|
|
|
{
|
|
|
|
|
var scriptPath = Path.Combine(_pathToPlaceShim, shellCommandName);
|
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
scriptPath += ".exe";
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return new FilePath(scriptPath);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static void SetUserExecutionPermissionToShimFile(FilePath scriptPath)
|
|
|
|
|
{
|
2018-01-18 14:54:10 -08:00
|
|
|
|
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
|
|
|
|
return;
|
2017-11-27 10:45:43 -08:00
|
|
|
|
|
|
|
|
|
CommandResult result = new CommandFactory()
|
2018-01-18 14:54:10 -08:00
|
|
|
|
.Create("chmod", new[] { "u+x", scriptPath.Value })
|
2017-11-27 10:45:43 -08:00
|
|
|
|
.CaptureStdOut()
|
|
|
|
|
.CaptureStdErr()
|
|
|
|
|
.Execute();
|
|
|
|
|
|
|
|
|
|
if (result.ExitCode != 0)
|
|
|
|
|
{
|
|
|
|
|
throw new GracefulException(
|
2018-01-13 09:40:48 -08:00
|
|
|
|
string.Format(CommonLocalizableStrings.FailInstallToolPermission, result.StdErr,
|
|
|
|
|
result.StdOut));
|
2017-11-27 10:45:43 -08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|