Files
Installer/Editor/ShrinkSdkManifestStore.cs
cneicy 96480dd488
Publish UPM package / publish (push) Successful in 2s
feat(installer): rebuild package manager with ui toolkit
2026-08-26 12:48:35 +08:00

167 lines
5.8 KiB
C#

#if UNITY_EDITOR
#nullable enable
using System;
using System.IO;
using System.Linq;
using System.Text;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using UnityEngine;
namespace ShrinkSDK.Installer
{
internal static class ShrinkSdkManifestStore
{
internal static string ManifestPath => Path.Combine(
Path.GetFullPath(Path.Combine(Application.dataPath, "..")),
"Packages",
"manifest.json");
internal static bool HasShrinkSdkRegistry()
{
var manifest = ReadManifest();
return GetShrinkSdkRegistry(manifest) != null;
}
internal static void EnsureShrinkSdkRegistry()
{
var manifest = ReadManifest();
EnsureShrinkSdkRegistry(manifest);
AtomicWrite(manifest.ToString(Formatting.Indented) + Environment.NewLine);
}
internal static void EnsurePackageInstallation(
System.Collections.Generic.IEnumerable<ShrinkSdkPackageEntry> packages)
{
var manifest = ReadManifest();
EnsureShrinkSdkRegistry(manifest);
var requiresUniTask = false;
foreach (var package in packages)
{
EnsurePinnedDependency(manifest, package.PackageName, package.Version);
requiresUniTask |= package.RequiresUniTask;
}
if (requiresUniTask)
EnsurePinnedDependency(manifest, ShrinkSdkPackageCatalog.UniTaskPackageName,
ShrinkSdkPackageCatalog.UniTaskGitUrl);
AtomicWrite(manifest.ToString(Formatting.Indented) + Environment.NewLine);
}
private static void EnsureShrinkSdkRegistry(JObject manifest)
{
var registries = manifest["scopedRegistries"] as JArray;
if (registries == null)
{
registries = new JArray();
manifest["scopedRegistries"] = registries;
}
var conflictingRegistry = registries
.OfType<JObject>()
.FirstOrDefault(registry =>
!UrlEquals((string?)registry["url"], ShrinkSdkPackageCatalog.RegistryUrl) &&
(registry["scopes"] as JArray)?.Values<string>().Any(scope =>
string.Equals(scope, ShrinkSdkPackageCatalog.RegistryScope, StringComparison.Ordinal)) == true);
if (conflictingRegistry != null)
{
throw new InvalidOperationException(
"Packages/manifest.json already maps com.cneicy to another scoped registry. Resolve that registry explicitly before installing ShrinkSDK.");
}
var registry = GetShrinkSdkRegistry(manifest);
if (registry == null)
{
registry = new JObject
{
["name"] = ShrinkSdkPackageCatalog.RegistryName,
["url"] = ShrinkSdkPackageCatalog.RegistryUrl,
["scopes"] = new JArray(ShrinkSdkPackageCatalog.RegistryScope)
};
registries.Add(registry);
}
else
{
registry["name"] = ShrinkSdkPackageCatalog.RegistryName;
registry["url"] = ShrinkSdkPackageCatalog.RegistryUrl;
var scopes = registry["scopes"] as JArray ?? new JArray();
if (!scopes.Values<string>().Any(scope =>
string.Equals(scope, ShrinkSdkPackageCatalog.RegistryScope, StringComparison.Ordinal)))
{
scopes.Add(ShrinkSdkPackageCatalog.RegistryScope);
}
registry["scopes"] = scopes;
}
}
private static void EnsurePinnedDependency(JObject manifest, string packageName, string version)
{
var dependencies = manifest["dependencies"] as JObject;
if (dependencies == null)
{
dependencies = new JObject();
manifest["dependencies"] = dependencies;
}
dependencies[packageName] = version;
}
private static JObject ReadManifest()
{
if (!File.Exists(ManifestPath))
{
throw new FileNotFoundException("Unity package manifest was not found.", ManifestPath);
}
return JObject.Parse(File.ReadAllText(ManifestPath, Encoding.UTF8));
}
private static JObject? GetShrinkSdkRegistry(JObject manifest)
{
return (manifest["scopedRegistries"] as JArray)?
.OfType<JObject>()
.FirstOrDefault(registry => UrlEquals((string?)registry["url"], ShrinkSdkPackageCatalog.RegistryUrl));
}
private static bool UrlEquals(string? left, string right)
{
return string.Equals(NormalizeUrl(left), NormalizeUrl(right), StringComparison.OrdinalIgnoreCase);
}
private static string NormalizeUrl(string? url)
{
return (url ?? string.Empty).Trim().TrimEnd('/') + "/";
}
private static void AtomicWrite(string content)
{
var directory = Path.GetDirectoryName(ManifestPath);
if (string.IsNullOrWhiteSpace(directory))
{
throw new InvalidOperationException("Unity package manifest directory could not be resolved.");
}
var temporaryPath = Path.Combine(directory, ".manifest.shrinksdk.tmp");
File.WriteAllText(temporaryPath, content, new UTF8Encoding(false));
try
{
File.Replace(temporaryPath, ManifestPath, null);
}
catch
{
if (File.Exists(temporaryPath))
{
File.Delete(temporaryPath);
}
throw;
}
}
}
}
#endif