Skip to content
This repository has been archived by the owner on Jul 5, 2024. It is now read-only.

Commit

Permalink
Remove dependency on SharpCompress
Browse files Browse the repository at this point in the history
  • Loading branch information
caesay committed Nov 14, 2023
1 parent 3d05acb commit 9eb03d8
Show file tree
Hide file tree
Showing 11 changed files with 3,748 additions and 106 deletions.
3,668 changes: 3,668 additions & 0 deletions src/Squirrel/Internal/BZip2Stream.cs

Large diffs are not rendered by default.

31 changes: 5 additions & 26 deletions src/Squirrel/Internal/DeltaPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,9 @@
using System.Text.RegularExpressions;
using Squirrel.SimpleSplat;
using Squirrel.Bsdiff;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using SharpCompress.Readers;
using SharpCompress.Compressors.Deflate;
using System.Threading.Tasks;
using System.Threading;
using System.IO.Compression;
using System.Runtime.InteropServices;

namespace Squirrel
Expand Down Expand Up @@ -89,11 +85,6 @@ public ReleasePackage CreateDeltaPackage(ReleasePackage basePackage, ReleasePack

int fNew = 0, fSame = 0, fChanged = 0, fWarnings = 0;

bool bytesAreIdentical(ReadOnlySpan<byte> a1, ReadOnlySpan<byte> a2)
{
return a1.SequenceEqual(a2);
}

void createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirectory)
{
// NB: There are three cases here that we'll handle:
Expand Down Expand Up @@ -121,7 +112,7 @@ void createDeltaForSingleFile(FileInfo targetFile, DirectoryInfo workingDirector
var oldData = File.ReadAllBytes(oldFilePath);
var newData = File.ReadAllBytes(targetFile.FullName);

if (bytesAreIdentical(oldData, newData)) {
if (Utility.ByteArrayCompareFast(oldData, newData)) {
// 2. exists in both, keep it the same
this.Log().Debug("{0} hasn't changed, writing dummy file", relativePath);
File.Create(targetFile.FullName + ".bsdiff").Dispose();
Expand Down Expand Up @@ -212,19 +203,12 @@ public ReleasePackage ApplyDeltaPackage(ReleasePackage basePackage, ReleasePacka

using (Utility.WithTempDirectory(out deltaPath, localAppDirectory))
using (Utility.WithTempDirectory(out workingPath, localAppDirectory)) {
var opts = new ExtractionOptions() { ExtractFullPath = true, Overwrite = true, PreserveFileTime = true };

using (var za = ZipArchive.Open(deltaPackage.InputPackageFile))
using (var reader = za.ExtractAllEntries()) {
reader.WriteAllToDirectory(deltaPath, opts);
}
ZipFile.ExtractToDirectory(deltaPackage.InputPackageFile, deltaPath);

progress(25);

using (var za = ZipArchive.Open(basePackage.InputPackageFile))
using (var reader = za.ExtractAllEntries()) {
reader.WriteAllToDirectory(workingPath, opts);
}
ZipFile.ExtractToDirectory(basePackage.InputPackageFile, workingPath);

progress(50);

Expand Down Expand Up @@ -269,12 +253,7 @@ public ReleasePackage ApplyDeltaPackage(ReleasePackage basePackage, ReleasePacka
});

this.Log().Info("Repacking into full package: {0}", outputFile);
using (var za = ZipArchive.Create())
using (var tgt = File.OpenWrite(outputFile)) {
za.DeflateCompressionLevel = CompressionLevel.BestSpeed;
za.AddAllFromDirectory(workingPath);
za.SaveTo(tgt);
}
ZipFile.CreateFromDirectory(workingPath, outputFile);

progress(100);
}
Expand Down
28 changes: 13 additions & 15 deletions src/Squirrel/Internal/EasyZip.cs
Original file line number Diff line number Diff line change
@@ -1,18 +1,16 @@
using System;
using System.Collections.Generic;
using System.IO.Compression;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using SharpCompress.Archives;
using SharpCompress.Archives.Zip;
using SharpCompress.Common;
using Squirrel.SimpleSplat;

namespace Squirrel
{
internal class EasyZip
internal static class EasyZip
{
private static IFullLogger Log = SquirrelLocator.CurrentMutable.GetService<ILogManager>().GetLogger(typeof(EasyZip));

Expand All @@ -21,24 +19,19 @@ public static void ExtractZipToDirectory(string inputFile, string outputDirector
if (Extract7z(inputFile, outputDirectory))
return;

Log.Info($"Extracting '{inputFile}' to '{outputDirectory}' using SharpCompress...");
using var archive = ZipArchive.Open(inputFile);
archive.WriteToDirectory(outputDirectory, new() {
PreserveFileTime = false,
Overwrite = true,
ExtractFullPath = true
});
Log.Info($"Extracting '{inputFile}' to '{outputDirectory}' using System.IO.Compression...");

Utility.DeleteFileOrDirectoryHard(outputDirectory);
ZipFile.ExtractToDirectory(inputFile, outputDirectory);
}

public static void CreateZipFromDirectory(string outputFile, string directoryToCompress)
{
if (Compress7z(outputFile, directoryToCompress))
return;

Log.Info($"Compressing '{directoryToCompress}' to '{outputFile}' using SharpCompress...");
using var archive = ZipArchive.Create();
archive.AddAllFromDirectory(directoryToCompress);
archive.SaveTo(outputFile, CompressionType.Deflate);
Log.Info($"Compressing '{directoryToCompress}' to '{outputFile}' using System.IO.Compression...");
ZipFile.CreateFromDirectory(directoryToCompress, outputFile);
}

private static bool Extract7z(string zipFilePath, string outFolder)
Expand Down Expand Up @@ -80,5 +73,10 @@ private static bool Compress7z(string zipFilePath, string inFolder)
return false;
}
}

public static bool IsDirectory(this ZipArchiveEntry entry)
{
return entry.FullName.EndsWith("/") || entry.FullName.EndsWith("\\") || String.IsNullOrEmpty(entry.Name);
}
}
}
34 changes: 17 additions & 17 deletions src/Squirrel/Internal/ReleasePackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,7 @@
using Squirrel.NuGet;
using Squirrel.SimpleSplat;
using System.Threading.Tasks;
using SharpCompress.Archives.Zip;
using SharpCompress.Readers;
using System.IO.Compression;

namespace Squirrel
{
Expand Down Expand Up @@ -127,25 +126,25 @@ internal string CreateReleasePackage(string outputFile, Func<string, string> rel
static Task extractZipWithEscaping(string zipFilePath, string outFolder)
{
return Task.Run(() => {
using (var za = ZipArchive.Open(zipFilePath))
using (var reader = za.ExtractAllEntries()) {
while (reader.MoveToNextEntry()) {
var parts = reader.Entry.Key.Split('\\', '/').Select(x => Uri.UnescapeDataString(x));
using (var fs = File.OpenRead(zipFilePath))
using (var za = new ZipArchive(fs))
foreach (var entry in za.Entries) {
var parts = entry.FullName.Split('\\', '/').Select(x => Uri.UnescapeDataString(x));
var decoded = String.Join(Path.DirectorySeparatorChar.ToString(), parts);
var fullTargetFile = Path.Combine(outFolder, decoded);
var fullTargetDir = Path.GetDirectoryName(fullTargetFile);
Directory.CreateDirectory(fullTargetDir);
var isDirectory = entry.IsDirectory();
Utility.Retry(() => {
if (reader.Entry.IsDirectory) {
Directory.CreateDirectory(Path.Combine(outFolder, decoded));
if (isDirectory) {
Directory.CreateDirectory(fullTargetFile);
} else {
reader.WriteEntryToFile(Path.Combine(outFolder, decoded));
entry.ExtractToFile(fullTargetFile, true);
}
}, 5);
}
}
});
}

Expand All @@ -159,18 +158,18 @@ public static Task ExtractZipForInstall(string zipFilePath, string outFolder, st
var re = new Regex(@"lib[\\\/][^\\\/]*[\\\/]", RegexOptions.CultureInvariant | RegexOptions.IgnoreCase);

return Task.Run(() => {
using (var za = ZipArchive.Open(zipFilePath))
using (var reader = za.ExtractAllEntries()) {
using (var fs = File.OpenRead(zipFilePath))
using (var za = new ZipArchive(fs)) {
var totalItems = za.Entries.Count;
var currentItem = 0;
while (reader.MoveToNextEntry()) {
foreach (var entry in za.Entries) {
// Report progress early since we might be need to continue for non-matches
currentItem++;
var percentage = (currentItem * 100d) / totalItems;
progress((int) percentage);
var parts = reader.Entry.Key.Split('\\', '/').Select(x => Uri.UnescapeDataString(x));
var parts = entry.FullName.Split('\\', '/').Select(x => Uri.UnescapeDataString(x));
var decoded = String.Join(Path.DirectorySeparatorChar.ToString(), parts);
if (!re.IsMatch(decoded)) continue;
Expand All @@ -179,9 +178,10 @@ public static Task ExtractZipForInstall(string zipFilePath, string outFolder, st
var fullTargetFile = Path.Combine(outFolder, decoded);
var fullTargetDir = Path.GetDirectoryName(fullTargetFile);
Directory.CreateDirectory(fullTargetDir);
var isDirectory = entry.IsDirectory();
var failureIsOkay = false;
if (!reader.Entry.IsDirectory && decoded.Contains("_ExecutionStub.exe")) {
if (!isDirectory && decoded.Contains("_ExecutionStub.exe")) {
// NB: On upgrade, many of these stubs will be in-use, nbd tho.
failureIsOkay = true;
Expand All @@ -194,10 +194,10 @@ public static Task ExtractZipForInstall(string zipFilePath, string outFolder, st
try {
Utility.Retry(() => {
if (reader.Entry.IsDirectory) {
if (isDirectory) {
Directory.CreateDirectory(fullTargetFile);
} else {
reader.WriteEntryToFile(fullTargetFile);
entry.ExtractToFile(fullTargetFile, true);
}
}, 5);
} catch (Exception e) {
Expand Down
24 changes: 23 additions & 1 deletion src/Squirrel/Internal/Utility.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.Contracts;
Expand Down Expand Up @@ -848,6 +848,28 @@ static void SwapBytes(byte[] guid, int left, int right)
guid[right] = temp;
}


#if NETSTANDARD2_1_OR_GREATER || NET5_0_OR_GREATER
public static bool ByteArrayCompareFast(ReadOnlySpan<byte> a1, ReadOnlySpan<byte> a2)
{
return a1.SequenceEqual(a2);
}
#elif NETFRAMEWORK
[DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)]
static extern int memcmp(byte[] b1, byte[] b2, long count);
public static bool ByteArrayCompareFast(byte[] b1, byte[] b2)
{
// Validate buffers are the same length.
// This also ensures that the count does not exceed the length of either buffer.
return b1.Length == b2.Length && memcmp(b1, b2, b1.Length) == 0;
}
#else
public static bool ByteArrayCompareFast(byte[] a1, byte[] a2)
{
return a1.SequenceEqual(a2);
}
#endif

#if NET5_0_OR_GREATER
[System.Runtime.Versioning.SupportedOSPlatform("windows")]
#endif
Expand Down
3 changes: 1 addition & 2 deletions src/Squirrel/Lib/BinaryPatchUtility.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
using System;
using System.IO;
using System.IO.Compression;
using System.Threading;
using SharpCompress.Compressors;
using SharpCompress.Compressors.BZip2;

// Adapted from https://github.com/LogosBible/bsdiff.net/blob/master/src/bsdiff/BinaryPatchUtility.cs

Expand Down
20 changes: 10 additions & 10 deletions src/Squirrel/NuGet/ZipPackage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Xml;
using System.Xml.Linq;
using SharpCompress.Archives.Zip;

namespace Squirrel.NuGet
{
Expand Down Expand Up @@ -70,16 +70,16 @@ public ZipPackage(string filePath) : this(File.OpenRead(filePath))

public ZipPackage(Stream zipStream, bool leaveOpen = false)
{
using var zip = ZipArchive.Open(zipStream, new() { LeaveStreamOpen = leaveOpen });
using var manifest = GetManifestEntry(zip).OpenEntryStream();
using var zip = new ZipArchive(zipStream, ZipArchiveMode.Read, leaveOpen);
using var manifest = GetManifestEntry(zip).Open();
ReadManifest(manifest);
Files = GetPackageFiles(zip).ToArray();
Frameworks = GetFrameworks(Files);

// we pre-load some images so the zip doesn't need to be opened again later
SetupSplashBytes = ReadFileToBytes(zip, z => Path.GetFileNameWithoutExtension(z.Key) == "splashimage");
SetupIconBytes = ReadFileToBytes(zip, z => z.Key == "setup.ico");
AppIconBytes = ReadFileToBytes(zip, z => z.Key == "app.ico") ?? ReadFileToBytes(zip, z => z.Key.EndsWith("app.ico"));
SetupSplashBytes = ReadFileToBytes(zip, z => Path.GetFileNameWithoutExtension(z.FullName) == "splashimage");
SetupIconBytes = ReadFileToBytes(zip, z => z.FullName == "setup.ico");
AppIconBytes = ReadFileToBytes(zip, z => z.FullName == "app.ico") ?? ReadFileToBytes(zip, z => z.FullName.EndsWith("app.ico"));
}

private byte[] ReadFileToBytes(ZipArchive archive, Func<ZipArchiveEntry, bool> predicate)
Expand All @@ -88,7 +88,7 @@ private byte[] ReadFileToBytes(ZipArchive archive, Func<ZipArchiveEntry, bool> p
if (f == null)
return null;

using var stream = f.OpenEntryStream();
using var stream = f.Open();
if (stream == null)
return null;

Expand Down Expand Up @@ -130,8 +130,8 @@ public static void SetSquirrelMetadata(string nuspecPath, RuntimeCpu architectur
private IEnumerable<ZipPackageFile> GetPackageFiles(ZipArchive zip)
{
return from entry in zip.Entries
where !entry.IsDirectory
let uri = new Uri(entry.Key, UriKind.Relative)
where !entry.IsDirectory()
let uri = new Uri(entry.FullName, UriKind.Relative)
let path = NugetUtil.GetPath(uri)
where IsPackageFile(path)
select new ZipPackageFile(uri);
Expand All @@ -150,7 +150,7 @@ private string[] GetFrameworks(IEnumerable<ZipPackageFile> files)
private ZipArchiveEntry GetManifestEntry(ZipArchive zip)
{
var manifest = zip.Entries
.FirstOrDefault(f => f.Key.EndsWith(NugetUtil.ManifestExtension, StringComparison.OrdinalIgnoreCase));
.FirstOrDefault(f => f.FullName.EndsWith(NugetUtil.ManifestExtension, StringComparison.OrdinalIgnoreCase));

if (manifest == null)
throw new InvalidDataException("PackageDoesNotContainManifest");
Expand Down
8 changes: 0 additions & 8 deletions src/Squirrel/NuGet/ZipPackageFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using SharpCompress.Archives.Zip;

namespace Squirrel.NuGet
{
Expand Down Expand Up @@ -42,13 +41,6 @@ public ZipPackageFile(Uri relpath)
EffectivePath = effectivePath;
}

//public Stream GetEntryStream(Stream archiveStream)
//{
// using var zip = ZipArchive.Open(archiveStream, new() { LeaveStreamOpen = true });
// var entry = zip.Entries.FirstOrDefault(f => new Uri(f.Key, UriKind.Relative) == _entryKey);
// return entry?.OpenEntryStream();
//}

public bool IsLibFile() => IsFileInTopDirectory(NugetUtil.LibDirectory);
public bool IsContentFile() => IsFileInTopDirectory(NugetUtil.ContentDirectory);

Expand Down
25 changes: 7 additions & 18 deletions src/Squirrel/Squirrel.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -18,23 +18,12 @@
<PackageReference Include="Microsoft.Win32.Registry" Version="5.0.0" />
</ItemGroup>

<Choose>
<When Condition=" $(TargetFramework.StartsWith('net4')) ">
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.26.0" Condition=" $(TargetFramework) == 'net46'" />
<PackageReference Include="SharpCompress" Version="0.32.2" Condition=" $(TargetFramework) == 'net461'" />
<PackageReference Include="SharpCompress" Version="0.33.0" Condition=" $(TargetFramework) == 'net462' " />
<PackageReference Include="SharpCompress" Version="0.33.0" Condition=" $(TargetFramework) == 'net48' " />
<PackageReference Include="System.ValueTuple" Version="4.5" />
<Reference Include="System.Web" />
<Reference Include="System.Net.Http" />
</ItemGroup>
</When>
<Otherwise>
<ItemGroup>
<PackageReference Include="SharpCompress" Version="0.34.1" />
</ItemGroup>
</Otherwise>
</Choose>
<ItemGroup Condition=" $(TargetFramework.StartsWith('net4')) ">
<PackageReference Include="System.ValueTuple" Version="4.5" />
<Reference Include="System.Web" />
<Reference Include="System.Net.Http" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
</ItemGroup>

</Project>
2 changes: 2 additions & 0 deletions test/Squirrel.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@
<ItemGroup>
<Reference Include="System.Net.Http" />
<Reference Include="System.Web" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.IO.Compression.FileSystem" />
</ItemGroup>

</Project>
Loading

0 comments on commit 9eb03d8

Please sign in to comment.