Remove System.IO.Packaging dependency, add some tests

This commit is contained in:
Caelan Sayler
2022-01-01 19:34:47 +00:00
parent a1bcfaf3f4
commit 377fac415d
9 changed files with 225 additions and 85 deletions

View File

@@ -1,28 +0,0 @@
using System;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Runtime.Versioning;
namespace Squirrel.NuGet
{
internal static class PackageHelper
{
public static bool IsManifest(string path)
{
return Path.GetExtension(path).Equals(Constants.ManifestExtension, StringComparison.OrdinalIgnoreCase);
}
public static bool IsPackageFile(string path)
{
return Path.GetExtension(path).Equals(Constants.PackageExtension, StringComparison.OrdinalIgnoreCase);
}
public static bool IsAssembly(string path)
{
return path.EndsWith(".dll", StringComparison.OrdinalIgnoreCase) ||
path.EndsWith(".winmd", StringComparison.OrdinalIgnoreCase) ||
path.EndsWith(".exe", StringComparison.OrdinalIgnoreCase);
}
}
}

View File

@@ -1,7 +1,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Xml;
@@ -26,15 +25,6 @@ namespace Squirrel.NuGet
return Uri.UnescapeDataString(path.Replace('/', Path.DirectorySeparatorChar));
}
internal static Uri CreatePartUri(string path)
{
// Only the segments between the path separators should be escaped
var segments = path.Split(new[] { '/', Path.DirectorySeparatorChar }, StringSplitOptions.None)
.Select(Uri.EscapeDataString);
var escapedPath = String.Join("/", segments);
return PackUriHelper.CreatePartUri(new Uri(escapedPath, UriKind.Relative));
}
// Bug 2379: SettingsCredentialProvider does not work
private static Uri CreateODataAgnosticUri(string uri)
{

View File

@@ -2,10 +2,9 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Runtime.Versioning;
using System.Xml.Linq;
using SharpCompress.Archives.Zip;
namespace Squirrel.NuGet
{
@@ -61,16 +60,14 @@ namespace Squirrel.NuGet
public IEnumerable<string> GetSupportedFrameworks()
{
IEnumerable<string> fileFrameworks;
using var stream = _streamFactory();
using var zip = ZipArchive.Open(stream);
using (Stream stream = _streamFactory()) {
var package = Package.Open(stream);
string effectivePath;
fileFrameworks = from part in package.GetParts()
where IsPackageFile(part)
select VersionUtility.ParseFrameworkNameFromFilePath(UriUtility.GetPath(part.Uri), out effectivePath);
}
var fileFrameworks = from entries in zip.Entries
let uri = new Uri(entries.Key, UriKind.Relative)
let path = UriUtility.GetPath(uri)
where IsPackageFile(path)
select VersionUtility.ParseFrameworkNameFromFilePath(path, out var effectivePath);
return FrameworkAssemblies.SelectMany(f => f.SupportedFrameworks)
.Concat(fileFrameworks)
@@ -96,13 +93,16 @@ namespace Squirrel.NuGet
public List<IPackageFile> GetFiles()
{
using (Stream stream = _streamFactory()) {
Package package = Package.Open(stream);
using var stream = _streamFactory();
using var zip = ZipArchive.Open(stream);
return (from part in package.GetParts()
where IsPackageFile(part)
select (IPackageFile) new ZipPackageFile(part)).ToList();
}
var files = from entries in zip.Entries
let uri = new Uri(entries.Key, UriKind.Relative)
let path = UriUtility.GetPath(uri)
where IsPackageFile(path)
select (IPackageFile) new ZipPackageFile(path, entries);
return files.ToList();
}
public string GetFullName()
@@ -112,25 +112,17 @@ namespace Squirrel.NuGet
private void EnsureManifest()
{
using (Stream stream = _streamFactory()) {
Package package = Package.Open(stream);
using var stream = _streamFactory();
using var zip = ZipArchive.Open(stream);
PackageRelationship relationshipType = package.GetRelationshipsByType(Constants.PackageRelationshipNamespace + ManifestRelationType).SingleOrDefault();
var manifest = zip.Entries
.FirstOrDefault(f => f.Key.EndsWith(Constants.ManifestExtension, StringComparison.OrdinalIgnoreCase));
if (relationshipType == null) {
throw new InvalidOperationException("PackageDoesNotContainManifest");
}
if (manifest == null)
throw new InvalidOperationException("PackageDoesNotContainManifest");
PackagePart manifestPart = package.GetPart(relationshipType.TargetUri);
if (manifestPart == null) {
throw new InvalidOperationException("PackageDoesNotContainManifest");
}
using (Stream manifestStream = manifestPart.GetStream()) {
ReadManifest(manifestStream);
}
}
using var manifestStream = manifest.OpenEntryStream();
ReadManifest(manifestStream);
}
void ReadManifest(Stream manifestStream)
@@ -172,7 +164,7 @@ namespace Squirrel.NuGet
Version = new SemanticVersion(value);
break;
case "authors":
Authors = value?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries) ?? Enumerable.Empty<string>();
Authors = value?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries).Select(s => s.Trim()) ?? Enumerable.Empty<string>();
break;
//case "owners":
// Owners = value;
@@ -290,14 +282,16 @@ namespace Squirrel.NuGet
.Select(VersionUtility.ParseFrameworkName);
}
bool IsPackageFile(PackagePart part)
bool IsPackageFile(string partPath)
{
string path = UriUtility.GetPath(part.Uri);
string directory = Path.GetDirectoryName(path);
if (Path.GetFileName(partPath).Equals(ContentType.ContentTypeFileName, StringComparison.OrdinalIgnoreCase))
return false;
// We exclude any opc files and the manifest file (.nuspec)
return !ExcludePaths.Any(p => directory.StartsWith(p, StringComparison.OrdinalIgnoreCase)) &&
!PackageHelper.IsManifest(path);
if (Path.GetExtension(partPath).Equals(Constants.ManifestExtension, StringComparison.OrdinalIgnoreCase))
return false;
string directory = Path.GetDirectoryName(partPath);
return !ExcludePaths.Any(p => directory.StartsWith(p, StringComparison.OrdinalIgnoreCase));
}
}
}

