diff --git a/ADO2025/PI6/Helper-2025-05-19.cs b/ADO2025/PI6/Helper-2025-05-19.cs index e2e8d54..8f234c2 100644 --- a/ADO2025/PI6/Helper-2025-05-19.cs +++ b/ADO2025/PI6/Helper-2025-05-19.cs @@ -13,11 +13,18 @@ internal static partial class Helper20250519 { private record RelativePath(string LeftDirectory, string? RightDirectory, - Record[] Records); + Record[] Records) { + + public override string ToString() { + string result = JsonSerializer.Serialize(this, Helper20250519RelativePath.Default.RelativePath); + return result; + } + + } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(RelativePath))] - private partial class RelativePathSourceGenerationContext : JsonSerializerContext { + private partial class Helper20250519RelativePath : JsonSerializerContext { } private record Review(Segment[]? AreEqual, @@ -26,11 +33,18 @@ internal static partial class Helper20250519 { Segment[]? NotEqualBut, Record[]? Records, Segment[]? RightSideIsNewer, - Segment[]? RightSideOnly); + Segment[]? RightSideOnly) { + + public override string ToString() { + string result = JsonSerializer.Serialize(this, Helper20250519Review.Default.Review); + return result; + } + + } [JsonSourceGenerationOptions(WriteIndented = true)] [JsonSerializable(typeof(Review))] - private partial class ReviewSourceGenerationContext : JsonSerializerContext { + private partial class Helper20250519Review : JsonSerializerContext { } private record Record(string RelativePath, @@ -49,6 +63,38 @@ internal static partial class Helper20250519 { long Ticks, string UrlEncodedFile); + private record Input(string RightDirectory, + string LeftDirectory, + string IncludePatternsFile, + string ExcludePatternsFile, + string[] BaseAddresses, + string Page, + string[] Segments) { + + private static string GetDirectory(List args) => + Path.GetFullPath(args[0].Split('~')[0]); + + internal static Input Get(List args) => + new(RightDirectory: GetDirectory(args), + LeftDirectory: Path.GetFullPath(args[2].Split('~')[0]), + IncludePatternsFile: Path.Combine(GetDirectory(args), ".vscode", args[3]), + ExcludePatternsFile: Path.Combine(GetDirectory(args), ".vscode", args[4]), + BaseAddresses: args.Count < 5 ? [] : args[5].Split('~'), + Page: args[6], + Segments: args[9].Split('~')); + + public override string ToString() { + string result = JsonSerializer.Serialize(this, Helper20250519Input.Default.Input); + return result; + } + + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(Input))] + private partial class Helper20250519Input : JsonSerializerContext { + } + private record Logic(string Comment, char GreaterThan, bool? LeftSideIsNewer, @@ -85,53 +131,53 @@ internal static partial class Helper20250519 { const int leftSideIsNewerIndex = 1; const int rightSideIsNewerIndex = 3; string comment = segments[commentIndex]; - if (string.IsNullOrEmpty(segments[leftSideOnlyIndex])) + if (string.IsNullOrEmpty(segments[leftSideOnlyIndex])) { leftSideOnly = null; - else if (segments[leftSideOnlyIndex][0] == plus) + } else if (segments[leftSideOnlyIndex][0] == plus) { leftSideOnly = true; - else if (segments[leftSideOnlyIndex][0] == minus) + } else if (segments[leftSideOnlyIndex][0] == minus) { leftSideOnly = false; - else { + } else { check = false; leftSideOnly = null; } - if (string.IsNullOrEmpty(segments[leftSideIsNewerIndex])) + if (string.IsNullOrEmpty(segments[leftSideIsNewerIndex])) { leftSideIsNewer = null; - else if (segments[leftSideIsNewerIndex][0] == greaterThan) + } else if (segments[leftSideIsNewerIndex][0] == greaterThan) { leftSideIsNewer = true; - else if (segments[leftSideIsNewerIndex][0] == lessThan) + } else if (segments[leftSideIsNewerIndex][0] == lessThan) { leftSideIsNewer = false; - else { + } else { check = false; leftSideIsNewer = null; } - if (string.IsNullOrEmpty(segments[notEqualButIndex])) + if (string.IsNullOrEmpty(segments[notEqualButIndex])) { notEqualBut = null; - else if (segments[notEqualButIndex][0] == greaterThan) + } else if (segments[notEqualButIndex][0] == greaterThan) { notEqualBut = true; - else if (segments[notEqualButIndex][0] == lessThan) + } else if (segments[notEqualButIndex][0] == lessThan) { notEqualBut = false; - else { + } else { check = false; notEqualBut = null; } - if (string.IsNullOrEmpty(segments[rightSideIsNewerIndex])) + if (string.IsNullOrEmpty(segments[rightSideIsNewerIndex])) { rightSideIsNewer = null; - else if (segments[rightSideIsNewerIndex][0] == greaterThan) + } else if (segments[rightSideIsNewerIndex][0] == greaterThan) { rightSideIsNewer = true; - else if (segments[rightSideIsNewerIndex][0] == lessThan) + } else if (segments[rightSideIsNewerIndex][0] == lessThan) { rightSideIsNewer = false; - else { + } else { check = false; rightSideIsNewer = null; } - if (string.IsNullOrEmpty(segments[rightSideOnlyIndex])) + if (string.IsNullOrEmpty(segments[rightSideOnlyIndex])) { rightSideOnly = null; - else if (segments[rightSideOnlyIndex][0] == plus) + } else if (segments[rightSideOnlyIndex][0] == plus) { rightSideOnly = true; - else if (segments[rightSideOnlyIndex][0] == minus) + } else if (segments[rightSideOnlyIndex][0] == minus) { rightSideOnly = false; - else { + } else { check = false; rightSideOnly = null; } @@ -154,27 +200,46 @@ internal static partial class Helper20250519 { return result; } + public override string ToString() { + string result = JsonSerializer.Serialize(this, Helper20250519Logic.Default.Logic); + return result; + } + + } + + [JsonSourceGenerationOptions(WriteIndented = true)] + [JsonSerializable(typeof(Logic))] + private partial class Helper20250519Logic : JsonSerializerContext { } internal static void LiveSync(ILogger logger, List args) { - string[] segments = args[9].Split('~'); - Logic? logic = segments.Length != 6 ? null : Logic.Get(segments); - string[] baseAddresses = args.Count < 5 ? [] : args[5].Split('~'); - if (logic is null || baseAddresses.Length == 0) - logger.LogInformation("Invalid input!"); - else { - string rightDirectory = Path.GetFullPath(args[0].Split('~')[0]); - string excludePatternsFile = Path.Combine(rightDirectory, args[4]); - string includePatternsFile = Path.Combine(rightDirectory, args[3]); - Matcher matcher = GetMatcher(excludePatternsFile, includePatternsFile); - ReadOnlyCollection records = GetRecords(rightDirectory, matcher); - if (records.Count == 0) + logger.LogInformation(args[0]); + logger.LogInformation(args[1]); + logger.LogInformation(args[2]); + if (args[2].EndsWith("input.json") && !File.Exists(args[2])) { + File.WriteAllText(args[2], "{}"); + } + string? json = !args[2].EndsWith("input.json") ? null : File.ReadAllText(args[2]); + Input input = string.IsNullOrEmpty(json) + ? Input.Get(args) + : JsonSerializer.Deserialize(json, Helper20250519Input.Default.Input) + ?? throw new Exception(); + Logic? logic = input.Segments.Length != 6 ? null : Logic.Get(input.Segments); + if (logic is null || input.BaseAddresses.Length == 0) { + logger.LogInformation($"Invalid input!{Environment.NewLine}{input}"); + } else { + Matcher matcher = GetMatcher(input.ExcludePatternsFile, input.IncludePatternsFile); + ReadOnlyCollection records = GetRecords(input.RightDirectory, matcher); + if (records.Count == 0) { logger.LogInformation("No source records"); - else { - string page = args[6]; - string leftDirectory = Path.GetFullPath(args[2].Split('~')[0]); - RelativePath relativePath = new(LeftDirectory: leftDirectory, RightDirectory: rightDirectory, Records: records.ToArray()); - LiveSync180(logger, logic, baseAddresses, page, relativePath); + } else { + RelativePath relativePath = new(LeftDirectory: input.LeftDirectory, RightDirectory: input.RightDirectory, Records: records.ToArray()); + json = JsonSerializer.Serialize(relativePath, Helper20250519RelativePath.Default.RelativePath); + if (string.IsNullOrEmpty(json)) { + LiveSync180(logger, logic, input.BaseAddresses, input.Page, relativePath); + } else { + File.WriteAllText(Path.Combine(input.RightDirectory, ".vscode", $"{nameof(RelativePath)}.json"), json); + } } } } @@ -197,11 +262,13 @@ internal static partial class Helper20250519 { ReadOnlyCollection> collection = Helpers.HelperDirectory.GetFilesCollection(directory, "*", "*"); foreach (ReadOnlyCollection c in collection) { foreach (string f in c) { - if (!matcher.Match(directory, f).HasMatches) + if (!matcher.Match(directory, f).HasMatches) { continue; + } fileInfo = new(f); - if (fileInfo.Length == 0) + if (fileInfo.Length == 0) { continue; + } relativePath = Path.GetRelativePath(directory, fileInfo.FullName); record = new(RelativePath: relativePath, Size: fileInfo.Length, @@ -216,13 +283,14 @@ internal static partial class Helper20250519 { Review? review; Task response; Task httpResponseMessage; - StringContent stringContent = new(JsonSerializer.Serialize(relativePath, RelativePathSourceGenerationContext.Default.RelativePath), Encoding.UTF8, "application/json"); + string json = JsonSerializer.Serialize(relativePath, Helper20250519RelativePath.Default.RelativePath); foreach (string baseAddress in baseAddresses) { if (!baseAddress.StartsWith("http:")) { logger.LogInformation("Not supported URL <{url}>", baseAddress); } else { HttpClient httpClient = new(); httpClient.BaseAddress = new(baseAddress); + StringContent stringContent = new(json, Encoding.UTF8, "application/json"); httpResponseMessage = httpClient.PostAsync(page, stringContent); httpResponseMessage.Wait(); if (!httpResponseMessage.Result.IsSuccessStatusCode) { @@ -230,7 +298,7 @@ internal static partial class Helper20250519 { } else { response = httpResponseMessage.Result.Content.ReadAsStringAsync(); response.Wait(); - review = JsonSerializer.Deserialize(response.Result, ReviewSourceGenerationContext.Default.Review); + review = JsonSerializer.Deserialize(response.Result, Helper20250519Review.Default.Review); if (review is null) { logger.LogInformation("Failed to download: <{uniformResourceLocator}>;", httpClient.BaseAddress); continue; @@ -242,26 +310,36 @@ internal static partial class Helper20250519 { } private static void LiveSync(ILogger logger, Logic l, string page, RelativePath relativePath, HttpClient httpClient, Review review) { - if (review.NotEqualBut.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Minus && !l.NotEqualBut.Value) + if (review.NotEqualBut?.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Minus && !l.NotEqualBut.Value) { logger.LogDebug("Doing nothing with {name}", nameof(Logic.NotEqualBut)); - if (review.LeftSideOnly.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Minus && !l.LeftSideOnly.Value) + } + if (review.LeftSideOnly?.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Minus && !l.LeftSideOnly.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideOnly select x.Left).ToArray().AsReadOnly(), HttpMethod.Delete, delete: false); - if (review.LeftSideIsNewer.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.LessThan && !l.LeftSideIsNewer.Value) + } + if (review.LeftSideIsNewer?.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.LessThan && !l.LeftSideIsNewer.Value) { throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideIsNewer select x.Left).ToArray().AsReadOnly(), HttpMethod.Patch, delete: true); - if (review.RightSideIsNewer.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.LessThan && !l.RightSideIsNewer.Value) + } + if (review.RightSideIsNewer?.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.LessThan && !l.RightSideIsNewer.Value) { throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideIsNewer select x.Right).ToArray().AsReadOnly(), HttpMethod.Patch, delete: true); - if (review.RightSideOnly.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Plus && l.RightSideOnly.Value) + } + if (review.RightSideOnly?.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Plus && l.RightSideOnly.Value) { throw new Exception(); // LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideOnly select x.Right).ToArray().AsReadOnly(), HttpMethod.Put, delete: false); - if (review.RightSideOnly.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Minus && !l.RightSideOnly.Value) + } + if (review.RightSideOnly?.Length > 0 && l is not null && l.RightSideOnly is not null && l.Raw[l.RightSideOnlyIndex][0] == l.Minus && !l.RightSideOnly.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideOnly select x.Right).ToArray().AsReadOnly(), httpMethod: null, delete: true); - if (review.LeftSideOnly.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Plus && l.LeftSideOnly.Value) + } + if (review.LeftSideOnly?.Length > 0 && l is not null && l.LeftSideOnly is not null && l.Raw[l.LeftSideOnlyIndex][0] == l.Plus && l.LeftSideOnly.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideOnly select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: false); - if (review.LeftSideIsNewer.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.GreaterThan && l.LeftSideIsNewer.Value) + } + if (review.LeftSideIsNewer?.Length > 0 && l is not null && l.LeftSideIsNewer is not null && l.Raw[l.LeftSideIsNewerIndex][0] == l.GreaterThan && l.LeftSideIsNewer.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.LeftSideIsNewer select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: true); - if (review.NotEqualBut.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Plus && l.NotEqualBut.Value) + } + if (review.NotEqualBut?.Length > 0 && l is not null && l.NotEqualBut is not null && l.Raw[l.NotEqualButIndex][0] == l.Plus && l.NotEqualBut.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.LeftDirectory, (from x in review.NotEqualBut select x.Left).ToArray().AsReadOnly(), HttpMethod.Get, delete: true); - if (review.RightSideIsNewer.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.GreaterThan && l.RightSideIsNewer.Value) + } + if (review.RightSideIsNewer?.Length > 0 && l is not null && l.RightSideIsNewer is not null && l.Raw[l.RightSideIsNewerIndex][0] == l.GreaterThan && l.RightSideIsNewer.Value) { LiveSync(logger, page, relativePath, httpClient, relativePath.RightDirectory, (from x in review.RightSideIsNewer select x.Right).ToArray().AsReadOnly(), HttpMethod.Get, delete: true); + } } private static void LiveSync(ILogger logger, string page, RelativePath relativePath, HttpClient httpClient, string directory, ReadOnlyCollection records, HttpMethod? httpMethod, bool delete) { @@ -308,8 +386,9 @@ internal static partial class Helper20250519 { progressBar.Tick(); #endif record = records[i]; - if (record is null) + if (record is null) { continue; + } size = GetSizeWithSuffix(record.Size); try { File.Delete(Path.Combine(directory, record.RelativePath)); @@ -359,9 +438,9 @@ internal static partial class Helper20250519 { throw new NotImplementedException(); httpResponseMessage = httpClient.SendAsync(httpRequestMessage); httpResponseMessage.Wait(-1); - if (!httpResponseMessage.Result.IsSuccessStatusCode) + if (!httpResponseMessage.Result.IsSuccessStatusCode) { logger.LogInformation("Failed to {httpMethod}: <{display}> - {size};", httpMethod, verb.Display, size); - else { + } else { try { if (httpMethod != HttpMethod.Get) { duration = GetDurationWithSuffix(ticks); @@ -401,12 +480,15 @@ internal static partial class Helper20250519 { checkFile = Path.Combine(directory, record.RelativePath); checkFileName = Path.GetFileName(checkFile); checkDirectory = Path.GetDirectoryName(checkFile); - if (string.IsNullOrEmpty(checkDirectory)) + if (string.IsNullOrEmpty(checkDirectory)) { continue; - if (!Directory.Exists(checkDirectory)) + } + if (!Directory.Exists(checkDirectory)) { _ = Directory.CreateDirectory(checkDirectory); - if (File.Exists(checkFile) && new FileInfo(checkFile).Length == 0) + } + if (File.Exists(checkFile) && new FileInfo(checkFile).Length == 0) { File.Delete(checkFile); + } verb = new(Directory: checkDirectory, Display: $"{checkFileName}{Environment.NewLine}{checkDirectory}", File: checkFile, @@ -419,26 +501,30 @@ internal static partial class Helper20250519 { } Verb[] sorted = (from l in collection orderby l.Size select l).ToArray(); int stop = sorted.Length < 100 ? sorted.Length : 100; - for (int i = 0; i < stop; i++) + for (int i = 0; i < stop; i++) { results.Add(sorted[i]); - for (int i = sorted.Length - 1; i > stop - 1; i--) + } + for (int i = sorted.Length - 1; i > stop - 1; i--) { results.Add(sorted[i]); - if (collection.Count != results.Count) + } + if (collection.Count != results.Count) { throw new Exception(); + } return results.AsReadOnly(); } private static string GetDurationWithSuffix(long ticks) { string result; TimeSpan timeSpan = new(DateTime.Now.Ticks - ticks); - if (timeSpan.TotalMilliseconds < 1000) + if (timeSpan.TotalMilliseconds < 1000) { result = $"{timeSpan.Milliseconds} ms"; - else if (timeSpan.TotalMilliseconds < 60000) + } else if (timeSpan.TotalMilliseconds < 60000) { result = $"{Math.Floor(timeSpan.TotalSeconds)} s"; - else if (timeSpan.TotalMilliseconds < 3600000) + } else if (timeSpan.TotalMilliseconds < 3600000) { result = $"{Math.Floor(timeSpan.TotalMinutes)} m"; - else + } else { result = $"{Math.Floor(timeSpan.TotalHours)} h"; + } return result; }