Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Initial support for overriding the location of cake.exe the TRX uses #105

Merged
merged 1 commit into from
Mar 21, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/Cake.VisualStudio.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
<Compile Include="Configuration\BindingParser.cs" />
<Compile Include="Configuration\ConfigurationExtensions.cs" />
<Compile Include="Configuration\ConfigurationParser.cs" />
<Compile Include="Configuration\ToolLocator.cs" />
<Compile Include="ContentType\CakeContentTypeDefinition.cs" />
<Compile Include="Editor\IndentationResult.cs" />
<Compile Include="Editor\LineExtensions.cs" />
Expand Down
50 changes: 50 additions & 0 deletions src/Configuration/ConfigurationParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,20 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Cake.VisualStudio.Helpers;
using IniParser;
using IniParser.Model.Configuration;
using IniParser.Parser;
using System.IO;
using System.Linq;

namespace Cake.VisualStudio.Configuration
{
internal sealed class ConfigurationParser
{
private static IniDataParser Parser => new IniDataParser(new IniParserConfiguration {AssigmentSpacer = ""});
internal string SectionName { get; set; } = "TaskRunnerBindings";

public ConfigurationParser(string filePath)
{
FilePath = filePath;
Expand Down Expand Up @@ -46,5 +50,51 @@ internal void RemoveBindings()
var removeSection = data.Sections.RemoveSection(SectionName);
parser.WriteFile(FilePath, data);
}

/// <summary>
/// Gets a key from the Paths section of cake.config
/// </summary>
/// <param name="key">The key to retrieve.</param>
/// <returns>The config value</returns>
/// <remarks>
/// This defaults the key to Tools since that's what we're using currently.
/// I've left this an argument in case we add a non-standard key to cake.config to specifically override VS.
/// </remarks>
internal string GetToolsPath(string key = "Tools")
{
var parser = new FileIniDataParser(Parser);
var data = parser.ReadFile(FilePath);
if (data.Sections.ContainsSection("Paths"))
{
return data["Paths"].ReadValues(key).LastOrDefault();
}
return null;
}

internal static string GetConfigFilePath(string configPath, bool create = false)
{
string bindingPath;
var path = CakePackage.Dte?.Solution?.FindProjectItem(Constants.ConfigFileName);
if (path != null && path.FileCount == 1)
{
bindingPath = path.FileNames[1];
}
else
{
var cpath = Path.Combine(Path.GetDirectoryName(configPath), Constants.ConfigFileName);
try
{

if (!File.Exists(cpath) && create) File.Create(cpath).Close();
if (File.Exists(cpath)) ProjectHelpers.GetSolutionItemsProject(CakePackage.Dte).AddFileToProject(cpath);
}
catch
{
// ignored
}
bindingPath = cpath;
}
return string.IsNullOrWhiteSpace(bindingPath) ? null : bindingPath; // remove the empty string scenario
}
}
}
67 changes: 67 additions & 0 deletions src/Configuration/ToolLocator.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using Cake.VisualStudio.Helpers;
using Microsoft.VisualStudio.Shell;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Cake.VisualStudio.Configuration
{
internal sealed class ToolLocator
{
private readonly string _executable;
private List<string> KnownPaths { get; set; } = new List<string>();

public ToolLocator(string executableName)
{
_executable = executableName;
}

public ToolLocator AddEnvironmentVariables(string variable = "CAKE_PATHS_TOOLS")
{
var env = Environment.GetEnvironmentVariable(variable);
if (!string.IsNullOrWhiteSpace(env) && Directory.Exists(env))
{
KnownPaths.Add(env);
}
return this;
}

public ToolLocator AddKnownPaths(params string[] paths)
{
KnownPaths.AddRange(paths);
return this;
}

public ToolLocator AddConfigPath(Func<ConfigurationParser> configFunc)
{
var path = configFunc?.Invoke()?.GetToolsPath();
if (path != null)
{
KnownPaths.Add(path);
KnownPaths.Add(Path.Combine(path, "Cake"));
}
return this;
}

public string Locate(string workingDirectory)
{
foreach (var path in KnownPaths.Select(p => p.TrimPrefix("./")))
{
var fullPath = Path.Combine(workingDirectory, path, _executable);
if (File.Exists(fullPath)) return fullPath;
}
if (PathHelpers.ExistsOnPath(_executable))
{
return _executable; // assume PATH
}
return null;
}
}
}
35 changes: 11 additions & 24 deletions src/TaskRunner/TaskRunner.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
using System.Threading.Tasks;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Cake.VisualStudio.Configuration;
using Cake.VisualStudio.Helpers;
using Microsoft.VisualStudio.TaskRunnerExplorer;

