diff --git a/Rhea.Nar.Validator/Program.cs b/Rhea.Nar.Validator/Program.cs
new file mode 100644
index 0000000..14f9c22
--- /dev/null
+++ b/Rhea.Nar.Validator/Program.cs
@@ -0,0 +1,114 @@
+using System.Diagnostics;
+using ArcaneLibs;
+using ArcaneLibs.Extensions;
+using Rhea.Nar;
+
+// A simple app to compare output between cppnix/Lix and the NAR serializer
+int maxVerifySize = 1024 * 1024 * 1024;
+
+// return;
+// while (true)
+// foreach (var srcPath in (string[])[
+// "/etc/nix/nix.conf",
+// FileUtils.GetBinDir() + "/Rhea.runtimeconfig.json",
+// "/etc/nix",
+// ".",
+// "/nix/store/06d2xkrl3h1pbyg3m1whz1mvhafqgsqq-source",
+// "/nix/store/0l93s9x3z2s9p4r58jls0xiyk64hwkxz-source",
+// "/nix/store/2g4sa9xcir93nckzib9iq1ky6ly6azgw-7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"
+// ])
+// foreach (var srcPath in (string[])["/nix/store/7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"])
+Parallel.ForEach(FileUtils.EnumerateDirectory("/nix/store")
+ .Where(x => x is DirectoryInfo)
+ .Select(x => x.FullName),
+ new() { MaxDegreeOfParallelism = 64 },
+ srcPath =>
+ // foreach (var srcPath in FileUtils.EnumerateDirectory("/nix/store").Select(x=>x.FullName))
+ {
+ var sw = Stopwatch.StartNew();
+ TimeSpan oldTime, newTime;
+ var log = "";
+ log += ($"\n - {srcPath}:");
+ bool tooLarge = false;
+ // Console.WriteLine($"Original {srcPath}:");
+
+ var origBuf = new List<byte>();
+ var nixProcess = Process.Start(new ProcessStartInfo("nix", ["nar", "dump-path", srcPath])
+ {
+ RedirectStandardOutput = true
+ });
+ int b;
+ byte[] oldBuf = new byte[16384];
+ while ((b = nixProcess.StandardOutput.BaseStream.Read(oldBuf)) != 0)
+ {
+ if (!tooLarge)
+ {
+ if (origBuf.Count < maxVerifySize)
+ origBuf.AddRange(oldBuf[..b]);
+ else tooLarge = true;
+ }
+ // Console.WriteLine(b + " @ " + sw.Elapsed + " -> " + Util.BytesToString(origBuf.Count));
+ // Thread.Sleep(1);
+ }
+
+ // origBuf.ToArray().HexDump(64);
+ oldTime = sw.GetElapsedAndRestart();
+
+ // Console.WriteLine($"\nNew {srcPath}:");
+ List<byte> tbuf = [];
+ // List<byte> buf = [];
+ foreach (var chunk in new NarWriter().GetNarStreamContents(srcPath))
+ {
+ // Console.WriteLine($"ret Chunk({chunk.Length})");
+ if (!tooLarge)
+ {
+ if (tbuf.Count < maxVerifySize)
+ tbuf.AddRange(chunk);
+ else tooLarge = true;
+ }
+ // buf.AddRange(chunk);
+ // while (buf.Count > 64)
+ // {
+ // byte[] data = buf[..64].ToArray();
+ // buf = buf[64..];
+ // data.HexDump(64);
+ // }
+ }
+
+ // buf.ToArray().HexDump(64);
+ newTime = sw.GetElapsedAndRestart();
+
+ log += ($"\nOld time: {oldTime}, new time: {newTime}");
+ if (!tooLarge)
+ {
+ log += ("\nIs equal: " + origBuf.SequenceEqual(tbuf));
+ if (!origBuf.SequenceEqual(tbuf))
+ {
+ // File.WriteAllBytes("a", origBuf.ToArray().AsHexString().AsBytes().ToArray());
+ // File.WriteAllBytes("b", tbuf.ToArray().AsHexString().AsBytes().ToArray());
+ var origStdout = Console.Out;
+ using (var fs = File.OpenWrite("a"))
+ {
+ using var fsw = new StreamWriter(fs);
+ Console.SetOut(fsw);
+ origBuf.HexDump(width: 16, colorize: false);
+ Console.SetOut(origStdout);
+ }
+
+ using (var fs = File.OpenWrite("b"))
+ {
+ using var fsw = new StreamWriter(fs);
+ Console.SetOut(fsw);
+ tbuf.HexDump(width: 16, colorize: false);
+ Console.SetOut(origStdout);
+ }
+
+ Console.WriteLine(log);
+ Environment.Exit(0);
+ }
+ }
+ else log += "\nToo large to check consistency";
+
+ Console.WriteLine(log);
+ }
+);
\ No newline at end of file
diff --git a/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj b/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj
new file mode 100644
index 0000000..d63bef5
--- /dev/null
+++ b/Rhea.Nar.Validator/Rhea.Nar.Validator.csproj
@@ -0,0 +1,20 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+ <PropertyGroup>
+ <OutputType>Exe</OutputType>
+ <TargetFramework>net10.0</TargetFramework>
+ <ImplicitUsings>enable</ImplicitUsings>
+ <Nullable>enable</Nullable>
+ <PublishAot>true</PublishAot>
+ <InvariantGlobalization>true</InvariantGlobalization>
+ </PropertyGroup>
+
+ <ItemGroup>
+ <PackageReference Include="ArcaneLibs" Version="1.0.1-preview.20260812-173005" />
+ </ItemGroup>
+
+ <ItemGroup>
+ <ProjectReference Include="..\Rhea.Nar\Rhea.Nar.csproj" />
+ </ItemGroup>
+
+</Project>
diff --git a/Rhea.Nar/NarWriter.cs b/Rhea.Nar/NarWriter.cs
index 0ca2e85..52bbb0e 100644
--- a/Rhea.Nar/NarWriter.cs
+++ b/Rhea.Nar/NarWriter.cs
@@ -31,6 +31,22 @@ public class NarWriter
foreach (var chunk in GetNarSymlinkContents(fe))
yield return chunk;
}
+
+ private IEnumerable<byte[]> GetNarStreamContentsInner(FileSystemInfo fsi)
+ {
+ if (string.IsNullOrWhiteSpace(fsi.LinkTarget))
+ {
+ if (fsi is DirectoryInfo di)
+ foreach (var chunk in GetNarDirectoryContents(di))
+ yield return chunk;
+ else
+ foreach (var chunk in GetNarFileContents(fsi as FileInfo ?? throw new Exception(fsi.GetType().Name +" != FileInfo")))
+ yield return chunk;
+ }
+ else
+ foreach (var chunk in GetNarSymlinkContents(fsi))
+ yield return chunk;
+ }
private IEnumerable<byte[]> GetNarDirectoryContents(DirectoryInfo de)
{
@@ -43,7 +59,7 @@ public class NarWriter
yield return GetLengthPrefixedPadded(fe.Name.AsBytes().ToArray());
yield return NarConsts.Node;
- foreach (var chunk in GetNarStreamContentsInner(fe.FullName))
+ foreach (var chunk in GetNarStreamContentsInner(fe))
yield return chunk;
yield return NarConsts.RightParen;
@@ -52,7 +68,7 @@ public class NarWriter
yield return NarConsts.RightParen;
}
- private IEnumerable<byte[]> GetNarSymlinkContents(FileInfo fe)
+ private IEnumerable<byte[]> GetNarSymlinkContents(FileSystemInfo fe)
{
// yield return NarConsts.LeftParen;
//
diff --git a/Rhea.slnx b/Rhea.slnx
index 8a1246f..ac81b67 100644
--- a/Rhea.slnx
+++ b/Rhea.slnx
@@ -1,4 +1,5 @@
<Solution>
+ <Project Path="Rhea.Nar.Validator/Rhea.Nar.Validator.csproj" />
<Project Path="Rhea.Nar/Rhea.Nar.csproj" />
<Project Path="Rhea/Rhea.csproj" />
</Solution>
diff --git a/Rhea/Program.cs b/Rhea/Program.cs
index 78fa787..3d12b02 100644
--- a/Rhea/Program.cs
+++ b/Rhea/Program.cs
@@ -26,115 +26,6 @@ foreach (var fieldInfo in typeof(NarConsts).GetFields())
);
}
-int maxVerifySize = 8_192_000;
-
-// return;
-// while (true)
-// foreach (var srcPath in (string[])[
-// "/etc/nix/nix.conf",
-// FileUtils.GetBinDir() + "/Rhea.runtimeconfig.json",
-// "/etc/nix",
-// ".",
-// "/nix/store/06d2xkrl3h1pbyg3m1whz1mvhafqgsqq-source",
-// "/nix/store/0l93s9x3z2s9p4r58jls0xiyk64hwkxz-source",
-// "/nix/store/2g4sa9xcir93nckzib9iq1ky6ly6azgw-7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"
-// ])
-// foreach (var srcPath in (string[])["/nix/store/7j1q60m17gf95k3s0gk2qvjqygnp1q36-source"])
-Parallel.ForEach(FileUtils.EnumerateDirectory("/nix/store")
- // .Where(x => x is not DirectoryInfo)
- .Select(x => x.FullName),
- new() { MaxDegreeOfParallelism = 32 },
- srcPath =>
- // foreach (var srcPath in FileUtils.EnumerateDirectory("/nix/store").Select(x=>x.FullName))
- {
- var sw = Stopwatch.StartNew();
- TimeSpan oldTime, newTime;
- var log = "";
- log += ($"\n - {srcPath}:");
- bool tooLarge = false;
- // Console.WriteLine($"Original {srcPath}:");
-
- var origBuf = new List<byte>();
- var nixProcess = Process.Start(new ProcessStartInfo("nix", ["nar", "dump-path", srcPath])
- {
- RedirectStandardOutput = true
- });
- int b;
- byte[] oldBuf = new byte[16384];
- while ((b = nixProcess.StandardOutput.BaseStream.Read(oldBuf)) != 0)
- {
- if (!tooLarge)
- {
- if (origBuf.Count < maxVerifySize)
- origBuf.AddRange(oldBuf[..b]);
- else tooLarge = true;
- }
- // Console.WriteLine(b + " @ " + sw.Elapsed + " -> " + Util.BytesToString(origBuf.Count));
- // Thread.Sleep(1);
- }
-
- // origBuf.ToArray().HexDump(64);
- oldTime = sw.GetElapsedAndRestart();
-
- // Console.WriteLine($"\nNew {srcPath}:");
- List<byte> tbuf = [];
- // List<byte> buf = [];
- foreach (var chunk in new NarWriter().GetNarStreamContents(srcPath))
- {
- // Console.WriteLine($"ret Chunk({chunk.Length})");
- if (!tooLarge)
- {
- if (tbuf.Count < maxVerifySize)
- tbuf.AddRange(chunk);
- else tooLarge = true;
- }
- // buf.AddRange(chunk);
- // while (buf.Count > 64)
- // {
- // byte[] data = buf[..64].ToArray();
- // buf = buf[64..];
- // data.HexDump(64);
- // }
- }
-
- // buf.ToArray().HexDump(64);
- newTime = sw.GetElapsedAndRestart();
-
- log += ($"\nOld time: {oldTime}, new time: {newTime}");
- if (!tooLarge)
- {
- log += ("\nIs equal: " + origBuf.SequenceEqual(tbuf));
- if (!origBuf.SequenceEqual(tbuf))
- {
- // File.WriteAllBytes("a", origBuf.ToArray().AsHexString().AsBytes().ToArray());
- // File.WriteAllBytes("b", tbuf.ToArray().AsHexString().AsBytes().ToArray());
- var origStdout = Console.Out;
- using (var fs = File.OpenWrite("a"))
- {
- using var fsw = new StreamWriter(fs);
- Console.SetOut(fsw);
- origBuf.HexDump(width: 16, colorize: false);
- Console.SetOut(origStdout);
- }
-
- using (var fs = File.OpenWrite("b"))
- {
- using var fsw = new StreamWriter(fs);
- Console.SetOut(fsw);
- tbuf.HexDump(width: 16, colorize: false);
- Console.SetOut(origStdout);
- }
-
- Console.WriteLine(log);
- Environment.Exit(0);
- }
- }
- else log += "\nToo large to check consistency";
-
- Console.WriteLine(log);
- }
-);
-
return;
var builder = WebApplication.CreateBuilder(args);
|