private void ExtractTo(string format, byte[] data, string path) { Console.WriteLine("Unpacking binary package from " + format + " archive"); switch (format) { case PackageManager.ARCHIVE_FORMAT_TAR_GZIP: { using (var memory = new MemoryStream(data)) { using (var decompress = new GZipStream(memory, CompressionMode.Decompress)) { using (var memory2 = new MemoryStream()) { decompress.CopyTo(memory2); memory2.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(memory2); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } } break; } case PackageManager.ARCHIVE_FORMAT_TAR_LZMA: { using (var inMemory = new MemoryStream(data)) { using (var outMemory = new MemoryStream()) { LZMA.LzmaHelper.Decompress(inMemory, outMemory); outMemory.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(outMemory); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } break; } default: throw new InvalidOperationException( "This version of Protobuild does not support the " + format + " package format."); } }
public void ExtractTo(string path) { Console.WriteLine("Unpacking binary package from " + this.Format + " archive"); switch (this.Format) { case PackageManager.ARCHIVE_FORMAT_TAR_GZIP: { using (var memory = new MemoryStream(this.PackageData)) { using (var decompress = new GZipStream(memory, CompressionMode.Decompress)) { using (var memory2 = new MemoryStream()) { decompress.CopyTo(memory2); memory2.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(memory2); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } } break; } case PackageManager.ARCHIVE_FORMAT_TAR_LZMA: { using (var inMemory = new MemoryStream(this.PackageData)) { using (var outMemory = new MemoryStream()) { LZMA.LzmaHelper.Decompress(inMemory, outMemory); outMemory.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(outMemory); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } break; } default: throw new InvalidOperationException( "This version of Protobuild does not support the " + this.Format + " package format."); } }
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); } }
private void ExtractTo(string workingDirectory, string packageName, string format, byte[] data, string path, string platform) { RedirectableConsole.WriteLine("Unpacking binary package from " + format + " archive"); switch (format) { case PackageManager.ARCHIVE_FORMAT_TAR_GZIP: { using (var memory = new MemoryStream(data)) { using (var decompress = new GZipStream(memory, CompressionMode.Decompress)) { using (var memory2 = new MemoryStream()) { decompress.CopyTo(memory2); memory2.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(memory2); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } } break; } case PackageManager.ARCHIVE_FORMAT_TAR_LZMA: { using (var inMemory = new MemoryStream(data)) { using (var outMemory = new MemoryStream()) { LZMA.LzmaHelper.Decompress(inMemory, outMemory); outMemory.Seek(0, SeekOrigin.Begin); var reader = new tar_cs.TarReader(outMemory); var reduplicator = new Reduplicator(); reduplicator.UnpackTarToFolder(reader, path); } } break; } case PackageManager.ARCHIVE_FORMAT_NUGET_ZIP: { using (var inMemory = new MemoryStream(data)) { using (var zipStorer = ZipStorer.Open(inMemory, FileAccess.Read, true)) { var reduplicator = new Reduplicator(); var extractedFiles = reduplicator.UnpackZipToFolder( zipStorer, path, candidatePath => candidatePath.Replace('\\', '/').StartsWith("protobuild/" + platform + "/"), outputPath => outputPath.Replace('\\', '/').Substring(("protobuild/" + platform + "/").Length)); if (extractedFiles.Count == 0) { // There were no files that matched protobuild/ which means this is // not a Protobuild-aware NuGet package. We need to convert it on-the-fly // to a compatible Protobuild format. ConvertNuGetOnlyPackage(reduplicator, zipStorer, path, packageName, workingDirectory, platform); } } } break; } default: throw new InvalidOperationException( "This version of Protobuild does not support the " + format + " package format."); } }