View File

@@ -1,8 +1,7 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Runtime.Versioning;
using SharpCompress.Archives.Zip;
namespace Squirrel.NuGet
{
@@ -14,13 +13,13 @@ namespace Squirrel.NuGet
Stream GetStream();
}
internal class ZipPackageFile : IPackageFile
internal class ZipPackageFile : IPackageFile, IEquatable<ZipPackageFile>
{
private readonly Func<Stream> _streamFactory;
private readonly string _targetFramework;
public ZipPackageFile(PackagePart part)
: this(UriUtility.GetPath(part.Uri), part.GetStream().ToStreamFactory())
public ZipPackageFile(string localPath, ZipArchiveEntry entry)
: this(localPath, entry.OpenEntryStream().ToStreamFactory())
{
}
@@ -29,7 +28,7 @@ namespace Squirrel.NuGet
{
}
protected ZipPackageFile(string path, Func<Stream> streamFactory)
internal ZipPackageFile(string path, Func<Stream> streamFactory)
{
Path = path;
_streamFactory = streamFactory;
@@ -73,5 +72,32 @@ namespace Squirrel.NuGet
{
return Path;
}
public override int GetHashCode()
{
unchecked {
int hash = 17;
hash = hash * 23 + Path.GetHashCode();
hash = hash * 23 + EffectivePath.GetHashCode();
hash = hash * 23 + TargetFramework.GetHashCode();
return hash;
}
}
public override bool Equals(object obj)
{
if (obj is ZipPackageFile zpf)
return Equals(zpf);
return false;
}
public bool Equals(ZipPackageFile other)
{
if (other == null) return false;
return
Path.Equals(other.Path) &&
EffectivePath.Equals(other.EffectivePath) &&
TargetFramework.Equals(other.TargetFramework);
}
}
}

View File

@@ -16,7 +16,6 @@
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.30.1" />
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
</ItemGroup>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net461')) ">

View File

@@ -6,6 +6,7 @@
<Description>Squirrel.Tests</Description>
<Title>Squirrel.Tests</Title>
<IsPackable>false</IsPackable>
<LangVersion>9</LangVersion>
<IsTest>true</IsTest>
<NoWarn>CS1998,xUnit2015,xUnit2017,xUnit2005,xUnit2009,xUnit2013,xUnit2004</NoWarn>
<SignAssembly>True</SignAssembly>
@@ -17,6 +18,7 @@
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3" PrivateAssets="All" />
<PackageReference Include="System.IO.Packaging" Version="5.0.0" />
</ItemGroup>
<ItemGroup>

120
test/ZipPackageTests.cs Normal file
View File

