Skip to content

Commit

Permalink
Merge pull request #368 from fredpointzero/feature/NuGetConfiguration…
Browse files Browse the repository at this point in the history
…WithPublish

Generate a NuGet.config file with resolved properties when publishing a script
  • Loading branch information
filipw committed Nov 7, 2018
2 parents 5f3afc5 + ce0ebe6 commit e9f22c6
Show file tree
Hide file tree
Showing 15 changed files with 327 additions and 28 deletions.
9 changes: 5 additions & 4 deletions src/Dotnet.Script.Core/ScriptPublisher.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using Dotnet.Script.DependencyModel.Environment;
using Dotnet.Script.Core.Internal;
using Dotnet.Script.DependencyModel.Environment;
using Dotnet.Script.DependencyModel.Logging;
using Dotnet.Script.DependencyModel.Process;
using Dotnet.Script.DependencyModel.ProjectSystem;
Expand Down Expand Up @@ -72,15 +73,15 @@ public void CreateExecutable<TReturn, THost>(ScriptContext context, LogFactory l
const string AssemblyName = "scriptAssembly";

var tempProjectPath = ScriptProjectProvider.GetPathToProjectFile(Path.GetDirectoryName(context.FilePath));
var tempProjectDirecory = Path.GetDirectoryName(tempProjectPath);
var tempProjectDirectory = Path.GetDirectoryName(tempProjectPath);

var scriptAssemblyPath = CreateScriptAssembly<TReturn, THost>(context, tempProjectDirecory, AssemblyName);
var scriptAssemblyPath = CreateScriptAssembly<TReturn, THost>(context, tempProjectDirectory, AssemblyName);
var projectFile = new ProjectFile(File.ReadAllText(tempProjectPath));
projectFile.PackageReferences.Add(new PackageReference("Microsoft.CodeAnalysis.Scripting", ScriptingVersion));
projectFile.AssemblyReferences.Add(new AssemblyReference(scriptAssemblyPath));
projectFile.Save(tempProjectPath);

CopyProgramTemplate(tempProjectDirecory);
CopyProgramTemplate(tempProjectDirectory);

var commandRunner = new CommandRunner(logFactory);
// todo: may want to add ability to return dotnet.exe errors
Expand Down
3 changes: 3 additions & 0 deletions src/Dotnet.Script.DependencyModel/AssemblyProperties.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Runtime.CompilerServices;

[assembly: InternalsVisibleTo("Dotnet.Script.Tests")]
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@

<ItemGroup>
<PackageReference Include="Microsoft.Extensions.DependencyModel" Version="2.1.0" />
<PackageReference Include="NuGet.Configuration" Version="4.8.0" />
</ItemGroup>

</Project>
70 changes: 70 additions & 0 deletions src/Dotnet.Script.DependencyModel/ProjectSystem/NuGetUtilities.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
using NuGet.Configuration;
using System.Collections.Generic;

namespace Dotnet.Script.DependencyModel.ProjectSystem
{
internal static class NuGetUtilities
{
struct NuGetConfigSection
{
public string Name;
public HashSet<string> KeysForPathValues;
public bool AreAllValuesPaths;
}

static readonly NuGetConfigSection[] NuGetSections =
{
new NuGetConfigSection { Name = "config", KeysForPathValues = new HashSet<string> { "globalPackagesFolder", "repositoryPath" } },
new NuGetConfigSection { Name = "bindingRedirects" },
new NuGetConfigSection { Name = "packageRestore" },
new NuGetConfigSection { Name = "solution" },
new NuGetConfigSection { Name = "packageSources", AreAllValuesPaths = true },
new NuGetConfigSection { Name = "packageSourceCredentials" },
new NuGetConfigSection { Name = "apikeys" },
new NuGetConfigSection { Name = "disabledPackageSources" },
new NuGetConfigSection { Name = "activePackageSource" },
};

// Create a NuGet file containing all properties with resolved absolute paths
public static void CreateNuGetConfigFromLocation(string pathToEvaluate, string targetDirectory)
{
var settings = Settings.LoadDefaultSettings(pathToEvaluate);
var target = new Settings(targetDirectory);

var valuesToSet = new List<SettingValue>();
foreach (var section in NuGetSections)
{
// Resolve properly path values
valuesToSet.Clear();
if (section.AreAllValuesPaths)
{
// All values are paths
var values = settings.GetSettingValues(section.Name, true);
valuesToSet.AddRange(values);
}
else
{
var values = settings.GetSettingValues(section.Name, false);
if (section.KeysForPathValues != null)
{
// Some values are path
foreach (var value in values)
{
if (section.KeysForPathValues.Contains(value.Key))
{
var val = settings.GetValue(section.Name, value.Key, true);
value.Value = val;
}

valuesToSet.Add(value);
}
}
else
// All values are not path
valuesToSet.AddRange(values);
}
target.SetValues(section.Name, valuesToSet);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Linq;
using Dotnet.Script.DependencyModel.Environment;
using Dotnet.Script.DependencyModel.Logging;
using NuGet.Configuration;

namespace Dotnet.Script.DependencyModel.ProjectSystem
{
Expand Down Expand Up @@ -60,7 +61,7 @@ public string CreateProjectForRepl(string code, string targetDirectory, string d

LogProjectFileInfo(pathToProjectFile);

CopyNuGetConfigFile(targetDirectory, Path.GetDirectoryName(pathToProjectFile));
EvaluateAndGenerateNuGetConfigFile(targetDirectory, Path.GetDirectoryName(pathToProjectFile));
return pathToProjectFile;
}

Expand Down Expand Up @@ -101,7 +102,7 @@ private string SaveProjectFileFromScriptFiles(string targetDirectory, string def

LogProjectFileInfo(pathToProjectFile);

CopyNuGetConfigFile(targetDirectory, Path.GetDirectoryName(pathToProjectFile));
EvaluateAndGenerateNuGetConfigFile(targetDirectory, Path.GetDirectoryName(pathToProjectFile));
return pathToProjectFile;
}

Expand All @@ -120,15 +121,15 @@ public ProjectFile CreateProjectFileFromScriptFiles(string defaultTargetFramewor
return projectFile;
}

private void CopyNuGetConfigFile(string targetDirectory, string pathToProjectFileFolder)
private void EvaluateAndGenerateNuGetConfigFile(string targetDirectory, string pathToProjectFileFolder)
{
var pathToNuGetConfigFile = Path.Combine(targetDirectory, "NuGet.Config");
if (File.Exists(pathToNuGetConfigFile))
{
var pathToDestinationNuGetConfigFile = Path.Combine(pathToProjectFileFolder, "NuGet.Config");
_logger.Debug($"Copying {pathToNuGetConfigFile} to {pathToDestinationNuGetConfigFile}");
File.Copy(pathToNuGetConfigFile, Path.Combine(pathToProjectFileFolder, "NuGet.Config"), true);
}
var pathToDestinationNuGetConfigFile = Path.Combine(pathToProjectFileFolder, Settings.DefaultSettingsFileName);

if (File.Exists(pathToDestinationNuGetConfigFile))
File.Delete(pathToDestinationNuGetConfigFile);

_logger.Debug($"Generating NuGet config evaluated at {targetDirectory} to {pathToDestinationNuGetConfigFile}");
NuGetUtilities.CreateNuGetConfigFromLocation(targetDirectory, pathToProjectFileFolder);
}

public static string GetPathToProjectFile(string targetDirectory)
Expand Down
224 changes: 224 additions & 0 deletions src/Dotnet.Script.Tests/NuGetUtilitiesTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,224 @@
using Dotnet.Script.DependencyModel.ProjectSystem;
using NuGet.Configuration;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using Xunit;

namespace Dotnet.Script.Tests
{
using SettingsSection = Dictionary<string, Dictionary<string, string>>;
using SettingsValues = Dictionary<string, string>;

public class NuGetUtilitiesTests
{
public static object[][] Args =
{
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<config>
<add key=""dependencyVersion"" value=""Highest"" />
<add key=""globalPackagesFolder"" value=""{0}/packages"" />
<add key=""repositoryPath"" value=""../installed_packages"" />
<add key=""http_proxy"" value=""http://company-squid:3128@contoso.com"" />
</config>
</configuration>",
new SettingsSection
{
{
"config",
new SettingsValues
{
{ "dependencyVersion", "Highest" },
{ "globalPackagesFolder", @"{1}/packages" },
{ "repositoryPath", @"{0}../installed_packages" },
{ "http_proxy", @"http://company-squid:3128@contoso.com" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<bindingRedirects>
<add key=""skip"" value=""true"" />
</bindingRedirects>
</configuration>",
new SettingsSection
{
{
"bindingRedirects",
new SettingsValues
{
{ "skip", "true" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<packageRestore>
<add key=""enabled"" value=""true"" />
<add key=""automatic"" value=""true"" />
</packageRestore >
</configuration>",
new SettingsSection
{
{
"packageRestore",
new SettingsValues
{
{ "enabled", "true" },
{ "automatic", "true" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<solution>
<add key=""disableSourceControlIntegration"" value=""true"" />
</solution>
</configuration>",
new SettingsSection
{
{
"solution",
new SettingsValues
{
{ "disableSourceControlIntegration", "true" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<packageSources>
<add key=""nuget.org"" value=""https://api.nuget.org/v3/index.json"" protocolVersion=""3"" />
<add key=""Contoso"" value=""https://contoso.com/packages/"" />
<add key=""Test Source"" value=""{0}/packages"" />
<add key=""Relative Test Source"" value=""../packages"" />
</packageSources>
</configuration>",
new SettingsSection
{
{
"packageSources",
new SettingsValues
{
{ "nuget.org", "https://api.nuget.org/v3/index.json" },
{ "Contoso", "https://contoso.com/packages/" },
{ "Test Source", "{1}/packages" },
{ "Relative Test Source", "{0}../packages" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<apikeys>
<add key=""https://MyRepo/ES/api/v2/package"" value=""encrypted_api_key"" />
</apikeys>
</configuration>",
new SettingsSection
{
{
"apikeys",
new SettingsValues
{
{ "https://MyRepo/ES/api/v2/package", "encrypted_api_key" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<disabledPackageSources>
<add key=""Contoso"" value=""true"" />
</disabledPackageSources>
</configuration>",
new SettingsSection
{
{
"disabledPackageSources",
new SettingsValues
{
{ "Contoso", "true" },
}
},
}
},
new object[]
{
@"<?xml version=""1.0"" encoding=""utf-8""?>
<configuration>
<activePackageSource>
<add key=""nuget.org"" value=""https://api.nuget.org/v3/index.json"" />
</activePackageSource >
</configuration>",
new SettingsSection
{
{
"activePackageSource",
new SettingsValues
{
{ "nuget.org", "https://api.nuget.org/v3/index.json" },
}
},
}
},
};

[Theory]
[MemberData(nameof(Args))]
public void ShouldGenerateEvaluatedNuGetConfigFile(string sourceNuGet, SettingsSection targetSettings)
{
using (var projectFolder = new DisposableFolder())
{
// Generate files and directories
var sourceFolder = Path.Combine(projectFolder.Path, "Source");
var sourceScript = Path.Combine(sourceFolder, "script.cs");
var targetFolder = Path.Combine(projectFolder.Path, "Target");
Directory.CreateDirectory(targetFolder);
Directory.CreateDirectory(sourceFolder);

var rootTokens = RuntimeInformation.IsOSPlatform(OSPlatform.Windows) ? "c:" : string.Empty;

var resolvedSourceNuGet = string.Format(sourceNuGet, rootTokens);
File.WriteAllText(Path.Combine(sourceFolder, Settings.DefaultSettingsFileName), resolvedSourceNuGet);

// Evaluate and generate the NuGet config file
NuGetUtilities.CreateNuGetConfigFromLocation(sourceScript, targetFolder);

// Validate the generated NuGet config file
var targetNuGetPath = Path.Combine(targetFolder, Settings.DefaultSettingsFileName);
Assert.True(File.Exists(targetNuGetPath), $"NuGet.config file was not generated at {targetNuGetPath}");

sourceFolder += Path.DirectorySeparatorChar;
var settings = new Settings(targetFolder);
foreach (var expectedSettings in targetSettings)
{
foreach (var expectedSetting in expectedSettings.Value)
{
var value = settings.GetValue(expectedSettings.Key, expectedSetting.Key);
var resolvedExpectedSetting = string.Format(expectedSetting.Value, sourceFolder, rootTokens);
Assert.Equal(resolvedExpectedSetting, value);
}
}
}
}
}
}
Loading

0 comments on commit e9f22c6

Please sign in to comment.