public static void ExtractAll(string path, string projectName) { if (!Directory.Exists(Path.Combine(path, "Projects"))) Directory.CreateDirectory(Path.Combine(path, "Projects")); var module = new ModuleInfo { Name = projectName }; module.Save(Path.Combine(path, "Module.xml")); }
public static void ExtractAll(string path, string projectName) { if (!Directory.Exists(Path.Combine(path, "Projects"))) { Directory.CreateDirectory(Path.Combine(path, "Projects")); } var module = new ModuleInfo { Name = projectName }; module.Save(Path.Combine(path, "Module.xml")); }
public byte[] Transform(string workingDirectory, string url, string gitReference, string platform, string format) { var urlAndPackageName = url.Split(new[] { '|' }, 2); if (urlAndPackageName.Length != 2) { RedirectableConsole.ErrorWriteLine( "ERROR: Malformed NuGet package reference '" + url + "'. Make sure you split the NuGet server URL and the package name with a pipe character (|)."); ExecEnvironment.Exit(1); } var repoUrl = urlAndPackageName[0]; var packageName = urlAndPackageName[1]; var originalFolder = DownloadOrUseExistingNuGetPackage(repoUrl.TrimEnd('/'), packageName, gitReference); if (Directory.Exists(Path.Combine(originalFolder, "protobuild"))) { // This is a Protobuild-aware NuGet package. In this case, we just use the contents of the // "protobuild" folder as the content of our package, and ignore everything else. RedirectableConsole.WriteLine("Detected Protobuild-aware package..."); RedirectableConsole.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(originalFolder)); filter.ApplyInclude("protobuild/(.*)"); filter.ApplyRewrite("protobuild/(.*)", "$1"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, originalFolder, format, platform); RedirectableConsole.WriteLine("Package conversion complete."); var bytes2 = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes2, 0, bytes2.Length); return(bytes2); } var folder = Path.GetTempFileName(); File.Delete(folder); Directory.CreateDirectory(folder); byte[] bytes; try { RedirectableConsole.WriteLine("Copying directory for package transformation..."); CopyFolder(new DirectoryInfo(originalFolder), new DirectoryInfo(folder)); RedirectableConsole.WriteLine("Auto-detecting libraries to reference from NuGet package..."); var packagePath = new DirectoryInfo(folder).GetFiles("*.nuspec").First().FullName; var libraryReferences = new Dictionary <string, string>(); var packageDependencies = new Dictionary <string, string>(); // Use the nuspec file if it exists. List <string> references = new List <string>(); if (File.Exists(packagePath)) { var packageDoc = new XmlDocument(); packageDoc.Load(packagePath); // If the references are explicitly provided in the nuspec, use // those as to what files should be referenced by the projects. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "references") > 0) { references = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "references") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "reference") .Select(x => x.Attributes["file"].Value) .ToList(); } // If there are dependencies specified, store them and convert them to // Protobuild references, and reference them in the Module.xml file. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "dependencies") > 0) { packageDependencies = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "dependencies") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "dependency") .ToDictionarySafe( k => k.Attributes["id"].Value, v => v.Attributes["version"].Value, (dict, c) => RedirectableConsole.WriteLine("WARNING: More than one dependency on " + c + " in NuGet package.")); } } // Determine the priority of the frameworks that we want to target // out of the available versions. string[] clrNames = _nuGetPlatformMapping.GetFrameworkNamesForRead(workingDirectory, platform); var referenceDirectories = new string[] { "ref", "lib" }; foreach (var directory in referenceDirectories) { // Determine the base path for all references; that is, the lib/ folder. var referenceBasePath = Path.Combine( folder, directory); if (Directory.Exists(referenceBasePath)) { // If no references are in nuspec, reference all of the libraries that // are on disk. if (references.Count == 0) { // Search through all of the target frameworks until we find one that // has at least one file in it. foreach (var clrNameOriginal in clrNames) { var clrName = clrNameOriginal; var foundClr = false; if (clrName[0] == '=') { // Exact match (strip the equals). clrName = clrName.Substring(1); // If this target framework doesn't exist for this library, skip it. var dirPath = Path.Combine( referenceBasePath, clrName); if (!Directory.Exists(dirPath)) { continue; } } else if (clrName[0] == '?') { // Substring, search the reference base path for any folders // with a matching substring. clrName = clrName.Substring(1); var baseDirPath = referenceBasePath; var found = false; foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories()) { if (subdir.Name.Contains(clrName)) { clrName = subdir.Name; found = true; break; } } if (!found) { continue; } } else { throw new InvalidOperationException("Unknown CLR name match type with '" + clrName + "'"); } // Otherwise enumerate through all of the libraries in this folder. foreach (var dll in Directory.EnumerateFiles( Path.Combine( referenceBasePath, clrName), "*.dll")) { // Determine the relative path to the library. var packageDll = Path.Combine( referenceBasePath, clrName, Path.GetFileName(dll)); // Confirm again that the file actually exists on disk when // combined with the root path. if (File.Exists( Path.Combine( packageDll))) { // Create the library reference. if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(dll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(dll), packageDll); } // Mark this target framework as having provided at least // one reference. foundClr = true; } } // Break if we have found at least one reference. if (foundClr) { break; } } } // For all of the references that were found in the original nuspec file, // add those references. foreach (var reference in references) { // Search through all of the target frameworks until we find the one // that has the reference in it. foreach (var clrName in clrNames) { // If this target framework doesn't exist for this library, skip it. var packageDll = Path.Combine( referenceBasePath, clrName, reference); if (File.Exists( Path.Combine( packageDll))) { if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(packageDll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(packageDll), packageDll); } break; } } } } } foreach (var kv in libraryReferences) { RedirectableConsole.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")"); } RedirectableConsole.WriteLine("Generating external project reference..."); var document = new XmlDocument(); var externalProject = document.CreateElement("ExternalProject"); externalProject.SetAttribute("Name", packageName); document.AppendChild(externalProject); foreach (var kv in libraryReferences) { var binaryReference = document.CreateElement("Binary"); binaryReference.SetAttribute("Name", kv.Key); binaryReference.SetAttribute("Path", kv.Value.Substring(folder.Length).TrimStart(new[] { '/', '\\' }).Replace("%2B", "-")); externalProject.AppendChild(binaryReference); } foreach (var package in packageDependencies) { var externalReference = document.CreateElement("Reference"); externalReference.SetAttribute("Include", package.Key); externalProject.AppendChild(externalReference); } document.Save(Path.Combine(folder, "_ProtobuildExternalProject.xml")); RedirectableConsole.WriteLine("Generating module..."); var generatedModule = new ModuleInfo(); generatedModule.Name = packageName; generatedModule.Packages = new List <PackageRef>(); foreach (var package in packageDependencies) { generatedModule.Packages.Add(new PackageRef { Uri = repoUrl.Replace("http://", "http-nuget://").Replace("https://", "https-nuget://") + "|" + package.Key, GitRef = package.Value.TrimStart('[').TrimEnd(']'), Folder = package.Key }); } generatedModule.Save(Path.Combine(folder, "_ProtobuildModule.xml")); RedirectableConsole.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(folder)); foreach (var kv in libraryReferences) { filter.ApplyInclude( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/'))); filter.ApplyRewrite( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/')), kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-")); } filter.ApplyInclude("_ProtobuildExternalProject\\.xml"); filter.ApplyRewrite("_ProtobuildExternalProject\\.xml", "Build/Projects/" + packageName + ".definition"); filter.ApplyInclude("_ProtobuildModule\\.xml"); filter.ApplyRewrite("_ProtobuildModule\\.xml", "Build/Module.xml"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, folder, format, platform); RedirectableConsole.WriteLine("Package conversion complete."); bytes = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes, 0, bytes.Length); } finally { RedirectableConsole.WriteLine("Cleaning up temporary data..."); PathUtils.AggressiveDirectoryDelete(folder); } return(bytes); }
private void ConvertNuGetOnlyPackage(Reduplicator reduplicator, ZipStorer zipStorer, string path, string packageName, string workingDirectory, string platform) { var folder = Path.GetTempFileName(); File.Delete(folder); Directory.CreateDirectory(folder); try { reduplicator.UnpackZipToFolder( zipStorer, folder, candidatePath => true, outputPath => outputPath); var references = new List <string>(); var libraryReferences = new Dictionary <string, string>(); var packageDependencies = new Dictionary <string, string>(); // Load NuGet specification file. var specFile = Directory.GetFiles(folder, "*.nuspec").FirstOrDefault(); if (specFile != null) { specFile = Path.Combine(folder, specFile); if (File.Exists(specFile)) { var packageDoc = new XmlDocument(); packageDoc.Load(specFile); if (packageDoc?.DocumentElement != null) { // If we have an id in the package, that forms the package name. if (packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "id") > 0) { var newName = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "id").InnerText.Trim(); if (!string.IsNullOrWhiteSpace(newName)) { packageName = newName; } } // If the references are explicitly provided in the nuspec, use // those as to what files should be referenced by the projects. if (packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "references") > 0) { references = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "references") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "reference") .Select(x => x.Attributes["file"].Value) .ToList(); } // If there are dependencies specified, store them and convert them to // Protobuild references, and reference them in the Module.xml file. if (packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .Count(x => x.Name == "dependencies") > 0) { packageDependencies = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType <XmlElement>() .First(x => x.Name == "dependencies") .ChildNodes.OfType <XmlElement>() .Where(x => x.Name == "dependency") .ToDictionarySafe( k => k.Attributes["id"].Value, v => v.Attributes["version"].Value, (dict, c) => RedirectableConsole.WriteLine("WARNING: More than one dependency on " + c + " in NuGet package.")); } } } } if (string.IsNullOrWhiteSpace(packageName)) { throw new InvalidOperationException("Expected package name when converting NuGet-only package!"); } // Determine the priority of the frameworks that we want to target // out of the available versions. string[] clrNames = _nugetPlatformMapping.GetFrameworkNamesForRead(workingDirectory, platform); var referenceDirectories = new string[] { "ref", "lib" }; foreach (var directory in referenceDirectories) { // Determine the base path for all references; that is, the lib/ folder. var referenceBasePath = Path.Combine( folder, directory); if (Directory.Exists(referenceBasePath)) { // If no references are in nuspec, reference all of the libraries that // are on disk. if (references.Count == 0) { // Search through all of the target frameworks until we find one that // has at least one file in it. foreach (var clrNameOriginal in clrNames) { var clrName = clrNameOriginal; var foundClr = false; if (clrName[0] == '=') { // Exact match (strip the equals). clrName = clrName.Substring(1); // If this target framework doesn't exist for this library, skip it. var dirPath = Path.Combine( referenceBasePath, clrName); if (!Directory.Exists(dirPath)) { continue; } } else if (clrName[0] == '?') { // Substring, search the reference base path for any folders // with a matching substring. clrName = clrName.Substring(1); var baseDirPath = referenceBasePath; var found = false; foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories()) { if (subdir.Name.Contains(clrName)) { clrName = subdir.Name; found = true; break; } } if (!found) { continue; } } else { throw new InvalidOperationException("Unknown CLR name match type with '" + clrName + "'"); } // Otherwise enumerate through all of the libraries in this folder. foreach (var dll in Directory.EnumerateFiles( Path.Combine( referenceBasePath, clrName), "*.dll")) { // Determine the relative path to the library. var packageDll = Path.Combine( referenceBasePath, clrName, Path.GetFileName(dll)); // Confirm again that the file actually exists on disk when // combined with the root path. if (File.Exists( Path.Combine( packageDll))) { // Create the library reference. if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(dll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(dll), packageDll); } // Mark this target framework as having provided at least // one reference. foundClr = true; } } // Break if we have found at least one reference. if (foundClr) { break; } } } // For all of the references that were found in the original nuspec file, // add those references. foreach (var reference in references) { // Search through all of the target frameworks until we find the one // that has the reference in it. foreach (var clrName in clrNames) { // If this target framework doesn't exist for this library, skip it. var packageDll = Path.Combine( referenceBasePath, clrName, reference); if (File.Exists( Path.Combine( packageDll))) { if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(packageDll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(packageDll), packageDll); } break; } } } } } foreach (var kv in libraryReferences) { RedirectableConsole.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")"); } RedirectableConsole.WriteLine("Generating external project reference..."); var document = new XmlDocument(); var externalProject = document.CreateElement("ExternalProject"); externalProject.SetAttribute("Name", packageName); document.AppendChild(externalProject); foreach (var kv in libraryReferences) { var binaryReference = document.CreateElement("Binary"); binaryReference.SetAttribute("Name", kv.Key); binaryReference.SetAttribute("Path", kv.Value.Substring(folder.Length).TrimStart(new[] { '/', '\\' }).Replace("%2B", "-")); externalProject.AppendChild(binaryReference); } foreach (var package in packageDependencies) { var externalReference = document.CreateElement("Reference"); externalReference.SetAttribute("Include", package.Key); externalProject.AppendChild(externalReference); } Directory.CreateDirectory(Path.Combine(path, "Build", "Projects")); document.Save(Path.Combine(path, "Build", "Projects", packageName + ".definition")); RedirectableConsole.WriteLine("Generating module..."); var generatedModule = new ModuleInfo(); generatedModule.Name = packageName; generatedModule.Packages = new List <PackageRef>(); foreach (var package in packageDependencies) { generatedModule.Packages.Add(new PackageRef { Uri = "https-nuget-v3://api.nuget.org/v3/index.json|" + package.Key, GitRef = package.Value.TrimStart('[').TrimEnd(']'), Folder = package.Key }); } generatedModule.Save(Path.Combine(path, "Build", "Module.xml")); foreach (var kv in libraryReferences) { var targetFile = new FileInfo(Path.Combine(path, kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-"))); targetFile.Directory.Create(); File.Copy(kv.Value, targetFile.FullName); } } finally { PathUtils.AggressiveDirectoryDelete(folder); } }
public byte[] Transform(string url, string gitReference, string platform, out string format) { var urlAndPackageName = url.Split(new[] { '|' }, 2); var repoUrl = urlAndPackageName[0]; var packageName = urlAndPackageName[1]; var packagesUrl = repoUrl.TrimEnd('/') + "/Packages(Id='" + packageName + "',Version='" + gitReference + "')"; var client = new WebClient(); Console.WriteLine("HTTP GET " + packagesUrl); var xmlString = client.DownloadString(packagesUrl); var xDocument = XDocument.Parse(xmlString); Console.WriteLine("Retrieved package information"); var title = xDocument.Root.Elements().First(x => x.Name.LocalName == "title"); var content = xDocument.Root.Elements().First(x => x.Name.LocalName == "content"); Console.WriteLine("Found NuGet package '" + title.Value + "'"); var downloadUrl = content.Attributes().First(x => x.Name.LocalName == "src").Value; var downloadedZipData = _progressiveWebOperation.Get(downloadUrl); // Save the ZIP file onto disk. var tempFile = Path.GetTempFileName(); using (var writer = new FileStream(tempFile, FileMode.Truncate, FileAccess.Write)) { writer.Write(downloadedZipData, 0, downloadedZipData.Length); } // TODO: Add a hash of the package URL and version into this path. var tempFolder = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); Directory.CreateDirectory(tempFolder); Console.WriteLine("Extracting package to " + tempFolder + "..."); var zip = ZipStorer.Open(tempFile, FileAccess.Read); var files = zip.ReadCentralDir(); foreach (var file in files) { var targetPath = Path.Combine(tempFolder, file.FilenameInZip); var directory = new FileInfo(targetPath).DirectoryName; if (directory != null) Directory.CreateDirectory(directory); zip.ExtractFile(file, targetPath); } Console.WriteLine("Extraction complete."); Console.WriteLine("Auto-detecting libraries to reference from NuGet package..."); var packagePath = new DirectoryInfo(tempFolder).GetFiles("*.nuspec").First().FullName; var libraryReferences = new Dictionary<string, string>(); var packageDependencies = new Dictionary<string, string>(); // Use the nuspec file if it exists. List<string> references = new List<string>(); if (File.Exists(packagePath)) { var packageDoc = new XmlDocument(); packageDoc.Load(packagePath); // If the references are explicitly provided in the nuspec, use // those as to what files should be referenced by the projects. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .Count(x => x.Name == "references") > 0) { references = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .First(x => x.Name == "references") .ChildNodes.OfType<XmlElement>() .Where(x => x.Name == "reference") .Select(x => x.Attributes["file"].Value) .ToList(); } // If there are dependencies specified, store them and convert them to // Protobuild references, and reference them in the Module.xml file. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .Count(x => x.Name == "dependencies") > 0) { packageDependencies = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .First(x => x.Name == "dependencies") .ChildNodes.OfType<XmlElement>() .Where(x => x.Name == "dependency") .ToDictionarySafe( k => k.Attributes["id"].Value, v => v.Attributes["version"].Value, c => Console.WriteLine("WARNING: More than one dependency on " + c + " in NuGet package.")); } } // Determine the priority of the frameworks that we want to target // out of the available versions. string[] clrNames = new[] { // Exact matches "=net40-client", "=Net40-client", "=net40", "=Net40", "=net35", "=Net35", "=net20", "=Net20", "=20", "=11", "=", "=net45", "=Net45", // Substring matches "?net4", "?Net4", "?MonoAndroid", }; // Determine the base path for all references; that is, the lib/ folder. var referenceBasePath = Path.Combine( tempFolder, "lib"); // If we don't have a lib/ folder, then we aren't able to reference anything // anyway (this might be a tools only package like xunit.runners). if (!Directory.Exists(referenceBasePath)) { Console.WriteLine( "No lib/ folder found in downloaded NuGet " + "package. There is nothing to reference."); } else { // If no references are in nuspec, reference all of the libraries that // are on disk. if (references.Count == 0) { // Search through all of the target frameworks until we find one that // has at least one file in it. foreach (var clrNameOriginal in clrNames) { var clrName = clrNameOriginal; var foundClr = false; if (clrName[0] == '=') { // Exact match (strip the equals). clrName = clrName.Substring(1); // If this target framework doesn't exist for this library, skip it. var dirPath = Path.Combine( referenceBasePath, clrName); if (!Directory.Exists(dirPath)) { continue; } } else if (clrName[0] == '?') { // Substring, search the reference base path for any folders // with a matching substring. clrName = clrName.Substring(1); var baseDirPath = referenceBasePath; var found = false; foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories()) { if (subdir.Name.Contains(clrName)) { clrName = subdir.Name; found = true; break; } } if (!found) { continue; } } else { throw new InvalidOperationException("Unknown CLR name match type with '" + clrName + "'"); } // Otherwise enumerate through all of the libraries in this folder. foreach (var dll in Directory.EnumerateFiles( Path.Combine( referenceBasePath, clrName), "*.dll")) { // Determine the relative path to the library. var packageDll = Path.Combine( referenceBasePath, clrName, Path.GetFileName(dll)); // Confirm again that the file actually exists on disk when // combined with the root path. if (File.Exists( Path.Combine( packageDll))) { // Create the library reference. libraryReferences.Add( Path.GetFileNameWithoutExtension(dll), packageDll); // Mark this target framework as having provided at least // one reference. foundClr = true; } } // Break if we have found at least one reference. if (foundClr) break; } } // For all of the references that were found in the original nuspec file, // add those references. foreach (var reference in references) { // Search through all of the target frameworks until we find the one // that has the reference in it. foreach (var clrName in clrNames) { // If this target framework doesn't exist for this library, skip it. var packageDll = Path.Combine( referenceBasePath, clrName, reference); if (File.Exists( Path.Combine( packageDll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(packageDll), packageDll); break; } } } } foreach (var kv in libraryReferences) { Console.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")"); } Console.WriteLine("Generating external project reference..."); var document = new XmlDocument(); var externalProject = document.CreateElement("ExternalProject"); externalProject.SetAttribute("Name", packageName); document.AppendChild(externalProject); foreach (var kv in libraryReferences) { var binaryReference = document.CreateElement("Binary"); binaryReference.SetAttribute("Name", kv.Key); binaryReference.SetAttribute("Path", kv.Value.Substring(tempFolder.Length).TrimStart(new[] { '/', '\\' }).Replace("%2B", "-")); externalProject.AppendChild(binaryReference); } foreach (var package in packageDependencies) { var externalReference = document.CreateElement("Reference"); externalReference.SetAttribute("Include", package.Key); externalProject.AppendChild(externalReference); } document.Save(Path.Combine(tempFolder, "_ProtobuildExternalProject.xml")); Console.WriteLine("Generating module..."); var generatedModule = new ModuleInfo(); generatedModule.Name = packageName; generatedModule.Packages = new List<PackageRef>(); foreach (var package in packageDependencies) { generatedModule.Packages.Add(new PackageRef { Uri = repoUrl.Replace("http://", "http-nuget://").Replace("https://", "https-nuget://") + "|" + package.Key, GitRef = package.Value.TrimStart('[').TrimEnd(']'), Folder = package.Key }); } generatedModule.Save(Path.Combine(tempFolder, "_ProtobuildModule.xml")); Console.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(tempFolder)); foreach (var kv in libraryReferences) { filter.ApplyInclude( Regex.Escape(kv.Value.Substring(tempFolder.Length).Replace('\\', '/').TrimStart('/'))); filter.ApplyRewrite( Regex.Escape(kv.Value.Substring(tempFolder.Length).Replace('\\', '/').TrimStart('/')), kv.Value.Substring(tempFolder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-")); } filter.ApplyInclude("_ProtobuildExternalProject\\.xml"); filter.ApplyRewrite("_ProtobuildExternalProject\\.xml", "Build/Projects/" + packageName + ".definition"); filter.ApplyInclude("_ProtobuildModule\\.xml"); filter.ApplyRewrite("_ProtobuildModule\\.xml", "Build/Module.xml"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, tempFolder, PackageManager.ARCHIVE_FORMAT_TAR_LZMA); format = PackageManager.ARCHIVE_FORMAT_TAR_LZMA; Console.WriteLine("Cleaning up temporary files..."); Directory.Delete(tempFolder, true); Console.WriteLine("Package conversion complete."); var bytes = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes, 0, bytes.Length); return bytes; }
public byte[] Transform(string url, string gitReference, string platform, string format) { var urlAndPackageName = url.Split(new[] { '|' }, 2); if (urlAndPackageName.Length != 2) { Console.Error.WriteLine( "ERROR: Malformed NuGet package reference '" + url + "'. Make sure you split the NuGet server URL and the package name with a pipe character (|)."); ExecEnvironment.Exit(1); } var repoUrl = urlAndPackageName[0]; var packageName = urlAndPackageName[1]; var originalFolder = DownloadOrUseExistingNuGetPackage(repoUrl.TrimEnd('/'), packageName, gitReference); var folder = Path.GetTempFileName(); File.Delete(folder); Directory.CreateDirectory(folder); byte[] bytes; try { Console.WriteLine("Copying directory for package transformation..."); CopyFolder(new DirectoryInfo(originalFolder), new DirectoryInfo(folder)); Console.WriteLine("Auto-detecting libraries to reference from NuGet package..."); var packagePath = new DirectoryInfo(folder).GetFiles("*.nuspec").First().FullName; var libraryReferences = new Dictionary<string, string>(); var packageDependencies = new Dictionary<string, string>(); // Use the nuspec file if it exists. List<string> references = new List<string>(); if (File.Exists(packagePath)) { var packageDoc = new XmlDocument(); packageDoc.Load(packagePath); // If the references are explicitly provided in the nuspec, use // those as to what files should be referenced by the projects. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .Count(x => x.Name == "references") > 0) { references = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .First(x => x.Name == "references") .ChildNodes.OfType<XmlElement>() .Where(x => x.Name == "reference") .Select(x => x.Attributes["file"].Value) .ToList(); } // If there are dependencies specified, store them and convert them to // Protobuild references, and reference them in the Module.xml file. if ( packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .Count(x => x.Name == "dependencies") > 0) { packageDependencies = packageDoc.DocumentElement.FirstChild.ChildNodes.OfType<XmlElement>() .First(x => x.Name == "dependencies") .ChildNodes.OfType<XmlElement>() .Where(x => x.Name == "dependency") .ToDictionarySafe( k => k.Attributes["id"].Value, v => v.Attributes["version"].Value, (dict, c) => Console.WriteLine("WARNING: More than one dependency on " + c + " in NuGet package.")); } } // Determine the priority of the frameworks that we want to target // out of the available versions. string[] clrNames = new[] { // Exact matches "=net40-client", "=Net40-client", "=net40", "=Net40", "=net35", "=Net35", "=net20", "=Net20", "=20", "=11", "=", "=net45", "=Net45", // Substring matches "?net4", "?Net4", "?MonoAndroid", }; if (platform == "WindowsUniversal") { // This is the priority list for Windows Universal Apps. clrNames = new[] { "=uap10.0", "=uap", "=netcore451", "=netcore", "=dotnet" }; } var referenceDirectories = new string[] {"ref", "lib"}; foreach (var directory in referenceDirectories) { // Determine the base path for all references; that is, the lib/ folder. var referenceBasePath = Path.Combine( folder, directory); if (Directory.Exists(referenceBasePath)) { // If no references are in nuspec, reference all of the libraries that // are on disk. if (references.Count == 0) { // Search through all of the target frameworks until we find one that // has at least one file in it. foreach (var clrNameOriginal in clrNames) { var clrName = clrNameOriginal; var foundClr = false; if (clrName[0] == '=') { // Exact match (strip the equals). clrName = clrName.Substring(1); // If this target framework doesn't exist for this library, skip it. var dirPath = Path.Combine( referenceBasePath, clrName); if (!Directory.Exists(dirPath)) { continue; } } else if (clrName[0] == '?') { // Substring, search the reference base path for any folders // with a matching substring. clrName = clrName.Substring(1); var baseDirPath = referenceBasePath; var found = false; foreach (var subdir in new DirectoryInfo(baseDirPath).GetDirectories()) { if (subdir.Name.Contains(clrName)) { clrName = subdir.Name; found = true; break; } } if (!found) { continue; } } else { throw new InvalidOperationException("Unknown CLR name match type with '" + clrName + "'"); } // Otherwise enumerate through all of the libraries in this folder. foreach (var dll in Directory.EnumerateFiles( Path.Combine( referenceBasePath, clrName), "*.dll")) { // Determine the relative path to the library. var packageDll = Path.Combine( referenceBasePath, clrName, Path.GetFileName(dll)); // Confirm again that the file actually exists on disk when // combined with the root path. if (File.Exists( Path.Combine( packageDll))) { // Create the library reference. if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(dll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(dll), packageDll); } // Mark this target framework as having provided at least // one reference. foundClr = true; } } // Break if we have found at least one reference. if (foundClr) break; } } // For all of the references that were found in the original nuspec file, // add those references. foreach (var reference in references) { // Search through all of the target frameworks until we find the one // that has the reference in it. foreach (var clrName in clrNames) { // If this target framework doesn't exist for this library, skip it. var packageDll = Path.Combine( referenceBasePath, clrName, reference); if (File.Exists( Path.Combine( packageDll))) { if (!libraryReferences.ContainsKey(Path.GetFileNameWithoutExtension(packageDll))) { libraryReferences.Add( Path.GetFileNameWithoutExtension(packageDll), packageDll); } break; } } } } } foreach (var kv in libraryReferences) { Console.WriteLine("Found library to reference: " + kv.Key + " (at " + kv.Value + ")"); } Console.WriteLine("Generating external project reference..."); var document = new XmlDocument(); var externalProject = document.CreateElement("ExternalProject"); externalProject.SetAttribute("Name", packageName); document.AppendChild(externalProject); foreach (var kv in libraryReferences) { var binaryReference = document.CreateElement("Binary"); binaryReference.SetAttribute("Name", kv.Key); binaryReference.SetAttribute("Path", kv.Value.Substring(folder.Length).TrimStart(new[] {'/', '\\'}).Replace("%2B", "-")); externalProject.AppendChild(binaryReference); } foreach (var package in packageDependencies) { var externalReference = document.CreateElement("Reference"); externalReference.SetAttribute("Include", package.Key); externalProject.AppendChild(externalReference); } document.Save(Path.Combine(folder, "_ProtobuildExternalProject.xml")); Console.WriteLine("Generating module..."); var generatedModule = new ModuleInfo(); generatedModule.Name = packageName; generatedModule.Packages = new List<PackageRef>(); foreach (var package in packageDependencies) { generatedModule.Packages.Add(new PackageRef { Uri = repoUrl.Replace("http://", "http-nuget://").Replace("https://", "https-nuget://") + "|" + package.Key, GitRef = package.Value.TrimStart('[').TrimEnd(']'), Folder = package.Key }); } generatedModule.Save(Path.Combine(folder, "_ProtobuildModule.xml")); Console.WriteLine("Converting to a Protobuild package..."); var target = new MemoryStream(); var filter = new FileFilter(_getRecursiveUtilitiesInPath.GetRecursiveFilesInPath(folder)); foreach (var kv in libraryReferences) { filter.ApplyInclude( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/'))); filter.ApplyRewrite( Regex.Escape(kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/')), kv.Value.Substring(folder.Length).Replace('\\', '/').TrimStart('/').Replace("%2B", "-")); } filter.ApplyInclude("_ProtobuildExternalProject\\.xml"); filter.ApplyRewrite("_ProtobuildExternalProject\\.xml", "Build/Projects/" + packageName + ".definition"); filter.ApplyInclude("_ProtobuildModule\\.xml"); filter.ApplyRewrite("_ProtobuildModule\\.xml", "Build/Module.xml"); filter.ImplyDirectories(); _packageCreator.Create( target, filter, folder, format); Console.WriteLine("Package conversion complete."); bytes = new byte[target.Position]; target.Seek(0, SeekOrigin.Begin); target.Read(bytes, 0, bytes.Length); } finally { Console.WriteLine("Cleaning up temporary data..."); PathUtils.AggressiveDirectoryDelete(folder); } return bytes; }