person-key-to-immich-import birthday json (Day-Helper-2024-05-18)

csharp_prefer_braces = true
This commit is contained in:
2025-09-06 11:16:55 -07:00
parent 8ec89953bc
commit 6102da7266
54 changed files with 2218 additions and 1721 deletions

296
ADO2024/PI2/.editorconfig Normal file
View File

@ -0,0 +1,296 @@
[*.md]
end_of_line = crlf
file_header_template = unset
indent_size = 2
indent_style = space
insert_final_newline = false
root = true
tab_width = 2
[*.csproj]
end_of_line = crlf
file_header_template = unset
indent_size = 2
indent_style = space
insert_final_newline = false
root = true
tab_width = 2
[*.cs]
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = one_less_than_current
csharp_indent_switch_labels = true
csharp_new_line_before_catch = false
csharp_new_line_before_else = false
csharp_new_line_before_finally = false
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = none
csharp_new_line_between_query_expression_clauses = true
csharp_prefer_braces = true
csharp_prefer_qualified_reference = true:error
csharp_prefer_simple_default_expression = true:warning
csharp_prefer_simple_using_statement = true:warning
csharp_prefer_static_local_function = true:warning
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_parameter_list_parentheses = false
csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_allow_blank_line_after_colon_in_constructor_initializer_experimental = true
csharp_style_allow_blank_lines_between_consecutive_braces_experimental = true
csharp_style_allow_embedded_statements_on_same_line_experimental = true
csharp_style_conditional_delegate_call = true
csharp_style_deconstructed_variable_declaration = false
csharp_style_expression_bodied_accessors = when_on_single_line:warning
csharp_style_expression_bodied_constructors = when_on_single_line:warning
csharp_style_expression_bodied_indexers = when_on_single_line:warning
csharp_style_expression_bodied_lambdas = when_on_single_line:warning
csharp_style_expression_bodied_local_functions = when_on_single_line:warning
csharp_style_expression_bodied_methods = when_on_single_line:warning
csharp_style_expression_bodied_operators = when_on_single_line:warning
csharp_style_expression_bodied_properties = when_on_single_line:warning
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
csharp_style_inlined_variable_declaration = false
csharp_style_namespace_declarations = file_scoped:warning
csharp_style_pattern_local_over_anonymous_function = true:warning
csharp_style_pattern_matching_over_as_with_null_check = true:warning
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
csharp_style_prefer_index_operator = true:warning
csharp_style_prefer_not_pattern = true:warning
csharp_style_prefer_null_check_over_type_check = true
csharp_style_prefer_pattern_matching = true:warning
csharp_style_prefer_range_operator = true:warning
csharp_style_prefer_switch_expression = true:warning
csharp_style_throw_expression = true
csharp_style_unused_value_assignment_preference = discard_variable:warning
csharp_style_unused_value_expression_statement_preference = discard_variable:warning
csharp_style_var_elsewhere = false:warning
csharp_style_var_for_built_in_types = false:warning
csharp_style_var_when_type_is_apparent = false:warning
csharp_using_directive_placement = outside_namespace
dotnet_analyzer_diagnostic.category-Design.severity = error
dotnet_analyzer_diagnostic.category-Documentation.severity = error
dotnet_analyzer_diagnostic.category-Globalization.severity = none
dotnet_analyzer_diagnostic.category-Interoperability.severity = error
dotnet_analyzer_diagnostic.category-Maintainability.severity = error
dotnet_analyzer_diagnostic.category-Naming.severity = none
dotnet_analyzer_diagnostic.category-Performance.severity = none
dotnet_analyzer_diagnostic.category-Reliability.severity = error
dotnet_analyzer_diagnostic.category-Security.severity = error
dotnet_analyzer_diagnostic.category-SingleFile.severity = error
dotnet_analyzer_diagnostic.category-Style.severity = error
dotnet_analyzer_diagnostic.category-Usage.severity = error
dotnet_code_quality_unused_parameters = all
dotnet_code_quality_unused_parameters = non_public
dotnet_code_quality.CAXXXX.api_surface = private, internal
dotnet_diagnostic.CA1001.severity = error # CA1001: Types that own disposable fields should be disposable
dotnet_diagnostic.CA1051.severity = error # CA1051: Do not declare visible instance fields
dotnet_diagnostic.CA1511.severity = warning # CA1511: Use 'ArgumentException.ThrowIfNullOrEmpty' instead of explicitly throwing a new exception instance
dotnet_diagnostic.CA1513.severity = warning # Use 'ObjectDisposedException.ThrowIf' instead of explicitly throwing a new exception instance
dotnet_diagnostic.CA1825.severity = warning # CA1825: Avoid zero-length array allocations
dotnet_diagnostic.CA1829.severity = warning # CA1829: Use Length/Count property instead of Count() when available
dotnet_diagnostic.CA1834.severity = warning # CA1834: Consider using 'StringBuilder.Append(char)' when applicable
dotnet_diagnostic.CA1860.severity = error # CA1860: Prefer comparing 'Count' to 0 rather than using 'Any()', both for clarity and for performance
dotnet_diagnostic.CA1862.severity = warning # CA1862: Prefer using 'string.Equals(string, StringComparison)' to perform a case-insensitive comparison, but keep in mind that this might cause subtle changes in behavior, so make sure to conduct thorough testing after applying the suggestion, or if culturally sensitive comparison is not required, consider using 'StringComparison.OrdinalIgnoreCase'
dotnet_diagnostic.CA1869.severity = none # CA1869: Avoid creating a new 'JsonSerializerOptions' instance for every serialization operation. Cache and reuse instances instead.
dotnet_diagnostic.CA2201.severity = none # CA2201: Exception type System.NullReferenceException is reserved by the runtime
dotnet_diagnostic.CA2254.severity = none # CA2254: The logging message template should not vary between calls to 'LoggerExtensions.LogInformation(ILogger, string?, params object?[])'
dotnet_diagnostic.IDE0001.severity = warning # IDE0001: Simplify name
dotnet_diagnostic.IDE0002.severity = warning # Simplify (member access) - System.Version.Equals("1", "2"); Version.Equals("1", "2");
dotnet_diagnostic.IDE0004.severity = warning # IDE0004: Cast is redundant.
dotnet_diagnostic.IDE0005.severity = warning # Using directive is unnecessary
dotnet_diagnostic.IDE0010.severity = none # Add missing cases to switch statement (IDE0010)
dotnet_diagnostic.IDE0028.severity = error # IDE0028: Collection initialization can be simplified
dotnet_diagnostic.IDE0031.severity = warning # Use null propagation (IDE0031)
dotnet_diagnostic.IDE0047.severity = warning # IDE0047: Parentheses can be removed
dotnet_diagnostic.IDE0048.severity = none # Parentheses preferences (IDE0047 and IDE0048)
dotnet_diagnostic.IDE0049.severity = warning # Use language keywords instead of framework type names for type references (IDE0049)
dotnet_diagnostic.IDE0051.severity = error # Private member '' is unused [, ]
dotnet_diagnostic.IDE0058.severity = warning # IDE0058: Expression value is never used
dotnet_diagnostic.IDE0060.severity = error # IDE0060: Remove unused parameter
dotnet_diagnostic.IDE0074.severity = warning # IDE0074: Use compound assignment
dotnet_diagnostic.IDE0130.severity = none # Namespace does not match folder structure (IDE0130)
dotnet_diagnostic.IDE0270.severity = warning # IDE0270: Null check can be simplified
dotnet_diagnostic.IDE0290.severity = none # Use primary constructor [Distance]csharp(IDE0290)
dotnet_diagnostic.IDE0300.severity = error # IDE0300: Collection initialization can be simplified
dotnet_diagnostic.IDE0301.severity = error #IDE0301: Collection initialization can be simplified
dotnet_diagnostic.IDE0305.severity = none # IDE0305: Collection initialization can be simplified
dotnet_naming_rule.abstract_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.abstract_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.abstract_method_should_be_pascal_case.symbols = abstract_method
dotnet_naming_rule.class_should_be_pascal_case.severity = warning
dotnet_naming_rule.class_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.class_should_be_pascal_case.symbols = class
dotnet_naming_rule.delegate_should_be_pascal_case.severity = warning
dotnet_naming_rule.delegate_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.delegate_should_be_pascal_case.symbols = delegate
dotnet_naming_rule.enum_should_be_pascal_case.severity = warning
dotnet_naming_rule.enum_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.enum_should_be_pascal_case.symbols = enum
dotnet_naming_rule.event_should_be_pascal_case.severity = warning
dotnet_naming_rule.event_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.event_should_be_pascal_case.symbols = event
dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
dotnet_naming_rule.method_should_be_pascal_case.severity = warning
dotnet_naming_rule.method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.method_should_be_pascal_case.symbols = method
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = warning
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.private_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.private_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.private_method_should_be_pascal_case.symbols = private_method
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_field_should_be_private_of_internal_field.symbols = private_or_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.private_or_internal_static_field_should_be_private_of_internal_field.symbols = private_or_internal_static_field
dotnet_naming_rule.property_should_be_pascal_case.severity = warning
dotnet_naming_rule.property_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.property_should_be_pascal_case.symbols = property
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.severity = warning
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.style = private_of_internal_field
dotnet_naming_rule.public_or_protected_field_should_be_private_of_internal_field.symbols = public_or_protected_field
dotnet_naming_rule.static_field_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_field_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_field_should_be_pascal_case.symbols = static_field
dotnet_naming_rule.static_method_should_be_pascal_case.severity = warning
dotnet_naming_rule.static_method_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.static_method_should_be_pascal_case.symbols = static_method
dotnet_naming_rule.struct_should_be_pascal_case.severity = warning
dotnet_naming_rule.struct_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.struct_should_be_pascal_case.symbols = struct
dotnet_naming_rule.types_should_be_pascal_case.severity = warning
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_style.begins_with_i.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.private_of_internal_field.capitalization = pascal_case
dotnet_naming_style.private_of_internal_field.required_prefix = _
dotnet_naming_style.private_of_internal_field.required_suffix =
dotnet_naming_style.private_of_internal_field.word_separator =
dotnet_naming_symbols.abstract_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.abstract_method.applicable_kinds = method
dotnet_naming_symbols.abstract_method.required_modifiers = abstract
dotnet_naming_symbols.class.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.class.applicable_kinds = class
dotnet_naming_symbols.class.required_modifiers =
dotnet_naming_symbols.delegate.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.delegate.applicable_kinds = delegate
dotnet_naming_symbols.delegate.required_modifiers =
dotnet_naming_symbols.enum.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enum.applicable_kinds = enum
dotnet_naming_symbols.enum.required_modifiers =
dotnet_naming_symbols.event.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.event.applicable_kinds = event
dotnet_naming_symbols.event.required_modifiers =
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.method.applicable_accessibilities = public
dotnet_naming_symbols.method.applicable_kinds = method
dotnet_naming_symbols.method.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.private_method.applicable_accessibilities = private
dotnet_naming_symbols.private_method.applicable_kinds = method
dotnet_naming_symbols.private_method.required_modifiers =
dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_field.required_modifiers =
dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected
dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field
dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = static
dotnet_naming_symbols.property.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.property.applicable_kinds = property
dotnet_naming_symbols.property.required_modifiers =
dotnet_naming_symbols.public_or_protected_field.applicable_accessibilities = public, protected
dotnet_naming_symbols.public_or_protected_field.applicable_kinds = field
dotnet_naming_symbols.public_or_protected_field.required_modifiers =
dotnet_naming_symbols.static_field.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_field.applicable_kinds = field
dotnet_naming_symbols.static_field.required_modifiers = static
dotnet_naming_symbols.static_method.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.static_method.applicable_kinds = method
dotnet_naming_symbols.static_method.required_modifiers = static
dotnet_naming_symbols.struct.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.struct.applicable_kinds = struct
dotnet_naming_symbols.struct.required_modifiers =
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.required_modifiers =
dotnet_remove_unnecessary_suppression_exclusions = 0
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
dotnet_style_allow_multiple_blank_lines_experimental = false:warning
dotnet_style_allow_statement_immediately_after_block_experimental = true
dotnet_style_coalesce_expression = true
dotnet_style_collection_initializer = true:warning
dotnet_style_explicit_tuple_names = true:warning
dotnet_style_namespace_match_folder = true
dotnet_style_null_propagation = true:warning
dotnet_style_object_initializer = true:warning
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity
dotnet_style_parentheses_in_other_operators = never_if_unnecessary
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity
dotnet_style_predefined_type_for_locals_parameters_members = true
dotnet_style_predefined_type_for_member_access = true:warning
dotnet_style_prefer_auto_properties = true:warning
dotnet_style_prefer_compound_assignment = true:warning
dotnet_style_prefer_conditional_expression_over_assignment = false
dotnet_style_prefer_conditional_expression_over_return = false
dotnet_style_prefer_inferred_anonymous_type_member_names = true:warning
dotnet_style_prefer_inferred_tuple_names = true:warning
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:warning
dotnet_style_prefer_simplified_boolean_expressions = true:warning
dotnet_style_prefer_simplified_interpolation = true
dotnet_style_qualification_for_event = false:error
dotnet_style_qualification_for_field = false
dotnet_style_qualification_for_method = false:error
dotnet_style_qualification_for_property = false:error
dotnet_style_readonly_field = true:warning
dotnet_style_require_accessibility_modifiers = for_non_interface_members
end_of_line = crlf
file_header_template = unset
indent_size = 4
indent_style = space
insert_final_newline = false
root = true
tab_width = 4
# https://docs.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1822
# https://github.com/dotnet/aspnetcore/blob/main/.editorconfig
# https://github.com/dotnet/project-system/blob/main/.editorconfig

View File

