ILRepack.IntegrationTests/NuGet/NuGetHelpers.cs (72 lines of code) (raw):
using ICSharpCode.SharpZipLib.Zip;
using System;
using System.IO;
using System.Linq;
using System.Net;
using System.Reactive.Disposables;
using System.Reactive.Linq;
using System.Reactive.Subjects;
namespace ILRepack.IntegrationTests.NuGet
{
static class NuGetHelpers
{
private static IObservable<byte[]> CreateDownloadObservable(Uri uri)
{
return Observable.Create<byte[]>(o => {
var result = new ReplaySubject<byte[]>();
var inner = Observable.Using(() => new WebClient(), wc => {
var obs = Observable
.FromEventPattern<
DownloadDataCompletedEventHandler,
DownloadDataCompletedEventArgs>(
h => wc.DownloadDataCompleted += h,
h => wc.DownloadDataCompleted -= h)
.Take(1);
wc.DownloadDataAsync(uri);
return obs;
}).Subscribe(ep => {
if (ep.EventArgs.Cancelled) {
result.OnCompleted();
} else {
if (ep.EventArgs.Error != null) {
result.OnError(ep.EventArgs.Error);
} else {
result.OnNext(ep.EventArgs.Result);
result.OnCompleted();
}
}
}, ex => {
result.OnError(ex);
});
return new CompositeDisposable(inner, result.Subscribe(o));
}).Retry(5);
}
private static bool IsDllOrExe(Tuple<string, Func<Stream>> tuple)
{
return Path.GetExtension(tuple.Item1) == ".dll" || Path.GetExtension(tuple.Item1) == ".exe";
}
public static IObservable<Tuple<string, Func<Stream>>> GetNupkgAssembliesAsync(Package package)
{
return GetNupkgContentAsync(package).Where(IsDllOrExe).Where(package.Matches);
}
public static IObservable<Tuple<string, Func<Stream>>> GetNupkgContentAsync(Package package)
{
var o = CreateDownloadObservable(new Uri($"http://nuget.org/api/v2/package/{package.Name}/{package.Version}"));
return o.SelectMany(input => {
return Observable.Create<Tuple<ZipFile, ZipEntry>>(observer => {
var z = new ZipFile(new MemoryStream(input)) { IsStreamOwner = true };
var sub = z.Cast<ZipEntry>().ToObservable()
.Select(ze => Tuple.Create(z, ze))
.Subscribe(observer);
return new CompositeDisposable() { z, sub };
});
})
.Select(t => Tuple.Create<string, Func<Stream>>(
t.Item2.Name
.Replace('\\', Path.DirectorySeparatorChar)
.Replace('/', Path.DirectorySeparatorChar)
.Replace("%2B", "+"),
() => t.Item1.GetInputStream(t.Item2)));
}
}
}