Rasagar/Library/PackageCache/com.unity.package-validation-suite/Lib/PvpXray/MetaFileVerifierV3.cs
2024-08-26 23:07:20 +03:00

116 lines
4.9 KiB
C#

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Text;
namespace PvpXray
{
class MetaFileVerifierV3 : Verifier.IChecker
{
const string k_Check = "PVP-26-3";
const string k_MetaExtension = ".meta";
public static string[] Checks => new[] { k_Check };
public static int PassCount => 0;
// Derive directories from file paths. This assumes that there are no empty directories.
internal static List<PathEntry> GetFileAndDirectoryEntries(IEnumerable<string> files)
{
var fileEntries = files.Select(path => new PathEntry(path)).ToList();
var entries = fileEntries.ToList();
var seenDirectories = new HashSet<string>();
var pathBuilder = new StringBuilder();
foreach (var fileEntry in fileEntries)
{
if (fileEntry.Components.Length > 1)
{
var componentsWithCase = fileEntry.PathWithCase.Split('/');
for (var length = 1; length < componentsWithCase.Length; length++)
{
pathBuilder.Clear();
pathBuilder.Append(componentsWithCase[0]);
for (var index = 1; index < length; index++)
{
pathBuilder.Append("/");
pathBuilder.Append(componentsWithCase[index]);
}
var directoryPath = pathBuilder.ToString();
if (seenDirectories.Add(directoryPath))
{
entries.Add(new PathEntry(directoryPath, isDirectory: true));
}
}
}
}
return entries;
}
public MetaFileVerifierV3(Verifier.Context context)
{
// We need to know about directories since folder assets also have corresponding meta files.
var entries = GetFileAndDirectoryEntries(context.Files);
var minVersion = context.Manifest["unity"].IfPresent?.String;
int i;
var targetUnityRequiresMetaFilesInPluginDirs = minVersion == null || (
(i = minVersion.IndexOf('.')) != -1 &&
int.TryParse(minVersion.SpanOrSubstring(0, i), NumberStyles.Integer, CultureInfo.InvariantCulture, out var major) &&
int.TryParse(minVersion.SpanOrSubstring(i + 1), NumberStyles.Integer, CultureInfo.InvariantCulture, out var minor) &&
(major < 2020 || (major <= 2021 && minor < 3) || (major == 2022 && minor < 2))
);
var entriesByPath = entries.ToDictionary(e => e.Path);
foreach (var entry in entries)
{
// ignore all files inside plugin directories, unless targeting old Unity version
if (!targetUnityRequiresMetaFilesInPluginDirs && entry.IsInsidePluginDirectory) continue;
if (entry.HasExtension(k_MetaExtension))
{
// ignore .meta files inside hidden directories (like Samples~)
if (entry.Components.Length > 1 && new PathEntry(entry.DirectoryWithCase, isDirectory: true).IsHidden) continue;
if (entry.IsDirectory)
{
context.AddError(k_Check, $"{entry.PathWithCase}: Directory with meta file extension");
}
else
{
var assetPath = entry.Path.Substring(0, entry.Path.Length - k_MetaExtension.Length);
if (!entriesByPath.TryGetValue(assetPath, out var assetEntry))
{
context.AddError(k_Check, $"{entry.PathWithCase}: Meta file without corresponding asset");
}
else if (assetEntry.IsHidden)
{
context.AddError(k_Check, $"{entry.PathWithCase}: Meta file for hidden asset");
}
else if (assetEntry.HasExtension(k_MetaExtension))
{
context.AddError(k_Check, $"{entry.PathWithCase}: Meta file for asset with meta file extension");
}
}
}
else if (!entry.IsHidden)
{
var metaPath = entry.Path + k_MetaExtension;
if (!entriesByPath.ContainsKey(metaPath))
{
context.AddError(k_Check, $"{entry.PathWithCase}: Asset without corresponding meta file");
}
}
}
}
public void CheckItem(Verifier.PackageFile file, int passIndex)
{
throw new InvalidOperationException();
}
public void Finish()
{
}
}
}