Skip to content

Commit 5d08378

Browse files
authored
Merge pull request #485 from LogExperts/480-importing-settings-doesnt-work
Pull Request Overview This PR implements settings loss prevention features for LogExpert, including import validation, atomic file writes with backup, deserialization recovery, and comprehensive unit tests. The changes add robustness to configuration management by detecting empty/corrupt settings, implementing backup recovery mechanisms, and providing better error handling. Key Changes Import validation with user confirmation for empty/default settings Atomic file write operations with automatic backup creation and recovery Comprehensive unit test suite covering import validation, atomic writes, and deserialization recovery Enum renaming from DragOrientationsEnum to DragOrientations for consistency XML persistence fallback support for legacy project files
2 parents d1608e4 + 7d09850 commit 5d08378

26 files changed

+2360
-254
lines changed

README.md

Lines changed: 35 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# LogExpert [![.NET](https://github.com/LogExperts/LogExpert/actions/workflows/build_dotnet.yml/badge.svg)](https://github.com/LogExperts/LogExpert/actions/workflows/build_dotnet.yml)
22

3-
This is a clone from (no longer exists) https://logexpert.codeplex.com/
3+
This is a clone from (no longer exists) <https://logexpert.codeplex.com/>
4+
5+
## Overview
46

5-
# Overview
67
LogExpert is a Windows tail program (a GUI replacement for the Unix tail command).
78

89
Summary of (most) features:
@@ -23,51 +24,61 @@ Summary of (most) features:
2324
* Serilog.Formatting.Compact format support (Experimental)
2425
* Portable (all options / settings saved in application startup directory)
2526

