Installation optimizations and fixes

This commit is contained in:
Timothy Baldridge 2020-09-10 19:22:07 -06:00
parent d3ea54f4e2
commit d7371294f9
4 changed files with 54 additions and 21 deletions

View File

@ -334,7 +334,6 @@ namespace Wabbajack.Lib
.PMap(Queue, UpdateTracker, async f =>
{
var relativeTo = f.RelativeTo(OutputFolder);
Utils.Status($"Checking if ModList file {relativeTo}");
if (indexed.ContainsKey(relativeTo) || f.InFolder(DownloadFolder))
return;
@ -378,17 +377,19 @@ namespace Wabbajack.Lib
Utils.Log("Error when trying to clean empty folders. This doesn't really matter.");
}
var existingfiles = OutputFolder.EnumerateFiles().ToHashSet();
UpdateTracker.NextStep("Looking for unmodified files");
(await indexed.Values.PMap(Queue, UpdateTracker, async d =>
{
// Bit backwards, but we want to return null for
// all files we *want* installed. We return the files
// to remove from the install list.
Status($"Optimizing {d.To}");
var path = OutputFolder.Combine(d.To);
if (!path.Exists) return null;
if (!existingfiles.Contains(path)) return null;
if (path.Size != d.Size) return null;
Status($"Optimizing {d.To}");
return await path.FileHashCachedAsync() == d.Hash ? d : null;
}))

View File

@ -248,23 +248,19 @@ namespace Wabbajack.Lib
private async Task InstallIncludedDownloadMetas()
{
await ModList.Directives
.OfType<ArchiveMeta>()
.PMap(Queue, async directive =>
await ModList.Archives
.PMap(Queue, async archive =>
{
Status($"Writing .meta file {directive.To}");
foreach (var archive in ModList.Archives)
if (HashedArchives.TryGetValue(archive.Hash, out var paths))
{
if (HashedArchives.TryGetValue(archive.Hash, out var paths))
var metaPath = paths.WithExtension(Consts.MetaFileExtension);
if (!metaPath.Exists)
{
var metaPath = paths.WithExtension(Consts.MetaFileExtension);
if (!metaPath.Exists)
{
var meta = AddInstalled(archive.State.GetMetaIni()).ToArray();
await metaPath.WriteAllLinesAsync(meta);
}
Status($"Writing {metaPath.FileName}");
var meta = AddInstalled(archive.State.GetMetaIni()).ToArray();
await metaPath.WriteAllLinesAsync(meta);
}
}
}
});
}

View File

@ -55,10 +55,10 @@ namespace Wabbajack.VirtualFileSystem.Test
var results = await FileExtractor2.GatheringExtract(new NativeFileStreamFactory(archive.Path),
_ => true,
async (path, sfn) =>
{
await using var s = await sfn.GetStream();
return await s.xxHashAsync();
});
{
await using var s = await sfn.GetStream();
return await s.xxHashAsync();
});
Assert.Equal(10, results.Count);
foreach (var (path, hash) in results)
@ -67,6 +67,35 @@ namespace Wabbajack.VirtualFileSystem.Test
}
}
[Fact]
public async Task CanExtractEmptyFiles()
{
await using var temp = await TempFolder.Create();
await using var archive = new TempFile();
for (int i = 0; i < 1; i ++)
{
await WriteRandomData(temp.Dir.Combine($"{i}.bin"), _rng.Next(10, 1024));
}
await (await temp.Dir.Combine("empty.txt").Create()).DisposeAsync();
await ZipUpFolder(temp.Dir, archive.Path, false);
var results = await FileExtractor2.GatheringExtract(new NativeFileStreamFactory(archive.Path),
_ => true,
async (path, sfn) =>
{
await using var s = await sfn.GetStream();
return await s.xxHashAsync();
});
Assert.Equal(2, results.Count);
foreach (var (path, hash) in results)
{
Assert.Equal(await temp.Dir.Combine(path).FileHashAsync(), hash);
}
}
private static Extension OMODExtension = new Extension(".omod");
private static Extension CRCExtension = new Extension(".crc");

View File

@ -25,7 +25,6 @@ namespace Wabbajack.VirtualFileSystem
public GatheringExtractor(Stream stream, Definitions.FileType sig, Predicate<RelativePath> shouldExtract, Func<RelativePath,IStreamFactory, ValueTask<T>> mapfn)
{
_shouldExtract = shouldExtract;
_mapFn = mapfn;
_results = new Dictionary<RelativePath, T>();
@ -89,6 +88,14 @@ namespace Wabbajack.VirtualFileSystem
{
if (_indexes.ContainsKey(index))
{
var path = _indexes[index].Item1;
Utils.Status($"Extracting {path}", Percent.FactoryPutInRange(_results.Count, _indexes.Count));
// Empty files are never extracted via a write call, so we have to fake that now
if (_indexes[index].Item2 == 0)
{
var result = _mapFn(path, new MemoryStreamFactory(new MemoryStream(), path)).Result;
_results.Add(path, result);
}
outStream = new GatheringExtractorStream<T>(this, index);
return 0;
}