Skip to content

Instantly share code, notes, and snippets.

@AndreyAkinshin
Last active August 16, 2016 20:34
Show Gist options
  • Save AndreyAkinshin/24f87bda5a64c1a32f8e43cc224cafb5 to your computer and use it in GitHub Desktop.
Save AndreyAkinshin/24f87bda5a64c1a32f8e43cc224cafb5 to your computer and use it in GitHub Desktop.
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
namespace NuGetUltimateBuilder
{
// Requires nuget.exe >= v3.5.0-rc1
internal class Program
{
private const string TargetVersion = "3.5.0-rc1-final";
private const string TargetVersionCore = "2.13.0-rc1-final";
private const string TargetPackagesDirectory = "packages";
private const string TargetLibDirectory = "lib";
private const string TargetLibMoniker = "net45";
private static readonly string[] TargetLibAdditionalMonikers = {"net", "net40"};
private static readonly string TargetLibMonikerDirectory = Path.Combine(TargetLibDirectory, TargetLibMoniker);
private const int ExecTimeout = 10000;
private const string InstallDefaultArgs = "-ExcludeVersion -Source https://api.nuget.org/v3/index.json -NoCache";
private const string FakeSymbol = "_";
private static bool ClearTargetPackageDirectory = true;
#region Main
private static void Main()
{
PrepareEnvironment();
var packages = DownloadPackages();
PrepareLibDirectory(packages);
PackPackage(packages);
}
private static void PrepareEnvironment()
{
Exec("nuget");
if (Directory.Exists(TargetPackagesDirectory) && ClearTargetPackageDirectory)
Directory.Delete(TargetPackagesDirectory, true);
if (Directory.Exists(TargetLibMonikerDirectory))
Directory.Delete(TargetLibMonikerDirectory, true);
var currentDirectory = Directory.GetCurrentDirectory();
foreach (var ext in new[] {"nuspec", "nupkg", "dll", "xml"})
foreach (var fileName in Directory.EnumerateFiles(currentDirectory, $"*.{ext}"))
File.Delete(fileName);
}
private static List<string> DownloadPackages()
{
List<string> fail = new List<string>(), success = new List<string>();
var sw = Stopwatch.StartNew();
foreach (var package in TargetPackages)
if (!Directory.Exists(Path.Combine(TargetPackagesDirectory, package)))
{
if (Exec("nuget",
$"install {package} -Version {TargetVersion} -OutputDirectory {TargetPackagesDirectory} {InstallDefaultArgs}"))
success.Add(package);
else
fail.Add(package);
}
else
{
WriteLine("Skip: " + package + "(already installed)");
success.Add(package);
}
sw.Stop();
WriteLine();
WriteLine($"Total download time: {sw.Elapsed.TotalSeconds} sec", ConsoleColor.DarkCyan);
if (fail.Any())
WriteLine("Failed to install: " + string.Join(", ", fail), ConsoleColor.Red);
WriteLine("--------------------------------");
return success;
}
private static void PrepareLibDirectory(IEnumerable<string> packages)
{
Directory.CreateDirectory(TargetLibMonikerDirectory);
foreach (var moniker in TargetLibAdditionalMonikers)
{
var path = TargetLibMonikerDirectory.Replace(TargetLibMoniker, moniker);
Directory.CreateDirectory(path);
File.WriteAllText(Path.Combine(path, $"{FakeSymbol}.{FakeSymbol}"), "");
}
foreach (var package in packages)
{
var src = Path.Combine(TargetPackagesDirectory, package, TargetLibMonikerDirectory, package);
var dst = Path.Combine(TargetLibMonikerDirectory, package);
foreach (var ext in TargetFileExtensions)
{
var sourceName = $"{src}.{ext}";
var destName = $"{dst}.{ext}";
WriteLine($"Copy: {sourceName} -> {destName}");
try
{
File.Copy(sourceName, destName);
}
catch (Exception e)
{
WriteLine(e.ToString(), ConsoleColor.Red);
}
}
}
}
private static void PackPackage(List<string> packages)
{
var nuspecFileName = $"NuGet.Core.Ultimate.{TargetVersion}.nuspec";
File.WriteAllText(nuspecFileName, BuildNuspec(packages));
Exec("nuget", $"pack {nuspecFileName}");
if (packages.Count < TargetPackages.Count())
WriteLine("Failed to pack the target package with all the target dependencies", ConsoleColor.Red);
else
WriteLine("The target packages was successfully packed", ConsoleColor.Green);
}
#endregion
#region Helpers
private static bool Exec(string fileName, string arguments = "")
{
WriteLine();
WriteLine($"> {fileName} {arguments}", ConsoleColor.DarkGreen);
var startInfo = new ProcessStartInfo
{
CreateNoWindow = false,
UseShellExecute = false,
FileName = fileName,
WindowStyle = ProcessWindowStyle.Hidden,
Arguments = arguments
};
try
{
using (var process = Process.Start(startInfo))
{
process?.WaitForExit(ExecTimeout);
if (process == null || !process.HasExited)
{
process?.Kill();
throw new TimeoutException($"'{fileName} {arguments}': Timeout({ExecTimeout})");
}
}
return true;
}
catch (Exception e)
{
WriteLine(e.ToString(), ConsoleColor.Red);
return false;
}
finally
{
WriteLine();
}
}
private static void WriteLine(string value = "", ConsoleColor? color = null)
{
if (color.HasValue)
Console.ForegroundColor = color.Value;
Console.WriteLine(value);
if (color.HasValue)
Console.ResetColor();
}
private static string BuildNuspec(IEnumerable<string> packages) => NuspecTemplate.
Replace("$VERSION$", TargetVersion).
Replace("$VERSION-CORE$", TargetVersionCore).
Replace("$PLAIN-LIST$", string.Join(", ", TargetPackages)).
Replace("$FILES$", string.Join("", packages.Select(BuildFileNuspec))).
Replace("$FILES-FAKE$",
string.Join("", TargetLibAdditionalMonikers.Select(m => BuildFileNuspec(FakeSymbol, FakeSymbol, m))));
private static string BuildFileNuspec(string name)
=> string.Join("", TargetFileExtensions.Select(ext => BuildFileNuspec(name, ext)));
private static string BuildFileNuspec(string name, string ext, string moniker = TargetLibMoniker)
=> NuspecFileTemplate.
Replace("$LIB$", TargetLibDirectory).
Replace("$MONIKER$", moniker).
Replace("$NAME$", name).
Replace("$EXT$", ext) + Environment.NewLine;
#endregion
#region Package list and templates
private static readonly string[] TargetFileExtensions = {"xml", "dll"};
private static readonly string[] TargetPackages =
{
"NuGet.Client", "NuGet.Commands", "NuGet.Common", "NuGet.Configuration", "NuGet.ContentModel",
"NuGet.DependencyResolver.Core", "NuGet.DependencyResolver", "NuGet.Frameworks", "NuGet.LibraryModel",
"NuGet.PackageManagement", "NuGet.Packaging.Core",
"NuGet.Packaging.Core.Types", "NuGet.Packaging", "NuGet.ProjectManagement", "NuGet.ProjectModel",
"NuGet.Protocol.Core.Types",
"NuGet.Protocol.Core.v2", "NuGet.Protocol.Core.v3",
"NuGet.Protocol.VisualStudio", "NuGet.Repositories", "NuGet.Resolver", "NuGet.RuntimeModel",
"NuGet.Versioning"
};
private const string NuspecFileTemplate =
@" <file src=""$LIB$\$MONIKER$\$NAME$.$EXT$"" target=""$LIB$\$MONIKER$\$NAME$.$EXT$"" />";
private const string NuspecTemplate = @"<?xml version=""1.0"" encoding=""utf-8""?>
<package xmlns=""http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd"">
<metadata>
<id>NuGet.Core.Ultimate</id>
<version>$VERSION$</version>
<authors>NuGet</authors>
<owners>NuGet</owners>
<projectUrl>https://github.com/NuGet/</projectUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<summary>Ultimate package that contains a set of official NuGet packages.</summary>
<description>Ultimate package that contains a set of official NuGet packages. Content: $PLAIN-LIST$.</description>
<copyright>Copyright .NET Foundation. All rights reserved.</copyright>
<tags>nuget configuration nuget.config</tags>
<dependencies>
<group targetFramework="".NETFramework4.5"">
<dependency id=""Microsoft.Web.Xdt"" version=""2.1.1"" />
<dependency id=""Newtonsoft.Json"" version=""6.0.4"" />
<dependency id=""NuGet.Core"" version=""$VERSION-CORE$"" />
</group>
</dependencies>
<frameworkAssemblies>
<frameworkAssembly assemblyName=""Microsoft.CSharp"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""mscorlib"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Collections.Concurrent"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.ComponentModel.Composition"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Core"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Globalization"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.IdentityModel"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.IO.Compression"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Net.Http"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Net.Http.WebRequest"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Runtime.Serialization"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Security"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.ServiceModel"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Xml"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""System.Xml.Linq"" targetFramework="".NETFramework4.5"" />
<frameworkAssembly assemblyName=""WindowsBase"" targetFramework="".NETFramework4.5"" />
</frameworkAssemblies>
</metadata>
<files>
$FILES-FAKE$
$FILES$
</files>
</package>";
}
#endregion
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment