private void PushBinary(string targetUri, byte[] bytes) { try { using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var uploadProgressRenderer = new UploadProgressRenderer(); client.UploadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } result = e.Result; done = true; }; client.UploadProgressChanged += (sender, e) => { if (!done) { uploadProgressRenderer.Update(e.ProgressPercentage, e.BytesSent / 1024); } }; client.UploadDataAsync(new Uri(targetUri), "PUT", bytes); while (!done) { System.Threading.Thread.Sleep(0); } uploadProgressRenderer.Finalize(); if (ex != null) { throw new InvalidOperationException("Upload error", ex); } return; } } catch (WebException) { if (targetUri.StartsWith("https://")) { // Attempt fallback to HTTP. Console.Error.WriteLine("Web exception while using HTTPS; attempting HTTP fallback..."); targetUri = "http" + targetUri.Substring("https".Length); PushBinary(targetUri, bytes); return; } Console.WriteLine("Web exception when sending to: " + targetUri); throw; } }
public byte[] Get(string uri) { using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var downloadProgressRenderer = new DownloadProgressRenderer(); client.DownloadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } try { if (e.Result != null) { downloadProgressRenderer.Update(100, e.Result.Length / 1024); } result = e.Result; } catch (System.Reflection.TargetInvocationException) { // This is sometimes thrown when an error occurs. It is // thrown when reporting that the result is invalid. } done = true; }; client.DownloadProgressChanged += (sender, e) => { if (!done) { downloadProgressRenderer.Update(e.ProgressPercentage, e.BytesReceived / 1024); } }; client.DownloadDataAsync(new Uri(uri)); while (!done) { System.Threading.Thread.Sleep(0); } downloadProgressRenderer.FinalizeRendering(); if (ex != null) { throw new InvalidOperationException("Download error", ex); } return(result); } }
private void PushBinary(string targetUri, string file) { byte[] bytes; using (var stream = new FileStream(file, FileMode.Open, FileAccess.Read, FileShare.None)) { bytes = new byte[(int)stream.Length]; stream.Read(bytes, 0, bytes.Length); } using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var uploadProgressRenderer = new UploadProgressRenderer(); client.UploadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } result = e.Result; done = true; }; client.UploadProgressChanged += (sender, e) => { if (!done) { uploadProgressRenderer.Update(e.ProgressPercentage, e.BytesSent / 1024); } }; client.UploadDataAsync(new Uri(targetUri), "PUT", bytes); while (!done) { System.Threading.Thread.Sleep(0); } uploadProgressRenderer.FinalizeRendering(); if (ex != null) { throw new InvalidOperationException("Upload error", ex); } return; } }
public int Execute(Execution execution) { using (var client = new RetryableWebClient()) { var sourcePackage = _packageUrlParser.Parse(execution.PackageUrl); RedirectableConsole.WriteLine("Retrieving source package..."); var metadata = _packageLookup.Lookup(execution.WorkingDirectory, new PackageRequestRef( sourcePackage.Uri, sourcePackage.GitRef, execution.PackagePushPlatform, true, sourcePackage.IsStaticReference)); if (metadata.GetProtobuildPackageBinary == null) { RedirectableConsole.ErrorWriteLine( "ERROR: URL resolved to a package metadata type '" + metadata.GetType().Name + "', " + "but this type doesn't provide a mechanism to convert to a Protobuild package."); } string archiveType; byte[] archiveData; metadata.GetProtobuildPackageBinary(metadata, out archiveType, out archiveData); var protobuildPackageMetadata = metadata as ProtobuildPackageMetadata; if (protobuildPackageMetadata == null) { RedirectableConsole.ErrorWriteLine("--repush requires that the source URL resolve to a Protobuild package"); return(1); } RedirectableConsole.WriteLine("Detected package type as " + archiveType + "."); if (execution.PackagePushVersion.StartsWith("hash:", StringComparison.InvariantCulture)) { var sha1 = new SHA1Managed(); var hashed = sha1.ComputeHash(Encoding.ASCII.GetBytes(execution.PackagePushVersion.Substring("hash:".Length))); execution.PackagePushVersion = BitConverter.ToString(hashed).ToLowerInvariant().Replace("-", ""); } RedirectableConsole.WriteLine("Creating new package version..."); var uploadParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "version", execution.PackagePushVersion }, { "platform", execution.PackagePushPlatform }, }; var json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues(execution.PackagePushUrl + "/version/new/api", uploadParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } var uploadTarget = (string)json.result.uploadUrl; var finalizeTarget = (string)json.result.finalizeUrl; RedirectableConsole.WriteLine("Uploading package..."); this.PushBinary(uploadTarget, archiveData); RedirectableConsole.WriteLine("Finalizing package version..."); var finalizeParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "archiveType", archiveType }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues(finalizeTarget, finalizeParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } if (execution.PackagePushBranchToUpdate != null) { RedirectableConsole.WriteLine("Updating branch " + execution.PackagePushBranchToUpdate + " to point at new version..."); var branchUpdateParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "name", execution.PackagePushBranchToUpdate }, { "git", execution.PackagePushVersion }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues( execution.PackagePushUrl + "/branch/edit/" + execution.PackagePushBranchToUpdate + "/api", branchUpdateParameters))); if (json.has_error) { RedirectableConsole.WriteLine(json.error); return(1); } } RedirectableConsole.WriteLine("Package version repushed successfully."); } return(0); }
private string DownloadOrUseExistingNuGetPackage(string repoUrl, string packageName, string gitReference) { var nugetPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", packageName, gitReference); if (Directory.Exists(nugetPath)) { return(nugetPath); } var packagesUrl = repoUrl + "/Packages(Id='" + packageName + "',Version='" + gitReference + "')"; var client = new RetryableWebClient(); var xmlString = client.DownloadString(packagesUrl); var xDocument = XDocument.Parse(xmlString); RedirectableConsole.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"); RedirectableConsole.WriteLine("Found NuGet package '" + title.Value + "'"); var downloadUrl = content.Attributes().First(x => x.Name.LocalName == "src").Value; // Some packages (like Protobuild packages), have a component of their version after a + symbol. Even // though NuGet gives us a download URL with that component in it, it doesn't actually exist when you // request it. var plusUrl = downloadUrl.IndexOf("%2b", StringComparison.InvariantCultureIgnoreCase); if (plusUrl != -1) { downloadUrl = downloadUrl.Substring(0, plusUrl); } plusUrl = downloadUrl.IndexOf("+", StringComparison.InvariantCultureIgnoreCase); if (plusUrl != -1) { downloadUrl = downloadUrl.Substring(0, plusUrl); } var downloadedZipData = _progressiveWebOperation.Get(downloadUrl); // Save the ZIP file onto disk. var tempFile = Path.GetTempFileName(); try { using (var writer = new FileStream(tempFile, FileMode.Truncate, FileAccess.Write)) { writer.Write(downloadedZipData, 0, downloadedZipData.Length); } Directory.CreateDirectory(nugetPath); RedirectableConsole.WriteLine("Extracting package to " + nugetPath + "..."); using (var zip = ZipStorer.Open(tempFile, FileAccess.Read)) { var files = zip.ReadCentralDir(); foreach (var file in files) { var targetPath = Path.Combine(nugetPath, file.FilenameInZip); var directory = new FileInfo(targetPath).DirectoryName; if (directory != null) { Directory.CreateDirectory(directory); } zip.ExtractFile(file, targetPath); } } RedirectableConsole.WriteLine("Extraction complete."); } finally { File.Delete(tempFile); } return(nugetPath); }
public int Execute(Execution execution) { using (var client = new RetryableWebClient()) { var archiveType = this.DetectPackageType(execution.PackagePushFile); Console.WriteLine("Detected package type as " + archiveType + "."); Console.WriteLine("Creating new package version..."); if (execution.PackagePushVersion.StartsWith("hash:", StringComparison.InvariantCulture)) { var sha1 = new SHA1Managed(); var hashed = sha1.ComputeHash(Encoding.ASCII.GetBytes(execution.PackagePushVersion.Substring("hash:".Length))); execution.PackagePushVersion = BitConverter.ToString(hashed).ToLowerInvariant().Replace("-", ""); } var uploadParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "version", execution.PackagePushVersion }, { "platform", execution.PackagePushPlatform }, }; byte[] versionData; try { versionData = client.UploadValues(execution.PackagePushUrl + "/version/new/api", uploadParameters); } catch (WebException ex) { var responseData = string.Empty; // Try and get the full response from the server to display in the exception message. try { var stream = ex.Response.GetResponseStream(); if (stream != null) { using (var reader = new StreamReader(stream, Encoding.Default, true, 4096, true)) { responseData = reader.ReadToEnd(); } } } catch (Exception) { } throw new WebException(ex.Message + " Content of response was: " + responseData); } var json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( versionData)); if (json.has_error) { Console.WriteLine(json.error); if (execution.PackagePushIgnoreOnExisting && ((string)json.error.ToString()).Contains("Another version already exists with this Git hash and platform")) { return(0); } return(1); } var uploadTarget = (string)json.result.uploadUrl; var finalizeTarget = (string)json.result.finalizeUrl; Console.WriteLine("Uploading package..."); this.PushBinary(uploadTarget, execution.PackagePushFile); Console.WriteLine("Finalizing package version..."); var finalizeParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "archiveType", archiveType }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues(finalizeTarget, finalizeParameters))); if (json.has_error) { Console.WriteLine(json.error); return(1); } if (execution.PackagePushBranchToUpdate != null) { Console.WriteLine("Updating branch " + execution.PackagePushBranchToUpdate + " to point at new version..."); var branchUpdateParameters = new System.Collections.Specialized.NameValueCollection { { "__apikey__", execution.PackagePushApiKey }, { "name", execution.PackagePushBranchToUpdate }, { "git", execution.PackagePushVersion }, }; json = fastJSON.JSON.ToDynamic( System.Text.Encoding.ASCII.GetString( client.UploadValues( execution.PackagePushUrl + "/branch/edit/" + execution.PackagePushBranchToUpdate + "/api", branchUpdateParameters))); if (json.has_error) { Console.WriteLine(json.error); return(1); } } Console.WriteLine("Package version pushed successfully."); } return(0); }
public byte[] Get(string uri) { try { using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var downloadProgressRenderer = new DownloadProgressRenderer(); client.DownloadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } try { if (e.Result != null) { downloadProgressRenderer.Update(100, e.Result.Length / 1024); } result = e.Result; } catch (System.Reflection.TargetInvocationException) { // This is sometimes thrown when an error occurs. It is // thrown when reporting that the result is invalid. } done = true; }; client.DownloadProgressChanged += (sender, e) => { if (!done) { downloadProgressRenderer.Update(e.ProgressPercentage, e.BytesReceived / 1024); } }; client.DownloadDataAsync(new Uri(uri)); while (!done) { System.Threading.Thread.Sleep(0); } downloadProgressRenderer.Finalize(); if (ex != null) { throw new InvalidOperationException("Download error", ex); } return(result); } } catch (WebException) { if (uri.StartsWith("https://")) { // Attempt fallback to HTTP. Console.Error.WriteLine("Web exception while using HTTPS; attempting HTTP fallback..."); uri = "http" + uri.Substring("https".Length); return(Get(uri)); } Console.WriteLine("Web exception when retrieving: " + uri); throw; } }
public int Execute(object handle) { var instructions = (List <ParsedInstruction>)handle; var protobuild = Assembly.GetEntryAssembly().Location; var workingDirectory = _workingDirectoryProvider.GetPath(); var targets = string.Empty; var buildTarget = string.Empty; var buildProcessArch = string.Empty; var buildProperties = new Dictionary <string, string>(); string executeConfiguration = null; var predicates = new Stack <ParsedInstruction>(); foreach (var inst in instructions) { if (inst.Predicate != null) { predicates.Push(inst); } else if (inst.EndPredicate) { predicates.Pop(); } else if (predicates.All(x => x.Predicate())) { if (inst.Command == "native-execute") { var components = inst.Arguments.Split(new[] { ' ' }, 2); string path; try { path = FindNativeProgram(components[0]); } catch (ApplicationException ex) { Console.Error.WriteLine(ex); return(1); } var args = components.Length == 2 ? components[1] : string.Empty; Console.WriteLine("+ native-execute " + path + " " + args); var process = Process.Start(new ProcessStartInfo(path, args) { WorkingDirectory = workingDirectory, UseShellExecute = false }); if (process == null) { Console.Error.WriteLine("ERROR: Process did not start when running " + path + " " + args); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { Console.Error.WriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } else if (inst.Command == "nuget") { // See if we have a copy of NuGet available for use. var cachedNuget = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "NuGet.exe"); if (!File.Exists(cachedNuget)) { var client = new RetryableWebClient(); client.DownloadFile("https://dist.nuget.org/win-x86-commandline/latest/nuget.exe", cachedNuget); } string runtime = null; var hostPlatform = _hostPlatformDetector.DetectPlatform(); if (hostPlatform != "Windows") { try { runtime = FindNativeProgram("mono"); } catch (ApplicationException ex) { Console.Error.WriteLine(ex); return(1); } } Process process; if (hostPlatform != "Windows" && runtime != null) { Console.WriteLine("+ " + runtime + " \"" + cachedNuget + "\" " + inst.Arguments); process = Process.Start(new ProcessStartInfo(runtime, "\"" + cachedNuget + "\" " + inst.Arguments) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } else { Console.WriteLine("+ " + cachedNuget + " " + inst.Arguments); process = Process.Start(new ProcessStartInfo(cachedNuget, inst.Arguments) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } if (process == null) { Console.Error.WriteLine( "ERROR: Process did not start when running NuGet with arguments " + inst.Arguments); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { Console.Error.WriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } else if (inst.Command != null) { var args = string.Empty; switch (inst.Command) { case "execute": if (executeConfiguration != null) { args = "--execute-configuration " + executeConfiguration + " --" + inst.Command + " " + inst.Arguments; } else { args = "--" + inst.Command + " " + inst.Arguments; } break; case "build": args = "--" + inst.Command + " " + targets + " "; if (buildTarget != string.Empty) { args += "--build-target " + buildTarget + " "; } if (buildProcessArch != string.Empty) { args += "--build-process-arch " + buildProcessArch + " "; } args = buildProperties.Aggregate(args, (current, prop) => current + ("--build-property " + prop.Key + " " + prop.Value + " ")); args += " " + inst.Arguments; break; case "pack": case "push": case "repush": args = "--" + inst.Command + " " + inst.Arguments; break; default: args = "--" + inst.Command + " " + targets + " " + inst.Arguments; break; } var runSets = new List <string>(); if (args.Contains("$TARGET_PLATFORM")) { var targetsSplit = targets.Split(','); if (targetsSplit.Length < 1 || string.IsNullOrWhiteSpace(targetsSplit[0])) { runSets.Add(_hostPlatformDetector.DetectPlatform()); } else { runSets.AddRange(targetsSplit); } } else { runSets.Add(_hostPlatformDetector.DetectPlatform()); } if (args.Contains("$GIT_COMMIT") || args.Contains("$GIT_BRANCH")) { string commit; string branch; try { Console.WriteLine("+ git rev-parse HEAD"); commit = GitUtils.RunGitAndCapture(workingDirectory, "rev-parse HEAD").Trim(); try { Console.WriteLine("+ git show-ref --heads"); var branchesText = GitUtils.RunGitAndCapture(workingDirectory, "show-ref --heads"); var branches = branchesText.Split(new[] { Environment.NewLine, "\n" }, StringSplitOptions.RemoveEmptyEntries); var branchRaw = branches.FirstOrDefault(x => x.StartsWith(commit, StringComparison.Ordinal)); branch = string.Empty; if (branchRaw != null) { var branchComponents = branchRaw.Trim().Split(' '); if (branchComponents.Length >= 2) { if (branchComponents[1].StartsWith("refs/heads/", StringComparison.Ordinal)) { branch = branchComponents[1].Substring("refs/heads/".Length); } } } } catch (InvalidOperationException) { branch = string.Empty; } } catch (InvalidOperationException) { commit = string.Empty; branch = string.Empty; } args = args.Replace("$GIT_COMMIT", commit); args = args.Replace("$GIT_BRANCH", branch); } string runtime = null; var hostPlatform = _hostPlatformDetector.DetectPlatform(); if (hostPlatform != "Windows") { try { runtime = FindNativeProgram("mono"); } catch (ApplicationException ex) { Console.Error.WriteLine(ex); return(1); } } foreach (var run in runSets) { var runArgs = args .Replace("$TARGET_PLATFORM", run); Process process; if (hostPlatform != "Windows" && runtime != null) { Console.WriteLine("+ " + runtime + " \"" + protobuild + "\" " + runArgs); process = Process.Start(new ProcessStartInfo(runtime, "\"" + protobuild + "\" " + runArgs) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } else { Console.WriteLine("+ " + protobuild + " " + runArgs); process = Process.Start(new ProcessStartInfo(protobuild, runArgs) { WorkingDirectory = workingDirectory, UseShellExecute = false }); } if (process == null) { Console.Error.WriteLine( "ERROR: Process did not start when running Protobuild with arguments " + args); return(1); } process.WaitForExit(); if (process.ExitCode != 0) { Console.Error.WriteLine( "ERROR: Non-zero exit code " + process.ExitCode); return(process.ExitCode); } } } else if (inst.Key != null) { Console.WriteLine("+ set " + inst.Key + " -> " + inst.Values.Aggregate((a, b) => a + ", " + b)); switch (inst.Key) { case "target-platforms": targets = inst.Values.Aggregate((a, b) => a + "," + b); break; case "build-target": buildTarget = inst.Values.First(); break; case "build-process-arch": buildProcessArch = inst.Values.First(); break; case "build-property": buildProperties.Add(inst.Values[0], inst.Values.Length >= 2 ? inst.Values[1] : string.Empty); break; case "execute-configuration": executeConfiguration = inst.Values.First(); break; } } else if (inst.Echo != null) { Console.WriteLine(inst.Echo); } } } Console.WriteLine("Automated build script completed successfully."); return(0); }
private async Task <int> PushNuGetBinaryAsync(string targetUri, string apiKey, MemoryStream file, bool ignoreOnExisting) { byte[] fileBytes; fileBytes = new byte[(int)file.Length]; file.Read(fileBytes, 0, fileBytes.Length); const string ApiKeyHeader = "X-NuGet-ApiKey"; var boundary = Guid.NewGuid().ToString(); byte[] boundaryBytes = Encoding.UTF8.GetBytes("--" + boundary + "\r\n"); byte[] trailer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n"); byte[] header = Encoding.UTF8.GetBytes( string.Format( "Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\";\r\nContent-Type: {2}\r\n\r\n", "package", "package.nupkg", "application/octet-stream")); var requestLength = boundaryBytes.Length + header.Length + trailer.Length + fileBytes.Length; var combinedContent = new byte[requestLength]; if (combinedContent == null) { throw new InvalidOperationException("Unable to create byte array " + requestLength + " bytes long for upload!"); } boundaryBytes.CopyTo(combinedContent, 0); header.CopyTo(combinedContent, boundaryBytes.Length); fileBytes.CopyTo(combinedContent, boundaryBytes.Length + header.Length); trailer.CopyTo(combinedContent, boundaryBytes.Length + header.Length + fileBytes.Length); using (var client = new RetryableWebClient()) { var done = false; byte[] result = null; Exception ex = null; var uploadProgressRenderer = new UploadProgressRenderer(); client.UploadDataCompleted += (sender, e) => { if (e.Error != null) { ex = e.Error; } try { result = e.Result; } catch { } done = true; }; client.UploadProgressChanged += (sender, e) => { if (!done) { uploadProgressRenderer.Update(e.ProgressPercentage, e.BytesSent / 1024); } }; client.SetHeader("Content-Type", "multipart/form-data; boundary=\"" + boundary + "\""); if (!string.IsNullOrWhiteSpace(apiKey)) { client.SetHeader(ApiKeyHeader, apiKey); } client.SetHeader("X-NuGet-Protocol-Version", "4.1.0"); client.SetHeader("User-Agent", "Protobuild"); client.UploadDataAsync(new Uri(targetUri), "PUT", combinedContent); while (!done) { System.Threading.Thread.Sleep(0); } uploadProgressRenderer.FinalizeRendering(); if (ex != null) { var webException = ex as WebException; if (webException != null) { var httpResponse = webException.Response as HttpWebResponse; if (httpResponse != null) { RedirectableConsole.ErrorWriteLine(httpResponse.StatusDescription); if (httpResponse.StatusCode == HttpStatusCode.Conflict) { if (ignoreOnExisting) { // This is okay - the user doesn't care if there's an existing package with the same version. return(0); } else { return(1); } } return(1); } } else { throw new InvalidOperationException("Upload error", ex); } } if (result != null) { var resultDecoded = Encoding.UTF8.GetString(result); if (!string.IsNullOrWhiteSpace(resultDecoded)) { RedirectableConsole.WriteLine(Encoding.UTF8.GetString(result)); } else { RedirectableConsole.WriteLine("Package uploaded successfully"); } } else { RedirectableConsole.WriteLine("Package uploaded successfully"); } return(0); } }
private string DownloadOrUseExistingNuGetPackage(string repoUrl, string packageName, string gitReference) { var nugetPath = Path.Combine( Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), ".nuget", "packages", packageName, gitReference); if (Directory.Exists(nugetPath)) { return(nugetPath); } var packagesUrl = repoUrl + "/Packages(Id='" + packageName + "',Version='" + gitReference + "')"; var client = new RetryableWebClient(); 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(); try { using (var writer = new FileStream(tempFile, FileMode.Truncate, FileAccess.Write)) { writer.Write(downloadedZipData, 0, downloadedZipData.Length); } Directory.CreateDirectory(nugetPath); Console.WriteLine("Extracting package to " + nugetPath + "..."); using (var zip = ZipStorer.Open(tempFile, FileAccess.Read)) { var files = zip.ReadCentralDir(); foreach (var file in files) { var targetPath = Path.Combine(nugetPath, file.FilenameInZip); var directory = new FileInfo(targetPath).DirectoryName; if (directory != null) { Directory.CreateDirectory(directory); } zip.ExtractFile(file, targetPath); } } Console.WriteLine("Extraction complete."); } finally { File.Delete(tempFile); } return(nugetPath); }