26-
# Download
27+
## Download
28+
2729
Follow the [Link](https://github.com/LogExperts/LogExpert/releases/latest) and download the latest package. Just extract it where you want and execute the application or download the Setup and install it
2830

2931
Or Install via chocolatey
3032

3133
```choco install logexpert```
3234

3335
Requirements
34-
- https://dotnet.microsoft.com/en-us/download/dotnet/8.0
35-
- .NET 8 (https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.13-windows-x64-installer or https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.13-windows-x86-installer)
36+
37+
* <https://dotnet.microsoft.com/en-us/download/dotnet/8.0>
38+
* .NET 8 (<https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.13-windows-x64-installer> or <https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/runtime-8.0.13-windows-x86-installer>)
3639

3740
## CI
41+
3842
This is a continous integration build. So always the latest and greates changes. It should be stable but no promises. Can be viewed as Beta.
3943

4044
[CI Download](https://ci.appveyor.com/project/Zarunbal/logexpert)
4145

42-
# How to Build
46+
## How to Build
4347

44-
- Clone / Fork / Download the source code
45-
- Open the Solution (src/LogExpert.sln) with Visual Studio 2017 (e.g. Community Edition)
46-
- Restore Nuget Packages on Solution
47-
- Build
48-
- The output is under bin/(Debug/Release)/
48+
* Clone / Fork / Download the source code
49+
* Open the Solution (src/LogExpert.sln) with Visual Studio 2017 (e.g. Community Edition)
50+
* Restore Nuget Packages on Solution
51+
* Build
52+
* The output is under bin/(Debug/Release)/
4953

5054
Nuke.build Requirements
51-
- Chocolatey must be installed
52-
- Optional for Setup Inno Script 5 or 6
5355

54-
# Pull Request
55-
- Use Development branch as target
56+
* Chocolatey must be installed
57+
* Optional for Setup Inno Script 5 or 6
58+
59+
## Pull Request
60+
61+
* Use Development branch as target
62+
63+
## FAQ / HELP / Informations / Examples
5664

57-
# FAQ / HELP / Informations / Examples
5865
Please checkout the wiki for FAQ / HELP / Informations / Examples
5966

60-
# High DPI
61-
- dont use AutoScaleMode for single GUI controls like Buttons etc.
62-
- dont use AutoScaleDimensions for single GUI controls like Buttons etc.
67+
## High DPI
68+
69+
* dont use AutoScaleMode for single GUI controls like Buttons etc.
70+
71+
* dont use AutoScaleDimensions for single GUI controls like Buttons etc.
72+
73+
<https://github.com/LogExperts/LogExpert/wiki>
74+
75+
## Discord Server
6376

64-
https://github.com/LogExperts/LogExpert/wiki
77+
<https://discord.gg/SjxkuckRe9>
6578

66-
# Discord Server
67-
https://discord.gg/SjxkuckRe9
79+
### Credits
6880

69-
## Credits
70-
### Contributors
81+
#### Contributors
7182

7283
This project exists thanks to all the people who contribute.
7384
<a href="https://github.com/LogExperts/LogExpert/graphs/contributors">

src/.editorconfig

Lines changed: 113 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -34,23 +34,23 @@ dotnet_sort_system_directives_first = true
3434
file_header_template = unset
3535

3636
# this. and Me. preferences
37-
dotnet_style_qualification_for_event = false
38-
dotnet_style_qualification_for_field = false
39-
dotnet_style_qualification_for_method = false
40-
dotnet_style_qualification_for_property = false
37+
dotnet_style_qualification_for_event = false:suggestion
38+
dotnet_style_qualification_for_field = false:suggestion
39+
dotnet_style_qualification_for_method = false:suggestion
40+
dotnet_style_qualification_for_property = false:suggestion
4141

4242
# Language keywords vs BCL types preferences
43-
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
44-
dotnet_style_predefined_type_for_member_access = true:warning
43+
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
44+
dotnet_style_predefined_type_for_member_access = true:suggestion
4545

4646
# Parentheses preferences
47-
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:warning
47+
dotnet_style_parentheses_in_arithmetic_binary_operators = never_if_unnecessary:none
4848
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:warning
4949
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:warning
50-
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:warning
50+
dotnet_style_parentheses_in_relational_binary_operators = never_if_unnecessary:none
5151

5252
# Modifier preferences
53-
dotnet_style_require_accessibility_modifiers = for_non_interface_members
53+
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
5454

5555
# Expression-level preferences
5656
dotnet_prefer_system_hash_code = true
@@ -89,22 +89,22 @@ dotnet_style_allow_statement_immediately_after_block_experimental = false:warnin
8989
#### C# Coding Conventions ####
9090

9191
# var preferences
92-
csharp_style_var_elsewhere = true:suggestion
93-
csharp_style_var_for_built_in_types = true:warning
94-
csharp_style_var_when_type_is_apparent = true:warning
92+
csharp_style_var_elsewhere = false:suggestion
93+
csharp_style_var_for_built_in_types = false:suggestion
94+
csharp_style_var_when_type_is_apparent = true:suggestion
9595

9696
# Expression-bodied members
9797
csharp_style_expression_bodied_accessors = true:suggestion
98-
csharp_style_expression_bodied_constructors = false:warning
98+
csharp_style_expression_bodied_constructors = false:suggestion
9999
csharp_style_expression_bodied_indexers = true:suggestion
100100
csharp_style_expression_bodied_lambdas = true:suggestion
101101
csharp_style_expression_bodied_local_functions = true:suggestion
102-
csharp_style_expression_bodied_methods = true:suggestion
102+
csharp_style_expression_bodied_methods = false:suggestion
103103
csharp_style_expression_bodied_operators = true:suggestion
104104
csharp_style_expression_bodied_properties = true:suggestion
105105

106106
# Pattern matching preferences
107-
csharp_style_pattern_matching_over_as_with_null_check = true:warning
107+
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
108108
csharp_style_pattern_matching_over_is_with_cast_check = true:warning
109109
csharp_style_prefer_extended_property_pattern = true:warning
110110
csharp_style_prefer_not_pattern = true:warning
@@ -120,7 +120,7 @@ csharp_prefer_static_anonymous_function = true
120120
csharp_prefer_static_local_function = true:warning
121121
csharp_style_prefer_readonly_struct = true
122122
csharp_style_prefer_readonly_struct_member = true
123-
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async
123+
csharp_preferred_modifier_order = public,private,protected,internal,file,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,required,volatile,async:suggestion
124124

125125
# Code-block preferences
126126
csharp_prefer_braces = true:warning
@@ -132,11 +132,11 @@ csharp_style_prefer_primary_constructors = true:suggestion
132132
csharp_style_prefer_top_level_statements = true:silent
133133

134134
# Expression-level preferences
135-
csharp_prefer_simple_default_expression = true:warning
135+
csharp_prefer_simple_default_expression = false:suggestion
136136
csharp_style_deconstructed_variable_declaration = true:warning
137137
csharp_style_implicit_object_creation_when_type_is_apparent = true:warning
138-
csharp_style_inlined_variable_declaration = true:warning
139-
csharp_style_prefer_local_over_anonymous_function = true:warning
138+
csharp_style_inlined_variable_declaration = true:suggestion
139+
csharp_style_prefer_local_over_anonymous_function = true:suggestion
140140
csharp_style_prefer_index_operator = true:warning
141141
csharp_style_prefer_null_check_over_type_check = true:warning
142142
csharp_style_prefer_range_operator = true:warning
@@ -163,7 +163,7 @@ csharp_new_line_before_catch = true
163163
csharp_new_line_before_else = true
164164
csharp_new_line_before_finally = true
165165
csharp_new_line_before_members_in_anonymous_types = true
166-
csharp_new_line_before_members_in_object_initializers = true
166+
csharp_new_line_before_members_in_object_initializers = false
167167
csharp_new_line_before_open_brace = all
168168
csharp_new_line_between_query_expression_clauses = true
169169

@@ -201,11 +201,61 @@ csharp_space_between_square_brackets = false
201201

202202
# Wrapping preferences
203203
csharp_preserve_single_line_blocks = true
204-
csharp_preserve_single_line_statements = false
204+
csharp_preserve_single_line_statements = true
205205

206206
#### Naming styles ####
207207

208208
# Naming rules
209+
dotnet_naming_rule.constants_rule.import_to_resharper = as_predefined
210+
dotnet_naming_rule.constants_rule.severity = warning
211+
dotnet_naming_rule.constants_rule.style = all_upper_style
212+
dotnet_naming_rule.constants_rule.symbols = constants_symbols
213+
214+
dotnet_naming_rule.local_functions_rule.import_to_resharper = as_predefined
215+
dotnet_naming_rule.local_functions_rule.severity = warning
216+
dotnet_naming_rule.local_functions_rule.style = lower_camel_case_style
217+
dotnet_naming_rule.local_functions_rule.symbols = local_functions_symbols
218+
219+
dotnet_naming_rule.private_constants_rule.import_to_resharper = as_predefined
220+
dotnet_naming_rule.private_constants_rule.severity = warning
221+
dotnet_naming_rule.private_constants_rule.style = all_upper_style
222+
dotnet_naming_rule.private_constants_rule.symbols = private_constants_symbols
223+
224+
dotnet_naming_rule.private_static_readonly_rule.import_to_resharper = as_predefined
225+
dotnet_naming_rule.private_static_readonly_rule.severity = warning
226+
dotnet_naming_rule.private_static_readonly_rule.style = lower_camel_case_style_1
227+
dotnet_naming_rule.private_static_readonly_rule.symbols = private_static_readonly_symbols
228+
229+
dotnet_naming_rule.type_parameters_rule.import_to_resharper = as_predefined
230+
dotnet_naming_rule.type_parameters_rule.severity = warning
231+
dotnet_naming_rule.type_parameters_rule.style = upper_camel_case_style
232+
dotnet_naming_rule.type_parameters_rule.symbols = type_parameters_symbols
233+
234+
dotnet_naming_style.all_upper_style.capitalization = all_upper
235+
dotnet_naming_style.all_upper_style.word_separator = _
236+
237+
dotnet_naming_style.lower_camel_case_style.capitalization = camel_case
238+
dotnet_naming_style.lower_camel_case_style_1.capitalization = camel_case
239+
dotnet_naming_style.lower_camel_case_style_1.required_prefix = _
240+
dotnet_naming_style.upper_camel_case_style.capitalization = pascal_case
241+
242+
dotnet_naming_symbols.constants_symbols.applicable_accessibilities = public,internal,protected,protected_internal,private_protected
243+
dotnet_naming_symbols.constants_symbols.applicable_kinds = field
244+
dotnet_naming_symbols.constants_symbols.required_modifiers = const
245+
246+
dotnet_naming_symbols.local_functions_symbols.applicable_accessibilities = *
247+
dotnet_naming_symbols.local_functions_symbols.applicable_kinds = local_function
248+
249+
dotnet_naming_symbols.private_constants_symbols.applicable_accessibilities = private
250+
dotnet_naming_symbols.private_constants_symbols.applicable_kinds = field
251+
dotnet_naming_symbols.private_constants_symbols.required_modifiers = const
252+
253+
dotnet_naming_symbols.private_static_readonly_symbols.applicable_accessibilities = private
254+
dotnet_naming_symbols.private_static_readonly_symbols.applicable_kinds = field
255+
dotnet_naming_symbols.private_static_readonly_symbols.required_modifiers = static,readonly
256+
257+
dotnet_naming_symbols.type_parameters_symbols.applicable_accessibilities = *
258+
dotnet_naming_symbols.type_parameters_symbols.applicable_kinds = type_parameter
209259

210260
dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
211261
dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
@@ -269,6 +319,47 @@ dotnet_diagnostic.CS0649.severity = none
269319
dotnet_diagnostic.CS0169.severity = none
270320
dotnet_diagnostic.CS1591.severity = none
271321

322+
# ReSharper properties
323+
resharper_braces_for_for = required
324+
resharper_braces_for_foreach = required
325+
resharper_braces_for_ifelse = required
326+
resharper_braces_for_while = required
327+
resharper_csharp_align_multiline_parameter = true
328+
resharper_csharp_insert_final_newline = true
329+
resharper_csharp_max_line_length = 500
330+
resharper_csharp_use_indent_from_vs = false
331+
resharper_csharp_wrap_lines = false
332+
resharper_indent_nested_fixed_stmt = true
333+
resharper_indent_nested_foreach_stmt = true
334+
resharper_indent_nested_for_stmt = true
335+
resharper_indent_nested_lock_stmt = true
336+
resharper_indent_nested_usings_stmt = true
337+
resharper_indent_nested_while_stmt = true
338+
resharper_indent_preprocessor_if = outdent
339+
resharper_keep_existing_declaration_block_arrangement = false
340+
resharper_keep_existing_embedded_block_arrangement = false
341+
resharper_keep_existing_enum_arrangement = false
342+
resharper_place_accessorholder_attribute_on_same_line = false
343+
resharper_show_autodetect_configure_formatting_tip = false
344+
resharper_space_within_single_line_array_initializer_braces = false
345+
resharper_use_heuristics_for_body_style = true
346+
347+
# ReSharper inspection severities
348+
resharper_arrange_constructor_or_destructor_body_highlighting = none
349+
resharper_arrange_method_or_operator_body_highlighting = none
350+
resharper_arrange_redundant_parentheses_highlighting = hint
351+
resharper_arrange_this_qualifier_highlighting = hint
352+
resharper_arrange_type_member_modifiers_highlighting = hint
353+
resharper_arrange_type_modifiers_highlighting = hint
354+
resharper_built_in_type_reference_style_for_member_access_highlighting = hint
355+
resharper_built_in_type_reference_style_highlighting = hint
356+
resharper_redundant_base_qualifier_highlighting = warning
357+
resharper_suggest_var_or_type_built_in_types_highlighting = hint
358+
resharper_suggest_var_or_type_elsewhere_highlighting = hint
359+
resharper_suggest_var_or_type_simple_types_highlighting = hint
360+
resharper_use_object_or_collection_initializer_highlighting = hint
361+
362+
272363
#### Analyzers Rules ####
273364

274365
## Microsoft.CodeAnalysis.CSharp.CodeStyle
@@ -295,7 +386,7 @@ dotnet_diagnostic.IDE0005.severity = none
295386
dotnet_diagnostic.IDE0007.severity = warning
296387

297388
# IDE0008: Use explicit type instead of 'var'
298-
dotnet_diagnostic.IDE0008.severity = warning
389+
dotnet_diagnostic.IDE0008.severity = none
299390

300391
# IDE0009: Add this or Me qualification
301392
dotnet_diagnostic.IDE0009.severity = warning

src/LogExpert.Core/Classes/Persister/JsonColumnizerPropertyAttribute.cs renamed to src/LogExpert.Core/Classes/Attributes/JsonColumnizerPropertyAttribute.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
1-
namespace LogExpert.Core.Classes.Persister;
1+
namespace LogExpert.Core.Classes.Attributes;
22

33
/// <summary>
44
/// Marks a property for inclusion in columnizer JSON serialization.
55
/// </summary>
66
[AttributeUsage(AttributeTargets.Property)]
7-
public class JsonColumnizerPropertyAttribute : Attribute
7+
public sealed class JsonColumnizerPropertyAttribute : Attribute
88
{
99
}
1010

src/LogExpert.Core/Classes/Filter/FilterParams.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
using System.Drawing;
44
using System.Text.RegularExpressions;
55

6-
using LogExpert.Core.Classes.Persister;
6+
using LogExpert.Core.Classes.JsonConverters;
77

88
using Newtonsoft.Json;
99

src/LogExpert.Core/Classes/Persister/ColumnizerJsonConverter.cs renamed to src/LogExpert.Core/Classes/JsonConverters/ColumnizerJsonConverter.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
11
using System.Reflection;
22

3+
using LogExpert.Core.Classes.Attributes;
4+
35
using Newtonsoft.Json;
46
using Newtonsoft.Json.Linq;
57

6-
namespace LogExpert.Core.Classes.Persister;
8+
namespace LogExpert.Core.Classes.JsonConverters;
79

810
/// <summary>
911
/// Custom JsonConverter for ILogLineColumnizer implementations.

src/LogExpert.Core/Classes/Persister/EncodingJsonConverter.cs renamed to src/LogExpert.Core/Classes/JsonConverters/EncodingJsonConverter.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
using Newtonsoft.Json;
44

5-
namespace LogExpert.Core.Classes.Persister;
5+
namespace LogExpert.Core.Classes.JsonConverters;
66

77
/// <summary>
88
/// Custom JsonConverter for Encoding objects.
@@ -15,9 +15,16 @@ public override bool CanConvert (Type objectType)
1515
return typeof(Encoding).IsAssignableFrom(objectType);
1616
}
1717

18+
/// <summary>
19+
/// Serializes the Encoding object to its name.
20+
/// </summary>
21+
/// <param name="writer"></param>
22+
/// <param name="value"></param>
23+
/// <param name="serializer"></param>
1824
public override void WriteJson (JsonWriter writer, object? value, JsonSerializer serializer)
1925
{
2026
ArgumentNullException.ThrowIfNull(writer);
27+
2128
if (value is not Encoding encoding)
2229
{
2330
writer.WriteNull();
@@ -27,9 +34,19 @@ public override void WriteJson (JsonWriter writer, object? value, JsonSerializer
2734
writer.WriteValue(encoding.WebName);
2835
}
2936

37+
/// <summary>
38+
/// Reads a JSON value and converts it to an <see cref="Encoding"/> object.
39+
/// </summary>
40+
/// <param name="reader">The <see cref="JsonReader"/> to read from. Cannot be <see langword="null"/>.</param>
41+
/// <param name="objectType">The type of the object to deserialize. This parameter is not used in this method.</param>
42+
/// <param name="existingValue">The existing value of the object being deserialized. This parameter is not used in this method.</param>
43+
/// <param name="serializer">The calling serializer. This parameter is not used in this method.</param>
44+
/// <returns>An <see cref="Encoding"/> object corresponding to the JSON value. Returns <see cref="Encoding.Default"/> if the
45+
/// JSON value is <see langword="null"/>, empty, or an invalid encoding name.</returns>
3046
public override object? ReadJson (JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
3147
{
3248
ArgumentNullException.ThrowIfNull(reader);
49+
3350
if (reader.TokenType == JsonToken.Null)
3451
{
3552
return null;

0 commit comments

Comments
 (0)