using System.Collections.ObjectModel; using System.Text.Json; using File_Folder_Helper.Models; using Microsoft.Extensions.Logging; namespace File_Folder_Helper.ADO2025.PI5; internal static partial class Helper20250305 { private static readonly HttpClient _HttpClient = new(); private record Record(Uri URI, string Path, DateTime LastModified, int? TotalSeconds); internal static void WriteNginxFileSystemDelta(ILogger logger, List args) { string host = args[2]; string rootDirectoryName = args[3]; string format = NginxFileSystem.GetFormat(); TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local; string compareDirectory = Path.GetFullPath(args[0]); logger.LogInformation("Comparing files on {host}", host); ReadOnlyCollection records = GetRecords(format, timeZoneInfo, host, new([rootDirectoryName]), compareDirectory); #if ShellProgressBar ProgressBar progressBar = new(records.Count, "Downloading", new ProgressBarOptions() { ProgressCharacter = '─', ProgressBarOnBottom = true, DisableBottomPercentage = true }); #endif foreach (Record record in records) { #if ShellProgressBar progressBar.Tick(); #endif if (record.TotalSeconds is null) Download(record); else if (record.TotalSeconds.Value == 0) logger.LogInformation("Different lengths"); else if (record.TotalSeconds.Value > 0) logger.LogInformation("Overwrite remote (https)"); else logger.LogInformation("Overwrite local"); } #if ShellProgressBar progressBar.Dispose(); #endif } private static ReadOnlyCollection GetRecords(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection directoryNames, string compareDirectory) { List results = []; Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}"); ReadOnlyCollection? nginxFileSystems = GetCollection(format, timeZoneInfo, uri); if (nginxFileSystems is not null) { NginxFileSystem nginxFileSystem; ReadOnlyCollection records; string checkDirectory = $"{compareDirectory}\\{string.Join('\\', directoryNames)}"; if (!Directory.Exists(checkDirectory)) _ = Directory.CreateDirectory(checkDirectory); for (int i = 0; i < nginxFileSystems.Count; i++) { nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]); if (nginxFileSystem.Type == "file") { Record? record = CompareFile(host, directoryNames, compareDirectory, nginxFileSystem); if (record is not null) results.Add(record); } else { records = CompareDirectory(format, timeZoneInfo, host, directoryNames, compareDirectory, nginxFileSystem); foreach (Record record in records) results.Add(record); } } } return results.AsReadOnly(); } private static ReadOnlyCollection? GetCollection(string format, TimeZoneInfo timeZoneInfo, Uri uri) { List? results; Task taskHttpResponseMessage = _HttpClient.GetAsync(uri); taskHttpResponseMessage.Wait(); if (!taskHttpResponseMessage.Result.IsSuccessStatusCode) results = null; else { Task taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync(); taskString.Wait(); if (taskString.Result.StartsWith('<')) results = null; else { NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray); if (nginxFileSystems is null) results = null; else { results = []; NginxFileSystem nginxFileSystem; for (int i = 0; i < nginxFileSystems.Length; i++) { nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]); results.Add(nginxFileSystem); } } } } return results?.AsReadOnly(); } private static Record? CompareFile(string host, ReadOnlyCollection directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) { Record? result; if (nginxFileSystem.LastModified is null || nginxFileSystem.Length is null) result = null; else { Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}/{nginxFileSystem.Name}"); FileInfo fileInfo = new($"{compareDirectory}\\{string.Join('\\', directoryNames)}\\{nginxFileSystem.Name}"); if (!fileInfo.Exists) result = new(URI: uri, Path: fileInfo.FullName, LastModified: nginxFileSystem.LastModified.Value, TotalSeconds: null); else { int totalSeconds = (int)new TimeSpan(fileInfo.LastWriteTime.Ticks - nginxFileSystem.LastModified.Value.Ticks).TotalSeconds; if (totalSeconds is not < 2 or not > -2) result = new(URI: uri, Path: fileInfo.FullName, LastModified: nginxFileSystem.LastModified.Value, TotalSeconds: totalSeconds); else if (fileInfo.Length != nginxFileSystem.Length.Value) result = new(URI: uri, Path: fileInfo.FullName, LastModified: nginxFileSystem.LastModified.Value, TotalSeconds: 0); else result = null; } } return result; } private static ReadOnlyCollection CompareDirectory(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) { ReadOnlyCollection results; List collection = directoryNames.ToList(); collection.Add(nginxFileSystem.Name); results = GetRecords(format, timeZoneInfo, host, collection.AsReadOnly(), compareDirectory); return results; } private static void Download(Record record) { Task taskHttpResponseMessage = _HttpClient.GetAsync(record.URI); taskHttpResponseMessage.Wait(); if (taskHttpResponseMessage.Result.IsSuccessStatusCode) { Task taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync(); taskString.Wait(); File.WriteAllText(record.Path, taskString.Result); File.SetLastWriteTime(record.Path, record.LastModified); } } }