mirror of
https://github.com/spacebarchat/server.git
synced 2026-05-04 22:35:22 +00:00
190 lines
8.9 KiB
C#
Executable File
190 lines
8.9 KiB
C#
Executable File
#! /usr/bin/env dotnet
|
|
#:property Nullable=enable
|
|
#:property PublishAOT=false
|
|
#:package ArcaneLibs@1.0.1-preview.2026*
|
|
|
|
using System.Diagnostics;
|
|
using ArcaneLibs;
|
|
using System.Text.Json;
|
|
|
|
#region Sync package versions for CDN worker
|
|
|
|
{
|
|
Console.WriteLine("==> Ensuring CDN worker dependencies are in sync...");
|
|
var origContent = await File.ReadAllTextAsync("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16-HDRI.x86_64.csproj");
|
|
var depToReplace = "Magick.NET-Q16-HDRI-OpenMP-x64";
|
|
(string Project, string Dependency)[] replaceTargets = [
|
|
// ("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16-HDRI.x86_64.csproj", "Magick.NET-Q16-HDRI-OpenMP-x64"), // source
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16.x86_64.csproj", "Magick.NET-Q16-OpenMP-x64"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q8.x86_64.csproj", "Magick.NET-Q8-OpenMP-x64"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16-HDRI.aarch64.csproj", "Magick.NET-Q16-HDRI-OpenMP-arm64"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16.aarch64.csproj", "Magick.NET-Q16-OpenMP-arm64"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q8.aarch64.csproj", "Magick.NET-Q8-OpenMP-arm64"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16-HDRI.AnyCPU.csproj", "Magick.NET-Q16-HDRI-AnyCPU"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q16.AnyCPU.csproj", "Magick.NET-Q16-AnyCPU"),
|
|
("Spacebar.Cdn.Worker/Spacebar.Cdn.Worker.Q8.AnyCPU.csproj", "Magick.NET-Q8-AnyCPU"),
|
|
];
|
|
|
|
foreach (var target in replaceTargets) {
|
|
Console.WriteLine($" ==> {target.Project} -> {target.Dependency}");
|
|
await File.WriteAllTextAsync(target.Project, origContent.Replace(depToReplace, target.Dependency));
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
Console.WriteLine("==> Getting outputs...");
|
|
var outNames = JsonSerializer
|
|
.Deserialize<string[]>(Util.GetCommandOutputSync("nix", $"eval --json .#packages.x86_64-linux --apply builtins.attrNames", silent: true, stderr: false))!
|
|
.Where(o => args.Length == 0 || args.Select(x => x.Replace('.', '-')).Any(o.Contains)).ToArray();
|
|
|
|
Console.WriteLine($"==> Updating dependencies for {outNames.Length} projects...");
|
|
|
|
#region Dependency resolution
|
|
|
|
var sortSw = Stopwatch.StartNew();
|
|
Console.WriteLine($"==> Sorting projects by dependencies...");
|
|
Console.WriteLine($" ==> Getting project references...");
|
|
(string Name, string[] References)[] byName = await Task.WhenAll(outNames
|
|
.Select(async x => {
|
|
await Task.Delay(Random.Shared.Next(outNames.Length));
|
|
var refJson = Util.GetCommandOutputSync("nix", $"eval --json .#packages.x86_64-linux.{x}.passthru.__sbDmProjectRefs.names", silent: true, stderr: false);
|
|
var references = string.IsNullOrEmpty(refJson) ? [] : JsonSerializer.Deserialize<string[]>(refJson)!.Select(x => x.Replace('.', '-')).ToArray();
|
|
if (references.Length > 0)
|
|
Console.WriteLine($" ==> Got {references.Length} project references for {x}");
|
|
// Console.WriteLine($" ==> Got {references.Length} project references for {x}: {string.Join(", ", references)}");
|
|
return (x, references);
|
|
}).ToList());
|
|
|
|
Console.WriteLine($" ==> Mapping to tree nodes...");
|
|
// create nodes first
|
|
var deps = byName.Select(x => new ProjectDependencyNode() {
|
|
Name = x.Name,
|
|
References = []
|
|
}).ToArray();
|
|
|
|
// actually fill in references
|
|
foreach (var d in deps) {
|
|
d.References = deps.Where(x => byName.First(bn => bn.Name == d.Name).References.Contains(x.Name)).ToArray();
|
|
Console.WriteLine($" ==> {d.Name} => {string.Join(", ", d.References.Select(x => x.GetShortName()))}");
|
|
}
|
|
|
|
Console.WriteLine($" ==> Sorting...");
|
|
|
|
deps = deps.OrderBy(x => x.GetDepth()).ThenBy(x => x.GetWeight()).ThenBy(x => x.Name).ToArray();
|
|
foreach (var d in deps) {
|
|
// just a nice thing when debugging
|
|
d.References = d.References.OrderBy(x => x.GetDepth()).ThenBy(x => x.GetWeight()).ThenBy(x => x.Name).ToArray();
|
|
Console.WriteLine($" ==> {d.GetNameWithWeights()} => {string.Join(", ", d.References.Select(x => $"{x.GetNameWithWeights(true)}"))}");
|
|
}
|
|
|
|
Console.WriteLine($" ==> Sorted dependency tree with {deps.Length} projects in {sortSw.Elapsed}");
|
|
|
|
#endregion
|
|
|
|
var maxNameLength = deps.Max(x => x.Name.Length);
|
|
|
|
foreach (var depthGroup in deps.GroupBy(x => x.GetDepth())) {
|
|
var tasks = depthGroup.Index().Select(indexedOutpEnt => Task.Run(async () => {
|
|
var (idx, outpEnt) = indexedOutpEnt;
|
|
var outp = outpEnt.Name;
|
|
var prefix = ConsoleUtils.ColoredString(
|
|
$"{outpEnt.GetDepth():00}.{idx:00}({outpEnt.GetWeight():000}) {outpEnt.Name.PadRight(maxNameLength)}>",
|
|
(byte)((outp.GetHashCode() >> 16) & 0xff),
|
|
(byte)((outp.GetHashCode() >> 8) & 0xff),
|
|
(byte)(outp.GetHashCode() & 0xff)
|
|
);
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> Updating {outp}...", 0x80, 0x80, 0xff));
|
|
|
|
var rootDir = outpEnt.GetRelativeRootDir();
|
|
var depsFile = outpEnt.GetDepsFile();
|
|
if (depsFile is null) {
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> No __nugetDeps attribute, skipping!", 0xff, 0x80, 0x80));
|
|
return;
|
|
}
|
|
|
|
Console.WriteLine(
|
|
prefix
|
|
+ ConsoleUtils.ColoredString($" ==> Got project root directory: ", 0x80, 0xff, 0xff)
|
|
+ ConsoleUtils.ColoredString($"{rootDir}", 0x80, 0xff, 0xff)
|
|
+ " - "
|
|
+ ConsoleUtils.ColoredString($"{depsFile.Value.StorePath.Replace(depsFile.Value.Name, "")}", 0x80, 0x80, 0xff)
|
|
+ ConsoleUtils.ColoredString($"{depsFile.Value.Name}", 0x80, 0xff, 0x80)
|
|
+ (File.Exists(depsFile.Value.LocalPath)
|
|
? ConsoleUtils.ColoredString($" (exists)", 0x80, 0xff, 0x80)
|
|
: ConsoleUtils.ColoredString($" (does not exist)", 0xf, 0x80, 0x80))
|
|
);
|
|
|
|
if (!File.Exists(depsFile.Value.LocalPath)) {
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> No NuGet deps file, skipping!", 0xff, 0x80, 0x80));
|
|
return;
|
|
}
|
|
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> Building fetch-deps script...", 0x80, 0xff, 0x80));
|
|
var fname = outpEnt.GetDepsUpdateScript();
|
|
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> Running fetch-deps script, writing into {depsFile.Value.LocalPath}...", 0x80, 0xff, 0x80));
|
|
RunCommandSync(fname, depsFile.Value.LocalPath);
|
|
|
|
var resolvedDeps = JsonSerializer.Deserialize<object[]>(await File.ReadAllTextAsync(depsFile.Value.LocalPath));
|
|
Console.WriteLine(prefix + ConsoleUtils.ColoredString($" ==> Locked {resolvedDeps.Length} dependencies!",
|
|
(byte)(resolvedDeps.Length == 0 ? 0xff : 0x80),
|
|
(byte)(resolvedDeps.Length == 0 ? 0x80 : 0xff),
|
|
0x80
|
|
));
|
|
RunCommandSync("nix", $"run nixpkgs#git -- add {depsFile.Value.LocalPath}");
|
|
})).ToList();
|
|
|
|
await Task.WhenAll(tasks);
|
|
}
|
|
|
|
static void RunCommandSync(string command, string args = "", bool silent = false) {
|
|
// Console.WriteLine($"Executing command (silent: {silent}): {command} {args}");
|
|
Util.RunCommandSync(command, args, silent);
|
|
}
|
|
|
|
public class ProjectDependencyNode : IComparable {
|
|
public required string Name;
|
|
public required ProjectDependencyNode[] References;
|
|
|
|
public int GetDepth() {
|
|
if (References.Length == 0) return 0;
|
|
return References.Max(x => x.GetDepth()) + 1;
|
|
}
|
|
|
|
public int GetWeight() {
|
|
if (References.Length == 0) return 1;
|
|
return References.Sum(x => x.GetWeight()) + 1;
|
|
}
|
|
|
|
public string GetNameWithWeights(bool compact = false) =>
|
|
compact
|
|
? $"{GetShortName()}:{GetDepth()}w{GetWeight()}"
|
|
: $"{Name} @ {GetDepth()} | {GetWeight()}";
|
|
|
|
public string GetShortName() => Name.Replace("Spacebar-", "Sb-")
|
|
.Replace("-Models-", "-Mdl-")
|
|
.Replace("-Interop-", "-Intp-")
|
|
.Replace("-Replication-", "-Rpl-")
|
|
.Replace("-Authentication-", "-Auth-");
|
|
|
|
public string GetRelativeRootDir() => JsonSerializer
|
|
.Deserialize<string>(Util.GetCommandOutputSync("nix", $"eval --json .#packages.x86_64-linux.{Name}.srcRoot", silent: true, stderr: false))!
|
|
.Split("/extra/admin-api/", 2)[1];
|
|
|
|
public string GetDepsUpdateScript() => Util.GetCommandOutputSync("nix", $"build .#{Name}.passthru.fetch-deps --no-link --print-out-paths", stderr: false);
|
|
|
|
public (string Name, string StorePath, string LocalPath)? GetDepsFile() {
|
|
var storePath = JsonSerializer.Deserialize<string>(Util.GetCommandOutputSync("nix", $"eval --json .#packages.x86_64-linux.{Name}.passthru.__nugetDeps", silent: true,
|
|
stderr: false));
|
|
return storePath == null
|
|
? null
|
|
: (
|
|
new FileInfo(storePath).Name,
|
|
storePath,
|
|
Path.Combine(GetRelativeRootDir(), new FileInfo(storePath).Name)
|
|
);
|
|
}
|
|
|
|
public int CompareTo(object? obj) => References.Any(x => x.Name == Name) ? 1 : 0;
|
|
} |