2021-09-27 12:42:46 +00:00
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Collections.Immutable;
|
|
|
|
using System.Linq;
|
|
|
|
using System.Threading.Tasks;
|
|
|
|
using Wabbajack.Hashing.xxHash64;
|
|
|
|
using Wabbajack.Paths;
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
namespace Wabbajack.VFS;
|
|
|
|
|
|
|
|
public class IndexRoot
|
2021-09-27 12:42:46 +00:00
|
|
|
{
|
2021-10-23 16:51:17 +00:00
|
|
|
public static IndexRoot Empty = new();
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public IndexRoot(IReadOnlyList<VirtualFile> aFiles,
|
|
|
|
IDictionary<FullPath, VirtualFile> byFullPath,
|
|
|
|
ILookup<Hash, VirtualFile> byHash,
|
|
|
|
IDictionary<AbsolutePath, VirtualFile> byRoot,
|
|
|
|
ILookup<IPath, VirtualFile> byName)
|
|
|
|
{
|
|
|
|
AllFiles = aFiles;
|
|
|
|
ByFullPath = byFullPath;
|
|
|
|
ByHash = byHash;
|
|
|
|
ByRootPath = byRoot;
|
|
|
|
ByName = byName;
|
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public IndexRoot()
|
|
|
|
{
|
|
|
|
AllFiles = ImmutableList<VirtualFile>.Empty;
|
|
|
|
ByFullPath = new Dictionary<FullPath, VirtualFile>();
|
|
|
|
ByHash = EmptyLookup<Hash, VirtualFile>.Instance;
|
|
|
|
ByRootPath = new Dictionary<AbsolutePath, VirtualFile>();
|
|
|
|
ByName = EmptyLookup<IPath, VirtualFile>.Instance;
|
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
|
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public IReadOnlyList<VirtualFile> AllFiles { get; }
|
|
|
|
public IDictionary<FullPath, VirtualFile> ByFullPath { get; }
|
|
|
|
public ILookup<Hash, VirtualFile> ByHash { get; }
|
|
|
|
public ILookup<IPath, VirtualFile> ByName { get; set; }
|
|
|
|
public IDictionary<AbsolutePath, VirtualFile> ByRootPath { get; }
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public async Task<IndexRoot> Integrate(IEnumerable<VirtualFile> files)
|
|
|
|
{
|
|
|
|
var allFiles = AllFiles.Concat(files)
|
|
|
|
.OrderByDescending(f => f.LastModified)
|
|
|
|
.GroupBy(f => f.FullPath)
|
|
|
|
.Select(g => g.Last())
|
|
|
|
.ToList();
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
var byFullPath = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren)
|
|
|
|
.ToDictionary(f => f.FullPath));
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
var byHash = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren)
|
|
|
|
.Where(f => f.Hash != default)
|
|
|
|
.ToLookup(f => f.Hash));
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
var byName = Task.Run(() => allFiles.SelectMany(f => f.ThisAndAllChildren)
|
|
|
|
.ToLookup(f => f.Name));
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
var byRootPath = Task.Run(() => allFiles.ToDictionary(f => f.AbsoluteName));
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
var result = new IndexRoot(allFiles,
|
|
|
|
await byFullPath,
|
|
|
|
await byHash,
|
|
|
|
await byRootPath,
|
|
|
|
await byName);
|
|
|
|
return result;
|
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public VirtualFile FileForArchiveHashPath(HashRelativePath argArchiveHashPath)
|
|
|
|
{
|
|
|
|
var cur = ByHash[argArchiveHashPath.Hash].First(f => f.Parent == null);
|
|
|
|
return argArchiveHashPath.Parts.Aggregate(cur,
|
|
|
|
(current, itm) => ByName[itm].First(f => f.Parent == current));
|
|
|
|
}
|
2021-09-27 12:42:46 +00:00
|
|
|
|
2021-10-23 16:51:17 +00:00
|
|
|
public static class EmptyLookup<TKey, TElement>
|
|
|
|
{
|
|
|
|
public static ILookup<TKey, TElement> Instance { get; } =
|
|
|
|
Enumerable.Empty<TElement>().ToLookup(x => default(TKey));
|
2021-09-27 12:42:46 +00:00
|
|
|
}
|
|
|
|
}
|