mirror of
https://github.com/wabbajack-tools/wabbajack.git
synced 2024-08-30 18:42:17 +00:00
Fixes for installer verification
This commit is contained in:
@ -129,9 +129,24 @@ public class NexusDownloader : ADownloader<Nexus>, IUrlDownloader
|
|||||||
var urls = await _api.DownloadLink(state.Game.MetaData().NexusName!, state.ModID, state.FileID, token);
|
var urls = await _api.DownloadLink(state.Game.MetaData().NexusName!, state.ModID, state.FileID, token);
|
||||||
_logger.LogInformation("Downloading Nexus File: {game}|{modid}|{fileid}", state.Game, state.ModID,
|
_logger.LogInformation("Downloading Nexus File: {game}|{modid}|{fileid}", state.Game, state.ModID,
|
||||||
state.FileID);
|
state.FileID);
|
||||||
var message = new HttpRequestMessage(HttpMethod.Get, urls.info.First().URI);
|
foreach (var link in urls.info)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var message = new HttpRequestMessage(HttpMethod.Get, link.URI);
|
||||||
return await _downloader.Download(message, destination, job, token);
|
return await _downloader.Download(message, destination, job, token);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
if (link.URI == urls.info.Last().URI)
|
||||||
|
throw;
|
||||||
|
_logger.LogInformation(ex, "While downloading {URI}, trying another link", link.URI);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should never be hit
|
||||||
|
throw new NotImplementedException();
|
||||||
|
}
|
||||||
catch (HttpRequestException ex)
|
catch (HttpRequestException ex)
|
||||||
{
|
{
|
||||||
_logger.LogError(ex, "While downloading from the Nexus {Message}", ex.Message);
|
_logger.LogError(ex, "While downloading from the Nexus {Message}", ex.Message);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Wabbajack.Common;
|
||||||
using Wabbajack.DTOs.Streams;
|
using Wabbajack.DTOs.Streams;
|
||||||
|
using Wabbajack.Hashing.xxHash64;
|
||||||
using Wabbajack.Paths;
|
using Wabbajack.Paths;
|
||||||
|
|
||||||
namespace Wabbajack.FileExtractor.ExtractedFiles;
|
namespace Wabbajack.FileExtractor.ExtractedFiles;
|
||||||
@ -16,4 +18,23 @@ public interface IExtractedFile : IStreamFactory
|
|||||||
/// <param name="newPath">destination to move the entry to</param>
|
/// <param name="newPath">destination to move the entry to</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public ValueTask Move(AbsolutePath newPath, CancellationToken token);
|
public ValueTask Move(AbsolutePath newPath, CancellationToken token);
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class IExtractedFileExtensions
|
||||||
|
{
|
||||||
|
public static async Task<Hash> MoveHashedAsync(this IExtractedFile file, AbsolutePath destPath, CancellationToken token)
|
||||||
|
{
|
||||||
|
if (file.CanMove)
|
||||||
|
{
|
||||||
|
await file.Move(destPath, token);
|
||||||
|
return await destPath.Hash(token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await using var s = await file.GetStream();
|
||||||
|
return await destPath.WriteAllHashedAsync(s, token, false);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -16,6 +16,7 @@ using Wabbajack.DTOs.BSA.FileStates;
|
|||||||
using Wabbajack.DTOs.Directives;
|
using Wabbajack.DTOs.Directives;
|
||||||
using Wabbajack.DTOs.DownloadStates;
|
using Wabbajack.DTOs.DownloadStates;
|
||||||
using Wabbajack.DTOs.JsonConverters;
|
using Wabbajack.DTOs.JsonConverters;
|
||||||
|
using Wabbajack.FileExtractor.ExtractedFiles;
|
||||||
using Wabbajack.Hashing.PHash;
|
using Wabbajack.Hashing.PHash;
|
||||||
using Wabbajack.Hashing.xxHash64;
|
using Wabbajack.Hashing.xxHash64;
|
||||||
using Wabbajack.Installer.Utilities;
|
using Wabbajack.Installer.Utilities;
|
||||||
@ -265,7 +266,8 @@ public abstract class AInstaller<T>
|
|||||||
case FromArchive _:
|
case FromArchive _:
|
||||||
if (grouped[vf].Count() == 1)
|
if (grouped[vf].Count() == 1)
|
||||||
{
|
{
|
||||||
await sf.Move(destPath, token);
|
var hash = await sf.MoveHashedAsync(destPath, token);
|
||||||
|
ThrowOnNonMatchingHash(file, hash);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -299,6 +301,7 @@ public abstract class AInstaller<T>
|
|||||||
|
|
||||||
protected void ThrowOnNonMatchingHash(CreateBSA bsa, Directive directive, AFile state, Hash hash)
|
protected void ThrowOnNonMatchingHash(CreateBSA bsa, Directive directive, AFile state, Hash hash)
|
||||||
{
|
{
|
||||||
|
if (hash == directive.Hash) return;
|
||||||
_logger.LogError("Hashes for BSA don't match after extraction, {BSA}, {Directive}, {ExpectedHash}, {Hash}", bsa.To, directive.To, directive.Hash, hash);
|
_logger.LogError("Hashes for BSA don't match after extraction, {BSA}, {Directive}, {ExpectedHash}, {Hash}", bsa.To, directive.To, directive.Hash, hash);
|
||||||
throw new Exception($"Hashes for {bsa.To} file {directive.To} did not match, expected {directive.Hash} got {hash}");
|
throw new Exception($"Hashes for {bsa.To} file {directive.To} did not match, expected {directive.Hash} got {hash}");
|
||||||
}
|
}
|
||||||
|
@ -274,7 +274,7 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
|||||||
{
|
{
|
||||||
var bsas = ModList.Directives.OfType<CreateBSA>().ToList();
|
var bsas = ModList.Directives.OfType<CreateBSA>().ToList();
|
||||||
_logger.LogInformation("Generating debug caches");
|
_logger.LogInformation("Generating debug caches");
|
||||||
var indexedByDestination = ModList.Directives.ToDictionary(d => d.To);
|
var indexedByDestination = UnoptimizedDirectives.ToDictionary(d => d.To);
|
||||||
_logger.LogInformation("Building {bsasCount} bsa files", bsas.Count);
|
_logger.LogInformation("Building {bsasCount} bsa files", bsas.Count);
|
||||||
NextStep("Installing", "Building BSAs", bsas.Count);
|
NextStep("Installing", "Building BSAs", bsas.Count);
|
||||||
|
|
||||||
@ -287,19 +287,19 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
|||||||
await using var a = BSADispatch.CreateBuilder(bsa.State, _manager);
|
await using var a = BSADispatch.CreateBuilder(bsa.State, _manager);
|
||||||
var streams = await bsa.FileStates.PMapAllBatchedAsync(_limiter, async state =>
|
var streams = await bsa.FileStates.PMapAllBatchedAsync(_limiter, async state =>
|
||||||
{
|
{
|
||||||
using var job = await _limiter.Begin($"Adding {state.Path.FileName}", 0, token);
|
|
||||||
var fs = sourceDir.Combine(state.Path).Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
var fs = sourceDir.Combine(state.Path).Open(FileMode.Open, FileAccess.Read, FileShare.Read);
|
||||||
var size = fs.Length;
|
|
||||||
job.Size = size;
|
|
||||||
await a.AddFile(state, fs, token);
|
await a.AddFile(state, fs, token);
|
||||||
await job.Report((int)size, token);
|
|
||||||
return fs;
|
return fs;
|
||||||
}).ToList();
|
}).ToList();
|
||||||
|
|
||||||
_logger.LogInformation("Writing {bsaTo}", bsa.To);
|
_logger.LogInformation("Writing {bsaTo}", bsa.To);
|
||||||
var outPath = _configuration.Install.Combine(bsa.To);
|
var outPath = _configuration.Install.Combine(bsa.To);
|
||||||
await using var outStream = outPath.Open(FileMode.Create, FileAccess.Write, FileShare.None);
|
|
||||||
|
await using (var outStream = outPath.Open(FileMode.Create, FileAccess.Write, FileShare.None))
|
||||||
|
{
|
||||||
await a.Build(outStream, token);
|
await a.Build(outStream, token);
|
||||||
|
}
|
||||||
|
|
||||||
streams.Do(s => s.Dispose());
|
streams.Do(s => s.Dispose());
|
||||||
|
|
||||||
await FileHashCache.FileHashWriteCache(outPath, bsa.Hash);
|
await FileHashCache.FileHashWriteCache(outPath, bsa.Hash);
|
||||||
@ -330,7 +330,10 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static HashSet<RelativePath> KnownModifiedFiles = new[]
|
||||||
|
{
|
||||||
|
"modlist.txt"
|
||||||
|
}.Select(r => r.ToRelativePath()).ToHashSet();
|
||||||
private async Task InstallIncludedFiles(CancellationToken token)
|
private async Task InstallIncludedFiles(CancellationToken token)
|
||||||
{
|
{
|
||||||
_logger.LogInformation("Writing inline files");
|
_logger.LogInformation("Writing inline files");
|
||||||
@ -351,7 +354,9 @@ public class StandardInstaller : AInstaller<StandardInstaller>
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
var hash = await outPath.WriteAllHashedAsync(await LoadBytesFromPath(directive.SourceDataID), token);
|
var hash = await outPath.WriteAllHashedAsync(await LoadBytesFromPath(directive.SourceDataID), token);
|
||||||
|
if (!KnownModifiedFiles.Contains(directive.To.FileName))
|
||||||
ThrowOnNonMatchingHash(directive, hash);
|
ThrowOnNonMatchingHash(directive, hash);
|
||||||
|
|
||||||
await FileHashCache.FileHashWriteCache(outPath, directive.Hash);
|
await FileHashCache.FileHashWriteCache(outPath, directive.Hash);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user