@@ -0,0 +1,120 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.IO.Packaging;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Squirrel.NuGet;
using Squirrel.Tests.TestHelpers;
using Xunit;
using ZipPackage = Squirrel.NuGet.ZipPackage;
namespace Squirrel.Tests
{
public class ZipPackageTests
{
[Fact]
public void HasSameFilesAndDependenciesAsPackaging()
{
var inputPackage = IntegrationTestHelper.GetPath("fixtures", "slack-1.1.8-full.nupkg");
var zp = new ZipPackage(inputPackage);
var zipfw = zp.GetSupportedFrameworks();
var zipf = zp.GetFiles().OrderBy(f => f.Path).ToArray();
var zipfLib = zp.GetLibFiles().OrderBy(f => f.Path).ToArray();
using Package package = Package.Open(inputPackage);
var packagingfw = GetSupportedFrameworks(zp, package);
var packaging = GetFiles(package).OrderBy(f => f.Path).ToArray();
var packagingLib = GetLibFiles(package).OrderBy(f => f.Path).ToArray();
//for (int i = 0; i < zipf.Length; i++) {
// if (zipf[i] != packagingLib[i])
// throw new Exception();
//}
Assert.Equal(packaging, zipf);
Assert.Equal(packagingLib, zipfLib);
}
[Fact]
public void ParsesNuspecCorrectly()
{
var inputPackage = IntegrationTestHelper.GetPath("fixtures", "FullNuspec.1.0.0.nupkg");
var zp = new ZipPackage(inputPackage);
Assert.Equal("FullNuspec", zp.Id);
Assert.Equal(new SemanticVersion("1.0"), zp.Version);
Assert.Equal(new [] { "Anaïs Betts", "Caelan Sayler" }, zp.Authors);
Assert.Equal(new Uri("https://github.com/clowd/Clowd.Squirrel"), zp.ProjectUrl);
Assert.Equal(new Uri("https://user-images.githubusercontent.com/1287295/131249078-9e131e51-0b66-4dc7-8c0a-99cbea6bcf80.png"), zp.IconUrl);
Assert.Equal("A test description", zp.Description);
Assert.Equal("A summary", zp.Summary);
Assert.Equal("release notes\nwith multiple lines", zp.ReleaseNotes);
Assert.Equal("Copyright ©", zp.Copyright);
Assert.Equal("en-US", zp.Language);
Assert.Equal("Squirrel for Windows", zp.Title);
Assert.NotEmpty(zp.DependencySets);
var net461 = zp.DependencySets.First();
Assert.Equal(new[] { ".NETFramework4.6.1" }, net461.SupportedFrameworks);
Assert.Equal(".NETFramework4.6.1", net461.TargetFramework);
Assert.NotEmpty(net461.Dependencies);
var dvt = net461.Dependencies.First();
Assert.Equal("System.ValueTuple", dvt.Id);
Assert.Equal("4.5.0", dvt.VersionSpec);
Assert.Equal(new[] { "net5.0" }, zp.DependencySets.Last().SupportedFrameworks);
Assert.NotEmpty(zp.FrameworkAssemblies);
var fw = zp.FrameworkAssemblies.First();
Assert.Equal("System.Net.Http", fw.AssemblyName);
Assert.Equal(new [] { ".NETFramework4.6.1" }, fw.SupportedFrameworks);
}
IEnumerable<string> GetSupportedFrameworks(ZipPackage zp, Package package)
{
var fileFrameworks = from part in package.GetParts()
where IsPackageFile(part)
select VersionUtility.ParseFrameworkNameFromFilePath(UriUtility.GetPath(part.Uri), out var effectivePath);
return zp.FrameworkAssemblies.SelectMany(f => f.SupportedFrameworks)
.Concat(fileFrameworks)
.Where(f => f != null)
.Distinct();
}
IEnumerable<IPackageFile> GetLibFiles(Package package)
{
return GetFiles(package, Constants.LibDirectory);
}
IEnumerable<IPackageFile> GetFiles(Package package, string directory)
{
string folderPrefix = directory + Path.DirectorySeparatorChar;
return GetFiles(package).Where(file => file.Path.StartsWith(folderPrefix, StringComparison.OrdinalIgnoreCase));
}
List<IPackageFile> GetFiles(Package package)
{
return (from part in package.GetParts()
where IsPackageFile(part)
select (IPackageFile) new ZipPackageFile(UriUtility.GetPath(part.Uri), part.GetStream().ToStreamFactory())).ToList();
}
bool IsPackageFile(PackagePart part)
{
string path = UriUtility.GetPath(part.Uri);
string directory = Path.GetDirectoryName(path);
string[] ExcludePaths = new[] { "_rels", "package" };
return !ExcludePaths.Any(p => directory.StartsWith(p, StringComparison.OrdinalIgnoreCase)) && !IsManifest(path);
}
bool IsManifest(string p)
{
return Path.GetExtension(p).Equals(Constants.ManifestExtension, StringComparison.OrdinalIgnoreCase);
}
}
}

36
test/fixtures/FullNuspec.nuspec vendored Normal file
View File

@@ -0,0 +1,36 @@
<?xml version="1.0"?>
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>FullNuspec</id>
<version>1.0</version>
<authors>Anaïs Betts, Caelan Sayler</authors>
<projectUrl>https://github.com/clowd/Clowd.Squirrel</projectUrl>
<iconUrl>https://user-images.githubusercontent.com/1287295/131249078-9e131e51-0b66-4dc7-8c0a-99cbea6bcf80.png</iconUrl>
<description>A test description</description>
<summary>A summary</summary>
<releaseNotes>
release notes
with multiple lines
</releaseNotes>
<copyright>Copyright ©</copyright>
<language>en-US</language>
<title>Squirrel for Windows</title>
<dependencies>
<group targetFramework=".NETFramework4.6.1">
<dependency id="System.ValueTuple" version="4.5.0" exclude="Build,Analyzers" />
</group>
<group targetFramework="net5.0">
<dependency id="System.IO.Packaging" version="5.0.0" exclude="Build,Analyzers" />
</group>
</dependencies>
<frameworkAssemblies>
<frameworkAssembly assemblyName="System.Net.Http" targetFramework=".NETFramework4.6.1" />
<frameworkAssembly assemblyName="System.Web" targetFramework=".NETFramework4.6.1" />
</frameworkAssemblies>
</metadata>
<files>
<file src="FullNuspec.txt" target="tools" />
</files>
</package>

1
test/fixtures/FullNuspec.txt vendored Normal file
View File

@@ -0,0 +1 @@
asd