Last active
August 16, 2016 20:34
-
-
Save AndreyAkinshin/24f87bda5a64c1a32f8e43cc224cafb5 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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