@ -3,11 +3,9 @@ using System.Diagnostics;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240429
{
internal static partial class Helper20240429 {
internal static void GitConfigCleanUp(ILogger<Worker> logger, List<string> args)
{
internal static void GitConfigCleanUp(ILogger<Worker> logger, List<string> args) {
string[] files;
Process? process;
string? directory;
@ -19,34 +17,34 @@ internal static partial class Helper20240429
string[] removeRemotes = args[4].Split(',');
string systemVolumeInformation = Path.Combine(root, args[2]);
string[] subDirectories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
foreach (string subDirectory in subDirectories)
{
if (subDirectory == systemVolumeInformation)
foreach (string subDirectory in subDirectories) {
if (subDirectory == systemVolumeInformation) {
continue;
}
files = Directory.GetFiles(subDirectory, searchPattern, SearchOption.AllDirectories);
foreach (string file in files)
{
foreach (string file in files) {
directory = Path.GetDirectoryName(file);
if (directory is null)
if (directory is null) {
continue;
foreach (string removeRemote in removeRemotes)
{
processStartInfo = new()
{
}
foreach (string removeRemote in removeRemotes) {
processStartInfo = new() {
FileName = "git",
WorkingDirectory = directory,
Arguments = $"remote rm {removeRemote}",
RedirectStandardError = true
};
process = Process.Start(processStartInfo);
if (process is null)
if (process is null) {
continue;
}
#pragma warning disable IDE0058
process.WaitForExit(7000);
#pragma warning restore IDE0058
standardError = process.StandardError.ReadToEnd();
if (!standardError.Contains(ignoreError))
if (!standardError.Contains(ignoreError)) {
logger.LogInformation(standardError);
}
logger.LogInformation("for <{directoryName}> remote rm {removeRemote}", directory, removeRemote);
}
}

View File

@ -2,33 +2,33 @@ using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240510
{
internal static partial class Helper20240510 {
internal static void PullIconsForBLM(ILogger<Worker> logger, List<string> args)
{
internal static void PullIconsForBLM(ILogger<Worker> logger, List<string> args) {
string fileName;
FileInfo fileInfo;
string searchPattern = args[4];
string sourceDirectory = args[3];
string root = Path.GetFullPath(args[0]);
string createDirectory = Path.Combine(root, args[2]);
if (!Directory.Exists(createDirectory))
if (!Directory.Exists(createDirectory)) {
_ = Directory.CreateDirectory(createDirectory);
}
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
foreach (string file in files) {
fileName = Path.GetFileName(file);
fileInfo = new(Path.Combine(createDirectory, fileName));
if (fileInfo.Exists && fileInfo.LastWriteTime == new FileInfo(file).LastWriteTime)
if (fileInfo.Exists && fileInfo.LastWriteTime == new FileInfo(file).LastWriteTime) {
continue;
}
File.Copy(file, fileInfo.FullName, overwrite: true);
logger.LogInformation("<{fileName}> copied", fileName);
}
logger.LogWarning("What reactor is this near?");
string? reactor = Console.ReadLine();
if (!string.IsNullOrEmpty(reactor))
if (!string.IsNullOrEmpty(reactor)) {
_ = Directory.CreateDirectory(Path.Combine(sourceDirectory, Environment.MachineName, reactor));
}
}
}

View File

@ -4,11 +4,9 @@ using System.Text.Json;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240513
{
internal static partial class Helper20240513 {
internal static void PersonKeyToName(ILogger<Worker> logger, List<string> args)
{
internal static void PersonKeyToName(ILogger<Worker> logger, List<string> args) {
Person? person;
string directoryName;
string checkDirectory;
@ -17,20 +15,21 @@ internal static partial class Helper20240513
Dictionary<string, Person> keyValuePairs = [];
string[] directories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
Dictionary<long, Person> people = JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException();
foreach (KeyValuePair<long, Person> keyValuePair in people)
{
if (keyValuePair.Value.Birth?.Note is null)
foreach (KeyValuePair<long, Person> keyValuePair in people) {
if (keyValuePair.Value.Birth?.Note is null) {
continue;
}
keyValuePairs.Add(keyValuePair.Value.Birth.Note, keyValuePair.Value);
}
foreach (string directory in directories)
{
foreach (string directory in directories) {
directoryName = Path.GetFileName(directory);
if (!keyValuePairs.TryGetValue(directoryName, out person) || person.Name?.ForwardSlashFull is null)
if (!keyValuePairs.TryGetValue(directoryName, out person) || person.Name?.ForwardSlashFull is null) {
continue;
}
checkDirectory = Path.Combine(root, $"{person.Name.ForwardSlashFull.Replace('/', '-')}{directoryName}-{person.Id}");
if (Directory.Exists(checkDirectory))
if (Directory.Exists(checkDirectory)) {
continue;
}
Directory.Move(directory, checkDirectory);
logger.LogInformation("<{directory}> was moved", directory);
}

View File

@ -5,16 +5,14 @@ using System.Text.Json.Serialization;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240517
{
internal static partial class Helper20240517 {
private record ContentSignature([property: JsonPropertyName("contentSignature")] string Value,
[property: JsonPropertyName("contentSignatureType")] string ContentSignatureType);
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ContentSignature))]
private partial class ContentSignatureGenerationContext : JsonSerializerContext
{
private partial class ContentSignatureGenerationContext : JsonSerializerContext {
}
private record Type([property: JsonPropertyName("count")] int Count,
@ -23,8 +21,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Type))]
private partial class TypeGenerationContext : JsonSerializerContext
{
private partial class TypeGenerationContext : JsonSerializerContext {
}
private record ImageAmazon([property: JsonPropertyName("colorSpace")] string ColorSpace,
@ -54,8 +51,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ImageAmazon))]
private partial class ImageAmazonGenerationContext : JsonSerializerContext
{
private partial class ImageAmazonGenerationContext : JsonSerializerContext {
}
private record ContentProperties([property: JsonPropertyName("contentDate")] DateTime ContentDate,
@ -69,16 +65,14 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ContentProperties))]
private partial class ContentPropertiesGenerationContext : JsonSerializerContext
{
private partial class ContentPropertiesGenerationContext : JsonSerializerContext {
}
private record XAccntParentMap();
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(XAccntParentMap))]
private partial class XAccntParentMapGenerationContext : JsonSerializerContext
{
private partial class XAccntParentMapGenerationContext : JsonSerializerContext {
}
private record Datum([property: JsonPropertyName("accessRuleIds")] IReadOnlyList<object> AccessRuleIds,
@ -111,14 +105,12 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Datum))]
private partial class DatumGenerationContext : JsonSerializerContext
{
private partial class DatumGenerationContext : JsonSerializerContext {
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Dictionary<string, Datum>))]
private partial class DictionaryDatumGenerationContext : JsonSerializerContext
{
private partial class DictionaryDatumGenerationContext : JsonSerializerContext {
}
private record LocationAmazon([property: JsonPropertyName("count")] int Count,
@ -127,8 +119,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(LocationAmazon))]
private partial class LocationAmazonGenerationContext : JsonSerializerContext
{
private partial class LocationAmazonGenerationContext : JsonSerializerContext {
}
private record LocationInfo([property: JsonPropertyName("city")] string City,
@ -139,8 +130,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(LocationInfo))]
private partial class LocationInfoGenerationContext : JsonSerializerContext
{
private partial class LocationInfoGenerationContext : JsonSerializerContext {
}
private record SearchData([property: JsonPropertyName("clusterName")] string ClusterName,
@ -150,8 +140,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(SearchData))]
private partial class SearchDataGenerationContext : JsonSerializerContext
{
private partial class SearchDataGenerationContext : JsonSerializerContext {
}
private record AllPerson([property: JsonPropertyName("count")] int Count,
@ -160,8 +149,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(AllPerson))]
private partial class AllPersonGenerationContext : JsonSerializerContext
{
private partial class AllPersonGenerationContext : JsonSerializerContext {
}
private record PersonAmazon([property: JsonPropertyName("count")] int Count,
@ -170,8 +158,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(PersonAmazon))]
private partial class PersonAmazonGenerationContext : JsonSerializerContext
{
private partial class PersonAmazonGenerationContext : JsonSerializerContext {
}
private record ClusterId([property: JsonPropertyName("count")] int Count,
@ -180,8 +167,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ClusterId))]
private partial class ClusterIdGenerationContext : JsonSerializerContext
{
private partial class ClusterIdGenerationContext : JsonSerializerContext {
}
private record Thing([property: JsonPropertyName("count")] int Count,
@ -190,8 +176,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Thing))]
private partial class ThingGenerationContext : JsonSerializerContext
{
private partial class ThingGenerationContext : JsonSerializerContext {
}
private record Time([property: JsonPropertyName("count")] int Count,
@ -200,8 +185,7 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Time))]
private partial class TimeGenerationContext : JsonSerializerContext
{
private partial class TimeGenerationContext : JsonSerializerContext {
}
private record ParentMap([property: JsonPropertyName("FOLDER")] IReadOnlyList<string> FOLDER);
@ -216,14 +200,12 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Aggregations))]
private partial class AggregationsGenerationContext : JsonSerializerContext
{
private partial class AggregationsGenerationContext : JsonSerializerContext {
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(ParentMap))]
private partial class ParentMapGenerationContext : JsonSerializerContext
{
private partial class ParentMapGenerationContext : JsonSerializerContext {
}
private record RootAmazon([property: JsonPropertyName("aggregations")] Aggregations Aggregations,
@ -232,12 +214,23 @@ internal static partial class Helper20240517
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(RootAmazon))]
private partial class RootAmazonGenerationContext : JsonSerializerContext
{
private partial class RootAmazonGenerationContext : JsonSerializerContext {
}
private static void SaveAmazon(string destination, string harFile)
{
internal static void SaveAmazon(ILogger<Worker> logger, List<string> args) {
string root = Path.GetFullPath(args[0]);
string destination = Path.GetFullPath(args[2]);
if (string.IsNullOrEmpty(root)) {
throw new NullReferenceException(nameof(root));
}
string[] harFiles = Directory.GetFiles(root, "*.har", SearchOption.TopDirectoryOnly);
foreach (string harFile in harFiles) {
SaveAmazon(destination, harFile);
}
logger?.LogInformation("{harFiles} count", harFiles.Length);
}
private static void SaveAmazon(string destination, string harFile) {
string offset;
string personId;
RootAmazon amazon;
@ -247,37 +240,43 @@ internal static partial class Helper20240517
PersonAmazon personAmazon;
Dictionary<string, string> keyValuePairs = [];
ReadOnlyCollection<(string Url, string AggregationLine)> aggregationLines = GetAggregationLines(harFile);
foreach ((string url, string aggregationLine) in aggregationLines)
{
if (aggregationLine.Contains(",\"category\":\"allPeople\"}"))
foreach ((string url, string aggregationLine) in aggregationLines) {
if (aggregationLine.Contains(",\"category\":\"allPeople\"}")) {
continue;
}
amazon = JsonSerializer.Deserialize(aggregationLine, RootAmazonGenerationContext.Default.RootAmazon) ?? throw new Exception();
if (amazon.Aggregations?.People is null || amazon.Aggregations.People.Count < 1)
if (amazon.Aggregations?.People is null || amazon.Aggregations.People.Count < 1) {
continue;
}
personAmazon = amazon.Aggregations.People[0];
if (!url.Contains(personAmazon.Match))
if (!url.Contains(personAmazon.Match)) {
continue;
}
personDirectory = Path.Combine(destination, personAmazon.SearchData.ClusterName);
_ = Directory.CreateDirectory(personDirectory);
personIdFile = Path.Combine(personDirectory, $"000) {personAmazon.Match}.json");
_ = keyValuePairs.TryAdd(personAmazon.Match, personAmazon.SearchData.ClusterName);
SaveAmazon(amazon.Data, personIdFile);
}
foreach ((string url, string aggregationLine) in aggregationLines)
{
if (aggregationLine.Contains(",\"category\":\"allPeople\"}"))
foreach ((string url, string aggregationLine) in aggregationLines) {
if (aggregationLine.Contains(",\"category\":\"allPeople\"}")) {
continue;
}
amazon = JsonSerializer.Deserialize(aggregationLine, RootAmazonGenerationContext.Default.RootAmazon) ?? throw new Exception();
if (amazon.Aggregations?.People is not null && amazon.Aggregations.People.Count > 0)
if (amazon.Aggregations?.People is not null && amazon.Aggregations.People.Count > 0) {
continue;
if (!url.Contains("offset="))
}
if (!url.Contains("offset=")) {
continue;
}
offset = url.Split("offset=")[1];
if (!url.Contains("people%3A("))
if (!url.Contains("people%3A(")) {
continue;
}
personId = url.Split("people%3A(")[1].Split(')')[0];
if (!keyValuePairs.TryGetValue(personId, out personName))
if (!keyValuePairs.TryGetValue(personId, out personName)) {
continue;
}
personDirectory = Path.Combine(destination, personName);
_ = Directory.CreateDirectory(personDirectory);
personIdFile = Path.Combine(personDirectory, $"{offset.Split('&')[0]}) {personId}.json");
@ -285,46 +284,37 @@ internal static partial class Helper20240517
}
}
internal static void SaveAmazon(ILogger<Worker> logger, List<string> args)
{
string root = Path.GetFullPath(args[0]);
string destination = Path.GetFullPath(args[2]);
if (string.IsNullOrEmpty(root))
throw new NullReferenceException(nameof(root));
string[] harFiles = Directory.GetFiles(root, "*.har", SearchOption.TopDirectoryOnly);
foreach (string harFile in harFiles)
SaveAmazon(destination, harFile);
logger?.LogInformation("{harFiles} count", harFiles.Length);
}
private static void SaveAmazon(IReadOnlyList<Datum> data, string personIdFile)
{
private static void SaveAmazon(IReadOnlyList<Datum> data, string personIdFile) {
string json;
Dictionary<string, Datum> keyValuePairs = [];
foreach (Datum datum in data)
foreach (Datum datum in data) {
_ = keyValuePairs.TryAdd(datum.Name.Split('.')[0], datum);
}
json = JsonSerializer.Serialize(keyValuePairs, DictionaryDatumGenerationContext.Default.DictionaryStringDatum);
File.WriteAllText(personIdFile, json);
}
private static ReadOnlyCollection<(string, string)> GetAggregationLines(string harFile)
{
private static ReadOnlyCollection<(string, string)> GetAggregationLines(string harFile) {
List<(string, string)> results = [];
if (!File.Exists(harFile))
if (!File.Exists(harFile)) {
throw new Exception();
}
string lastUrl = string.Empty;
string text = "\"text\": \"{";
string[] lines = File.ReadAllLines(harFile);
foreach (string line in lines)
{
if (line.Contains("\"url\": \""))
foreach (string line in lines) {
if (line.Contains("\"url\": \"")) {
lastUrl = line;
if (!line.Contains(text))
}
if (!line.Contains(text)) {
continue;
if (!line.Contains("aggregations"))
}
if (!line.Contains("aggregations")) {
continue;
if (lastUrl.Contains("search?asset=NONE"))
}
if (lastUrl.Contains("search?asset=NONE")) {
continue;
}
results.Add(new(lastUrl, line.Trim()[(text.Length - 1)..^1].Replace("\\\"", "\"")));
lastUrl = string.Empty;
}

View File

@ -1,35 +1,58 @@
using File_Folder_Helper.Models;
using Microsoft.Extensions.Logging;
using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240518
{
internal static partial class Helper20240518 {
internal static void PersonKeyToImmichImport(ILogger<Worker> logger, List<string> args)
{
internal static void PersonKeyToImmichImport(ILogger<Worker> logger, List<string> args) {
string json;
string name;
Person person;
string birthDate;
string ownerId = args[5];
List<string> inserts = [];
string tableName = args[3];
string birthDateFormat = args[6];
string[] columns = args[4].Split(',');
string json = File.ReadAllText(args[2]);
string root = Path.GetFullPath(args[0]);
Dictionary<long, Person> people = JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ?? throw new NullReferenceException();
foreach (KeyValuePair<long, Person> keyValuePair in people)
{
if (keyValuePair.Value.Birth?.Note is null || keyValuePair.Value.Name?.ForwardSlashFull is null || keyValuePair.Value.Birth?.Date is null)
Dictionary<string, string> keyValuePairs = [];
json = File.ReadAllText(Path.Combine(root, args[2]));
DateOnly minimumBirthDate = DateOnly.ParseExact(args[7], birthDateFormat, CultureInfo.InvariantCulture);
Dictionary<long, Person> people = JsonSerializer.Deserialize(json, PeopleSourceGenerationContext.Default.DictionaryInt64Person) ??
throw new NullReferenceException();
foreach (KeyValuePair<long, Person> keyValuePair in people) {
person = keyValuePair.Value;
if (string.IsNullOrEmpty(person.Birth?.Note) || string.IsNullOrEmpty(person.Name?.ForwardSlashFull) || person.Birth.Date < minimumBirthDate) {
continue;
birthDate = keyValuePair.Value.Birth.Date.Value.ToString(birthDateFormat);
name = keyValuePair.Value.Name.ForwardSlashFull.Replace("/", string.Empty);
}
name = string.IsNullOrEmpty(person.Name.Suffix) ? person.Name.ForwardSlashFull : $"{person.Name.ForwardSlashFull} {person.Name.Suffix}";
keyValuePairs.Add(person.Birth.Note, name);
}
json = JsonSerializer.Serialize(keyValuePairs, DictionaryStringStringSourceGenerationContext.Default.DictionaryStringString);
string jsonFile = Path.Combine(root, $"{DateTime.Now.Ticks}.json");
logger.LogInformation("<{file}> saved", jsonFile);
File.WriteAllText(jsonFile, json);
foreach (KeyValuePair<long, Person> keyValuePair in people) {
person = keyValuePair.Value;
if (string.IsNullOrEmpty(person.Birth?.Note) || string.IsNullOrEmpty(person.Name?.ForwardSlashFull) || person.Birth?.Date is null) {
continue;
}
birthDate = person.Birth.Date.Value.ToString(birthDateFormat);
name = person.Name.ForwardSlashFull.Replace("/", string.Empty);
inserts.Add($"insert into \"{tableName}\" (\"{string.Join("\", \"", columns)}\") values ('{ownerId}', '{name}', '{birthDate}');");
}
string file = Path.Combine(root, $"{DateTime.Now.Ticks}.sql");
logger.LogInformation("<{file}> saved", file);
File.WriteAllLines(file, inserts);
string sqlFile = Path.Combine(root, $"{DateTime.Now.Ticks}.sql");
logger.LogInformation("<{file}> saved", sqlFile);
File.WriteAllLines(sqlFile, inserts);
}
}
[JsonSourceGenerationOptions(WriteIndented = true, DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull)]
[JsonSerializable(typeof(Dictionary<string, string>))]
internal partial class DictionaryStringStringSourceGenerationContext : JsonSerializerContext {
}

View File

@ -4,45 +4,27 @@ using System.Collections.ObjectModel;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240519
{
internal static partial class Helper20240519 {
private record Record(long Length, long Ticks);
private static ReadOnlyDictionary<string, Record> GetKeyValuePairs(string source, string[] sourceFiles)
{
Dictionary<string, Record> results = [];
string key;
Record? record;
FileInfo fileInfo;
int sourceLength = source.Length;
foreach (string sourceFile in sourceFiles)
{
fileInfo = new(sourceFile);
key = sourceFile[sourceLength..];
if (results.TryGetValue(key, out record))
throw new NotSupportedException();
results.Add(key, new(fileInfo.Length, fileInfo.LastWriteTime.Ticks));
}
return new(results);
}
internal static void FindReplaceDirectoryName(ILogger<Worker> logger, List<string> args)
{
internal static void FindReplaceDirectoryName(ILogger<Worker> logger, List<string> args) {
string checkDirectory;
string replaceText = args[3];
string[] findTexts = args[2].Split(',');
string root = Path.GetFullPath(args[0]);
string[] directories = Directory.GetDirectories(root, "*", SearchOption.TopDirectoryOnly);
foreach (string directory in directories)
{
foreach (string directory in directories) {
checkDirectory = directory;
foreach (string findText in findTexts)
foreach (string findText in findTexts) {
checkDirectory = checkDirectory.Replace(findText, replaceText);
if (checkDirectory == directory)
}
if (checkDirectory == directory) {
continue;
if (Directory.Exists(checkDirectory))
}
if (Directory.Exists(checkDirectory)) {
continue;
}
logger.LogInformation("<{directory}> to <{checkDirectory}>", directory, checkDirectory);
Directory.Move(directory, checkDirectory);
}
@ -57,24 +39,44 @@ internal static partial class Helper20240519
ReadOnlyDictionary<string, Record> keyValuePairs = GetKeyValuePairs(source, sourceFiles);
string[] compareFiles = Directory.GetFiles(compare, "*", SearchOption.AllDirectories);
int compareLength = compare.Length;
foreach (string compareFile in compareFiles)
{
foreach (string compareFile in compareFiles) {
fileInfo = new(compareFile);
key = compareFile[compareLength..];
if (!keyValuePairs.TryGetValue(key, out record))
if (!keyValuePairs.TryGetValue(key, out record)) {
continue;
if (fileInfo.Length != record.Length || fileInfo.LastWriteTime.Ticks != record.Ticks)
}
if (fileInfo.Length != record.Length || fileInfo.LastWriteTime.Ticks != record.Ticks) {
continue;
}
checkFile = $"{target}{key}";
checkDirectory = Path.GetDirectoryName(checkFile) ?? throw new NotSupportedException();
if (!Directory.Exists(checkDirectory))
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
if (File.Exists(checkFile))
}
if (File.Exists(checkFile)) {
continue;
}
logger.LogInformation("<{compareFile}> to <{checkFile}>", compareFile, checkFile);
File.Move(compareFile, checkFile);
}
HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, compare);
}
private static ReadOnlyDictionary<string, Record> GetKeyValuePairs(string source, string[] sourceFiles) {
Dictionary<string, Record> results = [];
string key;
Record? record;
FileInfo fileInfo;
int sourceLength = source.Length;
foreach (string sourceFile in sourceFiles) {
fileInfo = new(sourceFile);
key = sourceFile[sourceLength..];
if (results.TryGetValue(key, out record)) {
throw new NotSupportedException();
}
results.Add(key, new(fileInfo.Length, fileInfo.LastWriteTime.Ticks));
}
return new(results);
}
}

View File

@ -6,66 +6,23 @@ using System.Text.Json.Serialization;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240520
{
internal static partial class Helper20240520 {
private record RecordA(string Directory, string Extension, string SourceFile, Identifier Identifier);
private record RecordB(ReadOnlyDictionary<int, Identifier> IdTo, ReadOnlyDictionary<long, Identifier> LengthTo, ReadOnlyDictionary<string, Identifier> PaddedTo);
internal sealed record Identifier(int Id, long Length, string PaddedId, long Ticks)
{
public override string ToString()
{
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier))]
internal partial class IdentifierSourceGenerationContext : JsonSerializerContext
{
internal partial class IdentifierSourceGenerationContext : JsonSerializerContext {
}
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Identifier[]))]
internal partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext
{
internal partial class IdentifierCollectionSourceGenerationContext : JsonSerializerContext {
}
private static RecordB GetRecordB(string jsonFile)
{
RecordB result;
Dictionary<int, Identifier> idTo = [];
Dictionary<long, Identifier> lengthTo = [];
Dictionary<string, Identifier> paddedTo = [];
string? json = !File.Exists(jsonFile) ? null : File.ReadAllText(jsonFile);
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
if (identifiers is null && !string.IsNullOrEmpty(jsonFile))
throw new Exception($"Invalid {nameof(jsonFile)}");
if (identifiers is not null)
{
foreach (Identifier identifier in identifiers)
{
idTo.Add(identifier.Id, identifier);
paddedTo.Add(identifier.PaddedId, identifier);
if (lengthTo.ContainsKey(identifier.Length))
{
_ = lengthTo.Remove(identifier.Length);
continue;
}
lengthTo.Add(identifier.Length, identifier);
}
}
result = new(new(idTo), new(lengthTo), new(paddedTo));
return result;
}
internal static void IdentifierRename(ILogger<Worker> logger, List<string> args)
{
internal static void IdentifierRename(ILogger<Worker> logger, List<string> args) {
int id;
string key;
RecordA recordA;
@ -87,50 +44,48 @@ internal static partial class Helper20240520
string[] sourceFiles = Directory.GetFiles(source, "*", SearchOption.AllDirectories);
logger.LogInformation("Found {files}(s)", sourceFiles.Length);
int sourceLength = source.Length;
foreach (string sourceFile in sourceFiles)
{
foreach (string sourceFile in sourceFiles) {
fileInfo = new(sourceFile);
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileInfo.FullName);
if (fileInfo.Directory is null)
if (fileInfo.Directory is null) {
throw new NotSupportedException();
if (option == "Padded")
{
if (fileNameWithoutExtension.Length < intMinValueLength)
}
if (option == "Padded") {
if (fileNameWithoutExtension.Length < intMinValueLength) {
continue;
}
key = fileNameWithoutExtension;
if (recordB.PaddedTo.TryGetValue(key, out identifier))
{
if (recordB.PaddedTo.TryGetValue(key, out identifier)) {
recordACollection.Add(new($"{destination}{fileInfo.Directory.FullName[sourceLength..]}", fileInfo.Extension, fileInfo.FullName, identifier));
continue;
}
}
if (option == "Length")
{
if (recordB.LengthTo.TryGetValue(fileInfo.Length, out identifier))
{
if (option == "Length") {
if (recordB.LengthTo.TryGetValue(fileInfo.Length, out identifier)) {
checkDirectory = $"{destination}{fileInfo.Directory.FullName[sourceLength..]}";
if (!Directory.Exists(checkDirectory))
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
}
checkFile = Path.Combine(checkDirectory, $"{identifier.PaddedId}{fileInfo.Extension}");
if (File.Exists(checkFile))
if (File.Exists(checkFile)) {
continue;
}
File.Copy(fileInfo.FullName, checkFile);
logger.LogInformation("<{fileInfo.FullName}> was moved to <{checkFile}>", fileInfo.FullName, checkFile);
continue;
}
}
if (option == "Id")
{
if (int.TryParse(fileNameWithoutExtension, out id))
{
if (recordB.IdTo.TryGetValue(id, out identifier))
{
if (option == "Id") {
if (int.TryParse(fileNameWithoutExtension, out id)) {
if (recordB.IdTo.TryGetValue(id, out identifier)) {
checkDirectory = $"{destination}{fileInfo.Directory.FullName[sourceLength..]}";
if (!Directory.Exists(checkDirectory))
if (!Directory.Exists(checkDirectory)) {
_ = Directory.CreateDirectory(checkDirectory);
}
checkFile = Path.Combine(checkDirectory, $"{identifier.PaddedId}{fileInfo.Extension}");
if (File.Exists(checkFile))
if (File.Exists(checkFile)) {
continue;
}
File.Move(fileInfo.FullName, checkFile);
logger.LogInformation("<{fileInfo.FullName}> was moved to <{checkFile}>", fileInfo.FullName, checkFile);
continue;
@ -138,18 +93,19 @@ internal static partial class Helper20240520
}
}
}
if (option == "Padded")
{
if (!isOffsetDeterministicHashCode)
if (option == "Padded") {
if (!isOffsetDeterministicHashCode) {
recordACollection = (from l in recordACollection orderby l.Identifier.Ticks select l).ToList();
for (int i = 0; i < recordACollection.Count; i++)
{
}
for (int i = 0; i < recordACollection.Count; i++) {
recordA = recordACollection[i];
if (!Directory.Exists(recordA.Directory))
if (!Directory.Exists(recordA.Directory)) {
_ = Directory.CreateDirectory(recordA.Directory);
}
checkFile = Path.Combine(recordA.Directory, isOffsetDeterministicHashCode ? $"{recordA.Identifier.PaddedId}{recordA.Extension}" : $"{offset + i}{recordA.Identifier.PaddedId}{recordA.Extension}");
if (File.Exists(checkFile))
if (File.Exists(checkFile)) {
continue;
}
File.Move(recordA.SourceFile, checkFile);
logger.LogInformation("<{recordA.SourceFile}> was moved to <{checkFile}>", recordA.SourceFile, checkFile);
}
@ -157,4 +113,37 @@ internal static partial class Helper20240520
HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, source);
}
private static RecordB GetRecordB(string jsonFile) {
RecordB result;
Dictionary<int, Identifier> idTo = [];
Dictionary<long, Identifier> lengthTo = [];
Dictionary<string, Identifier> paddedTo = [];
string? json = !File.Exists(jsonFile) ? null : File.ReadAllText(jsonFile);
Identifier[]? identifiers = json is null ? null : JsonSerializer.Deserialize(json, IdentifierCollectionSourceGenerationContext.Default.IdentifierArray);
if (identifiers is null && !string.IsNullOrEmpty(jsonFile)) {
throw new Exception($"Invalid {nameof(jsonFile)}");
}
if (identifiers is not null) {
foreach (Identifier identifier in identifiers) {
idTo.Add(identifier.Id, identifier);
paddedTo.Add(identifier.PaddedId, identifier);
if (lengthTo.ContainsKey(identifier.Length)) {
_ = lengthTo.Remove(identifier.Length);
continue;
}
lengthTo.Add(identifier.Length, identifier);
}
}
result = new(new(idTo), new(lengthTo), new(paddedTo));
return result;
}
internal sealed record Identifier(int Id, long Length, string PaddedId, long Ticks) {
public override string ToString() {
string result = JsonSerializer.Serialize(this, IdentifierSourceGenerationContext.Default.Identifier);
return result;
}
}
}

View File

@ -10,8 +10,7 @@ using System.Text.RegularExpressions;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240623
{
internal static partial class Helper20240623 {
[GeneratedRegex("([A-Z]+(.))")]
private static partial Regex UpperCase();
@ -36,34 +35,34 @@ internal static partial class Helper20240623
[JsonSourceGenerationOptions(WriteIndented = true)]
[JsonSerializable(typeof(Input))]
private partial class InputSourceGenerationContext : JsonSerializerContext
{
private partial class InputSourceGenerationContext : JsonSerializerContext {
}
private static Record GetRecord(Input input, FileInfo fileInfo)
{
private static Record GetRecord(Input input, FileInfo fileInfo) {
Record result;
string line;
int? stopLine = null;
int? subTasksLine = null;
int? codeInsidersLine = null;
LineNumber lineNumber = HelperMarkdown.GetLineNumbers(fileInfo);
for (int i = 0; i < lineNumber.Lines.Count; i++)
{
for (int i = 0; i < lineNumber.Lines.Count; i++) {
line = lineNumber.Lines[i];
if (line.StartsWith(input.CodeInsiders) && line[^1] == ')')
if (line.StartsWith(input.CodeInsiders) && line[^1] == ')') {
codeInsidersLine = i;
if (line != input.SubTasks)
}
if (line != input.SubTasks) {
continue;
}
subTasksLine = i;
if (codeInsidersLine is null)
if (codeInsidersLine is null) {
break;
if (lineNumber.Lines.Count > i)
{
for (int j = i + 1; j < lineNumber.Lines.Count; j++)
{
if (lineNumber.Lines[j].Length > 0 && lineNumber.Lines[j][0] == '#')
{
}
if (lineNumber.Lines.Count > i) {
for (int j = i + 1; j < lineNumber.Lines.Count; j++) {
if (lineNumber.Lines[j].Length > 0 && lineNumber.Lines[j][0] == '#') {
stopLine = j;
break;
}
@ -76,22 +75,18 @@ internal static partial class Helper20240623
return result;
}
private static List<Record> GetRecords(Input input)
{
private static List<Record> GetRecords(Input input) {
List<Record> results = [];
Record record;
FileInfo fileInfo;
string sourceDirectory = input.SourceDirectory;
ReadOnlyCollection<string> directoryNames = HelperDirectory.GetDirectoryNames(input.SourceDirectory);
if (!directoryNames.Any(l => l.StartsWith(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase)))
{
if (!directoryNames.Any(l => l.StartsWith(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase))) {
string directoryName;
string[] checkDirectories = Directory.GetDirectories(input.SourceDirectory, "*", SearchOption.TopDirectoryOnly);
foreach (string checkDirectory in checkDirectories)
{
foreach (string checkDirectory in checkDirectories) {
directoryName = Path.GetFileName(checkDirectory);
if (directoryName.StartsWith(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase))
{
if (directoryName.StartsWith(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase)) {
sourceDirectory = checkDirectory;
break;
}
@ -99,10 +94,10 @@ internal static partial class Helper20240623
}
string[] subDirectories = Directory.GetDirectories(sourceDirectory, "*", SearchOption.TopDirectoryOnly);
List<string> files = Directory.GetFiles(sourceDirectory, input.SearchPattern, SearchOption.TopDirectoryOnly).ToList();
foreach (string subDirectory in subDirectories)
foreach (string subDirectory in subDirectories) {
files.AddRange(Directory.GetFiles(subDirectory, input.SearchPattern, SearchOption.TopDirectoryOnly));
foreach (string file in files)
{
}
foreach (string file in files) {
fileInfo = new(file);
record = GetRecord(input, fileInfo);
results.Add(record);
@ -110,20 +105,19 @@ internal static partial class Helper20240623
return results;
}
private static string GetParamCase(string value)
{
private static string GetParamCase(string value) {
string result;
StringBuilder stringBuilder = new(value);
Match[] matches = UpperCase().Matches(value).ToArray();
for (int i = matches.Length - 1; i > -1; i--)
for (int i = matches.Length - 1; i > -1; i--) {
_ = stringBuilder.Insert(matches[i].Index, '-');
}
string[] segments = InvalidCharacter().Split(stringBuilder.ToString().ToLower());
result = string.Join('-', segments).Trim('-');
return result;
}
private static ReadOnlyCollection<SubTaskLine> GetSubTaskLines(Input input, bool? foundStarted, bool? foundCompleted, string fallbackLine, Record record)
{
private static ReadOnlyCollection<SubTaskLine> GetSubTaskLines(Input input, bool? foundStarted, bool? foundCompleted, string fallbackLine, Record record) {
List<SubTaskLine> results = [];
char done;
string line;
@ -134,15 +128,17 @@ internal static partial class Helper20240623
bool foundSubTasks = false;
int tasksZeroLength = input.Tasks[0].Length;
long ticks = record.FileInfo.LastWriteTime.Ticks;
for (int i = 0; i < record.LineNumber.Lines.Count; i++)
{
for (int i = 0; i < record.LineNumber.Lines.Count; i++) {
line = record.LineNumber.Lines[i];
if (!foundSubTasks && line == input.SubTasks)
if (!foundSubTasks && line == input.SubTasks) {
foundSubTasks = true;
if (!foundSubTasks)
}
if (!foundSubTasks) {
continue;
if (line.Length <= tasksZeroLength || !line.StartsWith(input.Tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']')
}
if (line.Length <= tasksZeroLength || !line.StartsWith(input.Tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']') {
continue;
}
startedValue = foundStarted is not null && foundStarted.Value;
completedValue = foundCompleted is not null && foundCompleted.Value;
subTaskLine = new(Text: $" {line}", Started: startedValue, Completed: completedValue, Ticks: ticks, Line: i);
@ -150,10 +146,9 @@ internal static partial class Helper20240623
}
startedValue = foundStarted is not null && foundStarted.Value;
completedValue = foundCompleted is not null && foundCompleted.Value;
if (record.LineNumber.H1 is null)
if (record.LineNumber.H1 is null) {
subTaskLine = new(Text: fallbackLine, Started: startedValue, Completed: completedValue, Ticks: ticks, Line: null);
else
{
} else {
done = foundCompleted is null || !foundCompleted.Value ? ' ' : 'x';
string codeInsidersLine = record.CodeInsidersLine is null ? string.Empty : $" ~~{record.LineNumber.Lines[record.CodeInsidersLine.Value]}~~";
text = $"- [{done}] {ticks} {record.LineNumber.Lines[record.LineNumber.H1.Value]}{codeInsidersLine}";
@ -163,10 +158,8 @@ internal static partial class Helper20240623
return new(results);
}
private static string GetSeasonName(int dayOfYear)
{
string result = dayOfYear switch
{
private static string GetSeasonName(int dayOfYear) {
string result = dayOfYear switch {
< 78 => "0.Winter",
< 124 => "1.Spring",
< 171 => "2.Spring",
@ -259,21 +252,20 @@ internal static partial class Helper20240623
}
""".Replace("{}", directory.Replace('\\', '/'));
private static void FileWriteAllText(string path, string contents)
{
private static void FileWriteAllText(string path, string contents) {
// string checkJson = Regex.Replace(File.ReadAllText(path), @"\s+", " ", RegexOptions.Multiline);
// if (Regex.Replace(singletonJson, @"\s+", " ", RegexOptions.Multiline) != checkJson)
// File.WriteAllText(path, singletonJson);
string old = !File.Exists(path) ? string.Empty : File.ReadAllText(path);
if (old != contents)
if (old != contents) {
File.WriteAllText(path, contents);
}
}
private static void FileWriteAllText(string path, string[] contents) =>
FileWriteAllText(path, string.Join(Environment.NewLine, contents));
private static ReadOnlyCollection<H1AndParamCase> GetH1ParamCaseCollection(Input input, ReadOnlyCollection<string> lines)
{
private static ReadOnlyCollection<H1AndParamCase> GetH1ParamCaseCollection(Input input, ReadOnlyCollection<string> lines) {
List<H1AndParamCase> results = [];
string h1;
string line;
@ -281,18 +273,21 @@ internal static partial class Helper20240623
bool foundSubTasks = false;
H1AndParamCase h1AndParamCase;
int tasksZeroLength = input.Tasks[0].Length;
for (int i = 0; i < lines.Count; i++)
{
for (int i = 0; i < lines.Count; i++) {
line = lines[i];
if (!foundSubTasks && line == input.SubTasks)
if (!foundSubTasks && line == input.SubTasks) {
foundSubTasks = true;
if (!foundSubTasks)
}
if (!foundSubTasks) {
continue;
if (line.Length <= tasksZeroLength || !line.StartsWith(input.Tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']')
}
if (line.Length <= tasksZeroLength || !line.StartsWith(input.Tasks[0]) || line[tasksZeroLength] is not ' ' and not 'x' || line[tasksZeroLength + 1] != ']') {
continue;
}
h1 = line[(tasksZeroLength + 3)..];
if (string.IsNullOrEmpty(h1))
if (string.IsNullOrEmpty(h1)) {
continue;
}
paramCase = GetParamCase(h1);
h1AndParamCase = new(h1, paramCase);
results.Add(h1AndParamCase);
@ -300,23 +295,24 @@ internal static partial class Helper20240623
return results.AsReadOnly();
}
private static void CreateFiles(string directory, ReadOnlyCollection<H1AndParamCase> h1ParamCaseCollection)
{
foreach (H1AndParamCase h1ParamCase in h1ParamCaseCollection)
private static void CreateFiles(string directory, ReadOnlyCollection<H1AndParamCase> h1ParamCaseCollection) {
foreach (H1AndParamCase h1ParamCase in h1ParamCaseCollection) {
FileWriteAllText(Path.Combine(directory, $"{h1ParamCase.ParamCase}.md"), $"# {h1ParamCase.H1}");
}
}
private static string WriteAndGetIndexFile(string h1, string verifiedDirectory, ReadOnlyCollection<H1AndParamCase> h1ParamCaseCollection)
{
private static string WriteAndGetIndexFile(string h1, string verifiedDirectory, ReadOnlyCollection<H1AndParamCase> h1ParamCaseCollection) {
string result;
string[] indexLines = GetIndexLines(h1, h1ParamCaseCollection);
string kanbanDirectory = Path.Combine(verifiedDirectory, ".kanbn");
string tasksKanbanDirectory = Path.Combine(kanbanDirectory, "tasks");
if (!Directory.Exists(tasksKanbanDirectory))
if (!Directory.Exists(tasksKanbanDirectory)) {
_ = Directory.CreateDirectory(tasksKanbanDirectory);
}
string verifiedVisualStudioCodeDirectory = Path.Combine(verifiedDirectory, ".vscode");
if (!Directory.Exists(verifiedVisualStudioCodeDirectory))
if (!Directory.Exists(verifiedVisualStudioCodeDirectory)) {
_ = Directory.CreateDirectory(verifiedVisualStudioCodeDirectory);
}
result = Path.Combine(kanbanDirectory, "index.md");
CreateFiles(tasksKanbanDirectory, h1ParamCaseCollection);
FileWriteAllText(result, indexLines);
@ -326,48 +322,49 @@ internal static partial class Helper20240623
return result;
}
private static ReadOnlyCollection<string> GetXColumns(Input input, int frontMatterYamlEnd, int value, ReadOnlyCollection<string> lines)
{
private static ReadOnlyCollection<string> GetXColumns(Input input, int frontMatterYamlEnd, int value, ReadOnlyCollection<string> lines) {
List<string> results = [];
string[] segments;
for (int i = value + 1; i < frontMatterYamlEnd; i++)
{
for (int i = value + 1; i < frontMatterYamlEnd; i++) {
segments = lines[i].Replace("\t", " ").Split(" - ");
if (segments.Length != 2)
if (segments.Length != 2) {
break;
}
results.Add($"## {segments[1].Replace("'", string.Empty)}");
}
if (results.Count == 0)
if (results.Count == 0) {
results.Add(input.Done);
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<string> GetCompletedColumns(Input input, LineNumber lineNumber)
{
private static ReadOnlyCollection<string> GetCompletedColumns(Input input, LineNumber lineNumber) {
List<string> results;
if (lineNumber.FrontMatterYamlEnd is null || lineNumber.CompletedColumns is null)
if (lineNumber.FrontMatterYamlEnd is null || lineNumber.CompletedColumns is null) {
results = [];
else
} else {
results = GetXColumns(input, lineNumber.FrontMatterYamlEnd.Value, lineNumber.CompletedColumns.Value, lineNumber.Lines).ToList();
if (results.Count == 0)
}
if (results.Count == 0) {
results.Add(input.Done);
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<string> GetStartedColumns(Input input, LineNumber lineNumber)
{
private static ReadOnlyCollection<string> GetStartedColumns(Input input, LineNumber lineNumber) {
List<string> results;
if (lineNumber.FrontMatterYamlEnd is null || lineNumber.StartedColumns is null)
if (lineNumber.FrontMatterYamlEnd is null || lineNumber.StartedColumns is null) {
results = [];
else
} else {
results = GetXColumns(input, lineNumber.FrontMatterYamlEnd.Value, lineNumber.StartedColumns.Value, lineNumber.Lines).ToList();
if (results.Count == 0)
}
if (results.Count == 0) {
results.Add(input.Done);
}
return results.AsReadOnly();
}
private static ReadOnlyCollection<SubTaskLine> GetSubTaskLines(Input input, FileInfo fileInfo, LineNumber lineNumber)
{
private static ReadOnlyCollection<SubTaskLine> GetSubTaskLines(Input input, FileInfo fileInfo, LineNumber lineNumber) {
List<SubTaskLine> results = [];
FileInfo f;
Record record;
@ -382,37 +379,39 @@ internal static partial class Helper20240623
ReadOnlyCollection<string> startedColumns = GetStartedColumns(input, lineNumber);
ReadOnlyCollection<string> completedColumns = GetCompletedColumns(input, lineNumber);
int start = lineNumber.FrontMatterYamlEnd is null ? 0 : lineNumber.FrontMatterYamlEnd.Value + 1;
for (int i = start; i < lineNumber.Lines.Count; i++)
{
if ((foundStarted is null || !foundStarted.Value) && startedColumns.Any(lineNumber.Lines[i].StartsWith))
for (int i = start; i < lineNumber.Lines.Count; i++) {
if ((foundStarted is null || !foundStarted.Value) && startedColumns.Any(lineNumber.Lines[i].StartsWith)) {
foundStarted = true;
if ((foundCompleted is null || !foundCompleted.Value) && completedColumns.Any(lineNumber.Lines[i].StartsWith))
}
if ((foundCompleted is null || !foundCompleted.Value) && completedColumns.Any(lineNumber.Lines[i].StartsWith)) {
foundCompleted = true;
}
segments = lineNumber.Lines[i].Split(input.Tasks[1]);
startedValue = foundStarted is not null && foundStarted.Value;
completedValue = foundCompleted is not null && foundCompleted.Value;
if (segments.Length > 2 || !segments[0].StartsWith(input.Tasks[0]))
if (segments.Length > 2 || !segments[0].StartsWith(input.Tasks[0])) {
continue;
}
completed = foundCompleted is null || !foundCompleted.Value ? ' ' : 'x';
fallbackLine = $"- [{completed}] {segments[0][input.Tasks[0].Length..]} ~~FallbackLine~~";
if (string.IsNullOrEmpty(fileInfo.DirectoryName))
if (string.IsNullOrEmpty(fileInfo.DirectoryName)) {
continue;
}
f = new(Path.GetFullPath(Path.Combine(fileInfo.DirectoryName, segments[1][..^1])));
if (!f.Exists)
{
if (!f.Exists) {
results.Add(new(Text: fallbackLine, Started: startedValue, Completed: completedValue, Ticks: null, Line: null));
continue;
}
record = GetRecord(input, f);
subTaskLines = GetSubTaskLines(input, startedValue, completedValue, fallbackLine, record);
for (int j = subTaskLines.Count - 1; j >= 0; j--)
for (int j = subTaskLines.Count - 1; j >= 0; j--) {
results.Add(subTaskLines[j]);
}
}
return results.AsReadOnly();
}
private static Input GetInput(List<string> args)
{
private static Input GetInput(List<string> args) {
string indexFile = args[5];
string searchPattern = args[2];
string directoryFilter = args[8];
@ -433,46 +432,42 @@ internal static partial class Helper20240623
SubTasks: subTasks,
SourceDirectory: sourceDirectory,
Tasks: tasks.AsReadOnly());
if (input.Tasks[0] != "- [" || input.Tasks[1] != "](")
if (input.Tasks[0] != "- [" || input.Tasks[1] != "](") {
throw new Exception(JsonSerializer.Serialize(input, InputSourceGenerationContext.Default.Input));
}
return input;
}
private static string? MaybeWriteAndGetIndexFile(Input input, Record record, string? checkDirectory)
{
private static string? MaybeWriteAndGetIndexFile(Input input, Record record, string? checkDirectory) {
string? result;
if (string.IsNullOrEmpty(checkDirectory) || input.AfterEpochTotalMilliseconds is null || input.DestinationDirectories.Count == 0)
if (string.IsNullOrEmpty(checkDirectory) || input.AfterEpochTotalMilliseconds is null || input.DestinationDirectories.Count == 0) {
result = null;
else
{
if (!input.DestinationDirectories.Any(checkDirectory.Contains))
} else {
if (!input.DestinationDirectories.Any(checkDirectory.Contains)) {
result = null;
else
{
if (record.LineNumber.H1 is null)
} else {
if (record.LineNumber.H1 is null) {
result = null;
else
{
} else {
string segment = Path.GetFileName(checkDirectory);
string h1 = record.LineNumber.Lines[record.LineNumber.H1.Value];
DateTime utcEpochDateTime = new(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
long utcEpochTotalMilliseconds = (long)Math.Floor(DateTime.UtcNow.Subtract(utcEpochDateTime).TotalMilliseconds);
if (!long.TryParse(segment, out long check) || check < input.AfterEpochTotalMilliseconds || check > utcEpochTotalMilliseconds)
if (!long.TryParse(segment, out long check) || check < input.AfterEpochTotalMilliseconds || check > utcEpochTotalMilliseconds) {
result = null;
else
{
} else {
ReadOnlyCollection<H1AndParamCase> h1ParamCaseCollection = GetH1ParamCaseCollection(input, record.LineNumber.Lines);
if (h1ParamCaseCollection.Count == 0)
if (h1ParamCaseCollection.Count == 0) {
result = null;
else
{
} else {
DateTime dateTime = utcEpochDateTime.AddMilliseconds(check).ToLocalTime();
string seasonName = GetSeasonName(dateTime.DayOfYear);
ReadOnlyCollection<string> directoryNames = HelperDirectory.GetDirectoryNames(checkDirectory);
if (!directoryNames.Contains(dateTime.Year.ToString()) || !directoryNames.Contains($"{dateTime.Year}-{seasonName}") || !directoryNames.Contains(check.ToString()))
if (!directoryNames.Contains(dateTime.Year.ToString()) || !directoryNames.Contains($"{dateTime.Year}-{seasonName}") || !directoryNames.Contains(check.ToString())) {
result = null;
else
} else {
result = WriteAndGetIndexFile(h1, checkDirectory, h1ParamCaseCollection);
}
}
}
}
@ -481,53 +476,50 @@ internal static partial class Helper20240623
return result;
}
private static bool FileWrite(long ticks, Record record, List<string> newLines, double percent)
{
private static bool FileWrite(long ticks, Record record, List<string> newLines, double percent) {
bool result = false;
if (record.StopLine is not null && record.SubTasksLine is not null)
{
if (record.StopLine is not null && record.SubTasksLine is not null) {
string contents;
string progressLine;
List<string> resultLines;
if (record.FileInfo.LastWriteTime.Ticks <= ticks)
if (record.FileInfo.LastWriteTime.Ticks <= ticks) {
resultLines = record.LineNumber.Lines.ToList();
else
} else {
resultLines = File.ReadAllLines(record.FileInfo.FullName).ToList();
if (record.LineNumber.FrontMatterYamlEnd is not null)
{
}
if (record.LineNumber.FrontMatterYamlEnd is not null) {
progressLine = $"progress: {percent}";
if (record.LineNumber.Progress is not null)
if (record.LineNumber.Progress is not null) {
resultLines[record.LineNumber.Progress.Value] = progressLine;
else
{
} else {
resultLines.Insert(record.LineNumber.FrontMatterYamlEnd.Value, progressLine);
contents = string.Join(Environment.NewLine, resultLines);
FileWriteAllText(record.FileInfo.FullName, contents);
result = true;
}
if (!result && record.LineNumber.Completed is null && percent > 99.9)
{
if (!result && record.LineNumber.Completed is null && percent > 99.9) {
resultLines.Insert(record.LineNumber.FrontMatterYamlEnd.Value, $"completed: {DateTime.Now:yyyy-MM-dd}");
contents = string.Join(Environment.NewLine, resultLines);
FileWriteAllText(record.FileInfo.FullName, contents);
result = true;
}
if (!result && record.LineNumber.Completed is not null && percent < 99.9)
{
if (!result && record.LineNumber.Completed is not null && percent < 99.9) {
resultLines.RemoveAt(record.LineNumber.Completed.Value);
contents = string.Join(Environment.NewLine, resultLines);
FileWriteAllText(record.FileInfo.FullName, contents);
result = true;
}
}
if (!result)
{
for (int i = record.StopLine.Value - 1; i > record.SubTasksLine.Value + 1; i--)
if (!result) {
for (int i = record.StopLine.Value - 1; i > record.SubTasksLine.Value + 1; i--) {
resultLines.RemoveAt(i);
if (record.StopLine.Value == record.LineNumber.Lines.Count && resultLines[^1].Length == 0)
}
if (record.StopLine.Value == record.LineNumber.Lines.Count && resultLines[^1].Length == 0) {
resultLines.RemoveAt(resultLines.Count - 1);
for (int i = 0; i < newLines.Count; i++)
}
for (int i = 0; i < newLines.Count; i++) {
resultLines.Insert(record.SubTasksLine.Value + 1 + i, newLines[i]);
}
resultLines.Insert(record.SubTasksLine.Value + 1, string.Empty);
contents = string.Join(Environment.NewLine, resultLines);
FileWriteAllText(record.FileInfo.FullName, contents);
@ -536,102 +528,95 @@ internal static partial class Helper20240623
return result;
}
private static string? GetInferredCheckDirectory(string directory)
{
private static string? GetInferredCheckDirectory(string directory) {
string? result = null;
List<string> directoryNames = [];
DirectoryInfo directoryInfo;
string? checkDirectory = directory;
directoryNames.Add(Path.GetFileName(checkDirectory));
string pathRoot = Path.GetPathRoot(directory) ?? throw new Exception();
for (int i = 0; i < directory.Length; i++)
{
for (int i = 0; i < directory.Length; i++) {
checkDirectory = Path.GetDirectoryName(checkDirectory);
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot)
if (string.IsNullOrEmpty(checkDirectory) || checkDirectory == pathRoot) {
break;
}
directoryInfo = new(checkDirectory);
if (!directoryInfo.Exists)
if (!directoryInfo.Exists) {
directoryNames.Add(directoryInfo.Name);
else
{
} else {
directoryNames.Reverse();
result = string.IsNullOrEmpty(directoryInfo.LinkTarget) ? checkDirectory : directoryInfo.LinkTarget;
for (int j = 0; j < directoryNames.Count; j++)
for (int j = 0; j < directoryNames.Count; j++) {
result = Path.GetDirectoryName(result) ?? throw new Exception();
foreach (string directoryName in directoryNames)
}
foreach (string directoryName in directoryNames) {
result = Path.Combine(result, directoryName);
}
break;
}
}
return result;
}
private static void UpdateFileAndStartNewProcess(ILogger<Worker> logger, Input input, Record record, string inferredCheckDirectory)
{
if (record.CodeInsidersLine is null)
private static void UpdateFileAndStartNewProcess(ILogger<Worker> logger, Input input, Record record, string inferredCheckDirectory) {
if (record.CodeInsidersLine is null) {
throw new Exception();
}
List<string> lines = record.LineNumber.Lines.ToList();
lines[record.CodeInsidersLine.Value] = $"{input.CodeInsiders}{inferredCheckDirectory})";
string text = string.Join(Environment.NewLine, lines);
File.WriteAllText(record.FileInfo.FullName, text);
record.FileInfo.Refresh();
string file = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Programs", "Microsoft VS Code Insiders", "Code - Insiders.exe");
try
{ _ = Process.Start(file, $"\"{inferredCheckDirectory}\""); }
catch (Exception) { logger.LogWarning("Failed to start code-insiders!"); }
try { _ = Process.Start(file, $"\"{inferredCheckDirectory}\""); } catch (Exception) { logger.LogWarning("Failed to start code-insiders!"); }
}
private static FileInfo GetIndexFileInfo(ILogger<Worker> logger, Input input, Record record)
{
private static FileInfo GetIndexFileInfo(ILogger<Worker> logger, Input input, Record record) {
FileInfo result;
string? indexFile;
List<string> results;
if (record.CodeInsidersLine is null)
if (record.CodeInsidersLine is null) {
throw new Exception();
}
string codeInsidersLine = record.LineNumber.Lines[record.CodeInsidersLine.Value];
string raw = codeInsidersLine[input.CodeInsiders.Length..^1];
string checkDirectory = $"{raw[..2].ToUpper()}{raw[2..]}";
if (!Directory.Exists(checkDirectory))
{
if (input.DestinationDirectories.Count > 0 && input.DestinationDirectories.Any(checkDirectory.Contains))
{
if (!Directory.Exists(checkDirectory)) {
if (input.DestinationDirectories.Count > 0 && input.DestinationDirectories.Any(checkDirectory.Contains)) {
string? inferredCheckDirectory = GetInferredCheckDirectory(checkDirectory);
if (!string.IsNullOrEmpty(inferredCheckDirectory))
{
if (!string.IsNullOrEmpty(inferredCheckDirectory)) {
checkDirectory = inferredCheckDirectory;
_ = Directory.CreateDirectory(inferredCheckDirectory);
UpdateFileAndStartNewProcess(logger, input, record, inferredCheckDirectory);
}
}
}
if (!Directory.Exists(checkDirectory))
if (!Directory.Exists(checkDirectory)) {
results = [];
else
{
} else {
results = Directory.GetFiles(checkDirectory, input.IndexFile, SearchOption.AllDirectories).ToList();
if (results.Count != 1)
{
for (int i = results.Count - 1; i > -1; i--)
{
if (!results[i].Contains(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase))
if (results.Count != 1) {
for (int i = results.Count - 1; i > -1; i--) {
if (!results[i].Contains(input.DirectoryFilter, StringComparison.CurrentCultureIgnoreCase)) {
results.RemoveAt(i);
}
}
}
if (results.Count == 0)
{
if (results.Count == 0) {
indexFile = MaybeWriteAndGetIndexFile(input, record, checkDirectory);
if (!string.IsNullOrEmpty(indexFile))
if (!string.IsNullOrEmpty(indexFile)) {
results.Add(indexFile);
else
} else {
logger.LogInformation("<{checkDirectory}>", checkDirectory);
}
}
}
result = results.Count == 0 ? new(Path.Combine(checkDirectory, input.IndexFile)) : new(results[0]);
return result;
}
internal static void UpdateSubTasksInMarkdownFiles(ILogger<Worker> logger, List<string> args)
{
internal static void UpdateSubTasksInMarkdownFiles(ILogger<Worker> logger, List<string> args) {
bool reload;
int allCount;
int lineCheck;
@ -650,26 +635,24 @@ internal static partial class Helper20240623
string fileNameWithoutExtension;
long ticks = DateTime.Now.Ticks;
ReadOnlyCollection<SubTaskLine> subTaskLines;
for (int z = 0; z < 9; z++)
{
for (int z = 0; z < 9; z++) {
records = GetRecords(input);
foreach (Record record in from l in records orderby l.SubTasksLine is null, l.CodeInsidersLine is null select l)
{
if (record.SubTasksLine is null)
foreach (Record record in from l in records orderby l.SubTasksLine is null, l.CodeInsidersLine is null select l) {
if (record.SubTasksLine is null) {
continue;
}
fileNameWithoutExtension = Path.GetFileNameWithoutExtension(record.FileInfo.FullName);
if (record.CodeInsidersLine is not null)
if (record.CodeInsidersLine is not null) {
logger.LogInformation("<{file}> has [{subTasks}]", fileNameWithoutExtension, input.SubTasks);
else
{
} else {
logger.LogWarning("<{file}> has [{subTasks}] but doesn't have [{codeInsiders}]!", fileNameWithoutExtension, input.SubTasks, input.CodeInsiders);
continue;
}
if (record.StopLine is null)
if (record.StopLine is null) {
continue;
}
fileInfo = GetIndexFileInfo(logger, input, record);
if (!fileInfo.Exists)
{
if (!fileInfo.Exists) {
logger.LogError("<{checkDirectory}> doesn't have a [{indexFile}]", fileInfo.DirectoryName, input.IndexFile);
continue;
}
@ -677,18 +660,17 @@ internal static partial class Helper20240623
checkDirectory = fileInfo.DirectoryName;
lineNumber = HelperMarkdown.GetLineNumbers(fileInfo);
subTaskLines = GetSubTaskLines(input, fileInfo, lineNumber);
if (subTaskLines.Count == 0)
if (subTaskLines.Count == 0) {
continue;
}
lineCheck = 0;
for (int i = record.SubTasksLine.Value + 1; i < record.StopLine.Value - 1; i++)
for (int i = record.SubTasksLine.Value + 1; i < record.StopLine.Value - 1; i++) {
oldLines.Add(record.LineNumber.Lines[i]);
if (subTaskLines.Count == 0)
{
}
if (subTaskLines.Count == 0) {
percent = 0;
replace = "0";
}
else
{
} else {
allCount = (from l in subTaskLines where l.Line is not null && l.Line.Value == 0 select 1).Count();
completedCount = (from l in subTaskLines where l.Line is not null && l.Line.Value == 0 && l.Completed select 1).Count();
startedCount = (from l in subTaskLines where l.Line is not null && l.Line.Value == 0 && l.Started && !l.Completed select 1).Count();
@ -696,38 +678,40 @@ internal static partial class Helper20240623
// newLines.Insert(0, $"- [{done}] Sub-tasks {doneCount} of {allCount} [{percent * 100}%]");
replace = $"{allCount} » {startedCount} ✓ {completedCount} {Math.Floor(percent * 100)}%".Replace(" ✓ 0 0%", string.Empty).Replace(" 100%", string.Empty).Replace(" » 0", string.Empty);
}
if (subTaskLines.Any(l => l.Ticks is null))
if (subTaskLines.Any(l => l.Ticks is null)) {
newLines = (from l in subTaskLines
select l.Text).ToList();
else
{
} else {
newLines = (from l in subTaskLines
orderby l.Completed descending, l.Started descending, l.Ticks, l.Line
select l.Text.Replace($"{l.Ticks}", replace)).ToList();
}
if (newLines.Count == oldLines.Count)
{
for (int i = 0; i < newLines.Count; i++)
{
if (newLines[i] != record.LineNumber.Lines[record.SubTasksLine.Value + 1 + i])
if (newLines.Count == oldLines.Count) {
for (int i = 0; i < newLines.Count; i++) {
if (newLines[i] != record.LineNumber.Lines[record.SubTasksLine.Value + 1 + i]) {
continue;
}
lineCheck++;
}
if (lineCheck == newLines.Count)
if (lineCheck == newLines.Count) {
continue;
}
}
if (string.IsNullOrEmpty(checkDirectory))
if (string.IsNullOrEmpty(checkDirectory)) {
continue;
}
checkDirectory = Path.Combine(checkDirectory, DateTime.Now.Ticks.ToString());
_ = Directory.CreateDirectory(checkDirectory);
Thread.Sleep(500);
Directory.Delete(checkDirectory);
reload = FileWrite(ticks, record, newLines, percent);
if (!reloadAny && reload)
if (!reloadAny && reload) {
reloadAny = true;
}
}
if (!reloadAny)
if (!reloadAny) {
break;
}
}
}

View File

@ -2,11 +2,21 @@ using Microsoft.Extensions.Logging;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240624
{
internal static partial class Helper20240624 {
private static void MoveUpOndDirectory(ILogger<Worker> logger, string sourceDirectory, string[] files)
{
internal static void MoveUpOneDirectory(ILogger<Worker> logger, List<string> args) {
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0]);
string[] deleteMatchingIdsDirectoryNames = args[3].Split(',');
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
if (deleteMatchingIdsDirectoryNames.Length == 0) {
MoveUpOndDirectory(logger, sourceDirectory, files);
} else {
Distinct(args, sourceDirectory, deleteMatchingIdsDirectoryNames, files);
}
}
private static void MoveUpOndDirectory(ILogger<Worker> logger, string sourceDirectory, string[] files) {
string? match;
string checkFile;
FileInfo fileInfoA;
@ -14,75 +24,64 @@ internal static partial class Helper20240624
string? checkDirectory;
List<string> deleteFiles = [];
Dictionary<string, string> keyValuePairs = [];
foreach (string file in files)
{
foreach (string file in files) {
checkDirectory = Path.GetDirectoryName(Path.GetDirectoryName(file)) ?? throw new NotSupportedException();
checkFile = Path.Combine(checkDirectory, Path.GetFileName(file));
if (File.Exists(checkFile))
if (File.Exists(checkFile)) {
throw new NotSupportedException();
if (keyValuePairs.TryGetValue(checkFile, out match))
{
}
if (keyValuePairs.TryGetValue(checkFile, out match)) {
fileInfoA = new(file);
fileInfoB = new(match);
if (fileInfoA.Length != fileInfoB.Length)
if (fileInfoA.Length != fileInfoB.Length) {
throw new NotSupportedException("Files don't match!");
}
logger.LogWarning("<{file}> already exists!", file);
deleteFiles.Add(file);
continue;
}
keyValuePairs.Add(checkFile, file);
}
foreach (string file in deleteFiles)
foreach (string file in deleteFiles) {
File.Delete(file);
foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs)
}
foreach (KeyValuePair<string, string> keyValuePair in keyValuePairs) {
File.Move(keyValuePair.Value, keyValuePair.Key);
}
Helpers.HelperDeleteEmptyDirectories.DeleteEmptyDirectories(logger, sourceDirectory);
}
private static void Distinct(List<string> args, string sourceDirectory, string[] deleteMatchingIdsDirectoryNames, string[] files)
{
private static void Distinct(List<string> args, string sourceDirectory, string[] deleteMatchingIdsDirectoryNames, string[] files) {
string fileName;
string directory;
List<string> distinct = [];
List<string> duplicate = [];
string[] keepMatchingIdsDirectoryNames = args[4].Split(',');
if (deleteMatchingIdsDirectoryNames.Length != keepMatchingIdsDirectoryNames.Length)
if (deleteMatchingIdsDirectoryNames.Length != keepMatchingIdsDirectoryNames.Length) {
throw new NotSupportedException("Check arg lengths!");
}
string[] keepMatchingIdsDirectories = keepMatchingIdsDirectoryNames.Select(l => Path.Combine(sourceDirectory, l)).ToArray();
string[] deleteMatchingIdsDirectories = deleteMatchingIdsDirectoryNames.Select(l => Path.Combine(sourceDirectory, l)).ToArray();
foreach (string file in files)
{
foreach (string file in files) {
fileName = Path.GetFileName(file);
if (distinct.Contains(fileName))
{
if (distinct.Contains(fileName)) {
duplicate.Add(fileName);
continue;
}
distinct.Add(Path.GetFileName(file));
}
foreach (string file in files)
{
foreach (string file in files) {
fileName = Path.GetFileName(file);
directory = Path.GetDirectoryName(file) ?? throw new NotSupportedException();
if (!duplicate.Contains(fileName))
if (!duplicate.Contains(fileName)) {
continue;
if (deleteMatchingIdsDirectories.Contains(directory))
}
if (deleteMatchingIdsDirectories.Contains(directory)) {
File.Move(file, $"{file}.del");
else if (!keepMatchingIdsDirectories.Contains(directory))
} else if (!keepMatchingIdsDirectories.Contains(directory)) {
throw new NotSupportedException($"Missing <{Path.GetFileName(directory)}> as a directory for {fileName}");
}
}
}
internal static void MoveUpOneDirectory(ILogger<Worker> logger, List<string> args)
{
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0]);
string[] deleteMatchingIdsDirectoryNames = args[3].Split(',');
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
if (deleteMatchingIdsDirectoryNames.Length == 0)
MoveUpOndDirectory(logger, sourceDirectory, files);
else
Distinct(args, sourceDirectory, deleteMatchingIdsDirectoryNames, files);
}
}

View File

@ -3,11 +3,9 @@ using System.Collections.ObjectModel;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240711
{
internal static partial class Helper20240711 {
internal static void GitRemoteRemove(ILogger<Worker> logger, List<string> args)
{
internal static void GitRemoteRemove(ILogger<Worker> logger, List<string> args) {
string line;
string[] lines;
bool branchCheck;
@ -27,52 +25,56 @@ internal static partial class Helper20240711
string extension = args[7].Length > 2 ? args[7] : string.Empty;
string[] files = Directory.EnumerateFiles(sourceDirectory, searchPattern, new EnumerationOptions() { IgnoreInaccessible = true, RecurseSubdirectories = true, AttributesToSkip = FileAttributes.None }).ToArray();
logger.LogInformation("Found {files} file(s)", files.Length);
foreach (string file in files)
{
foreach (string file in files) {
branchCheck = false;
remoteCheck = false;
lines = File.ReadAllLines(file);
for (int i = 0; i < lines.Length; i++)
{
for (int i = 0; i < lines.Length; i++) {
line = lines[i];
if (!line.Contains(remoteToRemove))
if (!line.Contains(remoteToRemove)) {
continue;
if (!lines[i - 1].Contains(remoteToRemoveFilter))
}
if (!lines[i - 1].Contains(remoteToRemoveFilter)) {
continue;
}
remoteCheck = true;
break;
}
for (int i = 0; i < lines.Length; i++)
{
for (int i = 0; i < lines.Length; i++) {
line = lines[i];
if (!line.Contains(branchName))
if (!line.Contains(branchName)) {
continue;
}
branchCheck = true;
break;
}
if (!remoteCheck)
if (!remoteCheck) {
continue;
}
directory = Path.GetDirectoryName(file);
if (directory is null)
if (directory is null) {
continue;
}
parentDirectory = Path.GetDirectoryName(directory);
if (parentDirectory is null)
if (parentDirectory is null) {
continue;
}
parentDirectoryName = Path.GetFileName(parentDirectory).ToLower();
messages = Helpers.HelperGit.RemoteRemove(parentDirectory, lastRemoteSegment, CancellationToken.None);
foreach (string message in messages)
foreach (string message in messages) {
logger.LogInformation("{function} => {parentDirectoryName}: [{message}]", nameof(Helpers.HelperGit.RemoteRemove), parentDirectoryName, message);
}
messages = Helpers.HelperGit.RemoteAdd(parentDirectory, remoteToAddName, $"{remoteToAddUrl}{parentDirectoryName}{extension}", CancellationToken.None);
foreach (string message in messages)
foreach (string message in messages) {
logger.LogInformation("{function} => {parentDirectoryName}: [{message}]", nameof(Helpers.HelperGit.RemoteAdd), parentDirectoryName, message);
if (!branchCheck)
}
if (!branchCheck) {
continue;
try
{ messages = Helpers.HelperGit.PushBranch(parentDirectory, remoteToAddName, branchName, CancellationToken.None); }
catch (Exception ex)
{ messages = new([ex.Message]); }
foreach (string message in messages)
}
try { messages = Helpers.HelperGit.PushBranch(parentDirectory, remoteToAddName, branchName, CancellationToken.None); } catch (Exception ex) { messages = new([ex.Message]); }
foreach (string message in messages) {
logger.LogInformation("{function} => {parentDirectoryName}: [{message}]", nameof(Helpers.HelperGit.PushBranch), parentDirectoryName, message);
}
}
}

View File

@ -5,8 +5,7 @@ using System.Text.Json.Serialization;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240718
{
internal static partial class Helper20240718 {
private record Host([property: JsonPropertyName("a")] string? Id,
[property: JsonPropertyName("b")] string? Colon,
@ -21,67 +20,10 @@ internal static partial class Helper20240718
[JsonSourceGenerationOptions(WriteIndented = true, AllowTrailingCommas = true)]
[JsonSerializable(typeof(Host[]))]
private partial class HostsSourceGenerationContext : JsonSerializerContext
{
private partial class HostsSourceGenerationContext : JsonSerializerContext {
}
private static Host[] GetHosts(ILogger<Worker> logger, string file)
{
Host[] results;
string lines = File.ReadAllText(file);
string json = $"[{lines.Replace("\r\n", ",")}]";
logger.LogDebug(lines);
results = JsonSerializer.Deserialize(json, HostsSourceGenerationContext.Default.HostArray) ?? throw new NullReferenceException();
return results;
}
private static ReadOnlyCollection<string> GetLines(Host[] hosts, string title, string wired)
{
List<string> results = [$"# {title}", string.Empty, "```mermaid", "flowchart TB", $" subgraph {title}"];
int id;
string check;
List<int> distinct = [];
string newLine = $"{Environment.NewLine} ";
foreach (Host host in hosts)
{
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17)
continue;
if (!int.TryParse(host.Id, out id))
throw new NotSupportedException($"{host.Id} is not a number");
if (distinct.Contains(id))
throw new NotSupportedException($"{id} is not distinct!");
distinct.Add(id);
results.Add($" {id}(fa:{host.Type}{newLine}{host.Colon}{newLine}{host.Hyphen}{newLine}{host.Device}{newLine}https://{host.Name}/)");
}
results.Add(" end");
results.Add($" subgraph {title}");
foreach (Host host in from l in hosts orderby l.Location, l.Type, l.Line select l)
{
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17)
continue;
if (!int.TryParse(host.Id, out id))
throw new NotSupportedException($"{host.Id} is not a number");
check = host.Type == wired ? "-->" : "-.->";
results.Add($" {id} {check} |{id}| {host.Location}{host.Type}{host.Line}");
}
results.Add(" end");
results.Add($" subgraph {title}");
foreach (Host host in from l in hosts orderby l.Line, l.Location, l.Type select l)
{
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Line is null || host.Hyphen.Length != 17)
continue;
if (!int.TryParse(host.Id, out id))
throw new NotSupportedException($"{host.Id} is not a number");
check = host.Type == wired ? "-->" : "-.->";
results.Add($" {host.Location}{host.Type}{host.Line} {check} Line{host.Line}");
}
results.Add(" end");
results.Add("```");
return results.AsReadOnly();
}
internal static void JsonToMarkdown(ILogger<Worker> logger, List<string> args)
{
internal static void JsonToMarkdown(ILogger<Worker> logger, List<string> args) {
Host[] hosts;
string title = args[3];
string wired = args[4];
@ -90,12 +32,68 @@ internal static partial class Helper20240718
ReadOnlyCollection<string> lines;
string sourceDirectory = Path.GetFullPath(args[0]);
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
foreach (string file in files)
{
foreach (string file in files) {
hosts = GetHosts(logger, file);
lines = GetLines(hosts, title, wired);
File.WriteAllText($"{file}{extension}", string.Join(Environment.NewLine, lines));
}
}
private static Host[] GetHosts(ILogger<Worker> logger, string file) {
Host[] results;
string lines = File.ReadAllText(file);
string json = $"[{lines.Replace("\r\n", ",")}]";
logger.LogDebug(lines);
results = JsonSerializer.Deserialize(json, HostsSourceGenerationContext.Default.HostArray) ?? throw new NullReferenceException();
return results;
}
private static ReadOnlyCollection<string> GetLines(Host[] hosts, string title, string wired) {
List<string> results = [$"# {title}", string.Empty, "```mermaid", "flowchart TB", $" subgraph {title}"];
int id;
string check;
List<int> distinct = [];
string newLine = $"{Environment.NewLine} ";
foreach (Host host in hosts) {
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17) {
continue;
}
if (!int.TryParse(host.Id, out id)) {
throw new NotSupportedException($"{host.Id} is not a number");
}
if (distinct.Contains(id)) {
throw new NotSupportedException($"{id} is not distinct!");
}
distinct.Add(id);
results.Add($" {id}(fa:{host.Type}{newLine}{host.Colon}{newLine}{host.Hyphen}{newLine}{host.Device}{newLine}https://{host.Name}/)");
}
results.Add(" end");
results.Add($" subgraph {title}");
foreach (Host host in from l in hosts orderby l.Location, l.Type, l.Line select l) {
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Hyphen.Length != 17) {
continue;
}
if (!int.TryParse(host.Id, out id)) {
throw new NotSupportedException($"{host.Id} is not a number");
}
check = host.Type == wired ? "-->" : "-.->";
results.Add($" {id} {check} |{id}| {host.Location}{host.Type}{host.Line}");
}
results.Add(" end");
results.Add($" subgraph {title}");
foreach (Host host in from l in hosts orderby l.Line, l.Location, l.Type select l) {
if (host.Id is null || host.Hyphen is null || host.Device is null || host.Name is null || host.Line is null || host.Hyphen.Length != 17) {
continue;
}
if (!int.TryParse(host.Id, out id)) {
throw new NotSupportedException($"{host.Id} is not a number");
}
check = host.Type == wired ? "-->" : "-.->";
results.Add($" {host.Location}{host.Type}{host.Line} {check} Line{host.Line}");
}
results.Add(" end");
results.Add("```");
return results.AsReadOnly();
}
}

View File

@ -3,11 +3,9 @@ using System.Diagnostics;
namespace File_Folder_Helper.ADO2024.PI2;
internal static partial class Helper20240728
{
internal static partial class Helper20240728 {
internal static void DownloadSslCertificates(ILogger<Worker> logger, List<string> args)
{
internal static void DownloadSslCertificates(ILogger<Worker> logger, List<string> args) {
string file;
Process? process;
string[] segments;
@ -23,8 +21,7 @@ internal static partial class Helper20240728
int waitForExit = int.Parse(args[5]);
string[] subdomains = args[3].Split(',');
string sourceDirectory = Path.GetFullPath(args[0]);
ProcessStartInfo processStartInfo = new()
{
ProcessStartInfo processStartInfo = new() {
CreateNoWindow = true,
RedirectStandardError = true,
RedirectStandardOutput = true,
@ -32,28 +29,29 @@ internal static partial class Helper20240728
FileName = args[4],
WorkingDirectory = sourceDirectory
};
foreach (string subdomain in subdomains)
{
foreach (string subdomain in subdomains) {
argumentSegment = $"{subdomain}.{domain}:443 -servername {subdomain}.{domain}";
processStartInfo.Arguments = $"s_client -connect {subdomain}.{domain}:443 -servername {subdomain}.{domain}";
process = Process.Start(processStartInfo);
if (process is null)
if (process is null) {
continue;
}
_ = process.WaitForExit(waitForExit);
process.Kill(entireProcessTree: true);
standardOutput = process.StandardOutput.ReadToEnd();
if (!standardOutput.Contains(beginCertificate) || !standardOutput.Contains(endCertificate))
{
if (!standardOutput.Contains(beginCertificate) || !standardOutput.Contains(endCertificate)) {
standardError = process.StandardError.ReadToEnd();
logger.LogWarning($"Error: {subdomain}{Environment.NewLine}{standardOutput}{Environment.NewLine}{standardError}");
continue;
}
segments = standardOutput.Split(beginCertificate);
if (segments.Length != 2)
if (segments.Length != 2) {
break;
}
segments = segments[1].Split(endCertificate);
if (segments.Length != 2)
if (segments.Length != 2) {
break;
}
lines.Add($"{logSegment} \"{store}\" {subdomain}.{domain}.cert");
file = Path.Combine(sourceDirectory, $"{subdomain}.{domain}.cert");
File.WriteAllText(file, $"{beginCertificate}{segments[0]}{endCertificate}{Environment.NewLine}");

View File

@ -28,7 +28,7 @@ csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = none
csharp_new_line_between_query_expression_clauses = true
csharp_prefer_braces = false
csharp_prefer_braces = true
csharp_prefer_qualified_reference = true:error
csharp_prefer_simple_default_expression = true:warning
csharp_prefer_simple_using_statement = true:warning

View File

@ -45,8 +45,9 @@ internal static partial class Helper20241115 {
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0]);
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (files.Length != 1)
if (files.Length != 1) {
logger.LogError("No files found in {sourceDirectory} with search pattern {searchPattern}", sourceDirectory, searchPattern);
}
logger.LogError("GetComplete is not available in BioRad {args[1]}", args[1]);
}

View File

@ -10,8 +10,9 @@ internal static partial class Helper20241204 {
string searchPattern = args[2];
string sourceDirectory = Path.GetFullPath(args[0]);
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.TopDirectoryOnly);
if (files.Length == 0)
if (files.Length == 0) {
logger.LogError("No files found in {sourceDirectory} with search pattern {searchPattern}", sourceDirectory, searchPattern);
}
foreach (string file in files) {
text = File.ReadAllText(file);
File.WriteAllText(file, text, Encoding.UTF8);

View File

@ -13,19 +13,22 @@ internal static partial class Helper20241212 {
string[] searchPatterns = args[3].Split('~');
string sourceDirectory = Path.GetFullPath(args[0]);
string[] files = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
if (files.Length == 0)
if (files.Length == 0) {
logger.LogError("No files found in {sourceDirectory} with search pattern {searchPattern}", sourceDirectory, searchPattern);
}
foreach (string file in files) {
fileName = Path.GetFileName(file);
directoryName = Path.GetDirectoryName(file) ?? throw new Exception();
newFileName = fileName;
foreach (string pattern in searchPatterns)
foreach (string pattern in searchPatterns) {
newFileName = newFileName.Replace(pattern, "");
}
newFile = Path.Combine(directoryName, newFileName);
if (File.Exists(newFile))
if (File.Exists(newFile)) {
logger.LogError("File {newFile} already exists", newFile);
else
} else {
File.Move(file, newFile);
}
}
}

View File

@ -72,27 +72,31 @@ internal static partial class Helper20241217 {
string sourceDirectory = Path.GetFullPath(args[0]);
string? snap2HyperTextMarkupLanguage = args.Count < 6 ? null : Path.GetFullPath(args[5]);
logger.LogInformation("Searching <{sourceDirectory}> with search pattern {searchPattern}", args[0], searchPattern);
if (Debugger.IsAttached)
if (Debugger.IsAttached) {
Verify(searchPattern, ignoreFileNames);
}
for (int i = 1; i < 3; i++) {
if (i == 1) {
searchPatternFiles = Directory.EnumerateFiles(sourceDirectory, searchPattern, new EnumerationOptions { IgnoreInaccessible = true, RecurseSubdirectories = true });
} else if (i == 2) {
searchPatternFiles = Directory.GetFiles(sourceDirectory, searchPattern, SearchOption.AllDirectories);
} else
} else {
throw new NotImplementedException();
}
records = GetRecords(sourceDirectory, destination, searchPatternFiles);
foreach (Record record in records) {
if (record.Job is null || string.IsNullOrEmpty(record.Job.Extension))
if (record.Job is null || string.IsNullOrEmpty(record.Job.Extension)) {
continue;
}
logger.LogInformation("Searching <{directory}>", record.SourceDirectory);
files = GetFiles(searchPattern, ignoreFileNames, record);
jobNew = GetJob(searchPattern, ignoreFileNames, record, files);
json = JsonSerializer.Serialize(jobNew, JobSourceGenerationContext.Default.Job);
areTheyTheSame = GetAreTheyTheSame(logger, searchPattern, ignoreFileNames, record, jobNew);
if (snap2HyperTextMarkupLanguage is not null && System.IO.File.Exists(snap2HyperTextMarkupLanguage)) {
if (!areTheyTheSame || (areTheyTheSame && !System.IO.File.Exists(record.Snap2HyperTextMarkupLanguage)))
if (!areTheyTheSame || (areTheyTheSame && !System.IO.File.Exists(record.Snap2HyperTextMarkupLanguage))) {
WriteSnap2HyperTextMarkupLanguage(logger, snap2HyperTextMarkupLanguage, record);
}
}
if (areTheyTheSame) {
WriteAllText(record.Path, json);
@ -115,8 +119,9 @@ internal static partial class Helper20241217 {
new(null, new ServerMessageBlock("\\\\mesfs.infineon.com\\EC_APC\\DEV", true))
];
string directory = Path.Combine(Environment.CurrentDirectory, ".vscode", "helper");
if (!Directory.Exists(directory))
if (!Directory.Exists(directory)) {
_ = Directory.CreateDirectory(directory);
}
string path = Path.Combine(directory, "verify.json");
ReadOnlyCollection<File> files = GetFiles(directory, searchPattern, ignoreFileNames);
ReadOnlyCollection<File> collection = GetFilteredFiles(searchPattern, ignoreFileNames, files);
@ -137,15 +142,19 @@ internal static partial class Helper20241217 {
List<File> results = [];
string fileName;
foreach (File file in files) {
if (file.RelativePath == searchPattern)
if (file.RelativePath == searchPattern) {
continue;
}
fileName = Path.GetFileName(file.RelativePath);
if (fileName == searchPattern)
if (fileName == searchPattern) {
throw new Exception("Found nested file!");
if (ignoreFileNames.Any(l => l == fileName))
}
if (ignoreFileNames.Any(l => l == fileName)) {
continue;
if (file.Length == 0)
}
if (file.Length == 0) {
continue;
}
results.Add(file);
}
return results.AsReadOnly();
@ -170,10 +179,11 @@ internal static partial class Helper20241217 {
}
json = System.IO.File.ReadAllText(file);
snap2HyperTextMarkupLanguage = Path.Combine(sourceDirectory, ".html");
if (string.IsNullOrEmpty(json) || json is "{}" or "[]")
if (string.IsNullOrEmpty(json) || json is "{}" or "[]") {
job = null;
else
} else {
job = JsonSerializer.Deserialize(json, JobSourceGenerationContext.Default.Job);
}
job ??= new(AlternatePath: null,
Directory: directory,
Extension: ".iso",
@ -183,8 +193,9 @@ internal static partial class Helper20241217 {
Keep: 3,
Targets: []);
destinationDirectory = $"{destination}{sourceDirectory[2..]}";
if (!Directory.Exists(destinationDirectory))
if (!Directory.Exists(destinationDirectory)) {
_ = Directory.CreateDirectory(destinationDirectory);
}
record = new(DestinationDirectory: destinationDirectory,
DirectoryName: directoryName,
Job: job,
@ -195,21 +206,6 @@ internal static partial class Helper20241217 {
}
}
private static void WriteSnap2HyperTextMarkupLanguage(ILogger<Worker> logger, string snap2HyperTextMarkupLanguage, Record record) {
string title = Path.GetFileName(record.SourceDirectory);
ProcessStartInfo processStartInfo = new() {
Arguments = $"-path:\"{record.SourceDirectory}\" -outfile:\"{record.Snap2HyperTextMarkupLanguage}\" -title:\"{title}\" -hidden -silent",
FileName = snap2HyperTextMarkupLanguage,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
WorkingDirectory = record.SourceDirectory
};
Process? process = Process.Start(processStartInfo) ?? throw new Exception("Process should not be null.");
process.WaitForExit();
logger.LogInformation($"Snap2HyperTextMarkupLanguage: {process.StandardOutput.ReadToEnd()}{Environment.NewLine}{process.StandardError.ReadToEnd()}{Environment.NewLine}{process.ExitCode}");
}
private static ReadOnlyCollection<File> GetFiles(string directory, string searchPattern, string[] ignoreFileNames) {
List<File> results = [];
File file;
@ -217,15 +213,19 @@ internal static partial class Helper20241217 {
string[] files = Directory.GetFiles(directory, "*", SearchOption.AllDirectories);
FileInfo[] fileInfoCollection = files.Select(l => new FileInfo(l)).ToArray();
foreach (FileInfo fileInfo in fileInfoCollection) {
if (fileInfo.Name == searchPattern)
if (fileInfo.Name == searchPattern) {
continue;
if (ignoreFileNames.Any(l => l == fileInfo.Name))
}
if (ignoreFileNames.Any(l => l == fileInfo.Name)) {
continue;
if (!string.IsNullOrEmpty(fileInfo.LinkTarget))
}
if (!string.IsNullOrEmpty(fileInfo.LinkTarget)) {
continue;
}
relativePath = Path.GetRelativePath(directory, fileInfo.FullName).Replace(';', '_');
if (relativePath.StartsWith(".."))
if (relativePath.StartsWith("..")) {
relativePath = relativePath[3..];
}
file = new(LastWriteTicks: fileInfo.LastWriteTime.Ticks, Length: fileInfo.Length, RelativePath: relativePath);
results.Add(file);
}
@ -264,9 +264,9 @@ internal static partial class Helper20241217 {
} else {
string jsonNew = JsonSerializer.Serialize(jobNew.Files, FilesSourceGenerationContext.Default.FileArray);
string jsonOld = JsonSerializer.Serialize(collection.ToArray(), FilesSourceGenerationContext.Default.FileArray);
if (jsonNew == jsonOld)
if (jsonNew == jsonOld) {
result = true;
else {
} else {
result = false;
if (Debugger.IsAttached) {
WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", "old.json"), jsonOld);
@ -279,25 +279,43 @@ internal static partial class Helper20241217 {
return result;
}
private static void WriteSnap2HyperTextMarkupLanguage(ILogger<Worker> logger, string snap2HyperTextMarkupLanguage, Record record) {
string title = Path.GetFileName(record.SourceDirectory);
ProcessStartInfo processStartInfo = new() {
Arguments = $"-path:\"{record.SourceDirectory}\" -outfile:\"{record.Snap2HyperTextMarkupLanguage}\" -title:\"{title}\" -hidden -silent",
FileName = snap2HyperTextMarkupLanguage,
RedirectStandardError = true,
RedirectStandardInput = true,
RedirectStandardOutput = true,
WorkingDirectory = record.SourceDirectory
};
Process? process = Process.Start(processStartInfo) ?? throw new Exception("Process should not be null.");
process.WaitForExit();
logger.LogInformation($"Snap2HyperTextMarkupLanguage: {process.StandardOutput.ReadToEnd()}{Environment.NewLine}{process.StandardError.ReadToEnd()}{Environment.NewLine}{process.ExitCode}");
}
private static void WriteAllText(string path, string text) {
string check = !System.IO.File.Exists(path) ? string.Empty : System.IO.File.ReadAllText(path);
if (check != text)
if (check != text) {
System.IO.File.WriteAllText(path, text);
}
}
private static void WritePassedExtension(Record record, ReadOnlyCollection<File> files, string directoryName, string path) {
if (record.Job.Extension.Equals(".iso", StringComparison.OrdinalIgnoreCase))
if (record.Job.Extension.Equals(".iso", StringComparison.OrdinalIgnoreCase)) {
WriteISO(record, files, path, directoryName);
else if (record.Job.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase))
} else if (record.Job.Extension.Equals(".zip", StringComparison.OrdinalIgnoreCase)) {
WriteZIP(record, files, path);
else
} else {
throw new NotImplementedException();
}
}
private static void WriteISO(Record record, ReadOnlyCollection<File> files, string path, string directoryName) {
CDBuilder builder = new() { UseJoliet = true, VolumeIdentifier = directoryName.Length < 25 ? directoryName : directoryName[..25] };
foreach (File file in files)
foreach (File file in files) {
_ = builder.AddFile(file.RelativePath, Path.Combine(record.SourceDirectory, file.RelativePath));
}
builder.Build(path);
}
@ -307,21 +325,24 @@ internal static partial class Helper20241217 {
List<string> directoryEntries = [];
foreach (File file in files) {
directoryEntry = Path.GetDirectoryName(file.RelativePath) ?? throw new Exception();
if (!directoryEntries.Contains(directoryEntry))
if (!directoryEntries.Contains(directoryEntry)) {
continue;
}
directoryEntries.Add(directoryEntry);
_ = zip.CreateEntry(file.RelativePath);
}
foreach (File file in files)
foreach (File file in files) {
_ = zip.CreateEntryFromFile(Path.Combine(record.SourceDirectory, file.RelativePath), file.RelativePath);
}
}
private static void WriteAllText(Record record, string text, string path) {
WriteAllText(record.Path, text);
System.IO.File.Copy(record.Path, $"{path}.json");
string checkFile = Path.Combine(record.SourceDirectory, ".html");
if (System.IO.File.Exists(checkFile))
if (System.IO.File.Exists(checkFile)) {
System.IO.File.Copy(checkFile, $"{path}.html");
}
}
}

View File

@ -15,134 +15,6 @@ internal static partial class Helper20241224 {
private record Record(Uri URI, string Path, DateTime LastModified);
private static ReadOnlyCollection<NginxFileSystem>? GetRecursiveCollection(string host, string page) {
List<NginxFileSystem>? results;
Uri uri = new($"https://{host}/{page}");
string format = NginxFileSystem.GetFormat();
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local;
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(uri);
taskHttpResponseMessage.Wait();
if (!taskHttpResponseMessage.Result.IsSuccessStatusCode)
results = null;
else {
Task<string> taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync();
taskString.Wait();
NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray);
if (nginxFileSystems is null)
results = null;
else {
results = [];
NginxFileSystem nginxFileSystem;
ReadOnlyCollection<NginxFileSystem>? directory;
for (int i = 0; i < nginxFileSystems.Length; i++) {
nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]);
if (nginxFileSystem.Type == "file")
results.Add(nginxFileSystem);
else {
directory = GetRecursiveCollection(host, $"{page}/{nginxFileSystem.Name}");
if (directory is null)
continue;
results.AddRange(directory);
}
}
}
}
return results?.AsReadOnly();
}
private static ReadOnlyCollection<NginxFileSystem>? GetCollection(string format, TimeZoneInfo timeZoneInfo, Uri uri) {
List<NginxFileSystem>? results;
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(uri);
taskHttpResponseMessage.Wait();
if (!taskHttpResponseMessage.Result.IsSuccessStatusCode)
results = null;
else {
Task<string> 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<string> 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 || fileInfo.Length != nginxFileSystem.Length.Value)
result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value);
else {
double totalSeconds = new TimeSpan(fileInfo.LastWriteTime.Ticks - nginxFileSystem.LastModified.Value.Ticks).TotalSeconds;
if (totalSeconds is < 2 and > -2)
result = null;
else
result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value);
}
}
return result;
}
private static ReadOnlyCollection<Record> CompareDirectory(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection<string> directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) {
ReadOnlyCollection<Record> results;
List<string> collection = directoryNames.ToList();
collection.Add(nginxFileSystem.Name);
results = GetRecord(format, timeZoneInfo, host, collection.AsReadOnly(), compareDirectory);
return results;
}
private static ReadOnlyCollection<Record> GetRecord(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection<string> directoryNames, string compareDirectory) {
List<Record> results = [];
Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}");
ReadOnlyCollection<NginxFileSystem>? nginxFileSystems = GetCollection(format, timeZoneInfo, uri);
if (nginxFileSystems is not null) {
NginxFileSystem nginxFileSystem;
ReadOnlyCollection<Record> 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 void Download(Record record) {
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(record.URI);
taskHttpResponseMessage.Wait();
if (taskHttpResponseMessage.Result.IsSuccessStatusCode) {
Task<string> taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync();
taskString.Wait();
File.WriteAllText(record.Path, taskString.Result);
File.SetLastWriteTime(record.Path, record.LastModified);
}
}
internal static void Compare(ILogger<Worker> logger, List<string> args) {
string host = args[2];
string rootDirectoryName = args[3];
@ -166,9 +38,143 @@ internal static partial class Helper20241224 {
if (Debugger.IsAttached) {
ReadOnlyCollection<NginxFileSystem>? recursiveCollection = GetRecursiveCollection(host, rootDirectoryName);
string? json = recursiveCollection is null ? null : JsonSerializer.Serialize(recursiveCollection.ToArray(), NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray);
if (!string.IsNullOrEmpty(json))
if (!string.IsNullOrEmpty(json)) {
File.WriteAllText(Path.Combine(Environment.CurrentDirectory, ".vscode", "helper", ".json"), json);
}
}
}
private static ReadOnlyCollection<Record> GetRecord(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection<string> directoryNames, string compareDirectory) {
List<Record> results = [];
Uri uri = new($"https://{host}/{string.Join('/', directoryNames)}");
ReadOnlyCollection<NginxFileSystem>? nginxFileSystems = GetCollection(format, timeZoneInfo, uri);
if (nginxFileSystems is not null) {
NginxFileSystem nginxFileSystem;
ReadOnlyCollection<Record> 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<NginxFileSystem>? GetCollection(string format, TimeZoneInfo timeZoneInfo, Uri uri) {
List<NginxFileSystem>? results;
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(uri);
taskHttpResponseMessage.Wait();
if (!taskHttpResponseMessage.Result.IsSuccessStatusCode) {
results = null;
} else {
Task<string> 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<string> 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 || fileInfo.Length != nginxFileSystem.Length.Value) {
result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value);
} else {
double totalSeconds = new TimeSpan(fileInfo.LastWriteTime.Ticks - nginxFileSystem.LastModified.Value.Ticks).TotalSeconds;
if (totalSeconds is < 2 and > -2) {
result = null;
} else {
result = new(uri, fileInfo.FullName, nginxFileSystem.LastModified.Value);
}
}
}
return result;
}
private static ReadOnlyCollection<Record> CompareDirectory(string format, TimeZoneInfo timeZoneInfo, string host, ReadOnlyCollection<string> directoryNames, string compareDirectory, NginxFileSystem nginxFileSystem) {
ReadOnlyCollection<Record> results;
List<string> collection = directoryNames.ToList();
collection.Add(nginxFileSystem.Name);
results = GetRecord(format, timeZoneInfo, host, collection.AsReadOnly(), compareDirectory);
return results;
}
private static void Download(Record record) {
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(record.URI);
taskHttpResponseMessage.Wait();
if (taskHttpResponseMessage.Result.IsSuccessStatusCode) {
Task<string> taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync();
taskString.Wait();
File.WriteAllText(record.Path, taskString.Result);
File.SetLastWriteTime(record.Path, record.LastModified);
}
}
private static ReadOnlyCollection<NginxFileSystem>? GetRecursiveCollection(string host, string page) {
List<NginxFileSystem>? results;
Uri uri = new($"https://{host}/{page}");
string format = NginxFileSystem.GetFormat();
TimeZoneInfo timeZoneInfo = TimeZoneInfo.Local;
Task<HttpResponseMessage> taskHttpResponseMessage = _HttpClient.GetAsync(uri);
taskHttpResponseMessage.Wait();
if (!taskHttpResponseMessage.Result.IsSuccessStatusCode) {
results = null;
} else {
Task<string> taskString = taskHttpResponseMessage.Result.Content.ReadAsStringAsync();
taskString.Wait();
NginxFileSystem[]? nginxFileSystems = JsonSerializer.Deserialize(taskString.Result, NginxFileSystemCollectionSourceGenerationContext.Default.NginxFileSystemArray);
if (nginxFileSystems is null) {
results = null;
} else {
results = [];
NginxFileSystem nginxFileSystem;
ReadOnlyCollection<NginxFileSystem>? directory;
for (int i = 0; i < nginxFileSystems.Length; i++) {
nginxFileSystem = NginxFileSystem.Get(format, timeZoneInfo, uri, nginxFileSystems[i]);
if (nginxFileSystem.Type == "file") {
results.Add(nginxFileSystem);
} else {
directory = GetRecursiveCollection(host, $"{page}/{nginxFileSystem.Name}");
if (directory is null) {
continue;
}
results.AddRange(directory);
}
}
}
}
return results?.AsReadOnly();
}
}