Skip to content

Instantly share code, notes, and snippets.

@PaulStovell
Last active May 25, 2016 08:41
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save PaulStovell/4736445 to your computer and use it in GitHub Desktop.
Save PaulStovell/4736445 to your computer and use it in GitHub Desktop.
/// <summary>
/// Given a 180mb NuGet package, NuGet.Core's PackageManager uses 1.17GB of memory and 55 seconds to extract it.
/// This is because it continually takes package files and copies them to byte arrays in memory to work with.
/// This class simply uses the packaging API's directly to extract, and only uses 6mb and takes 10 seconds on the
/// same 180mb file.
/// </summary>
public class LightweightPackageInstaller
{
private static readonly string[] ExcludePaths = new[] { "_rels", "package\\services\\metadata" };
public void Install(string packageFile, string directory)
{
using (var package = Package.Open(packageFile, FileMode.Open, FileAccess.Read, FileShare.Read))
{
var files = (from part in package.GetParts()
where IsPackageFile(part)
select part).ToList();
foreach (var part in files)
{
Console.WriteLine(" " + part.Uri);
var path = UriUtility.GetPath(part.Uri);
path = Path.Combine(directory, path);
var parent = Path.GetDirectoryName(path);
if (parent != null && !Directory.Exists(parent))
{
Directory.CreateDirectory(parent);
}
using (var fileStream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read))
{
using (var stream = part.GetStream())
{
stream.CopyTo(fileStream);
fileStream.Flush();
fileStream.Dispose();
}
}
}
}
}
internal static bool IsPackageFile(PackagePart part)
{
var path = UriUtility.GetPath(part.Uri);
return !ExcludePaths.Any(p => path.StartsWith(p, StringComparison.OrdinalIgnoreCase)) &&
!PackageUtility.IsManifest(path);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment