Rename Feedser to Concelier
This commit is contained in:
		@@ -0,0 +1,52 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Security.Cryptography;
 | 
			
		||||
using System.Text;
 | 
			
		||||
 | 
			
		||||
namespace StellaOps.Concelier.Exporter.Json;
 | 
			
		||||
 | 
			
		||||
public static class ExportDigestCalculator
 | 
			
		||||
{
 | 
			
		||||
    public static string ComputeTreeDigest(JsonExportResult result)
 | 
			
		||||
    {
 | 
			
		||||
        ArgumentNullException.ThrowIfNull(result);
 | 
			
		||||
 | 
			
		||||
        using var sha256 = SHA256.Create();
 | 
			
		||||
        var buffer = new byte[128 * 1024];
 | 
			
		||||
 | 
			
		||||
        foreach (var file in result.FilePaths.OrderBy(static path => path, StringComparer.Ordinal))
 | 
			
		||||
        {
 | 
			
		||||
            var normalized = file.Replace("\\", "/");
 | 
			
		||||
            var pathBytes = Encoding.UTF8.GetBytes(normalized);
 | 
			
		||||
            _ = sha256.TransformBlock(pathBytes, 0, pathBytes.Length, null, 0);
 | 
			
		||||
 | 
			
		||||
            var fullPath = ResolveFullPath(result.ExportDirectory, normalized);
 | 
			
		||||
            using var stream = File.OpenRead(fullPath);
 | 
			
		||||
            int read;
 | 
			
		||||
            while ((read = stream.Read(buffer, 0, buffer.Length)) > 0)
 | 
			
		||||
            {
 | 
			
		||||
                _ = sha256.TransformBlock(buffer, 0, read, null, 0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        _ = sha256.TransformFinalBlock(Array.Empty<byte>(), 0, 0);
 | 
			
		||||
        var hash = sha256.Hash ?? Array.Empty<byte>();
 | 
			
		||||
        var hex = Convert.ToHexString(hash).ToLowerInvariant();
 | 
			
		||||
        return $"sha256:{hex}";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private static string ResolveFullPath(string root, string normalizedRelativePath)
 | 
			
		||||
    {
 | 
			
		||||
        var segments = normalizedRelativePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
 | 
			
		||||
        var parts = new string[segments.Length + 1];
 | 
			
		||||
        parts[0] = root;
 | 
			
		||||
        for (var i = 0; i < segments.Length; i++)
 | 
			
		||||
        {
 | 
			
		||||
            parts[i + 1] = segments[i];
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return Path.Combine(parts);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user