Expand Down Expand Up @@ -82,19 +83,6 @@ private ITaskRunnerNode NotFoundNode(string configPath)
Description = message,
Command = new TaskRunnerCommand(Path.GetDirectoryName(configPath), "echo", message),
};
/*
* return new TaskRunnerNode("Cake")
{
Children =
{
new TaskRunnerNode("Cake.exe not found", true)
{
Description = message,
Command = new TaskRunnerCommand(Path.GetDirectoryName(configPath), "echo", message),
}
}
};
*/
}

private ITaskRunnerNode LoadHierarchy(string configPath)
Expand Down Expand Up @@ -141,17 +129,16 @@ private ITaskRunnerCommand GetCommand(string cwd, string arguments)

private static string GetCakePath(string cwd)
{
var knownPaths = new[] {"tools/Cake/Cake.exe", "Cake/Cake.exe", "Cake.exe"};
foreach (var path in knownPaths)
{
var fullPath = Path.Combine(cwd, path);
if (File.Exists(fullPath)) return fullPath;
}
if (PathHelpers.ExistsOnPath("cake.exe") || PathHelpers.ExistsOnPath("cake"))
{
return "cake"; // assume PATH
}
return null;
var locator = new ToolLocator("cake.exe")
.AddConfigPath(() => new ConfigurationParser(ConfigurationParser.GetConfigFilePath(cwd)))
.AddEnvironmentVariables()
.AddKnownPaths("tools/Cake", "Cake", ".");
var path = locator.Locate(cwd);
return string.IsNullOrWhiteSpace(path)
? PathHelpers.ExistsOnPath("cake.exe")
? "cake"
: null
: path;
}

private static string GetExecutableFolder()
Expand Down
31 changes: 2 additions & 29 deletions src/TaskRunner/TaskRunnerConfig.cs
Original file line number Diff line number Diff line change
Expand Up @@ -35,40 +35,13 @@ public void Dispose()

public string LoadBindings(string configPath)
{
string bindingPath = GetBindingPath(configPath) ?? configPath + ".bindings";

string bindingPath = ConfigurationParser.GetConfigFilePath(configPath) ?? configPath + ".bindings";
return File.Exists(bindingPath) ? new ConfigurationParser(bindingPath).LoadBinding().ToXml() : "<binding />";
}

private string GetBindingPath(string configPath, bool create = false)
{
string bindingPath;
var path = CakePackage.Dte.Solution?.FindProjectItem(Constants.ConfigFileName);
if (path != null && path.FileCount == 1)
{
bindingPath = path.FileNames[1];
}
else
{
var cpath = Path.Combine(Path.GetDirectoryName(configPath), Constants.ConfigFileName);
try
{

if (!File.Exists(cpath) && create) File.Create(cpath).Close();
if (File.Exists(cpath)) ProjectHelpers.GetSolutionItemsProject(CakePackage.Dte).AddFileToProject(cpath);
}
catch
{
// ignored
}
bindingPath = cpath;
}
return string.IsNullOrWhiteSpace(bindingPath) ? null : bindingPath; // remove the empty string scenario
}

public bool SaveBindings(string configPath, string bindingsXml)
{
string bindingPath = GetBindingPath(configPath, true) ?? configPath + ".bindings";
string bindingPath = ConfigurationParser.GetConfigFilePath(configPath, true) ?? configPath + ".bindings";
var config = new ConfigurationParser(bindingPath);
try
{
Expand Down