code_style: using avalonia's editorconfig and run dotnet format.

This commit is contained in:
leo 2024-03-31 16:54:29 +08:00
parent 3c38f681bd
commit d89a00e559
233 changed files with 1806 additions and 1254 deletions

View file

@ -1,151 +1,138 @@
# editorconfig.org
# top-most EditorConfig file
root = true root = true
# All files # Default settings:
# A newline ending every file
# Use 4 spaces as indentation
[*] [*]
insert_final_newline = true
indent_style = space indent_style = space
indent_size = 4
# Xml files dotnet_style_operator_placement_when_wrapping = beginning_of_line
[*.xml] tab_width = 4
indent_size = 2 end_of_line = crlf
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_auto_properties = true:silent
dotnet_style_object_initializer = true:suggestion
dotnet_style_prefer_collection_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:silent
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:silent
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
dotnet_style_namespace_match_folder = true:suggestion
dotnet_style_readonly_field = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
dotnet_style_allow_multiple_blank_lines_experimental = true:silent
# C# files # C# files
[*.cs] [*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
tab_width = 4
# New line preferences # New line preferences
end_of_line = crlf
insert_final_newline = false
#### .NET Coding Conventions ####
[*.{cs,vb}]
# Organize usings
dotnet_separate_import_directive_groups = true
dotnet_sort_system_directives_first = true
file_header_template = unset
# Namespaces
dotnet_style_namespace_match_folder = true:suggestion
csharp_style_namespace_declarations = block_scoped:error
# this. and Me. preferences
dotnet_style_qualification_for_event = false:silent
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:silent
dotnet_style_qualification_for_property = false:silent
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:silent
dotnet_style_predefined_type_for_member_access = true:silent
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:silent
dotnet_style_parentheses_in_other_operators = never_if_unnecessary:silent
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:silent
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
# Expression-level preferences
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_object_initializer = true:suggestion
dotnet_style_operator_placement_when_wrapping = beginning_of_line
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
dotnet_style_prefer_simplified_boolean_expressions = true:suggestion
dotnet_style_prefer_simplified_interpolation = true:suggestion
# Field preferences
dotnet_style_readonly_field = true:warning
# Parameter preferences
dotnet_code_quality_unused_parameters = all:suggestion
# Suppression preferences
dotnet_remove_unnecessary_suppression_exclusions = none
#### C# Coding Conventions ####
[*.cs]
# var preferences
csharp_style_var_elsewhere = false:silent
csharp_style_var_for_built_in_types = false:silent
csharp_style_var_when_type_is_apparent = false:silent
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:suggestion
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = false:silent
csharp_style_expression_bodied_operators = false:silent
csharp_style_expression_bodied_properties = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_prefer_not_pattern = true:suggestion
csharp_style_prefer_pattern_matching = true:silent
csharp_style_prefer_switch_expression = true:suggestion
# Null-checking preferences
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
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:silent
# Code-block preferences
csharp_prefer_braces = true:silent
csharp_prefer_simple_using_statement = true:suggestion
# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_throw_expression = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:silent
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all csharp_new_line_before_open_brace = all
csharp_new_line_before_else = true
csharp_new_line_before_catch = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_between_query_expression_clauses = true csharp_new_line_between_query_expression_clauses = true
# trim_trailing_whitespace = true
# Indentation preferences # Indentation preferences
csharp_indent_block_contents = true csharp_indent_block_contents = true
csharp_indent_braces = false csharp_indent_braces = false
csharp_indent_case_contents = true 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_indent_switch_labels = true
csharp_indent_labels = one_less_than_current
# avoid this. unless absolutely necessary
dotnet_style_qualification_for_field = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_event = false:suggestion
# prefer var
csharp_style_var_for_built_in_types = true
csharp_style_var_when_type_is_apparent = true
csharp_style_var_elsewhere = true:suggestion
# use language keywords instead of BCL types
dotnet_style_predefined_type_for_locals_parameters_members = true:suggestion
dotnet_style_predefined_type_for_member_access = true:suggestion
# name all constant fields using PascalCase
dotnet_naming_rule.constant_fields_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols = constant_fields
dotnet_naming_rule.constant_fields_should_be_pascal_case.style = pascal_case_style
dotnet_naming_symbols.constant_fields.applicable_kinds = field
dotnet_naming_symbols.constant_fields.required_modifiers = const
dotnet_naming_style.pascal_case_style.capitalization = pascal_case
# private static fields should have s_ prefix
dotnet_naming_rule.private_static_fields_should_have_prefix.severity = suggestion
dotnet_naming_rule.private_static_fields_should_have_prefix.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_have_prefix.style = private_static_prefix_style
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private
dotnet_naming_style.private_static_prefix_style.required_prefix = s_
dotnet_naming_style.private_static_prefix_style.capitalization = camel_case
# internal and private fields should be _camelCase
dotnet_naming_rule.camel_case_for_private_internal_fields.severity = suggestion
dotnet_naming_rule.camel_case_for_private_internal_fields.symbols = private_internal_fields
dotnet_naming_rule.camel_case_for_private_internal_fields.style = camel_case_underscore_style
dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# use accessibility modifiers
dotnet_style_require_accessibility_modifiers = for_non_interface_members:suggestion
# Code style defaults
dotnet_sort_system_directives_first = true
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = false
# Expression-level preferences
dotnet_style_object_initializer = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_null_propagation = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_methods = false:none
csharp_style_expression_bodied_constructors = false:none
csharp_style_expression_bodied_operators = false:none
csharp_style_expression_bodied_properties = true:none
csharp_style_expression_bodied_indexers = true:none
csharp_style_expression_bodied_accessors = true:none
# Pattern matching
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
# Null checking preferences
csharp_style_throw_expression = true:suggestion
csharp_style_conditional_delegate_call = true:suggestion
# Space preferences # Space preferences
csharp_space_after_cast = false csharp_space_after_cast = false
@ -170,199 +157,138 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false csharp_space_between_square_brackets = false
space_within_single_line_array_initializer_braces = true
#Net Analyzer
dotnet_analyzer_diagnostic.category-Performance.severity = none #error - Uncomment when all violations are fixed.
# CS0649: Field 'field' is never assigned to, and will always have its default value 'value'
dotnet_diagnostic.CS0649.severity = error
# CS1591: Missing XML comment for publicly visible type or member
dotnet_diagnostic.CS1591.severity = suggestion
# CS0162: Remove unreachable code
dotnet_diagnostic.CS0162.severity = error
# CA1018: Mark attributes with AttributeUsageAttribute
dotnet_diagnostic.CA1018.severity = error
# CA1304: Specify CultureInfo
dotnet_diagnostic.CA1304.severity = warning
# CA1802: Use literals where appropriate
dotnet_diagnostic.CA1802.severity = warning
# CA1813: Avoid unsealed attributes
dotnet_diagnostic.CA1813.severity = error
# CA1815: Override equals and operator equals on value types
dotnet_diagnostic.CA1815.severity = warning
# CA1820: Test for empty strings using string length
dotnet_diagnostic.CA1820.severity = warning
# CA1821: Remove empty finalizers
dotnet_diagnostic.CA1821.severity = warning
# CA1822: Mark members as static
dotnet_diagnostic.CA1822.severity = suggestion
# CA1823: Avoid unused private fields
dotnet_diagnostic.CA1823.severity = warning
dotnet_code_quality.CA1822.api_surface = private, internal
# CA1825: Avoid zero-length array allocations
dotnet_diagnostic.CA1825.severity = warning
# CA1826: Use property instead of Linq Enumerable method
dotnet_diagnostic.CA1826.severity = suggestion
# CA1827: Do not use Count/LongCount when Any can be used
dotnet_diagnostic.CA1827.severity = warning
# CA1828: Do not use CountAsync/LongCountAsync when AnyAsync can be used
dotnet_diagnostic.CA1828.severity = warning
# CA1829: Use Length/Count property instead of Enumerable.Count method
dotnet_diagnostic.CA1829.severity = warning
#CA1847: Use string.Contains(char) instead of string.Contains(string) with single characters
dotnet_diagnostic.CA1847.severity = warning
#CA1854: Prefer the IDictionary.TryGetValue(TKey, out TValue) method
dotnet_diagnostic.CA1854.severity = warning
#CA2211:Non-constant fields should not be visible
dotnet_diagnostic.CA2211.severity = error
# Wrapping preferences # Wrapping preferences
csharp_preserve_single_line_blocks = true csharp_wrap_before_ternary_opsigns = false
csharp_preserve_single_line_statements = true
#### Naming styles #### # Avalonia DevAnalyzer preferences
[*.{cs,vb}] dotnet_diagnostic.AVADEV2001.severity = error
# Naming rules # Avalonia PublicAnalyzer preferences
dotnet_diagnostic.AVP1000.severity = error
dotnet_diagnostic.AVP1001.severity = error
dotnet_diagnostic.AVP1002.severity = error
dotnet_diagnostic.AVP1010.severity = error
dotnet_diagnostic.AVP1011.severity = error
dotnet_diagnostic.AVP1012.severity = warning
dotnet_diagnostic.AVP1013.severity = error
dotnet_diagnostic.AVP1020.severity = error
dotnet_diagnostic.AVP1021.severity = error
dotnet_diagnostic.AVP1022.severity = error
dotnet_diagnostic.AVP1030.severity = error
dotnet_diagnostic.AVP1031.severity = error
dotnet_diagnostic.AVP1032.severity = error
dotnet_diagnostic.AVP1040.severity = error
dotnet_diagnostic.AVA2001.severity = error
csharp_using_directive_placement = outside_namespace:silent
csharp_prefer_simple_using_statement = true:suggestion
csharp_prefer_braces = true:silent
csharp_style_namespace_declarations = block_scoped:silent
csharp_style_prefer_method_group_conversion = true:silent
csharp_style_prefer_top_level_statements = true:silent
csharp_style_prefer_primary_constructors = true:suggestion
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_prefer_null_check_over_type_check = true:suggestion
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_prefer_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_implicit_object_creation_when_type_is_apparent = true:suggestion
csharp_style_prefer_tuple_swap = true:suggestion
csharp_style_prefer_utf8_string_literals = true:suggestion
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
csharp_style_prefer_readonly_struct = true:suggestion
csharp_prefer_static_local_function = true:suggestion
csharp_style_prefer_readonly_struct_member = true:suggestion
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.severity = suggestion # Xaml files
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.symbols = types_and_namespaces [*.{xaml,axaml}]
dotnet_naming_rule.types_and_namespaces_should_be_pascalcase.style = pascalcase indent_size = 2
# DuplicateSetterError
avalonia_xaml_diagnostic.AVLN2203.severity = error
# StyleInMergedDictionaries
avalonia_xaml_diagnostic.AVLN2204.severity = error
# RequiredTemplatePartMissing
avalonia_xaml_diagnostic.AVLN2205.severity = error
# OptionalTemplatePartMissing
avalonia_xaml_diagnostic.AVLN2206.severity = info
# TemplatePartWrongType
avalonia_xaml_diagnostic.AVLN2207.severity = error
# Obsolete
avalonia_xaml_diagnostic.AVLN5001.severity = error
dotnet_naming_rule.interfaces_should_be_ipascalcase.severity = suggestion # Xml project files
dotnet_naming_rule.interfaces_should_be_ipascalcase.symbols = interfaces [*.{csproj,vcxproj,vcxproj.filters,proj,nativeproj,locproj}]
dotnet_naming_rule.interfaces_should_be_ipascalcase.style = ipascalcase indent_size = 2
dotnet_naming_rule.type_parameters_should_be_tpascalcase.severity = suggestion # Xml build files
dotnet_naming_rule.type_parameters_should_be_tpascalcase.symbols = type_parameters [*.builds]
dotnet_naming_rule.type_parameters_should_be_tpascalcase.style = tpascalcase indent_size = 2
dotnet_naming_rule.methods_should_be_pascalcase.severity = suggestion # Xml files
dotnet_naming_rule.methods_should_be_pascalcase.symbols = methods [*.{xml,stylecop,resx,ruleset}]
dotnet_naming_rule.methods_should_be_pascalcase.style = pascalcase indent_size = 2
dotnet_naming_rule.properties_should_be_pascalcase.severity = suggestion # Xml config files
dotnet_naming_rule.properties_should_be_pascalcase.symbols = properties [*.{props,targets,config,nuspec}]
dotnet_naming_rule.properties_should_be_pascalcase.style = pascalcase indent_size = 2
dotnet_naming_rule.events_should_be_pascalcase.severity = suggestion [*.json]
dotnet_naming_rule.events_should_be_pascalcase.symbols = events indent_size = 2
dotnet_naming_rule.events_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.local_variables_should_be_camelcase.severity = suggestion
dotnet_naming_rule.local_variables_should_be_camelcase.symbols = local_variables
dotnet_naming_rule.local_variables_should_be_camelcase.style = camelcase
dotnet_naming_rule.local_constants_should_be_camelcase.severity = suggestion
dotnet_naming_rule.local_constants_should_be_camelcase.symbols = local_constants
dotnet_naming_rule.local_constants_should_be_camelcase.style = camelcase
dotnet_naming_rule.parameters_should_be_camelcase.severity = suggestion
dotnet_naming_rule.parameters_should_be_camelcase.symbols = parameters
dotnet_naming_rule.parameters_should_be_camelcase.style = camelcase
dotnet_naming_rule.public_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_fields_should_be_pascalcase.symbols = public_fields
dotnet_naming_rule.public_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_fields_should_be__camelcase.severity = suggestion
dotnet_naming_rule.private_fields_should_be__camelcase.symbols = private_fields
dotnet_naming_rule.private_fields_should_be__camelcase.style = _camelcase
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.severity = suggestion
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.symbols = private_static_fields
dotnet_naming_rule.private_static_fields_should_be_s_camelcase.style = s_camelcase
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.symbols = public_constant_fields
dotnet_naming_rule.public_constant_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.symbols = private_constant_fields
dotnet_naming_rule.private_constant_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.symbols = public_static_readonly_fields
dotnet_naming_rule.public_static_readonly_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.symbols = private_static_readonly_fields
dotnet_naming_rule.private_static_readonly_fields_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.enums_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.enums_should_be_pascalcase.symbols = enums
dotnet_naming_rule.enums_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.local_functions_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.local_functions_should_be_pascalcase.symbols = local_functions
dotnet_naming_rule.local_functions_should_be_pascalcase.style = pascalcase
dotnet_naming_rule.non_field_members_should_be_pascalcase.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascalcase.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascalcase.style = pascalcase
# Symbol specifications
dotnet_naming_symbols.interfaces.applicable_kinds = interface
dotnet_naming_symbols.interfaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.interfaces.required_modifiers =
dotnet_naming_symbols.enums.applicable_kinds = enum
dotnet_naming_symbols.enums.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.enums.required_modifiers =
dotnet_naming_symbols.events.applicable_kinds = event
dotnet_naming_symbols.events.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.events.required_modifiers =
dotnet_naming_symbols.methods.applicable_kinds = method
dotnet_naming_symbols.methods.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.methods.required_modifiers =
dotnet_naming_symbols.properties.applicable_kinds = property
dotnet_naming_symbols.properties.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.properties.required_modifiers =
dotnet_naming_symbols.public_fields.applicable_kinds = field
dotnet_naming_symbols.public_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_fields.required_modifiers =
dotnet_naming_symbols.private_fields.applicable_kinds = field
dotnet_naming_symbols.private_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_fields.required_modifiers =
dotnet_naming_symbols.private_static_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_static_fields.required_modifiers = static
dotnet_naming_symbols.types_and_namespaces.applicable_kinds = namespace, class, struct, interface, enum
dotnet_naming_symbols.types_and_namespaces.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.types_and_namespaces.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected
dotnet_naming_symbols.non_field_members.required_modifiers =
dotnet_naming_symbols.type_parameters.applicable_kinds = namespace
dotnet_naming_symbols.type_parameters.applicable_accessibilities = *
dotnet_naming_symbols.type_parameters.required_modifiers =
dotnet_naming_symbols.private_constant_fields.applicable_kinds = field
dotnet_naming_symbols.private_constant_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_constant_fields.required_modifiers = const
dotnet_naming_symbols.local_variables.applicable_kinds = local
dotnet_naming_symbols.local_variables.applicable_accessibilities = local
dotnet_naming_symbols.local_variables.required_modifiers =
dotnet_naming_symbols.local_constants.applicable_kinds = local
dotnet_naming_symbols.local_constants.applicable_accessibilities = local
dotnet_naming_symbols.local_constants.required_modifiers = const
dotnet_naming_symbols.parameters.applicable_kinds = parameter
dotnet_naming_symbols.parameters.applicable_accessibilities = *
dotnet_naming_symbols.parameters.required_modifiers =
dotnet_naming_symbols.public_constant_fields.applicable_kinds = field
dotnet_naming_symbols.public_constant_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_constant_fields.required_modifiers = const
dotnet_naming_symbols.public_static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.public_static_readonly_fields.applicable_accessibilities = public, internal
dotnet_naming_symbols.public_static_readonly_fields.required_modifiers = readonly, static
dotnet_naming_symbols.private_static_readonly_fields.applicable_kinds = field
dotnet_naming_symbols.private_static_readonly_fields.applicable_accessibilities = private, protected, protected_internal, private_protected
dotnet_naming_symbols.private_static_readonly_fields.required_modifiers = readonly, static
dotnet_naming_symbols.local_functions.applicable_kinds = local_function
dotnet_naming_symbols.local_functions.applicable_accessibilities = *
dotnet_naming_symbols.local_functions.required_modifiers =
# Naming styles
dotnet_naming_style.pascalcase.required_prefix =
dotnet_naming_style.pascalcase.required_suffix =
dotnet_naming_style.pascalcase.word_separator =
dotnet_naming_style.pascalcase.capitalization = pascal_case
dotnet_naming_style.ipascalcase.required_prefix = I
dotnet_naming_style.ipascalcase.required_suffix =
dotnet_naming_style.ipascalcase.word_separator =
dotnet_naming_style.ipascalcase.capitalization = pascal_case
dotnet_naming_style.tpascalcase.required_prefix = T
dotnet_naming_style.tpascalcase.required_suffix =
dotnet_naming_style.tpascalcase.word_separator =
dotnet_naming_style.tpascalcase.capitalization = pascal_case
dotnet_naming_style._camelcase.required_prefix = _
dotnet_naming_style._camelcase.required_suffix =
dotnet_naming_style._camelcase.word_separator =
dotnet_naming_style._camelcase.capitalization = camel_case
dotnet_naming_style.camelcase.required_prefix =
dotnet_naming_style.camelcase.required_suffix =
dotnet_naming_style.camelcase.word_separator =
dotnet_naming_style.camelcase.capitalization = camel_case
dotnet_naming_style.s_camelcase.required_prefix = s_
dotnet_naming_style.s_camelcase.required_suffix =
dotnet_naming_style.s_camelcase.word_separator =
dotnet_naming_style.s_camelcase.capitalization = camel_case
# Shell scripts
[*.sh]
end_of_line = lf
[*.{cmd,bat}]
end_of_line = crlf

View file

@ -143,7 +143,8 @@ namespace SourceGit
public static string Text(string key, params object[] args) public static string Text(string key, params object[] args)
{ {
var fmt = Current.FindResource($"Text.{key}") as string; var fmt = Current.FindResource($"Text.{key}") as string;
if (string.IsNullOrWhiteSpace(fmt)) return $"Text.{key}"; if (string.IsNullOrWhiteSpace(fmt))
return $"Text.{key}";
return string.Format(fmt, args); return string.Format(fmt, args);
} }
@ -178,12 +179,14 @@ namespace SourceGit
// Parse json into Models.Version. // Parse json into Models.Version.
var ver = JsonSerializer.Deserialize(data, JsonCodeGen.Default.Version); var ver = JsonSerializer.Deserialize(data, JsonCodeGen.Default.Version);
if (ver == null) return; if (ver == null)
return;
// Check if already up-to-date. // Check if already up-to-date.
if (!ver.IsNewVersion) if (!ver.IsNewVersion)
{ {
if (manually) ShowSelfUpdateResult(new Models.AlreadyUpToDate()); if (manually)
ShowSelfUpdateResult(new Models.AlreadyUpToDate());
return; return;
} }
@ -191,14 +194,16 @@ namespace SourceGit
if (!manually) if (!manually)
{ {
var pref = ViewModels.Preference.Instance; var pref = ViewModels.Preference.Instance;
if (ver.TagName == pref.IgnoreUpdateTag) return; if (ver.TagName == pref.IgnoreUpdateTag)
return;
} }
ShowSelfUpdateResult(ver); ShowSelfUpdateResult(ver);
} }
catch (Exception e) catch (Exception e)
{ {
if (manually) ShowSelfUpdateResult(e); if (manually)
ShowSelfUpdateResult(e);
} }
}); });
} }
@ -232,7 +237,8 @@ namespace SourceGit
_notificationReceiver = launcher; _notificationReceiver = launcher;
desktop.MainWindow = launcher; desktop.MainWindow = launcher;
if (ViewModels.Preference.Instance.Check4UpdatesOnStartup) Check4Update(); if (ViewModels.Preference.Instance.Check4UpdatesOnStartup)
Check4Update();
} }
base.OnFrameworkInitializationCompleted(); base.OnFrameworkInitializationCompleted();

View file

@ -7,9 +7,12 @@
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "apply "; Args = "apply ";
if (ignoreWhitespace) Args += "--ignore-whitespace "; if (ignoreWhitespace)
else Args += $"--whitespace={whitespaceMode} "; Args += "--ignore-whitespace ";
if (!string.IsNullOrEmpty(extra)) Args += $"{extra} "; else
Args += $"--whitespace={whitespaceMode} ";
if (!string.IsNullOrEmpty(extra))
Args += $"{extra} ";
Args += $"\"{file}\""; Args += $"\"{file}\"";
} }
} }

View file

@ -7,7 +7,6 @@ namespace SourceGit.Commands
{ {
partial class ViewCommand : Command partial class ViewCommand : Command
{ {
[GeneratedRegex(@"^(\w)\s+(.+)$")] [GeneratedRegex(@"^(\w)\s+(.+)$")]
private static partial Regex REG(); private static partial Regex REG();
@ -27,7 +26,8 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG().Match(line); var match = REG().Match(line);
if (!match.Success) return; if (!match.Success)
return;
if (match.Groups[1].Value == "h") if (match.Groups[1].Value == "h")
{ {

View file

@ -46,8 +46,10 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
if (_result.IsBinary) return; if (_result.IsBinary)
if (string.IsNullOrEmpty(line)) return; return;
if (string.IsNullOrEmpty(line))
return;
if (line.IndexOf('\0', StringComparison.Ordinal) >= 0) if (line.IndexOf('\0', StringComparison.Ordinal) >= 0)
{ {
@ -57,7 +59,8 @@ namespace SourceGit.Commands
} }
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
return;
_content.AppendLine(match.Groups[4].Value); _content.AppendLine(match.Groups[4].Value);

View file

@ -23,9 +23,11 @@ namespace SourceGit.Commands
Args += "clone --progress --verbose --recurse-submodules "; Args += "clone --progress --verbose --recurse-submodules ";
if (!string.IsNullOrEmpty(extraArgs)) Args += $"{extraArgs} "; if (!string.IsNullOrEmpty(extraArgs))
Args += $"{extraArgs} ";
Args += $"{url} "; Args += $"{url} ";
if (!string.IsNullOrEmpty(localName)) Args += localName; if (!string.IsNullOrEmpty(localName))
Args += localName;
_notifyProgress = ouputHandler; _notifyProgress = ouputHandler;
} }

View file

@ -47,7 +47,8 @@ namespace SourceGit.Commands
start.Environment.Add("LANG", "en_US.UTF-8"); start.Environment.Add("LANG", "en_US.UTF-8");
} }
if (!string.IsNullOrEmpty(WorkingDirectory)) start.WorkingDirectory = WorkingDirectory; if (!string.IsNullOrEmpty(WorkingDirectory))
start.WorkingDirectory = WorkingDirectory;
var errs = new List<string>(); var errs = new List<string>();
var proc = new Process() { StartInfo = start }; var proc = new Process() { StartInfo = start };
@ -60,11 +61,13 @@ namespace SourceGit.Commands
isCancelled = true; isCancelled = true;
proc.CancelErrorRead(); proc.CancelErrorRead();
proc.CancelOutputRead(); proc.CancelOutputRead();
if (!proc.HasExited) proc.Kill(true); if (!proc.HasExited)
proc.Kill(true);
return; return;
} }
if (e.Data != null) OnReadline(e.Data); if (e.Data != null)
OnReadline(e.Data);
}; };
proc.ErrorDataReceived += (_, e) => proc.ErrorDataReceived += (_, e) =>
@ -74,19 +77,27 @@ namespace SourceGit.Commands
isCancelled = true; isCancelled = true;
proc.CancelErrorRead(); proc.CancelErrorRead();
proc.CancelOutputRead(); proc.CancelOutputRead();
if (!proc.HasExited) proc.Kill(true); if (!proc.HasExited)
proc.Kill(true);
return; return;
} }
if (string.IsNullOrEmpty(e.Data)) return; if (string.IsNullOrEmpty(e.Data))
if (TraitErrorAsOutput) OnReadline(e.Data); return;
if (TraitErrorAsOutput)
OnReadline(e.Data);
// Ignore progress messages // Ignore progress messages
if (e.Data.StartsWith("remote: Enumerating objects:", StringComparison.Ordinal)) return; if (e.Data.StartsWith("remote: Enumerating objects:", StringComparison.Ordinal))
if (e.Data.StartsWith("remote: Counting objects:", StringComparison.Ordinal)) return; return;
if (e.Data.StartsWith("remote: Compressing objects:", StringComparison.Ordinal)) return; if (e.Data.StartsWith("remote: Counting objects:", StringComparison.Ordinal))
if (e.Data.StartsWith("Filtering content:", StringComparison.Ordinal)) return; return;
if (_progressRegex().IsMatch(e.Data)) return; if (e.Data.StartsWith("remote: Compressing objects:", StringComparison.Ordinal))
return;
if (e.Data.StartsWith("Filtering content:", StringComparison.Ordinal))
return;
if (_progressRegex().IsMatch(e.Data))
return;
errs.Add(e.Data); errs.Add(e.Data);
}; };
@ -142,7 +153,8 @@ namespace SourceGit.Commands
start.StandardOutputEncoding = Encoding.UTF8; start.StandardOutputEncoding = Encoding.UTF8;
start.StandardErrorEncoding = Encoding.UTF8; start.StandardErrorEncoding = Encoding.UTF8;
if (!string.IsNullOrEmpty(WorkingDirectory)) start.WorkingDirectory = WorkingDirectory; if (!string.IsNullOrEmpty(WorkingDirectory))
start.WorkingDirectory = WorkingDirectory;
var proc = new Process() { StartInfo = start }; var proc = new Process() { StartInfo = start };
try try

View file

@ -12,8 +12,10 @@ namespace SourceGit.Commands
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"commit --file=\"{file}\""; Args = $"commit --file=\"{file}\"";
if (amend) Args += " --amend --no-edit"; if (amend)
if (allowEmpty) Args += " --allow-empty"; Args += " --amend --no-edit";
if (allowEmpty)
Args += " --allow-empty";
} }
} }
} }

View file

@ -25,18 +25,34 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
return;
var change = new Models.Change() { Path = match.Groups[2].Value }; var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value; var status = match.Groups[1].Value;
switch (status[0]) switch (status[0])
{ {
case 'M': change.Set(Models.ChangeState.Modified); _changes.Add(change); break; case 'M':
case 'A': change.Set(Models.ChangeState.Added); _changes.Add(change); break; change.Set(Models.ChangeState.Modified);
case 'D': change.Set(Models.ChangeState.Deleted); _changes.Add(change); break; _changes.Add(change);
case 'R': change.Set(Models.ChangeState.Renamed); _changes.Add(change); break; break;
case 'C': change.Set(Models.ChangeState.Copied); _changes.Add(change); break; case 'A':
change.Set(Models.ChangeState.Added);
_changes.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
_changes.Add(change);
break;
case 'R':
change.Set(Models.ChangeState.Renamed);
_changes.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
_changes.Add(change);
break;
} }
} }

View file

@ -8,9 +8,9 @@ namespace SourceGit.Commands
{ {
[GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")] [GeneratedRegex(@"^@@ \-(\d+),?\d* \+(\d+),?\d* @@")]
private static partial Regex REG_INDICATOR(); private static partial Regex REG_INDICATOR();
private static readonly string PREFIX_LFS_NEW = "+version https://git-lfs.github.com/spec/"; private const string PREFIX_LFS_NEW = "+version https://git-lfs.github.com/spec/";
private static readonly string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/"; private const string PREFIX_LFS_DEL = "-version https://git-lfs.github.com/spec/";
private static readonly string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/"; private const string PREFIX_LFS_MODIFY = " version https://git-lfs.github.com/spec/";
public Diff(string repo, Models.DiffOption opt) public Diff(string repo, Models.DiffOption opt)
{ {
@ -46,7 +46,8 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
if (_result.IsBinary) return; if (_result.IsBinary)
return;
if (_result.IsLFS) if (_result.IsLFS)
{ {
@ -85,7 +86,8 @@ namespace SourceGit.Commands
var match = REG_INDICATOR().Match(line); var match = REG_INDICATOR().Match(line);
if (!match.Success) if (!match.Success)
{ {
if (line.StartsWith("Binary", StringComparison.Ordinal)) _result.IsBinary = true; if (line.StartsWith("Binary", StringComparison.Ordinal))
_result.IsBinary = true;
return; return;
} }
@ -167,10 +169,12 @@ namespace SourceGit.Commands
var left = _deleted[i]; var left = _deleted[i];
var right = _added[i]; var right = _added[i];
if (left.Content.Length > 1024 || right.Content.Length > 1024) continue; if (left.Content.Length > 1024 || right.Content.Length > 1024)
continue;
var chunks = Models.TextInlineChange.Compare(left.Content, right.Content); var chunks = Models.TextInlineChange.Compare(left.Content, right.Content);
if (chunks.Count > 4) continue; if (chunks.Count > 4)
continue;
foreach (var chunk in chunks) foreach (var chunk in chunks)
{ {

View file

@ -47,7 +47,8 @@ namespace SourceGit.Commands
{ {
var count = Math.Min(10, changes.Count - i); var count = Math.Min(10, changes.Count - i);
var files = new List<string>(); var files = new List<string>();
for (int j = 0; j < count; j++) files.Add(changes[i + j].Path); for (int j = 0; j < count; j++)
files.Add(changes[i + j].Path);
new Restore(repo, files, "--staged --worktree").Exec(); new Restore(repo, files, "--staged --worktree").Exec();
} }
} }

View file

@ -25,7 +25,8 @@ namespace SourceGit.Commands
} }
Args += "fetch --progress --verbose "; Args += "fetch --progress --verbose ";
if (prune) Args += "--prune "; if (prune)
Args += "--prune ";
Args += remote; Args += remote;
AutoFetch.MarkFetched(repo); AutoFetch.MarkFetched(repo);
@ -61,6 +62,8 @@ namespace SourceGit.Commands
public class AutoFetch public class AutoFetch
{ {
private const double INTERVAL = 10 * 60;
public static bool IsEnabled public static bool IsEnabled
{ {
get; get;
@ -101,7 +104,7 @@ namespace SourceGit.Commands
foreach (var job in uptodate) foreach (var job in uptodate)
{ {
job.Cmd.Exec(); job.Cmd.Exec();
job.NextRunTimepoint = DateTime.Now.AddSeconds(_fetchInterval); job.NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL);
} }
Thread.Sleep(2000); Thread.Sleep(2000);
@ -114,7 +117,7 @@ namespace SourceGit.Commands
var job = new Job var job = new Job
{ {
Cmd = new Fetch(repo, "--all", true, null) { RaiseError = false }, Cmd = new Fetch(repo, "--all", true, null) { RaiseError = false },
NextRunTimepoint = DateTime.Now.AddSeconds(_fetchInterval), NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL),
}; };
lock (_lock) lock (_lock)
@ -142,15 +145,14 @@ namespace SourceGit.Commands
{ {
lock (_lock) lock (_lock)
{ {
if (_jobs.ContainsKey(repo)) if (_jobs.TryGetValue(repo, out var value))
{ {
_jobs[repo].NextRunTimepoint = DateTime.Now.AddSeconds(_fetchInterval); value.NextRunTimepoint = DateTime.Now.AddSeconds(INTERVAL);
} }
} }
} }
private static readonly Dictionary<string, Job> _jobs = new Dictionary<string, Job>(); private static readonly Dictionary<string, Job> _jobs = new Dictionary<string, Job>();
private static readonly object _lock = new object(); private static readonly object _lock = new object();
private static readonly double _fetchInterval = 10 * 60;
} }
} }

View file

@ -17,10 +17,12 @@ namespace SourceGit.Commands
var current = branches.Find(x => x.IsCurrent); var current = branches.Find(x => x.IsCurrent);
var masterBranch = branches.Find(x => x.Name == master); var masterBranch = branches.Find(x => x.Name == master);
if (masterBranch == null && current != null) Branch.Create(WorkingDirectory, master, current.Head); if (masterBranch == null && current != null)
Branch.Create(WorkingDirectory, master, current.Head);
var devBranch = branches.Find(x => x.Name == develop); var devBranch = branches.Find(x => x.Name == develop);
if (devBranch == null && current != null) Branch.Create(WorkingDirectory, develop, current.Head); if (devBranch == null && current != null)
Branch.Create(WorkingDirectory, develop, current.Head);
var cmd = new Config(WorkingDirectory); var cmd = new Config(WorkingDirectory);
cmd.Set("gitflow.branch.master", master); cmd.Set("gitflow.branch.master", master);

View file

@ -32,7 +32,8 @@ namespace SourceGit.Commands
public bool IsEnabled() public bool IsEnabled()
{ {
var path = Path.Combine(_repo, ".git", "hooks", "pre-push"); var path = Path.Combine(_repo, ".git", "hooks", "pre-push");
if (!File.Exists(path)) return false; if (!File.Exists(path))
return false;
var content = File.ReadAllText(path); var content = File.ReadAllText(path);
return content.Contains("git lfs pre-push"); return content.Contains("git lfs pre-push");

View file

@ -22,7 +22,8 @@ namespace SourceGit.Commands
} }
Args += "pull --verbose --progress --tags "; Args += "pull --verbose --progress --tags ";
if (useRebase) Args += "--rebase "; if (useRebase)
Args += "--rebase ";
Args += $"{remote} {branch}"; Args += $"{remote} {branch}";
} }

View file

@ -23,9 +23,12 @@ namespace SourceGit.Commands
Args += "push --progress --verbose "; Args += "push --progress --verbose ";
if (withTags) Args += "--tags "; if (withTags)
if (track) Args += "-u "; Args += "--tags ";
if (force) Args += "--force-with-lease "; if (track)
Args += "-u ";
if (force)
Args += "--force-with-lease ";
Args += $"{remote} {local}:{remoteBranch}"; Args += $"{remote} {local}:{remoteBranch}";
} }
@ -71,7 +74,8 @@ namespace SourceGit.Commands
} }
Args += "push "; Args += "push ";
if (isDelete) Args += "--delete "; if (isDelete)
Args += "--delete ";
Args += $"{remote} refs/tags/{tag}"; Args += $"{remote} refs/tags/{tag}";
} }

View file

@ -6,8 +6,8 @@ namespace SourceGit.Commands
{ {
public partial class QueryBranches : Command public partial class QueryBranches : Command
{ {
private static readonly string PREFIX_LOCAL = "refs/heads/"; private const string PREFIX_LOCAL = "refs/heads/";
private static readonly string PREFIX_REMOTE = "refs/remotes/"; private const string PREFIX_REMOTE = "refs/remotes/";
[GeneratedRegex(@"^(\d+)\s(\d+)$")] [GeneratedRegex(@"^(\d+)\s(\d+)$")]
private static partial Regex REG_AHEAD_BEHIND(); private static partial Regex REG_AHEAD_BEHIND();
@ -44,11 +44,13 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var parts = line.Split('$'); var parts = line.Split('$');
if (parts.Length != 5) return; if (parts.Length != 5)
return;
var branch = new Models.Branch(); var branch = new Models.Branch();
var refName = parts[0]; var refName = parts[0];
if (refName.EndsWith("/HEAD", StringComparison.Ordinal)) return; if (refName.EndsWith("/HEAD", StringComparison.Ordinal))
return;
if (refName.StartsWith(PREFIX_LOCAL, StringComparison.Ordinal)) if (refName.StartsWith(PREFIX_LOCAL, StringComparison.Ordinal))
{ {
@ -59,7 +61,8 @@ namespace SourceGit.Commands
{ {
var name = refName.Substring(PREFIX_REMOTE.Length); var name = refName.Substring(PREFIX_REMOTE.Length);
var shortNameIdx = name.IndexOf('/', StringComparison.Ordinal); var shortNameIdx = name.IndexOf('/', StringComparison.Ordinal);
if (shortNameIdx < 0) return; if (shortNameIdx < 0)
return;
branch.Remote = name.Substring(0, shortNameIdx); branch.Remote = name.Substring(0, shortNameIdx);
branch.Name = name.Substring(branch.Remote.Length + 1); branch.Name = name.Substring(branch.Remote.Length + 1);
@ -87,16 +90,20 @@ namespace SourceGit.Commands
cmd.Args = $"rev-list --left-right --count {local}...{upstream}"; cmd.Args = $"rev-list --left-right --count {local}...{upstream}";
var rs = cmd.ReadToEnd(); var rs = cmd.ReadToEnd();
if (!rs.IsSuccess) return string.Empty; if (!rs.IsSuccess)
return string.Empty;
var match = REG_AHEAD_BEHIND().Match(rs.StdOut); var match = REG_AHEAD_BEHIND().Match(rs.StdOut);
if (!match.Success) return string.Empty; if (!match.Success)
return string.Empty;
var ahead = int.Parse(match.Groups[1].Value); var ahead = int.Parse(match.Groups[1].Value);
var behind = int.Parse(match.Groups[2].Value); var behind = int.Parse(match.Groups[2].Value);
var track = ""; var track = "";
if (ahead > 0) track += $"{ahead}↑"; if (ahead > 0)
if (behind > 0) track += $" {behind}↓"; track += $"{ahead}↑";
if (behind > 0)
track += $" {behind}↓";
return track.Trim(); return track.Trim();
} }

View file

@ -25,18 +25,34 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
return;
var change = new Models.Change() { Path = match.Groups[2].Value }; var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value; var status = match.Groups[1].Value;
switch (status[0]) switch (status[0])
{ {
case 'M': change.Set(Models.ChangeState.Modified); _changes.Add(change); break; case 'M':
case 'A': change.Set(Models.ChangeState.Added); _changes.Add(change); break; change.Set(Models.ChangeState.Modified);
case 'D': change.Set(Models.ChangeState.Deleted); _changes.Add(change); break; _changes.Add(change);
case 'R': change.Set(Models.ChangeState.Renamed); _changes.Add(change); break; break;
case 'C': change.Set(Models.ChangeState.Copied); _changes.Add(change); break; case 'A':
change.Set(Models.ChangeState.Added);
_changes.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
_changes.Add(change);
break;
case 'R':
change.Set(Models.ChangeState.Renamed);
_changes.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
_changes.Add(change);
break;
} }
} }

View file

@ -5,8 +5,8 @@ namespace SourceGit.Commands
{ {
public class QueryCommits : Command public class QueryCommits : Command
{ {
private static readonly string GPGSIG_START = "gpgsig -----BEGIN PGP SIGNATURE-----"; private const string GPGSIG_START = "gpgsig -----BEGIN PGP SIGNATURE-----";
private static readonly string GPGSIG_END = " -----END PGP SIGNATURE-----"; private const string GPGSIG_END = " -----END PGP SIGNATURE-----";
private readonly List<Models.Commit> commits = new List<Models.Commit>(); private readonly List<Models.Commit> commits = new List<Models.Commit>();
private Models.Commit current = null; private Models.Commit current = null;
@ -43,7 +43,8 @@ namespace SourceGit.Commands
{ {
if (isSkipingGpgsig) if (isSkipingGpgsig)
{ {
if (line.StartsWith(GPGSIG_END, StringComparison.Ordinal)) isSkipingGpgsig = false; if (line.StartsWith(GPGSIG_END, StringComparison.Ordinal))
isSkipingGpgsig = false;
return; return;
} }
else if (line.StartsWith(GPGSIG_START, StringComparison.Ordinal)) else if (line.StartsWith(GPGSIG_START, StringComparison.Ordinal))
@ -72,13 +73,15 @@ namespace SourceGit.Commands
{ {
current.SHA = line.Substring(0, decoratorStart).Trim(); current.SHA = line.Substring(0, decoratorStart).Trim();
current.IsMerged = ParseDecorators(current.Decorators, line.Substring(decoratorStart + 1)); current.IsMerged = ParseDecorators(current.Decorators, line.Substring(decoratorStart + 1));
if (!isHeadFounded) isHeadFounded = current.IsMerged; if (!isHeadFounded)
isHeadFounded = current.IsMerged;
} }
return; return;
} }
if (current == null) return; if (current == null)
return;
if (line.StartsWith("tree ", StringComparison.Ordinal)) if (line.StartsWith("tree ", StringComparison.Ordinal))
{ {
@ -182,10 +185,12 @@ namespace SourceGit.Commands
var rs = ReadToEnd(); var rs = ReadToEnd();
var shas = rs.StdOut.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); var shas = rs.StdOut.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
if (shas.Length == 0) return; if (shas.Length == 0)
return;
var set = new HashSet<string>(); var set = new HashSet<string>();
foreach (var sha in shas) set.Add(sha); foreach (var sha in shas)
set.Add(sha);
foreach (var c in commits) foreach (var c in commits)
{ {

View file

@ -17,7 +17,8 @@ namespace SourceGit.Commands
public long Result() public long Result()
{ {
if (_result != 0) return _result; if (_result != 0)
return _result;
var rs = ReadToEnd(); var rs = ReadToEnd();
if (rs.IsSuccess) if (rs.IsSuccess)

View file

@ -14,10 +14,12 @@ namespace SourceGit.Commands
public string Result() public string Result()
{ {
var rs = ReadToEnd().StdOut; var rs = ReadToEnd().StdOut;
if (string.IsNullOrEmpty(rs)) return null; if (string.IsNullOrEmpty(rs))
return null;
rs = rs.Trim(); rs = rs.Trim();
if (Path.IsPathRooted(rs)) return rs; if (Path.IsPathRooted(rs))
return rs;
return Path.GetFullPath(Path.Combine(WorkingDirectory, rs)); return Path.GetFullPath(Path.Combine(WorkingDirectory, rs));
} }
} }

View file

@ -26,43 +26,102 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
if (line.EndsWith("/", StringComparison.Ordinal)) return; // Ignore changes with git-worktree return;
if (line.EndsWith("/", StringComparison.Ordinal))
return; // Ignore changes with git-worktree
var change = new Models.Change() { Path = match.Groups[2].Value }; var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value; var status = match.Groups[1].Value;
switch (status) switch (status)
{ {
case " M": change.Set(Models.ChangeState.None, Models.ChangeState.Modified); break; case " M":
case " A": change.Set(Models.ChangeState.None, Models.ChangeState.Added); break; change.Set(Models.ChangeState.None, Models.ChangeState.Modified);
case " D": change.Set(Models.ChangeState.None, Models.ChangeState.Deleted); break; break;
case " R": change.Set(Models.ChangeState.None, Models.ChangeState.Renamed); break; case " A":
case " C": change.Set(Models.ChangeState.None, Models.ChangeState.Copied); break; change.Set(Models.ChangeState.None, Models.ChangeState.Added);
case "M": change.Set(Models.ChangeState.Modified, Models.ChangeState.None); break; break;
case "MM": change.Set(Models.ChangeState.Modified, Models.ChangeState.Modified); break; case " D":
case "MD": change.Set(Models.ChangeState.Modified, Models.ChangeState.Deleted); break; change.Set(Models.ChangeState.None, Models.ChangeState.Deleted);
case "A": change.Set(Models.ChangeState.Added, Models.ChangeState.None); break; break;
case "AM": change.Set(Models.ChangeState.Added, Models.ChangeState.Modified); break; case " R":
case "AD": change.Set(Models.ChangeState.Added, Models.ChangeState.Deleted); break; change.Set(Models.ChangeState.None, Models.ChangeState.Renamed);
case "D": change.Set(Models.ChangeState.Deleted, Models.ChangeState.None); break; break;
case "R": change.Set(Models.ChangeState.Renamed, Models.ChangeState.None); break; case " C":
case "RM": change.Set(Models.ChangeState.Renamed, Models.ChangeState.Modified); break; change.Set(Models.ChangeState.None, Models.ChangeState.Copied);
case "RD": change.Set(Models.ChangeState.Renamed, Models.ChangeState.Deleted); break; break;
case "C": change.Set(Models.ChangeState.Copied, Models.ChangeState.None); break; case "M":
case "CM": change.Set(Models.ChangeState.Copied, Models.ChangeState.Modified); break; change.Set(Models.ChangeState.Modified, Models.ChangeState.None);
case "CD": change.Set(Models.ChangeState.Copied, Models.ChangeState.Deleted); break; break;
case "DR": change.Set(Models.ChangeState.Deleted, Models.ChangeState.Renamed); break; case "MM":
case "DC": change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied); break; change.Set(Models.ChangeState.Modified, Models.ChangeState.Modified);
case "DD": change.Set(Models.ChangeState.Deleted, Models.ChangeState.Deleted); break; break;
case "AU": change.Set(Models.ChangeState.Added, Models.ChangeState.Unmerged); break; case "MD":
case "UD": change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Deleted); break; change.Set(Models.ChangeState.Modified, Models.ChangeState.Deleted);
case "UA": change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Added); break; break;
case "DU": change.Set(Models.ChangeState.Deleted, Models.ChangeState.Unmerged); break; case "A":
case "AA": change.Set(Models.ChangeState.Added, Models.ChangeState.Added); break; change.Set(Models.ChangeState.Added, Models.ChangeState.None);
case "UU": change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Unmerged); break; break;
case "??": change.Set(Models.ChangeState.Untracked, Models.ChangeState.Untracked); break; case "AM":
default: return; change.Set(Models.ChangeState.Added, Models.ChangeState.Modified);
break;
case "AD":
change.Set(Models.ChangeState.Added, Models.ChangeState.Deleted);
break;
case "D":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.None);
break;
case "R":
change.Set(Models.ChangeState.Renamed, Models.ChangeState.None);
break;
case "RM":
change.Set(Models.ChangeState.Renamed, Models.ChangeState.Modified);
break;
case "RD":
change.Set(Models.ChangeState.Renamed, Models.ChangeState.Deleted);
break;
case "C":
change.Set(Models.ChangeState.Copied, Models.ChangeState.None);
break;
case "CM":
change.Set(Models.ChangeState.Copied, Models.ChangeState.Modified);
break;
case "CD":
change.Set(Models.ChangeState.Copied, Models.ChangeState.Deleted);
break;
case "DR":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Renamed);
break;
case "DC":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Copied);
break;
case "DD":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Deleted);
break;
case "AU":
change.Set(Models.ChangeState.Added, Models.ChangeState.Unmerged);
break;
case "UD":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Deleted);
break;
case "UA":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Added);
break;
case "DU":
change.Set(Models.ChangeState.Deleted, Models.ChangeState.Unmerged);
break;
case "AA":
change.Set(Models.ChangeState.Added, Models.ChangeState.Added);
break;
case "UU":
change.Set(Models.ChangeState.Unmerged, Models.ChangeState.Unmerged);
break;
case "??":
change.Set(Models.ChangeState.Untracked, Models.ChangeState.Untracked);
break;
default:
return;
} }
_changes.Add(change); _changes.Add(change);

View file

@ -24,7 +24,8 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_REMOTE().Match(line); var match = REG_REMOTE().Match(line);
if (!match.Success) return; if (!match.Success)
return;
var remote = new Models.Remote() var remote = new Models.Remote()
{ {
@ -32,7 +33,8 @@ namespace SourceGit.Commands
URL = match.Groups[2].Value, URL = match.Groups[2].Value,
}; };
if (_loaded.Find(x => x.Name == remote.Name) != null) return; if (_loaded.Find(x => x.Name == remote.Name) != null)
return;
_loaded.Add(remote); _loaded.Add(remote);
} }

View file

@ -12,7 +12,8 @@
public string Result() public string Result()
{ {
var rs = ReadToEnd().StdOut; var rs = ReadToEnd().StdOut;
if (string.IsNullOrEmpty(rs)) return null; if (string.IsNullOrEmpty(rs))
return null;
return rs.Trim(); return rs.Trim();
} }
} }

View file

@ -26,7 +26,8 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
return;
var obj = new Models.Object(); var obj = new Models.Object();
obj.SHA = match.Groups[2].Value; obj.SHA = match.Groups[2].Value;
@ -35,10 +36,18 @@ namespace SourceGit.Commands
switch (match.Groups[1].Value) switch (match.Groups[1].Value)
{ {
case "blob": obj.Type = Models.ObjectType.Blob; break; case "blob":
case "tree": obj.Type = Models.ObjectType.Tree; break; obj.Type = Models.ObjectType.Blob;
case "tag": obj.Type = Models.ObjectType.Tag; break; break;
case "commit": obj.Type = Models.ObjectType.Commit; break; case "tree":
obj.Type = Models.ObjectType.Tree;
break;
case "tag":
obj.Type = Models.ObjectType.Tag;
break;
case "commit":
obj.Type = Models.ObjectType.Commit;
break;
} }
objects.Add(obj); objects.Add(obj);

View file

@ -25,18 +25,34 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var match = REG_FORMAT().Match(line); var match = REG_FORMAT().Match(line);
if (!match.Success) return; if (!match.Success)
return;
var change = new Models.Change() { Path = match.Groups[2].Value }; var change = new Models.Change() { Path = match.Groups[2].Value };
var status = match.Groups[1].Value; var status = match.Groups[1].Value;
switch (status[0]) switch (status[0])
{ {
case 'M': change.Set(Models.ChangeState.Modified); _changes.Add(change); break; case 'M':
case 'A': change.Set(Models.ChangeState.Added); _changes.Add(change); break; change.Set(Models.ChangeState.Modified);
case 'D': change.Set(Models.ChangeState.Deleted); _changes.Add(change); break; _changes.Add(change);
case 'R': change.Set(Models.ChangeState.Renamed); _changes.Add(change); break; break;
case 'C': change.Set(Models.ChangeState.Copied); _changes.Add(change); break; case 'A':
change.Set(Models.ChangeState.Added);
_changes.Add(change);
break;
case 'D':
change.Set(Models.ChangeState.Deleted);
_changes.Add(change);
break;
case 'R':
change.Set(Models.ChangeState.Renamed);
_changes.Add(change);
break;
case 'C':
change.Set(Models.ChangeState.Copied);
_changes.Add(change);
break;
} }
} }

View file

@ -20,7 +20,8 @@ namespace SourceGit.Commands
public List<Models.Stash> Result() public List<Models.Stash> Result()
{ {
Exec(); Exec();
if (_current != null) _stashes.Add(_current); if (_current != null)
_stashes.Add(_current);
return _stashes; return _stashes;
} }
@ -28,17 +29,20 @@ namespace SourceGit.Commands
{ {
if (line.StartsWith("commit ", StringComparison.Ordinal)) if (line.StartsWith("commit ", StringComparison.Ordinal))
{ {
if (_current != null && !string.IsNullOrEmpty(_current.Name)) _stashes.Add(_current); if (_current != null && !string.IsNullOrEmpty(_current.Name))
_stashes.Add(_current);
_current = new Models.Stash() { SHA = line.Substring(7, 8) }; _current = new Models.Stash() { SHA = line.Substring(7, 8) };
return; return;
} }
if (_current == null) return; if (_current == null)
return;
if (line.StartsWith("Reflog: refs/stash@", StringComparison.Ordinal)) if (line.StartsWith("Reflog: refs/stash@", StringComparison.Ordinal))
{ {
var match = REG_STASH().Match(line); var match = REG_STASH().Match(line);
if (match.Success) _current.Name = match.Groups[1].Value; if (match.Success)
_current.Name = match.Groups[1].Value;
} }
else if (line.StartsWith("Reflog message: ", StringComparison.Ordinal)) else if (line.StartsWith("Reflog message: ", StringComparison.Ordinal))
{ {

View file

@ -7,7 +7,8 @@
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = "rebase "; Args = "rebase ";
if (autoStash) Args += "--autostash "; if (autoStash)
Args += "--autostash ";
Args += basedOn; Args += basedOn;
} }
} }

View file

@ -12,9 +12,11 @@ namespace SourceGit.Commands
StringBuilder builder = new StringBuilder(); StringBuilder builder = new StringBuilder();
builder.Append("restore "); builder.Append("restore ");
if (!string.IsNullOrEmpty(extra)) builder.Append(extra).Append(" "); if (!string.IsNullOrEmpty(extra))
builder.Append(extra).Append(" ");
builder.Append("--"); builder.Append("--");
foreach (var f in files) builder.Append(' ').Append('"').Append(f).Append('"'); foreach (var f in files)
builder.Append(' ').Append('"').Append(f).Append('"');
Args = builder.ToString(); Args = builder.ToString();
} }
} }

View file

@ -7,7 +7,8 @@
WorkingDirectory = repo; WorkingDirectory = repo;
Context = repo; Context = repo;
Args = $"revert {commit} --no-edit"; Args = $"revert {commit} --no-edit";
if (!autoCommit) Args += " --no-commit"; if (!autoCommit)
Args += " --no-commit";
} }
} }
} }

View file

@ -15,7 +15,8 @@ namespace SourceGit.Commands
{ {
foreach (var change in changes) foreach (var change in changes)
{ {
if (!ProcessSingleChange(repo, new Models.DiffOption(change, isUnstaged), sw)) return false; if (!ProcessSingleChange(repo, new Models.DiffOption(change, isUnstaged), sw))
return false;
} }
} }

View file

@ -53,7 +53,8 @@ namespace SourceGit.Commands
while (true) while (true)
{ {
var line = sr.ReadLine(); var line = sr.ReadLine();
if (line == null) break; if (line == null)
break;
proc.StandardInput.WriteLine(line); proc.StandardInput.WriteLine(line);
} }
} }

View file

@ -23,11 +23,13 @@ namespace SourceGit.Commands
protected override void OnReadline(string line) protected override void OnReadline(string line)
{ {
var dateEndIdx = line.IndexOf('$', StringComparison.Ordinal); var dateEndIdx = line.IndexOf('$', StringComparison.Ordinal);
if (dateEndIdx == -1) return; if (dateEndIdx == -1)
return;
var dateStr = line.Substring(0, dateEndIdx); var dateStr = line.Substring(0, dateEndIdx);
var date = 0.0; var date = 0.0;
if (!double.TryParse(dateStr, out date)) return; if (!double.TryParse(dateStr, out date))
return;
_statistics.AddCommit(line.Substring(dateEndIdx + 1), date); _statistics.AddCommit(line.Substring(dateEndIdx + 1), date);
} }

View file

@ -14,7 +14,8 @@ namespace SourceGit.Commands
{ {
_outputHandler = outputHandler; _outputHandler = outputHandler;
Args = $"submodule add {url} {relativePath}"; Args = $"submodule add {url} {relativePath}";
if (!Exec()) return false; if (!Exec())
return false;
if (recursive) if (recursive)
{ {
@ -37,7 +38,8 @@ namespace SourceGit.Commands
public bool Delete(string relativePath) public bool Delete(string relativePath)
{ {
Args = $"submodule deinit -f {relativePath}"; Args = $"submodule deinit -f {relativePath}";
if (!Exec()) return false; if (!Exec())
return false;
Args = $"rm -rf {relativePath}"; Args = $"rm -rf {relativePath}";
return Exec(); return Exec();

View file

@ -32,7 +32,8 @@ namespace SourceGit.Commands
cmd.WorkingDirectory = repo; cmd.WorkingDirectory = repo;
cmd.Context = repo; cmd.Context = repo;
cmd.Args = $"tag --delete {name}"; cmd.Args = $"tag --delete {name}";
if (!cmd.Exec()) return false; if (!cmd.Exec())
return false;
if (remotes != null) if (remotes != null)
{ {

View file

@ -11,7 +11,8 @@
public string Query() public string Query()
{ {
var rs = ReadToEnd(); var rs = ReadToEnd();
if (!rs.IsSuccess || string.IsNullOrWhiteSpace(rs.StdOut)) return string.Empty; if (!rs.IsSuccess || string.IsNullOrWhiteSpace(rs.StdOut))
return string.Empty;
return rs.StdOut.Trim().Substring("git version ".Length); return rs.StdOut.Trim().Substring("git version ".Length);
} }
} }

View file

@ -5,10 +5,10 @@ namespace SourceGit.Converters
{ {
public static class BookmarkConverters public static class BookmarkConverters
{ {
public static FuncValueConverter<int, IBrush> ToBrush = public static readonly FuncValueConverter<int, IBrush> ToBrush =
new FuncValueConverter<int, IBrush>(bookmark => Models.Bookmarks.Brushes[bookmark]); new FuncValueConverter<int, IBrush>(bookmark => Models.Bookmarks.Brushes[bookmark]);
public static FuncValueConverter<int, double> ToStrokeThickness = public static readonly FuncValueConverter<int, double> ToStrokeThickness =
new FuncValueConverter<int, double>(bookmark => bookmark == 0 ? 1.0 : 0); new FuncValueConverter<int, double>(bookmark => bookmark == 0 ? 1.0 : 0);
} }
} }

View file

@ -4,7 +4,7 @@ namespace SourceGit.Converters
{ {
public static class BoolConverters public static class BoolConverters
{ {
public static FuncValueConverter<bool, double> ToCommitOpacity = public static readonly FuncValueConverter<bool, double> ToCommitOpacity =
new FuncValueConverter<bool, double>(x => x ? 1 : 0.5); new FuncValueConverter<bool, double>(x => x ? 1 : 0.5);
} }
} }

View file

@ -4,7 +4,7 @@ namespace SourceGit.Converters
{ {
public static class BranchConverters public static class BranchConverters
{ {
public static FuncValueConverter<Models.Branch, string> ToName = public static readonly FuncValueConverter<Models.Branch, string> ToName =
new FuncValueConverter<Models.Branch, string>(v => v.IsLocal ? v.Name : $"{v.Remote}/{v.Name}"); new FuncValueConverter<Models.Branch, string>(v => v.IsLocal ? v.Name : $"{v.Remote}/{v.Name}");
} }
} }

View file

@ -6,7 +6,7 @@ namespace SourceGit.Converters
{ {
public static class ChangeViewModeConverters public static class ChangeViewModeConverters
{ {
public static FuncValueConverter<Models.ChangeViewMode, StreamGeometry> ToIcon = public static readonly FuncValueConverter<Models.ChangeViewMode, StreamGeometry> ToIcon =
new FuncValueConverter<Models.ChangeViewMode, StreamGeometry>(v => new FuncValueConverter<Models.ChangeViewMode, StreamGeometry>(v =>
{ {
switch (v) switch (v)
@ -20,13 +20,13 @@ namespace SourceGit.Converters
} }
}); });
public static FuncValueConverter<Models.ChangeViewMode, bool> IsList = public static readonly FuncValueConverter<Models.ChangeViewMode, bool> IsList =
new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.List); new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.List);
public static FuncValueConverter<Models.ChangeViewMode, bool> IsGrid = public static readonly FuncValueConverter<Models.ChangeViewMode, bool> IsGrid =
new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.Grid); new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.Grid);
public static FuncValueConverter<Models.ChangeViewMode, bool> IsTree = public static readonly FuncValueConverter<Models.ChangeViewMode, bool> IsTree =
new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.Tree); new FuncValueConverter<Models.ChangeViewMode, bool>(v => v == Models.ChangeViewMode.Tree);
} }
} }

View file

@ -7,14 +7,15 @@ namespace SourceGit.Converters
{ {
public static class DecoratorTypeConverters public static class DecoratorTypeConverters
{ {
public static FuncValueConverter<Models.DecoratorType, IBrush> ToBackground = public static readonly FuncValueConverter<Models.DecoratorType, IBrush> ToBackground =
new FuncValueConverter<Models.DecoratorType, IBrush>(v => new FuncValueConverter<Models.DecoratorType, IBrush>(v =>
{ {
if (v == Models.DecoratorType.Tag) return Models.DecoratorResources.Backgrounds[0]; if (v == Models.DecoratorType.Tag)
return Models.DecoratorResources.Backgrounds[0];
return Models.DecoratorResources.Backgrounds[1]; return Models.DecoratorResources.Backgrounds[1];
}); });
public static FuncValueConverter<Models.DecoratorType, StreamGeometry> ToIcon = public static readonly FuncValueConverter<Models.DecoratorType, StreamGeometry> ToIcon =
new FuncValueConverter<Models.DecoratorType, StreamGeometry>(v => new FuncValueConverter<Models.DecoratorType, StreamGeometry>(v =>
{ {
var key = "Icons.Tag"; var key = "Icons.Tag";

View file

@ -4,10 +4,10 @@ namespace SourceGit.Converters
{ {
public static class FontSizeModifyConverters public static class FontSizeModifyConverters
{ {
public static FuncValueConverter<double, double> Increase = public static readonly FuncValueConverter<double, double> Increase =
new FuncValueConverter<double, double>(v => v + 1.0); new FuncValueConverter<double, double>(v => v + 1.0);
public static FuncValueConverter<double, double> Decrease = public static readonly FuncValueConverter<double, double> Decrease =
new FuncValueConverter<double, double>(v => v - 1.0); new FuncValueConverter<double, double>(v => v - 1.0);
} }
} }

View file

@ -4,13 +4,13 @@ namespace SourceGit.Converters
{ {
public static class IntConverters public static class IntConverters
{ {
public static FuncValueConverter<int, bool> IsGreaterThanZero = public static readonly FuncValueConverter<int, bool> IsGreaterThanZero =
new FuncValueConverter<int, bool>(v => v > 0); new FuncValueConverter<int, bool>(v => v > 0);
public static FuncValueConverter<int, bool> IsZero = public static readonly FuncValueConverter<int, bool> IsZero =
new FuncValueConverter<int, bool>(v => v == 0); new FuncValueConverter<int, bool>(v => v == 0);
public static FuncValueConverter<int, bool> IsOne = public static readonly FuncValueConverter<int, bool> IsOne =
new FuncValueConverter<int, bool>(v => v == 1); new FuncValueConverter<int, bool>(v => v == 1);
} }
} }

View file

@ -7,17 +7,20 @@ namespace SourceGit.Converters
{ {
public static class LauncherPageConverters public static class LauncherPageConverters
{ {
public static FuncMultiValueConverter<object, bool> ToTabSeperatorVisible = public static readonly FuncMultiValueConverter<object, bool> ToTabSeperatorVisible =
new FuncMultiValueConverter<object, bool>(v => new FuncMultiValueConverter<object, bool>(v =>
{ {
if (v == null) return false; if (v == null)
return false;
var array = new List<object>(); var array = new List<object>();
array.AddRange(v); array.AddRange(v);
if (array.Count != 3) return false; if (array.Count != 3)
return false;
var self = array[0] as ViewModels.LauncherPage; var self = array[0] as ViewModels.LauncherPage;
if (self == null) return false; if (self == null)
return false;
var selected = array[1] as ViewModels.LauncherPage; var selected = array[1] as ViewModels.LauncherPage;
var collections = array[2] as AvaloniaList<ViewModels.LauncherPage>; var collections = array[2] as AvaloniaList<ViewModels.LauncherPage>;

View file

@ -6,10 +6,10 @@ namespace SourceGit.Converters
{ {
public static class ListConverters public static class ListConverters
{ {
public static FuncValueConverter<IList, string> ToCount = public static readonly FuncValueConverter<IList, string> ToCount =
new FuncValueConverter<IList, string>(v => $" ({v.Count})"); new FuncValueConverter<IList, string>(v => $" ({v.Count})");
public static FuncValueConverter<IList, bool> IsNotNullOrEmpty = public static readonly FuncValueConverter<IList, bool> IsNotNullOrEmpty =
new FuncValueConverter<IList, bool>(v => v != null && v.Count > 0); new FuncValueConverter<IList, bool>(v => v != null && v.Count > 0);
} }
} }

View file

@ -6,16 +6,17 @@ namespace SourceGit.Converters
{ {
public static class PathConverters public static class PathConverters
{ {
public static FuncValueConverter<string, string> PureFileName = public static readonly FuncValueConverter<string, string> PureFileName =
new FuncValueConverter<string, string>(fullpath => Path.GetFileName(fullpath) ?? ""); new FuncValueConverter<string, string>(fullpath => Path.GetFileName(fullpath) ?? "");
public static FuncValueConverter<string, string> PureDirectoryName = public static readonly FuncValueConverter<string, string> PureDirectoryName =
new FuncValueConverter<string, string>(fullpath => Path.GetDirectoryName(fullpath) ?? ""); new FuncValueConverter<string, string>(fullpath => Path.GetDirectoryName(fullpath) ?? "");
public static FuncValueConverter<string, string> TruncateIfTooLong = public static readonly FuncValueConverter<string, string> TruncateIfTooLong =
new FuncValueConverter<string, string>(fullpath => new FuncValueConverter<string, string>(fullpath =>
{ {
if (fullpath.Length <= 50) return fullpath; if (fullpath.Length <= 50)
return fullpath;
return fullpath.Substring(0, 20) + ".../" + Path.GetFileName(fullpath); return fullpath.Substring(0, 20) + ".../" + Path.GetFileName(fullpath);
}); });
} }

View file

@ -2,7 +2,6 @@
using System.Globalization; using System.Globalization;
using Avalonia.Data.Converters; using Avalonia.Data.Converters;
using Avalonia.Media;
using Avalonia.Styling; using Avalonia.Styling;
namespace SourceGit.Converters namespace SourceGit.Converters
@ -22,7 +21,7 @@ namespace SourceGit.Converters
} }
} }
public static ToLocaleConverter ToLocale = new ToLocaleConverter(); public static readonly ToLocaleConverter ToLocale = new ToLocaleConverter();
public class ToThemeConverter : IValueConverter public class ToThemeConverter : IValueConverter
{ {
@ -50,7 +49,7 @@ namespace SourceGit.Converters
} }
} }
public static ToThemeConverter ToTheme = new ToThemeConverter(); public static readonly ToThemeConverter ToTheme = new ToThemeConverter();
public class FormatByResourceKeyConverter : IValueConverter public class FormatByResourceKeyConverter : IValueConverter
{ {
@ -66,9 +65,9 @@ namespace SourceGit.Converters
} }
} }
public static FormatByResourceKeyConverter FormatByResourceKey = new FormatByResourceKeyConverter(); public static readonly FormatByResourceKeyConverter FormatByResourceKey = new FormatByResourceKeyConverter();
public static FuncValueConverter<string, string> ToShortSHA = public static readonly FuncValueConverter<string, string> ToShortSHA =
new FuncValueConverter<string, string>(v => v.Length > 10 ? v.Substring(0, 10) : v); new FuncValueConverter<string, string>(v => v.Length > 10 ? v.Substring(0, 10) : v);
} }
} }

View file

@ -9,7 +9,7 @@ namespace SourceGit.Converters
{ {
public static class WindowStateConverters public static class WindowStateConverters
{ {
public static FuncValueConverter<WindowState, Thickness> ToContentMargin = public static readonly FuncValueConverter<WindowState, Thickness> ToContentMargin =
new FuncValueConverter<WindowState, Thickness>(state => new FuncValueConverter<WindowState, Thickness>(state =>
{ {
if (OperatingSystem.IsWindows() && state == WindowState.Maximized) if (OperatingSystem.IsWindows() && state == WindowState.Maximized)
@ -26,7 +26,7 @@ namespace SourceGit.Converters
} }
}); });
public static FuncValueConverter<WindowState, GridLength> ToTitleBarHeight = public static readonly FuncValueConverter<WindowState, GridLength> ToTitleBarHeight =
new FuncValueConverter<WindowState, GridLength>(state => new FuncValueConverter<WindowState, GridLength>(state =>
{ {
if (state == WindowState.Maximized) if (state == WindowState.Maximized)
@ -39,7 +39,7 @@ namespace SourceGit.Converters
} }
}); });
public static FuncValueConverter<WindowState, StreamGeometry> ToMaxOrRestoreIcon = public static readonly FuncValueConverter<WindowState, StreamGeometry> ToMaxOrRestoreIcon =
new FuncValueConverter<WindowState, StreamGeometry>(state => new FuncValueConverter<WindowState, StreamGeometry>(state =>
{ {
if (state == WindowState.Maximized) if (state == WindowState.Maximized)
@ -52,7 +52,7 @@ namespace SourceGit.Converters
} }
}); });
public static FuncValueConverter<WindowState, bool> IsNormal = public static readonly FuncValueConverter<WindowState, bool> IsNormal =
new FuncValueConverter<WindowState, bool>(state => state == WindowState.Normal); new FuncValueConverter<WindowState, bool>(state => state == WindowState.Normal);
} }
} }

View file

@ -26,7 +26,8 @@ namespace SourceGit.Models
static AvatarManager() static AvatarManager()
{ {
_storePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SourceGit", "avatars"); _storePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "SourceGit", "avatars");
if (!Directory.Exists(_storePath)) Directory.CreateDirectory(_storePath); if (!Directory.Exists(_storePath))
Directory.CreateDirectory(_storePath);
Task.Run(() => Task.Run(() =>
{ {
@ -83,8 +84,10 @@ namespace SourceGit.Models
Dispatcher.UIThread.InvokeAsync(() => Dispatcher.UIThread.InvokeAsync(() =>
{ {
if (_resources.ContainsKey(md5)) _resources[md5] = img; if (_resources.ContainsKey(md5))
else _resources.Add(md5, img); _resources[md5] = img;
else
_resources.Add(md5, img);
NotifyResourceChanged(md5); NotifyResourceChanged(md5);
}); });
} }
@ -105,16 +108,19 @@ namespace SourceGit.Models
{ {
if (forceRefetch) if (forceRefetch)
{ {
if (_resources.ContainsKey(md5)) _resources.Remove(md5); if (_resources.ContainsKey(md5))
_resources.Remove(md5);
var localFile = Path.Combine(_storePath, md5); var localFile = Path.Combine(_storePath, md5);
if (File.Exists(localFile)) File.Delete(localFile); if (File.Exists(localFile))
File.Delete(localFile);
NotifyResourceChanged(md5); NotifyResourceChanged(md5);
} }
else else
{ {
if (_resources.ContainsKey(md5)) return _resources[md5]; if (_resources.TryGetValue(md5, out var value))
return value;
var localFile = Path.Combine(_storePath, md5); var localFile = Path.Combine(_storePath, md5);
if (File.Exists(localFile)) if (File.Exists(localFile))
@ -134,7 +140,8 @@ namespace SourceGit.Models
lock (_synclock) lock (_synclock)
{ {
if (!_requesting.Contains(md5)) _requesting.Add(md5); if (!_requesting.Contains(md5))
_requesting.Add(md5);
} }
return null; return null;

View file

@ -19,7 +19,8 @@ namespace SourceGit.Models
static Bookmarks() static Bookmarks()
{ {
for (int i = 0; i < Brushes.Length; i++) Supported.Add(i); for (int i = 0; i < Brushes.Length; i++)
Supported.Add(i);
} }
} }
} }

View file

@ -83,7 +83,8 @@ namespace SourceGit.Models
else else
{ {
var remote = _remotes.Find(x => x.Name == branch.Remote); var remote = _remotes.Find(x => x.Name == branch.Remote);
if (remote != null) MakeBranchNode(branch, remote.Children, $"remote/{remote.Name}", isFiltered); if (remote != null)
MakeBranchNode(branch, remote.Children, $"remote/{remote.Name}", isFiltered);
} }
} }
@ -106,7 +107,8 @@ namespace SourceGit.Models
foreach (var node in nodes) foreach (var node in nodes)
{ {
var path = prefix + "/" + node.Name; var path = prefix + "/" + node.Name;
if (node.Type != BranchTreeNodeType.Branch && node.IsExpanded) _expanded.Add(path); if (node.Type != BranchTreeNodeType.Branch && node.IsExpanded)
_expanded.Add(path);
CollectExpandedNodes(node.Children, path); CollectExpandedNodes(node.Children, path);
} }
} }
@ -134,9 +136,9 @@ namespace SourceGit.Models
for (int i = 0; i < subs.Length - 1; i++) for (int i = 0; i < subs.Length - 1; i++)
{ {
path = string.Concat(path, "/", subs[i]); path = string.Concat(path, "/", subs[i]);
if (_maps.ContainsKey(path)) if (_maps.TryGetValue(path, out var value))
{ {
lastFolder = _maps[path]; lastFolder = value;
} }
else if (lastFolder == null) else if (lastFolder == null)
{ {
@ -188,7 +190,8 @@ namespace SourceGit.Models
} }
}); });
foreach (var node in nodes) SortNodes(node.Children); foreach (var node in nodes)
SortNodes(node.Children);
} }
private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>(); private readonly List<BranchTreeNode> _locals = new List<BranchTreeNode>();

View file

@ -8,7 +8,7 @@ namespace SourceGit.Models
public string Value { get; set; } public string Value { get; set; }
public string Desc { get; set; } public string Desc { get; set; }
public static List<CRLFMode> Supported = new List<CRLFMode>() { public static readonly List<CRLFMode> Supported = new List<CRLFMode>() {
new CRLFMode("TRUE", "true", "Commit as LF, checkout as CRLF"), new CRLFMode("TRUE", "true", "Commit as LF, checkout as CRLF"),
new CRLFMode("INPUT", "input", "Only convert for commit"), new CRLFMode("INPUT", "input", "Only convert for commit"),
new CRLFMode("FALSE", "false", "Do NOT convert"), new CRLFMode("FALSE", "false", "Do NOT convert"),

View file

@ -32,9 +32,12 @@ namespace SourceGit.Models
{ {
get get
{ {
if (Index == ChangeState.Unmerged || WorkTree == ChangeState.Unmerged) return true; if (Index == ChangeState.Unmerged || WorkTree == ChangeState.Unmerged)
if (Index == ChangeState.Added && WorkTree == ChangeState.Added) return true; return true;
if (Index == ChangeState.Deleted && WorkTree == ChangeState.Deleted) return true; if (Index == ChangeState.Added && WorkTree == ChangeState.Added)
return true;
if (Index == ChangeState.Deleted && WorkTree == ChangeState.Deleted)
return true;
return false; return false;
} }
} }
@ -63,8 +66,10 @@ namespace SourceGit.Models
} }
} }
if (Path[0] == '"') Path = Path.Substring(1, Path.Length - 2); if (Path[0] == '"')
if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"') OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2); Path = Path.Substring(1, Path.Length - 2);
if (!string.IsNullOrEmpty(OriginalPath) && OriginalPath[0] == '"')
OriginalPath = OriginalPath.Substring(1, OriginalPath.Length - 2);
} }
} }
} }

View file

@ -38,7 +38,8 @@ namespace SourceGit.Models
public static void ParseUserAndTime(string data, ref User user, ref ulong time) public static void ParseUserAndTime(string data, ref User user, ref ulong time)
{ {
var userEndIdx = data.IndexOf('>', StringComparison.Ordinal); var userEndIdx = data.IndexOf('>', StringComparison.Ordinal);
if (userEndIdx < 0) return; if (userEndIdx < 0)
return;
var timeEndIdx = data.IndexOf(' ', userEndIdx + 2); var timeEndIdx = data.IndexOf(' ', userEndIdx + 2);
user = User.FindOrAdd(data.Substring(0, userEndIdx)); user = User.FindOrAdd(data.Substring(0, userEndIdx));

View file

@ -55,11 +55,13 @@ namespace SourceGit.Models
{ {
Add(new Point(LastX, LastY)); Add(new Point(LastX, LastY));
Add(new Point(x, y - halfHeight)); Add(new Point(x, y - halfHeight));
if (isEnd) Add(new Point(x, y)); if (isEnd)
Add(new Point(x, y));
} }
else if (x < LastX) else if (x < LastX)
{ {
if (y > LastY + halfHeight) Add(new Point(LastX, LastY + halfHeight)); if (y > LastY + halfHeight)
Add(new Point(LastX, LastY + halfHeight));
Add(new Point(x, y)); Add(new Point(x, y));
} }
else if (isEnd) else if (isEnd)
@ -136,7 +138,8 @@ namespace SourceGit.Models
if (commit.Parents.Count > 0) if (commit.Parents.Count > 0)
{ {
major.Next = commit.Parents[0]; major.Next = commit.Parents[0];
if (!mapUnsolved.ContainsKey(major.Next)) mapUnsolved.Add(major.Next, major); if (!mapUnsolved.ContainsKey(major.Next))
mapUnsolved.Add(major.Next, major);
} }
else else
{ {
@ -155,7 +158,8 @@ namespace SourceGit.Models
} }
else else
{ {
if (!mapUnsolved.ContainsKey(l.Next)) mapUnsolved.Add(l.Next, l); if (!mapUnsolved.ContainsKey(l.Next))
mapUnsolved.Add(l.Next, l);
offsetX += UNIT_WIDTH; offsetX += UNIT_WIDTH;
l.Add(offsetX, offsetY, HALF_HEIGHT); l.Add(offsetX, offsetY, HALF_HEIGHT);
} }
@ -188,9 +192,9 @@ namespace SourceGit.Models
for (int j = 1; j < commit.Parents.Count; j++) for (int j = 1; j < commit.Parents.Count; j++)
{ {
var parent = commit.Parents[j]; var parent = commit.Parents[j];
if (mapUnsolved.ContainsKey(parent)) if (mapUnsolved.TryGetValue(parent, out var value))
{ {
var l = mapUnsolved[parent]; var l = value;
var link = new Link(); var link = new Link();
link.Start = position; link.Start = position;
@ -233,7 +237,8 @@ namespace SourceGit.Models
var path = unsolved[i]; var path = unsolved[i];
var endY = (commits.Count - 0.5) * UNIT_HEIGHT; var endY = (commits.Count - 0.5) * UNIT_HEIGHT;
if (path.Path.Points.Count == 1 && path.Path.Points[0].Y == endY) continue; if (path.Path.Points.Count == 1 && path.Path.Points[0].Y == endY)
continue;
path.Add((i + 0.5) * UNIT_WIDTH, endY + HALF_HEIGHT, HALF_HEIGHT, true); path.Add((i + 0.5) * UNIT_WIDTH, endY + HALF_HEIGHT, HALF_HEIGHT, true);
} }
unsolved.Clear(); unsolved.Clear();

View file

@ -93,11 +93,14 @@ namespace SourceGit.Models
public override string ToString() public override string ToString()
{ {
var builder = new StringBuilder(); var builder = new StringBuilder();
if (!string.IsNullOrEmpty(_extra)) builder.Append($"{_extra} "); if (!string.IsNullOrEmpty(_extra))
foreach (var r in _revisions) builder.Append($"{r} "); builder.Append($"{_extra} ");
foreach (var r in _revisions)
builder.Append($"{r} ");
builder.Append("-- "); builder.Append("-- ");
if (!string.IsNullOrEmpty(_orgPath)) builder.Append($"\"{_orgPath}\" "); if (!string.IsNullOrEmpty(_orgPath))
builder.Append($"\"{_orgPath}\" ");
builder.Append($"\"{_path}\""); builder.Append($"\"{_path}\"");
return builder.ToString(); return builder.ToString();

View file

@ -71,13 +71,15 @@ namespace SourceGit.Models
var builder = new StringBuilder(); var builder = new StringBuilder();
builder.Append("diff --git a/").Append(change.Path).Append(" b/").Append(change.Path).Append('\n'); builder.Append("diff --git a/").Append(change.Path).Append(" b/").Append(change.Path).Append('\n');
if (!revert && !isTracked) builder.Append("new file mode 100644\n"); if (!revert && !isTracked)
builder.Append("new file mode 100644\n");
builder.Append("index 00000000...").Append(fileGuid).Append('\n'); builder.Append("index 00000000...").Append(fileGuid).Append('\n');
builder.Append("--- ").Append((revert || isTracked) ? $"a/{change.Path}\n" : "/dev/null\n"); builder.Append("--- ").Append((revert || isTracked) ? $"a/{change.Path}\n" : "/dev/null\n");
builder.Append("+++ b/").Append(change.Path).Append('\n'); builder.Append("+++ b/").Append(change.Path).Append('\n');
var additions = selection.EndLine - selection.StartLine; var additions = selection.EndLine - selection.StartLine;
if (selection.StartLine != 1) additions++; if (selection.StartLine != 1)
additions++;
if (revert) if (revert)
{ {
@ -86,7 +88,8 @@ namespace SourceGit.Models
for (int i = 1; i <= totalLines; i++) for (int i = 1; i <= totalLines; i++)
{ {
var line = Lines[i]; var line = Lines[i];
if (line.Type != TextDiffLineType.Added) continue; if (line.Type != TextDiffLineType.Added)
continue;
builder.Append(selection.IsInRange(i) ? "\n+" : "\n ").Append(line.Content); builder.Append(selection.IsInRange(i) ? "\n+" : "\n ").Append(line.Content);
} }
} }
@ -96,7 +99,8 @@ namespace SourceGit.Models
for (int i = selection.StartLine - 1; i < selection.EndLine; i++) for (int i = selection.StartLine - 1; i < selection.EndLine; i++)
{ {
var line = Lines[i]; var line = Lines[i];
if (line.Type != TextDiffLineType.Added) continue; if (line.Type != TextDiffLineType.Added)
continue;
builder.Append("\n+").Append(line.Content); builder.Append("\n+").Append(line.Content);
} }
} }
@ -125,7 +129,8 @@ namespace SourceGit.Models
for (int i = selection.EndLine; i < Lines.Count; i++) for (int i = selection.EndLine; i < Lines.Count; i++)
{ {
var line = Lines[i]; var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator) break; if (line.Type == TextDiffLineType.Indicator)
break;
if (revert) if (revert)
{ {
if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added) if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added)
@ -184,11 +189,13 @@ namespace SourceGit.Models
} }
else if (line.Type == TextDiffLineType.Added) else if (line.Type == TextDiffLineType.Added)
{ {
if (revert) builder.Append("\n ").Append(line.Content); if (revert)
builder.Append("\n ").Append(line.Content);
} }
else if (line.Type == TextDiffLineType.Deleted) else if (line.Type == TextDiffLineType.Deleted)
{ {
if (!revert) builder.Append("\n ").Append(line.Content); if (!revert)
builder.Append("\n ").Append(line.Content);
} }
else if (line.Type == TextDiffLineType.Normal) else if (line.Type == TextDiffLineType.Normal)
{ {
@ -247,7 +254,8 @@ namespace SourceGit.Models
for (int i = selection.EndLine; i < Lines.Count; i++) for (int i = selection.EndLine; i < Lines.Count; i++)
{ {
var line = Lines[i]; var line = Lines[i];
if (line.Type == TextDiffLineType.Indicator) break; if (line.Type == TextDiffLineType.Indicator)
break;
if (revert) if (revert)
{ {
if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added) if (line.Type == TextDiffLineType.Normal || line.Type == TextDiffLineType.Added)
@ -306,11 +314,13 @@ namespace SourceGit.Models
} }
else if (line.Type == TextDiffLineType.Added) else if (line.Type == TextDiffLineType.Added)
{ {
if (revert) builder.Append("\n ").Append(line.Content); if (revert)
builder.Append("\n ").Append(line.Content);
} }
else if (line.Type == TextDiffLineType.Deleted) else if (line.Type == TextDiffLineType.Deleted)
{ {
if (!revert) builder.Append("\n ").Append(line.Content); if (!revert)
builder.Append("\n ").Append(line.Content);
} }
else if (line.Type == TextDiffLineType.Normal) else if (line.Type == TextDiffLineType.Normal)
{ {
@ -390,7 +400,8 @@ namespace SourceGit.Models
for (int i = idx + 1; i < end; i++) for (int i = idx + 1; i < end; i++)
{ {
var test = Lines[i]; var test = Lines[i];
if (test.Type == TextDiffLineType.Indicator) break; if (test.Type == TextDiffLineType.Indicator)
break;
if (test.Type == TextDiffLineType.Normal) if (test.Type == TextDiffLineType.Normal)
{ {
@ -441,7 +452,8 @@ namespace SourceGit.Models
} }
} }
if (oldCount == 0 && newCount == 0) return false; if (oldCount == 0 && newCount == 0)
return false;
builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
return true; return true;
@ -457,7 +469,8 @@ namespace SourceGit.Models
for (int i = idx + 1; i < end; i++) for (int i = idx + 1; i < end; i++)
{ {
var test = Lines[i]; var test = Lines[i];
if (test.Type == TextDiffLineType.Indicator) break; if (test.Type == TextDiffLineType.Indicator)
break;
if (test.Type == TextDiffLineType.Normal) if (test.Type == TextDiffLineType.Normal)
{ {
@ -530,7 +543,8 @@ namespace SourceGit.Models
} }
} }
if (oldCount == 0 && newCount == 0) return false; if (oldCount == 0 && newCount == 0)
return false;
builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@"); builder.Append($"\n@@ -{oldStart},{oldCount} +{newStart},{newCount} @@");
return true; return true;

View file

@ -11,7 +11,7 @@ namespace SourceGit.Models
public string Cmd { get; set; } public string Cmd { get; set; }
public string DiffCmd { get; set; } public string DiffCmd { get; set; }
public static List<ExternalMergeTools> Supported; public static readonly List<ExternalMergeTools> Supported;
static ExternalMergeTools() static ExternalMergeTools()
{ {

View file

@ -26,10 +26,14 @@
public GitFlowBranchType GetBranchType(string name) public GitFlowBranchType GetBranchType(string name)
{ {
if (!IsEnabled) return GitFlowBranchType.None; if (!IsEnabled)
if (name.StartsWith(Feature)) return GitFlowBranchType.Feature; return GitFlowBranchType.None;
if (name.StartsWith(Release)) return GitFlowBranchType.Release; if (name.StartsWith(Feature))
if (name.StartsWith(Hotfix)) return GitFlowBranchType.Hotfix; return GitFlowBranchType.Feature;
if (name.StartsWith(Release))
return GitFlowBranchType.Release;
if (name.StartsWith(Hotfix))
return GitFlowBranchType.Hotfix;
return GitFlowBranchType.None; return GitFlowBranchType.None;
} }
} }

View file

@ -7,7 +7,7 @@ namespace SourceGit.Models
public string Name { get; set; } public string Name { get; set; }
public string Key { get; set; } public string Key { get; set; }
public static List<Locale> Supported = new List<Locale>() { public static readonly List<Locale> Supported = new List<Locale>() {
new Locale("English", "en_US"), new Locale("English", "en_US"),
new Locale("简体中文", "zh_CN"), new Locale("简体中文", "zh_CN"),
}; };

View file

@ -24,11 +24,13 @@ namespace SourceGit.Models
public static bool IsSSH(string url) public static bool IsSSH(string url)
{ {
if (string.IsNullOrWhiteSpace(url)) return false; if (string.IsNullOrWhiteSpace(url))
return false;
for (int i = 1; i < URL_FORMATS.Length; i++) for (int i = 1; i < URL_FORMATS.Length; i++)
{ {
if (URL_FORMATS[i].IsMatch(url)) return true; if (URL_FORMATS[i].IsMatch(url))
return true;
} }
return false; return false;
@ -38,7 +40,8 @@ namespace SourceGit.Models
{ {
foreach (var fmt in URL_FORMATS) foreach (var fmt in URL_FORMATS)
{ {
if (fmt.IsMatch(url)) return true; if (fmt.IsMatch(url))
return true;
} }
return false; return false;
} }

View file

@ -20,9 +20,9 @@ namespace SourceGit.Models
Total++; Total++;
Samples[index].Count++; Samples[index].Count++;
if (_mapByCommitter.ContainsKey(committer)) if (_mapByCommitter.TryGetValue(committer, out var value))
{ {
_mapByCommitter[committer].Count++; value.Count++;
} }
else else
{ {

View file

@ -79,10 +79,13 @@ namespace SourceGit.Models
var beginNew = posNew; var beginNew = posNew;
var countOld = 0; var countOld = 0;
var countNew = 0; var countNew = 0;
for (; posOld < sizeOld && chunksOld[posOld].Modified; posOld++) countOld += chunksOld[posOld].Size; for (; posOld < sizeOld && chunksOld[posOld].Modified; posOld++)
for (; posNew < sizeNew && chunksNew[posNew].Modified; posNew++) countNew += chunksNew[posNew].Size; countOld += chunksOld[posOld].Size;
for (; posNew < sizeNew && chunksNew[posNew].Modified; posNew++)
countNew += chunksNew[posNew].Size;
if (countOld + countNew == 0) continue; if (countOld + countNew == 0)
continue;
var diff = new TextInlineChange( var diff = new TextInlineChange(
countOld > 0 ? chunksOld[beginOld].Start : 0, countOld > 0 ? chunksOld[beginOld].Start : 0,
@ -120,13 +123,15 @@ namespace SourceGit.Models
var ch = text[i]; var ch = text[i];
if (delims.Contains(ch)) if (delims.Contains(ch))
{ {
if (start != i) AddChunk(chunks, hashes, text.Substring(start, i - start), start); if (start != i)
AddChunk(chunks, hashes, text.Substring(start, i - start), start);
AddChunk(chunks, hashes, text.Substring(i, 1), i); AddChunk(chunks, hashes, text.Substring(i, 1), i);
start = i + 1; start = i + 1;
} }
} }
if (start < size) AddChunk(chunks, hashes, text.Substring(start), start); if (start < size)
AddChunk(chunks, hashes, text.Substring(start), start);
return chunks; return chunks;
} }
@ -149,7 +154,8 @@ namespace SourceGit.Models
if (lenOld > 0 && lenNew > 0) if (lenOld > 0 && lenNew > 0)
{ {
var rs = CheckModifiedEdit(chunksOld, startOld, endOld, chunksNew, startNew, endNew, forward, reverse); var rs = CheckModifiedEdit(chunksOld, startOld, endOld, chunksNew, startNew, endNew, forward, reverse);
if (rs.State == Edit.None) return; if (rs.State == Edit.None)
return;
if (rs.State == Edit.DeletedRight && rs.DeleteStart - 1 > startOld) if (rs.State == Edit.DeletedRight && rs.DeleteStart - 1 > startOld)
{ {
@ -173,11 +179,13 @@ namespace SourceGit.Models
} }
else if (lenOld > 0) else if (lenOld > 0)
{ {
for (int i = startOld; i < endOld; i++) chunksOld[i].Modified = true; for (int i = startOld; i < endOld; i++)
chunksOld[i].Modified = true;
} }
else if (lenNew > 0) else if (lenNew > 0)
{ {
for (int i = startNew; i < endNew; i++) chunksNew[i].Modified = true; for (int i = startNew; i < endNew; i++)
chunksNew[i].Modified = true;
} }
} }

View file

@ -26,7 +26,8 @@ namespace SourceGit.Models
public static void SetThemeByApp(TextMate.Installation installation) public static void SetThemeByApp(TextMate.Installation installation)
{ {
if (installation == null) return; if (installation == null)
return;
var reg = installation.RegistryOptions as RegistryOptions; var reg = installation.RegistryOptions as RegistryOptions;
if (App.Current?.ActualThemeVariant == ThemeVariant.Dark) if (App.Current?.ActualThemeVariant == ThemeVariant.Dark)
@ -41,7 +42,8 @@ namespace SourceGit.Models
public static void SetGrammarByFileName(TextMate.Installation installation, string filePath) public static void SetGrammarByFileName(TextMate.Installation installation, string filePath)
{ {
if (installation == null) return; if (installation == null)
return;
var ext = Path.GetExtension(filePath); var ext = Path.GetExtension(filePath);
if (ext == ".h") if (ext == ".h")

View file

@ -4,15 +4,15 @@ namespace SourceGit.Models
{ {
public class User public class User
{ {
public static User Invalid = new User(); public static readonly User Invalid = new User();
public static Dictionary<string, User> Caches = new Dictionary<string, User>();
public string Name { get; set; } = string.Empty; public string Name { get; set; } = string.Empty;
public string Email { get; set; } = string.Empty; public string Email { get; set; } = string.Empty;
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
if (obj == null || !(obj is User)) return false; if (obj == null || !(obj is User))
return false;
var other = obj as User; var other = obj as User;
return Name == other.Name && Email == other.Email; return Name == other.Name && Email == other.Email;
@ -25,9 +25,9 @@ namespace SourceGit.Models
public static User FindOrAdd(string data) public static User FindOrAdd(string data)
{ {
if (Caches.ContainsKey(data)) if (_caches.TryGetValue(data, out var value))
{ {
return Caches[data]; return value;
} }
else else
{ {
@ -36,9 +36,11 @@ namespace SourceGit.Models
var email = data.Substring(nameEndIdx + 1); var email = data.Substring(nameEndIdx + 1);
User user = new User() { Name = name, Email = email }; User user = new User() { Name = name, Email = email };
Caches.Add(data, user); _caches.Add(data, user);
return user; return user;
} }
} }
private static Dictionary<string, User> _caches = new Dictionary<string, User>();
} }
} }

View file

@ -23,7 +23,8 @@ namespace SourceGit.Models
get get
{ {
var match = REG_VERSION_TAG().Match(TagName); var match = REG_VERSION_TAG().Match(TagName);
if (!match.Success) return false; if (!match.Success)
return false;
var major = int.Parse(match.Groups[1].Value); var major = int.Parse(match.Groups[1].Value);
var minor = int.Parse(match.Groups[2].Value); var minor = int.Parse(match.Groups[2].Value);

View file

@ -53,7 +53,8 @@ namespace SourceGit.Models
{ {
if (enabled) if (enabled)
{ {
if (_lockCount > 0) _lockCount--; if (_lockCount > 0)
_lockCount--;
} }
else else
{ {
@ -95,7 +96,8 @@ namespace SourceGit.Models
private void Tick(object sender) private void Tick(object sender)
{ {
if (_lockCount > 0) return; if (_lockCount > 0)
return;
var now = DateTime.Now.ToFileTime(); var now = DateTime.Now.ToFileTime();
if (_updateBranch > 0 && now > _updateBranch) if (_updateBranch > 0 && now > _updateBranch)
@ -153,7 +155,8 @@ namespace SourceGit.Models
private void OnRepositoryChanged(object o, FileSystemEventArgs e) private void OnRepositoryChanged(object o, FileSystemEventArgs e)
{ {
if (string.IsNullOrEmpty(e.Name)) return; if (string.IsNullOrEmpty(e.Name))
return;
var name = e.Name.Replace("\\", "/"); var name = e.Name.Replace("\\", "/");
if (name.StartsWith("modules", StringComparison.Ordinal)) if (name.StartsWith("modules", StringComparison.Ordinal))
@ -183,10 +186,12 @@ namespace SourceGit.Models
private void OnWorkingCopyChanged(object o, FileSystemEventArgs e) private void OnWorkingCopyChanged(object o, FileSystemEventArgs e)
{ {
if (string.IsNullOrEmpty(e.Name)) return; if (string.IsNullOrEmpty(e.Name))
return;
var name = e.Name.Replace("\\", "/"); var name = e.Name.Replace("\\", "/");
if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal)) return; if (name == ".git" || name.StartsWith(".git/", StringComparison.Ordinal))
return;
_updateWC = DateTime.Now.AddSeconds(1).ToFileTime(); _updateWC = DateTime.Now.AddSeconds(1).ToFileTime();
} }

View file

@ -25,21 +25,24 @@ namespace SourceGit.Native
public string FindGitExecutable() public string FindGitExecutable()
{ {
if (File.Exists("/usr/bin/git")) return "/usr/bin/git"; if (File.Exists("/usr/bin/git"))
return "/usr/bin/git";
return string.Empty; return string.Empty;
} }
public string FindVSCode() public string FindVSCode()
{ {
var toolPath = "/usr/share/code/code"; var toolPath = "/usr/share/code/code";
if (File.Exists(toolPath)) return toolPath; if (File.Exists(toolPath))
return toolPath;
return string.Empty; return string.Empty;
} }
public string FindFleet() public string FindFleet()
{ {
var toolPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/.local/share/JetBrains/Toolbox/apps/fleet/bin/Fleet"; var toolPath = $"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}/.local/share/JetBrains/Toolbox/apps/fleet/bin/Fleet";
if (File.Exists(toolPath)) return toolPath; if (File.Exists(toolPath))
return toolPath;
return string.Empty; return string.Empty;
} }

View file

@ -22,7 +22,8 @@ namespace SourceGit.Native
public string FindGitExecutable() public string FindGitExecutable()
{ {
if (File.Exists("/usr/bin/git")) return "/usr/bin/git"; if (File.Exists("/usr/bin/git"))
return "/usr/bin/git";
return string.Empty; return string.Empty;
} }

View file

@ -105,7 +105,8 @@ namespace SourceGit.Native
} }
var exePath = builder.ToString(); var exePath = builder.ToString();
if (string.IsNullOrEmpty(exePath)) return null; if (string.IsNullOrEmpty(exePath))
return null;
return exePath; return exePath;
} }
@ -123,14 +124,16 @@ namespace SourceGit.Native
} }
var toolPath = Environment.ExpandEnvironmentVariables($"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe"); var toolPath = Environment.ExpandEnvironmentVariables($"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\\AppData\\Local\\Programs\\Microsoft VS Code\\Code.exe");
if (File.Exists(toolPath)) return toolPath; if (File.Exists(toolPath))
return toolPath;
return string.Empty; return string.Empty;
} }
public string FindFleet() public string FindFleet()
{ {
var toolPath = Environment.ExpandEnvironmentVariables($"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\\AppData\\Local\\Programs\\Fleet\\Fleet.exe"); var toolPath = Environment.ExpandEnvironmentVariables($"{Environment.GetFolderPath(Environment.SpecialFolder.UserProfile)}\\AppData\\Local\\Programs\\Fleet\\Fleet.exe");
if (File.Exists(toolPath)) return toolPath; if (File.Exists(toolPath))
return toolPath;
return string.Empty; return string.Empty;
} }
@ -153,7 +156,8 @@ namespace SourceGit.Native
var startInfo = new ProcessStartInfo(); var startInfo = new ProcessStartInfo();
startInfo.UseShellExecute = true; startInfo.UseShellExecute = true;
startInfo.FileName = bash; startInfo.FileName = bash;
if (!string.IsNullOrEmpty(workdir) && Path.Exists(workdir)) startInfo.WorkingDirectory = workdir; if (!string.IsNullOrEmpty(workdir) && Path.Exists(workdir))
startInfo.WorkingDirectory = workdir;
Process.Start(startInfo); Process.Start(startInfo);
} }

View file

@ -21,7 +21,8 @@ namespace SourceGit.ViewModels
get => _url; get => _url;
set set
{ {
if (SetProperty(ref _url, value, true)) UseSSH = Models.Remote.IsSSH(value); if (SetProperty(ref _url, value, true))
UseSSH = Models.Remote.IsSSH(value);
} }
} }
@ -48,7 +49,8 @@ namespace SourceGit.ViewModels
if (ctx.ObjectInstance is AddRemote add) if (ctx.ObjectInstance is AddRemote add)
{ {
var exists = add._repo.Remotes.Find(x => x.Name == name); var exists = add._repo.Remotes.Find(x => x.Name == name);
if (exists != null) return new ValidationResult("A remote with given name already exists!!!"); if (exists != null)
return new ValidationResult("A remote with given name already exists!!!");
} }
return ValidationResult.Success; return ValidationResult.Success;
@ -58,10 +60,12 @@ namespace SourceGit.ViewModels
{ {
if (ctx.ObjectInstance is AddRemote add) if (ctx.ObjectInstance is AddRemote add)
{ {
if (!Models.Remote.IsValidURL(url)) return new ValidationResult("Bad remote URL format!!!"); if (!Models.Remote.IsValidURL(url))
return new ValidationResult("Bad remote URL format!!!");
var exists = add._repo.Remotes.Find(x => x.URL == url); var exists = add._repo.Remotes.Find(x => x.URL == url);
if (exists != null) return new ValidationResult("A remote with the same url already exists!!!"); if (exists != null)
return new ValidationResult("A remote with the same url already exists!!!");
} }
return ValidationResult.Success; return ValidationResult.Success;

View file

@ -36,7 +36,8 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateURL(string url, ValidationContext ctx) public static ValidationResult ValidateURL(string url, ValidationContext ctx)
{ {
if (!Models.Remote.IsValidURL(url)) return new ValidationResult("Invalid repository URL format"); if (!Models.Remote.IsValidURL(url))
return new ValidationResult("Invalid repository URL format");
return ValidationResult.Success; return ValidationResult.Success;
} }

View file

@ -58,7 +58,8 @@ namespace SourceGit.ViewModels
CallUIThread(() => CallUIThread(() =>
{ {
_repo.SetWatcherEnabled(true); _repo.SetWatcherEnabled(true);
if (succ) App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}"); if (succ)
App.SendNotification(_repo.FullPath, $"Save archive to : {_saveFile}");
}); });
return succ; return succ;

View file

@ -50,7 +50,8 @@ namespace SourceGit.ViewModels
public void NavigateToCommit(string commitSHA) public void NavigateToCommit(string commitSHA)
{ {
var repo = Preference.FindRepository(_repo); var repo = Preference.FindRepository(_repo);
if (repo != null) repo.NavigateToCommit(commitSHA); if (repo != null)
repo.NavigateToCommit(commitSHA);
} }
private readonly string _repo = string.Empty; private readonly string _repo = string.Empty;

View file

@ -14,7 +14,8 @@ namespace SourceGit.ViewModels
get => _remote; get => _remote;
set set
{ {
if (SetProperty(ref _remote, value, true)) UseSSH = Models.Remote.IsSSH(value); if (SetProperty(ref _remote, value, true))
UseSSH = Models.Remote.IsSSH(value);
} }
} }
@ -60,13 +61,15 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateRemote(string remote, ValidationContext _) public static ValidationResult ValidateRemote(string remote, ValidationContext _)
{ {
if (!Models.Remote.IsValidURL(remote)) return new ValidationResult("Invalid remote repository URL format"); if (!Models.Remote.IsValidURL(remote))
return new ValidationResult("Invalid remote repository URL format");
return ValidationResult.Success; return ValidationResult.Success;
} }
public static ValidationResult ValidateParentFolder(string folder, ValidationContext _) public static ValidationResult ValidateParentFolder(string folder, ValidationContext _)
{ {
if (!Directory.Exists(folder)) return new ValidationResult("Given path can NOT be found"); if (!Directory.Exists(folder))
return new ValidationResult("Given path can NOT be found");
return ValidationResult.Success; return ValidationResult.Success;
} }
@ -77,7 +80,8 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var cmd = new Commands.Clone(HostPageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs, SetProgressDescription); var cmd = new Commands.Clone(HostPageId, _parentFolder, _remote, _local, _useSSH ? _sshKey : "", _extraArgs, SetProgressDescription);
if (!cmd.Exec()) return false; if (!cmd.Exec())
return false;
var path = _parentFolder; var path = _parentFolder;
if (!string.IsNullOrEmpty(_local)) if (!string.IsNullOrEmpty(_local))
@ -87,7 +91,8 @@ namespace SourceGit.ViewModels
else else
{ {
var name = Path.GetFileName(_remote); var name = Path.GetFileName(_remote);
if (name.EndsWith(".git")) name = name.Substring(0, name.Length - 4); if (name.EndsWith(".git"))
name = name.Substring(0, name.Length - 4);
path = Path.GetFullPath(Path.Combine(path, name)); path = Path.GetFullPath(Path.Combine(path, name));
} }

View file

@ -30,7 +30,8 @@ namespace SourceGit.ViewModels
get => _commit; get => _commit;
set set
{ {
if (SetProperty(ref _commit, value)) Refresh(); if (SetProperty(ref _commit, value))
Refresh();
} }
} }
@ -153,15 +154,20 @@ namespace SourceGit.ViewModels
{ {
_repo = null; _repo = null;
_commit = null; _commit = null;
if (_changes != null) _changes.Clear(); if (_changes != null)
if (_visibleChanges != null) _visibleChanges.Clear(); _changes.Clear();
if (_changeTree != null) _changeTree.Clear(); if (_visibleChanges != null)
_visibleChanges.Clear();
if (_changeTree != null)
_changeTree.Clear();
_selectedChange = null; _selectedChange = null;
_selectedChangeNode = null; _selectedChangeNode = null;
_searchChangeFilter = null; _searchChangeFilter = null;
_diffContext = null; _diffContext = null;
if (_revisionFiles != null) _revisionFiles.Clear(); if (_revisionFiles != null)
if (_revisionFilesTree != null) _revisionFilesTree.Clear(); _revisionFiles.Clear();
if (_revisionFilesTree != null)
_revisionFilesTree.Clear();
_selectedRevisionFileNode = null; _selectedRevisionFileNode = null;
_searchFileFilter = null; _searchFileFilter = null;
_viewRevisionFileContent = null; _viewRevisionFileContent = null;
@ -171,7 +177,8 @@ namespace SourceGit.ViewModels
public void NavigateTo(string commitSHA) public void NavigateTo(string commitSHA)
{ {
var repo = Preference.FindRepository(_repo); var repo = Preference.FindRepository(_repo);
if (repo != null) repo.NavigateToCommit(commitSHA); if (repo != null)
repo.NavigateToCommit(commitSHA);
} }
public void ClearSearchChangeFilter() public void ClearSearchChangeFilter()
@ -278,7 +285,8 @@ namespace SourceGit.ViewModels
saveAs.Click += async (_, ev) => saveAs.Click += async (_, ev) =>
{ {
var topLevel = App.GetTopLevel(); var topLevel = App.GetTopLevel();
if (topLevel == null) return; if (topLevel == null)
return;
var options = new FolderPickerOpenOptions() { AllowMultiple = false }; var options = new FolderPickerOpenOptions() { AllowMultiple = false };
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options); var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
@ -316,8 +324,10 @@ namespace SourceGit.ViewModels
SelectedChange = null; SelectedChange = null;
RevisionFilesTree = null; RevisionFilesTree = null;
SelectedRevisionFileNode = null; SelectedRevisionFileNode = null;
if (_commit == null) return; if (_commit == null)
if (_cancelToken != null) _cancelToken.Requested = true; return;
if (_cancelToken != null)
_cancelToken.Requested = true;
_cancelToken = new Commands.Command.CancelToken(); _cancelToken = new Commands.Command.CancelToken();
var cmdChanges = new Commands.QueryCommitChanges(_repo, _commit.SHA) { Cancel = _cancelToken }; var cmdChanges = new Commands.QueryCommitChanges(_repo, _commit.SHA) { Cancel = _cancelToken };
@ -326,7 +336,8 @@ namespace SourceGit.ViewModels
Task.Run(() => Task.Run(() =>
{ {
var changes = cmdChanges.Result(); var changes = cmdChanges.Result();
if (cmdChanges.Cancel.Requested) return; if (cmdChanges.Cancel.Requested)
return;
var visible = changes; var visible = changes;
if (!string.IsNullOrWhiteSpace(_searchChangeFilter)) if (!string.IsNullOrWhiteSpace(_searchChangeFilter))
@ -353,7 +364,8 @@ namespace SourceGit.ViewModels
Task.Run(() => Task.Run(() =>
{ {
var files = cmdRevisionFiles.Result(); var files = cmdRevisionFiles.Result();
if (cmdRevisionFiles.Cancel.Requested) return; if (cmdRevisionFiles.Cancel.Requested)
return;
var visible = files; var visible = files;
if (!string.IsNullOrWhiteSpace(_searchFileFilter)) if (!string.IsNullOrWhiteSpace(_searchFileFilter))
@ -379,7 +391,8 @@ namespace SourceGit.ViewModels
private void RefreshVisibleChanges() private void RefreshVisibleChanges()
{ {
if (_changes == null) return; if (_changes == null)
return;
if (string.IsNullOrEmpty(_searchChangeFilter)) if (string.IsNullOrEmpty(_searchChangeFilter))
{ {
@ -404,7 +417,8 @@ namespace SourceGit.ViewModels
private void RefreshVisibleFiles() private void RefreshVisibleFiles()
{ {
if (_revisionFiles == null) return; if (_revisionFiles == null)
return;
var visible = _revisionFiles; var visible = _revisionFiles;
if (!string.IsNullOrWhiteSpace(_searchFileFilter)) if (!string.IsNullOrWhiteSpace(_searchFileFilter))

View file

@ -67,12 +67,14 @@ namespace SourceGit.ViewModels
public static ValidationResult ValidateBranchName(string name, ValidationContext ctx) public static ValidationResult ValidateBranchName(string name, ValidationContext ctx)
{ {
var creator = ctx.ObjectInstance as CreateBranch; var creator = ctx.ObjectInstance as CreateBranch;
if (creator == null) return new ValidationResult("Missing runtime context to create branch!"); if (creator == null)
return new ValidationResult("Missing runtime context to create branch!");
foreach (var b in creator._repo.Branches) foreach (var b in creator._repo.Branches)
{ {
var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}"; var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
if (test == name) return new ValidationResult("A branch with same name already exists!"); if (test == name)
return new ValidationResult("A branch with same name already exists!");
} }
return ValidationResult.Success; return ValidationResult.Success;

View file

@ -52,7 +52,8 @@ namespace SourceGit.ViewModels
if (creator != null) if (creator != null)
{ {
var found = creator._repo.Tags.Find(x => x.Name == name); var found = creator._repo.Tags.Find(x => x.Name == name);
if (found != null) return new ValidationResult("A tag with same name already exists!"); if (found != null)
return new ValidationResult("A tag with same name already exists!");
} }
return ValidationResult.Success; return ValidationResult.Success;
} }

View file

@ -21,7 +21,8 @@ namespace SourceGit.ViewModels
get => _url; get => _url;
set set
{ {
if (SetProperty(ref _url, value, true)) UseSSH = Models.Remote.IsSSH(value); if (SetProperty(ref _url, value, true))
UseSSH = Models.Remote.IsSSH(value);
} }
} }
@ -59,7 +60,8 @@ namespace SourceGit.ViewModels
{ {
foreach (var remote in edit._repo.Remotes) foreach (var remote in edit._repo.Remotes)
{ {
if (remote != edit._remote && name == remote.Name) new ValidationResult("A remote with given name already exists!!!"); if (remote != edit._remote && name == remote.Name)
new ValidationResult("A remote with given name already exists!!!");
} }
} }
@ -70,11 +72,13 @@ namespace SourceGit.ViewModels
{ {
if (ctx.ObjectInstance is EditRemote edit) if (ctx.ObjectInstance is EditRemote edit)
{ {
if (!Models.Remote.IsValidURL(url)) return new ValidationResult("Bad remote URL format!!!"); if (!Models.Remote.IsValidURL(url))
return new ValidationResult("Bad remote URL format!!!");
foreach (var remote in edit._repo.Remotes) foreach (var remote in edit._repo.Remotes)
{ {
if (remote != edit._remote && url == remote.URL) new ValidationResult("A remote with the same url already exists!!!"); if (remote != edit._remote && url == remote.URL)
new ValidationResult("A remote with the same url already exists!!!");
} }
} }
@ -91,13 +95,15 @@ namespace SourceGit.ViewModels
if (_remote.Name != _name) if (_remote.Name != _name)
{ {
var succ = new Commands.Remote(_repo.FullPath).Rename(_remote.Name, _name); var succ = new Commands.Remote(_repo.FullPath).Rename(_remote.Name, _name);
if (succ) _remote.Name = _name; if (succ)
_remote.Name = _name;
} }
if (_remote.URL != _url) if (_remote.URL != _url)
{ {
var succ = new Commands.Remote(_repo.FullPath).SetURL(_name, _url); var succ = new Commands.Remote(_repo.FullPath).SetURL(_name, _url);
if (succ) _remote.URL = _url; if (succ)
_remote.URL = _url;
} }
if (_useSSH) if (_useSSH)

View file

@ -67,7 +67,8 @@ namespace SourceGit.ViewModels
{ {
IsLoading = false; IsLoading = false;
Commits = commits; Commits = commits;
if (commits.Count > 0) SelectedCommit = commits[0]; if (commits.Count > 0)
SelectedCommit = commits[0];
}); });
}); });
} }

View file

@ -45,9 +45,9 @@ namespace SourceGit.ViewModels
while (sepIdx != -1) while (sepIdx != -1)
{ {
var folder = c.Path.Substring(0, sepIdx); var folder = c.Path.Substring(0, sepIdx);
if (folders.ContainsKey(folder)) if (folders.TryGetValue(folder, out var value))
{ {
lastFolder = folders[folder]; lastFolder = value;
} }
else if (lastFolder == null) else if (lastFolder == null)
{ {
@ -121,9 +121,9 @@ namespace SourceGit.ViewModels
while (sepIdx != -1) while (sepIdx != -1)
{ {
var folder = f.Path.Substring(0, sepIdx); var folder = f.Path.Substring(0, sepIdx);
if (folders.ContainsKey(folder)) if (folders.TryGetValue(folder, out var value))
{ {
lastFolder = folders[folder]; lastFolder = value;
} }
else if (lastFolder == null) else if (lastFolder == null)
{ {
@ -174,7 +174,8 @@ namespace SourceGit.ViewModels
{ {
foreach (var node in nodes) foreach (var node in nodes)
{ {
if (node.FullPath == path) return node; if (node.FullPath == path)
return node;
if (node.IsFolder && path.StartsWith(node.FullPath + "/", StringComparison.Ordinal)) if (node.IsFolder && path.StartsWith(node.FullPath + "/", StringComparison.Ordinal))
{ {
@ -206,7 +207,8 @@ namespace SourceGit.ViewModels
foreach (var node in nodes) foreach (var node in nodes)
{ {
if (node.Children.Count > 1) Sort(node.Children); if (node.Children.Count > 1)
Sort(node.Children);
} }
} }

View file

@ -52,7 +52,8 @@ namespace SourceGit.ViewModels
foreach (var b in starter._repo.Branches) foreach (var b in starter._repo.Branches)
{ {
var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}"; var test = b.IsLocal ? b.Name : $"{b.Remote}/{b.Name}";
if (test == check) return new ValidationResult("A branch with same name already exists!"); if (test == check)
return new ValidationResult("A branch with same name already exists!");
} }
} }

View file

@ -149,10 +149,12 @@ namespace SourceGit.ViewModels
public ContextMenu MakeContextMenu() public ContextMenu MakeContextMenu()
{ {
var detail = _detailContext as CommitDetail; var detail = _detailContext as CommitDetail;
if (detail == null) return null; if (detail == null)
return null;
var current = _repo.Branches.Find(x => x.IsCurrent); var current = _repo.Branches.Find(x => x.IsCurrent);
if (current == null) return null; if (current == null)
return null;
var commit = detail.Commit; var commit = detail.Commit;
var menu = new ContextMenu(); var menu = new ContextMenu();
@ -179,16 +181,19 @@ namespace SourceGit.ViewModels
else if (d.Type == Models.DecoratorType.Tag) else if (d.Type == Models.DecoratorType.Tag)
{ {
var t = _repo.Tags.Find(x => x.Name == d.Name); var t = _repo.Tags.Find(x => x.Name == d.Name);
if (t != null) tags.Add(t); if (t != null)
tags.Add(t);
} }
} }
if (menu.Items.Count > 0) menu.Items.Add(new MenuItem() { Header = "-" }); if (menu.Items.Count > 0)
menu.Items.Add(new MenuItem() { Header = "-" });
} }
if (tags.Count > 0) if (tags.Count > 0)
{ {
foreach (var tag in tags) FillTagMenu(menu, tag); foreach (var tag in tags)
FillTagMenu(menu, tag);
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
} }
@ -199,7 +204,8 @@ namespace SourceGit.ViewModels
reset.Icon = App.CreateMenuIcon("Icons.Reset"); reset.Icon = App.CreateMenuIcon("Icons.Reset");
reset.Click += (o, e) => reset.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Reset(_repo, current, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Reset(_repo, current, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(reset); menu.Items.Add(reset);
@ -211,7 +217,8 @@ namespace SourceGit.ViewModels
reword.Icon = App.CreateMenuIcon("Icons.Edit"); reword.Icon = App.CreateMenuIcon("Icons.Edit");
reword.Click += (o, e) => reword.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Reword(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Reword(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(reword); menu.Items.Add(reword);
@ -225,7 +232,8 @@ namespace SourceGit.ViewModels
if (commit.Parents.Count == 1) if (commit.Parents.Count == 1)
{ {
var parent = _commits.Find(x => x.SHA == commit.Parents[0]); var parent = _commits.Find(x => x.SHA == commit.Parents[0]);
if (parent != null && PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Squash(_repo, commit, parent)); if (parent != null && PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Squash(_repo, commit, parent));
} }
e.Handled = true; e.Handled = true;
@ -240,7 +248,8 @@ namespace SourceGit.ViewModels
rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
rebase.Click += (o, e) => rebase.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Rebase(_repo, current, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Rebase(_repo, current, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(rebase); menu.Items.Add(rebase);
@ -250,7 +259,8 @@ namespace SourceGit.ViewModels
cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick"); cherryPick.Icon = App.CreateMenuIcon("Icons.CherryPick");
cherryPick.Click += (o, e) => cherryPick.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CherryPick(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CherryPick(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(cherryPick); menu.Items.Add(cherryPick);
@ -262,7 +272,8 @@ namespace SourceGit.ViewModels
revert.Icon = App.CreateMenuIcon("Icons.Undo"); revert.Icon = App.CreateMenuIcon("Icons.Undo");
revert.Click += (o, e) => revert.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Revert(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Revert(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(revert); menu.Items.Add(revert);
@ -275,7 +286,8 @@ namespace SourceGit.ViewModels
createBranch.Header = App.Text("CreateBranch"); createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, e) => createBranch.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(createBranch); menu.Items.Add(createBranch);
@ -285,7 +297,8 @@ namespace SourceGit.ViewModels
createTag.Header = App.Text("CreateTag"); createTag.Header = App.Text("CreateTag");
createTag.Click += (o, e) => createTag.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateTag(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateTag(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(createTag); menu.Items.Add(createTag);
@ -297,14 +310,16 @@ namespace SourceGit.ViewModels
saveToPatch.Click += async (_, e) => saveToPatch.Click += async (_, e) =>
{ {
var topLevel = App.GetTopLevel(); var topLevel = App.GetTopLevel();
if (topLevel == null) return; if (topLevel == null)
return;
var options = new FolderPickerOpenOptions() { AllowMultiple = false }; var options = new FolderPickerOpenOptions() { AllowMultiple = false };
var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options); var selected = await topLevel.StorageProvider.OpenFolderPickerAsync(options);
if (selected.Count == 1) if (selected.Count == 1)
{ {
var succ = new Commands.FormatPatch(_repo.FullPath, commit.SHA, selected[0].Path.LocalPath).Exec(); var succ = new Commands.FormatPatch(_repo.FullPath, commit.SHA, selected[0].Path.LocalPath).Exec();
if (succ) App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess")); if (succ)
App.SendNotification(_repo.FullPath, App.Text("SaveAsPatchSuccess"));
} }
e.Handled = true; e.Handled = true;
@ -316,7 +331,8 @@ namespace SourceGit.ViewModels
archive.Header = App.Text("Archive"); archive.Header = App.Text("Archive");
archive.Click += (o, e) => archive.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Archive(_repo, commit)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Archive(_repo, commit));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(archive); menu.Items.Add(archive);
@ -347,10 +363,12 @@ namespace SourceGit.ViewModels
var fastForward = new MenuItem(); var fastForward = new MenuItem();
fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream); fastForward.Header = new Views.NameHighlightedTextBlock("BranchCM.FastForward", upstream);
fastForward.Icon = App.CreateMenuIcon("Icons.FastForward"); fastForward.Icon = App.CreateMenuIcon("Icons.FastForward");
fastForward.IsEnabled = !string.IsNullOrEmpty(current.UpstreamTrackStatus) && current.UpstreamTrackStatus.IndexOf('↑') < 0; ; fastForward.IsEnabled = !string.IsNullOrEmpty(current.UpstreamTrackStatus) && current.UpstreamTrackStatus.IndexOf('↑') < 0;
;
fastForward.Click += (o, e) => fastForward.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Merge(_repo, upstream, current.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Merge(_repo, upstream, current.Name));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(fastForward); submenu.Items.Add(fastForward);
@ -360,7 +378,8 @@ namespace SourceGit.ViewModels
pull.Icon = App.CreateMenuIcon("Icons.Pull"); pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.Click += (o, e) => pull.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Pull(_repo, null)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Pull(_repo, null));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(pull); submenu.Items.Add(pull);
@ -372,7 +391,8 @@ namespace SourceGit.ViewModels
push.IsEnabled = _repo.Remotes.Count > 0; push.IsEnabled = _repo.Remotes.Count > 0;
push.Click += (o, e) => push.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Push(_repo, current)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Push(_repo, current));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(push); submenu.Items.Add(push);
@ -386,7 +406,8 @@ namespace SourceGit.ViewModels
finish.Icon = App.CreateMenuIcon("Icons.Flow"); finish.Icon = App.CreateMenuIcon("Icons.Flow");
finish.Click += (o, e) => finish.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowFinish(_repo, current, type)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowFinish(_repo, current, type));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(finish); submenu.Items.Add(finish);
@ -398,7 +419,8 @@ namespace SourceGit.ViewModels
rename.Icon = App.CreateMenuIcon("Icons.Rename"); rename.Icon = App.CreateMenuIcon("Icons.Rename");
rename.Click += (o, e) => rename.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new RenameBranch(_repo, current)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new RenameBranch(_repo, current));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(rename); submenu.Items.Add(rename);
@ -417,7 +439,8 @@ namespace SourceGit.ViewModels
checkout.Icon = App.CreateMenuIcon("Icons.Check"); checkout.Icon = App.CreateMenuIcon("Icons.Check");
checkout.Click += (o, e) => checkout.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Checkout(_repo, branch.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Checkout(_repo, branch.Name));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(checkout); submenu.Items.Add(checkout);
@ -428,7 +451,8 @@ namespace SourceGit.ViewModels
merge.IsEnabled = !merged; merge.IsEnabled = !merged;
merge.Click += (o, e) => merge.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Merge(_repo, branch.Name, current.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Merge(_repo, branch.Name, current.Name));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(merge); submenu.Items.Add(merge);
@ -442,7 +466,8 @@ namespace SourceGit.ViewModels
finish.Icon = App.CreateMenuIcon("Icons.Flow"); finish.Icon = App.CreateMenuIcon("Icons.Flow");
finish.Click += (o, e) => finish.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowFinish(_repo, branch, type)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowFinish(_repo, branch, type));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(finish); submenu.Items.Add(finish);
@ -454,7 +479,8 @@ namespace SourceGit.ViewModels
rename.Icon = App.CreateMenuIcon("Icons.Rename"); rename.Icon = App.CreateMenuIcon("Icons.Rename");
rename.Click += (o, e) => rename.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new RenameBranch(_repo, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new RenameBranch(_repo, branch));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(rename); submenu.Items.Add(rename);
@ -464,7 +490,8 @@ namespace SourceGit.ViewModels
delete.Icon = App.CreateMenuIcon("Icons.Clear"); delete.Icon = App.CreateMenuIcon("Icons.Clear");
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteBranch(_repo, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteBranch(_repo, branch));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(delete); submenu.Items.Add(delete);
@ -489,13 +516,16 @@ namespace SourceGit.ViewModels
{ {
if (b.IsLocal && b.Upstream == branch.FullName) if (b.IsLocal && b.Upstream == branch.FullName)
{ {
if (b.IsCurrent) return; if (b.IsCurrent)
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Checkout(_repo, b.Name)); return;
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Checkout(_repo, b.Name));
return; return;
} }
} }
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(_repo, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(_repo, branch));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(checkout); submenu.Items.Add(checkout);
@ -506,7 +536,8 @@ namespace SourceGit.ViewModels
merge.IsEnabled = !merged; merge.IsEnabled = !merged;
merge.Click += (o, e) => merge.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Merge(_repo, name, current.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Merge(_repo, name, current.Name));
e.Handled = true; e.Handled = true;
}; };
@ -518,7 +549,8 @@ namespace SourceGit.ViewModels
delete.Icon = App.CreateMenuIcon("Icons.Clear"); delete.Icon = App.CreateMenuIcon("Icons.Clear");
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteBranch(_repo, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteBranch(_repo, branch));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(delete); submenu.Items.Add(delete);
@ -539,7 +571,8 @@ namespace SourceGit.ViewModels
push.IsEnabled = _repo.Remotes.Count > 0; push.IsEnabled = _repo.Remotes.Count > 0;
push.Click += (o, e) => push.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new PushTag(_repo, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new PushTag(_repo, tag));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(push); submenu.Items.Add(push);
@ -549,7 +582,8 @@ namespace SourceGit.ViewModels
delete.Icon = App.CreateMenuIcon("Icons.Clear"); delete.Icon = App.CreateMenuIcon("Icons.Clear");
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteTag(_repo, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteTag(_repo, tag));
e.Handled = true; e.Handled = true;
}; };
submenu.Items.Add(delete); submenu.Items.Add(delete);

View file

@ -24,7 +24,8 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = new Commands.Init(HostPageId, _targetPath).Exec(); var succ = new Commands.Init(HostPageId, _targetPath).Exec();
if (!succ) return false; if (!succ)
return false;
var gitDir = Path.GetFullPath(Path.Combine(_targetPath, ".git")); var gitDir = Path.GetFullPath(Path.Combine(_targetPath, ".git"));

View file

@ -69,7 +69,8 @@ namespace SourceGit.ViewModels
{ {
if (ctx.ObjectInstance is InitGitFlow initializer) if (ctx.ObjectInstance is InitGitFlow initializer)
{ {
if (initializer._master == initializer._develop) return new ValidationResult("Develop branch has the same name with master branch!"); if (initializer._master == initializer._develop)
return new ValidationResult("Develop branch has the same name with master branch!");
} }
return ValidationResult.Success; return ValidationResult.Success;

View file

@ -37,7 +37,8 @@ namespace SourceGit.ViewModels
foreach (var id in Preference.Instance.OpenedTabs) foreach (var id in Preference.Instance.OpenedTabs)
{ {
var node = Preference.FindNode(id); var node = Preference.FindNode(id);
if (node == null) continue; if (node == null)
continue;
OpenRepositoryInTab(node, null); OpenRepositoryInTab(node, null);
} }
@ -58,7 +59,8 @@ namespace SourceGit.ViewModels
{ {
foreach (var page in Pages) foreach (var page in Pages)
{ {
if (page.Node.IsRepository) Preference.Instance.OpenedTabs.Add(page.Node.Id); if (page.Node.IsRepository)
Preference.Instance.OpenedTabs.Add(page.Node.Id);
} }
} }
@ -83,7 +85,8 @@ namespace SourceGit.ViewModels
public void GotoNextTab() public void GotoNextTab()
{ {
if (Pages.Count == 1) return; if (Pages.Count == 1)
return;
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);
var nextIdx = (activeIdx + 1) % Pages.Count; var nextIdx = (activeIdx + 1) % Pages.Count;
@ -99,7 +102,8 @@ namespace SourceGit.ViewModels
} }
LauncherPage page = param as LauncherPage; LauncherPage page = param as LauncherPage;
if (page == null) page = _activePage; if (page == null)
page = _activePage;
var removeIdx = Pages.IndexOf(page); var removeIdx = Pages.IndexOf(page);
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);
@ -135,16 +139,19 @@ namespace SourceGit.ViewModels
public void CloseOtherTabs(object param) public void CloseOtherTabs(object param)
{ {
if (Pages.Count == 1) return; if (Pages.Count == 1)
return;
var page = param as LauncherPage; var page = param as LauncherPage;
if (page == null) page = _activePage; if (page == null)
page = _activePage;
ActivePage = page; ActivePage = page;
foreach (var one in Pages) foreach (var one in Pages)
{ {
if (one.Node.Id != page.Node.Id) CloseRepositoryInTab(one); if (one.Node.Id != page.Node.Id)
CloseRepositoryInTab(one);
} }
Pages = new AvaloniaList<LauncherPage> { page }; Pages = new AvaloniaList<LauncherPage> { page };
@ -156,7 +163,8 @@ namespace SourceGit.ViewModels
public void CloseRightTabs(object param) public void CloseRightTabs(object param)
{ {
LauncherPage page = param as LauncherPage; LauncherPage page = param as LauncherPage;
if (page == null) page = _activePage; if (page == null)
page = _activePage;
var endIdx = Pages.IndexOf(page); var endIdx = Pages.IndexOf(page);
var activeIdx = Pages.IndexOf(_activePage); var activeIdx = Pages.IndexOf(_activePage);

View file

@ -49,7 +49,8 @@ namespace SourceGit.ViewModels
public void CopyPath() public void CopyPath()
{ {
if (_node.IsRepository) App.CopyText(_node.Id); if (_node.IsRepository)
App.CopyText(_node.Id);
} }
public void DismissNotification(object param) public void DismissNotification(object param)

View file

@ -37,7 +37,8 @@ namespace SourceGit.ViewModels
[UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode")] [UnconditionalSuppressMessage("AssemblyLoadTrimming", "IL2026:RequiresUnreferencedCode")]
public bool Check() public bool Check()
{ {
if (HasErrors) return false; if (HasErrors)
return false;
ValidateAllProperties(); ValidateAllProperties();
return !HasErrors; return !HasErrors;
} }

View file

@ -44,7 +44,8 @@ namespace SourceGit.ViewModels
{ {
if (_popup != null) if (_popup != null)
{ {
if (!_popup.Check()) return; if (!_popup.Check())
return;
_popup.InProgress = true; _popup.InProgress = true;
var task = _popup.Sure(); var task = _popup.Sure();
@ -69,8 +70,10 @@ namespace SourceGit.ViewModels
public void CancelPopup() public void CancelPopup()
{ {
if (_popup == null) return; if (_popup == null)
if (_popup.InProgress) return; return;
if (_popup.InProgress)
return;
Popup = null; Popup = null;
} }

View file

@ -228,8 +228,10 @@ namespace SourceGit.ViewModels
if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMergeTools.Supported.Count) if (changed && !OperatingSystem.IsWindows() && value > 0 && value < Models.ExternalMergeTools.Supported.Count)
{ {
var tool = Models.ExternalMergeTools.Supported[value]; var tool = Models.ExternalMergeTools.Supported[value];
if (File.Exists(tool.Exec)) ExternalMergeToolPath = tool.Exec; if (File.Exists(tool.Exec))
else ExternalMergeToolPath = string.Empty; ExternalMergeToolPath = tool.Exec;
else
ExternalMergeToolPath = string.Empty;
} }
} }
} }
@ -308,8 +310,10 @@ namespace SourceGit.ViewModels
public static void MoveNode(RepositoryNode node, RepositoryNode to = null) public static void MoveNode(RepositoryNode node, RepositoryNode to = null)
{ {
if (to == null && _instance._repositoryNodes.Contains(node)) return; if (to == null && _instance._repositoryNodes.Contains(node))
if (to != null && to.SubNodes.Contains(node)) return; return;
if (to != null && to.SubNodes.Contains(node))
return;
RemoveNode(node); RemoveNode(node);
AddNode(node, to); AddNode(node, to);
@ -324,7 +328,8 @@ namespace SourceGit.ViewModels
{ {
foreach (var repo in _instance.Repositories) foreach (var repo in _instance.Repositories)
{ {
if (repo.FullPath == path) return repo; if (repo.FullPath == path)
return repo;
} }
return null; return null;
} }
@ -352,7 +357,8 @@ namespace SourceGit.ViewModels
public static void Save() public static void Save()
{ {
var dir = Path.GetDirectoryName(_savePath); var dir = Path.GetDirectoryName(_savePath);
if (!Directory.Exists(dir)) Directory.CreateDirectory(dir); if (!Directory.Exists(dir))
Directory.CreateDirectory(dir);
var data = JsonSerializer.Serialize(_instance, JsonCodeGen.Default.Preference); var data = JsonSerializer.Serialize(_instance, JsonCodeGen.Default.Preference);
File.WriteAllText(_savePath, data); File.WriteAllText(_savePath, data);
@ -362,10 +368,12 @@ namespace SourceGit.ViewModels
{ {
foreach (var node in collection) foreach (var node in collection)
{ {
if (node.Id == id) return node; if (node.Id == id)
return node;
var sub = FindNodeRecursive(id, node.SubNodes); var sub = FindNodeRecursive(id, node.SubNodes);
if (sub != null) return sub; if (sub != null)
return sub;
} }
return null; return null;
@ -381,7 +389,8 @@ namespace SourceGit.ViewModels
foreach (RepositoryNode one in collection) foreach (RepositoryNode one in collection)
{ {
if (RemoveNodeRecursive(node, one.SubNodes)) return true; if (RemoveNodeRecursive(node, one.SubNodes))
return true;
} }
return false; return false;

View file

@ -25,7 +25,8 @@ namespace SourceGit.ViewModels
var branches = new List<Models.Branch>(); var branches = new List<Models.Branch>();
foreach (var branch in _repo.Branches) foreach (var branch in _repo.Branches)
{ {
if (branch.Remote == value.Name) branches.Add(branch); if (branch.Remote == value.Name)
branches.Add(branch);
} }
RemoteBranches = branches; RemoteBranches = branches;
SelectedBranch = branches.Count > 0 ? branches[0] : null; SelectedBranch = branches.Count > 0 ? branches[0] : null;
@ -98,7 +99,8 @@ namespace SourceGit.ViewModels
_remoteBranches = new List<Models.Branch>(); _remoteBranches = new List<Models.Branch>();
foreach (var branch in _repo.Branches) foreach (var branch in _repo.Branches)
{ {
if (branch.Remote == _selectedRemote.Name) _remoteBranches.Add(branch); if (branch.Remote == _selectedRemote.Name)
_remoteBranches.Add(branch);
} }
if (_selectedBranch == null && _remoteBranches.Count > 0) if (_selectedBranch == null && _remoteBranches.Count > 0)

View file

@ -58,7 +58,8 @@ namespace SourceGit.ViewModels
get => _selectedRemote; get => _selectedRemote;
set set
{ {
if (SetProperty(ref _selectedRemote, value)) AutoSelectBranchByRemote(); if (SetProperty(ref _selectedRemote, value))
AutoSelectBranchByRemote();
} }
} }
@ -96,8 +97,10 @@ namespace SourceGit.ViewModels
var current = null as Models.Branch; var current = null as Models.Branch;
foreach (var branch in _repo.Branches) foreach (var branch in _repo.Branches)
{ {
if (branch.IsLocal) LocalBranches.Add(branch); if (branch.IsLocal)
if (branch.IsCurrent) current = branch; LocalBranches.Add(branch);
if (branch.IsCurrent)
current = branch;
} }
// Set default selected local branch. // Set default selected local branch.
@ -126,7 +129,8 @@ namespace SourceGit.ViewModels
} }
// Set default remote to the first if haven't been set. // Set default remote to the first if haven't been set.
if (_selectedRemote == null) _selectedRemote = repo.Remotes[0]; if (_selectedRemote == null)
_selectedRemote = repo.Remotes[0];
// Auto select preferred remote branch. // Auto select preferred remote branch.
AutoSelectBranchByRemote(); AutoSelectBranchByRemote();
@ -163,7 +167,8 @@ namespace SourceGit.ViewModels
var branches = new List<Models.Branch>(); var branches = new List<Models.Branch>();
foreach (var branch in _repo.Branches) foreach (var branch in _repo.Branches)
{ {
if (branch.Remote == _selectedRemote.Name) branches.Add(branch); if (branch.Remote == _selectedRemote.Name)
branches.Add(branch);
} }
// If selected local branch has upstream branch. Try to find it in current remote branches. // If selected local branch has upstream branch. Try to find it in current remote branches.

View file

@ -46,7 +46,8 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
if (_name == Target.Name) return null; if (_name == Target.Name)
return null;
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
ProgressDescription = $"Rename '{Target.Name}'"; ProgressDescription = $"Rename '{Target.Name}'";

View file

@ -185,7 +185,8 @@ namespace SourceGit.ViewModels
{ {
SearchedCommits = new List<Models.Commit>(); SearchedCommits = new List<Models.Commit>();
SearchCommitFilter = string.Empty; SearchCommitFilter = string.Empty;
if (value) SelectedViewIndex = 0; if (value)
SelectedViewIndex = 0;
} }
} }
} }
@ -292,7 +293,8 @@ namespace SourceGit.ViewModels
public void Fetch() public void Fetch()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
if (Remotes.Count == 0) if (Remotes.Count == 0)
{ {
@ -305,7 +307,8 @@ namespace SourceGit.ViewModels
public void Pull() public void Pull()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
if (Remotes.Count == 0) if (Remotes.Count == 0)
{ {
@ -318,7 +321,8 @@ namespace SourceGit.ViewModels
public void Push() public void Push()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
if (Remotes.Count == 0) if (Remotes.Count == 0)
{ {
@ -326,25 +330,29 @@ namespace SourceGit.ViewModels
return; return;
} }
if (Branches.Find(x => x.IsCurrent) == null) App.RaiseException(_fullpath, "Can NOT found current branch!!!"); if (Branches.Find(x => x.IsCurrent) == null)
App.RaiseException(_fullpath, "Can NOT found current branch!!!");
PopupHost.ShowPopup(new Push(this, null)); PopupHost.ShowPopup(new Push(this, null));
} }
public void ApplyPatch() public void ApplyPatch()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
PopupHost.ShowPopup(new Apply(this)); PopupHost.ShowPopup(new Apply(this));
} }
public void Cleanup() public void Cleanup()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
PopupHost.ShowAndStartPopup(new Cleanup(this)); PopupHost.ShowAndStartPopup(new Cleanup(this));
} }
public void OpenConfigure() public void OpenConfigure()
{ {
if (!PopupHost.CanCreatePopup()) return; if (!PopupHost.CanCreatePopup())
return;
PopupHost.ShowPopup(new RepositoryConfigure(this)); PopupHost.ShowPopup(new RepositoryConfigure(this));
} }
@ -355,7 +363,8 @@ namespace SourceGit.ViewModels
public void StartSearchCommits() public void StartSearchCommits()
{ {
if (_histories == null) return; if (_histories == null)
return;
var visible = new List<Models.Commit>(); var visible = new List<Models.Commit>();
foreach (var c in _histories.Commits) foreach (var c in _histories.Commits)
@ -377,17 +386,20 @@ namespace SourceGit.ViewModels
public void SetWatcherEnabled(bool enabled) public void SetWatcherEnabled(bool enabled)
{ {
if (_watcher != null) _watcher.SetEnabled(enabled); if (_watcher != null)
_watcher.SetEnabled(enabled);
} }
public void MarkBranchesDirtyManually() public void MarkBranchesDirtyManually()
{ {
if (_watcher != null) _watcher.MarkBranchDirtyManually(); if (_watcher != null)
_watcher.MarkBranchDirtyManually();
} }
public void MarkWorkingCopyDirtyManually() public void MarkWorkingCopyDirtyManually()
{ {
if (_watcher != null) _watcher.MarkWorkingCopyDirtyManually(); if (_watcher != null)
_watcher.MarkWorkingCopyDirtyManually();
} }
public void NavigateToCommit(string sha) public void NavigateToCommit(string sha)
@ -415,7 +427,8 @@ namespace SourceGit.ViewModels
changed = Filters.Remove(filter); changed = Filters.Remove(filter);
} }
if (changed) Task.Run(RefreshCommits); if (changed)
Task.Run(RefreshCommits);
} }
public void StashAll() public void StashAll()
@ -431,7 +444,8 @@ namespace SourceGit.ViewModels
public void GotoResolve() public void GotoResolve()
{ {
if (_workingCopy != null) SelectedViewIndex = 1; if (_workingCopy != null)
SelectedViewIndex = 1;
} }
public async void ContinueMerge() public async void ContinueMerge()
@ -476,12 +490,15 @@ namespace SourceGit.ViewModels
if (succ) if (succ)
{ {
if (_workingCopy != null) _workingCopy.CommitMessage = string.Empty; if (_workingCopy != null)
_workingCopy.CommitMessage = string.Empty;
if (mode == "rebase") if (mode == "rebase")
{ {
if (File.Exists(rebaseMerge)) File.Delete(rebaseMerge); if (File.Exists(rebaseMerge))
if (Directory.Exists(rebaseMergeFolder)) Directory.Delete(rebaseMergeFolder); File.Delete(rebaseMerge);
if (Directory.Exists(rebaseMergeFolder))
Directory.Delete(rebaseMergeFolder);
} }
} }
} }
@ -545,7 +562,8 @@ namespace SourceGit.ViewModels
public void RefreshTags() public void RefreshTags()
{ {
var tags = new Commands.QueryTags(FullPath).Result(); var tags = new Commands.QueryTags(FullPath).Result();
foreach (var tag in tags) tag.IsFiltered = Filters.Contains(tag.Name); foreach (var tag in tags)
tag.IsFiltered = Filters.Contains(tag.Name);
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
Tags = tags; Tags = tags;
@ -562,11 +580,13 @@ namespace SourceGit.ViewModels
{ {
if (filter.StartsWith("refs/", StringComparison.Ordinal)) if (filter.StartsWith("refs/", StringComparison.Ordinal))
{ {
if (_branches.FindIndex(x => x.FullName == filter) >= 0) validFilters.Add(filter); if (_branches.FindIndex(x => x.FullName == filter) >= 0)
validFilters.Add(filter);
} }
else else
{ {
if (_tags.FindIndex(t => t.Name == filter) >= 0) validFilters.Add(filter); if (_tags.FindIndex(t => t.Name == filter) >= 0)
validFilters.Add(filter);
} }
} }
if (validFilters.Count > 0) if (validFilters.Count > 0)
@ -615,9 +635,11 @@ namespace SourceGit.ViewModels
if (!runningMerge) if (!runningMerge)
{ {
if (Directory.Exists(rebaseMergeFolder)) Directory.Delete(rebaseMergeFolder, true); if (Directory.Exists(rebaseMergeFolder))
Directory.Delete(rebaseMergeFolder, true);
var applyFolder = Path.Combine(_gitDir, "rebase-apply"); var applyFolder = Path.Combine(_gitDir, "rebase-apply");
if (Directory.Exists(applyFolder)) Directory.Delete(applyFolder, true); if (Directory.Exists(applyFolder))
Directory.Delete(applyFolder, true);
} }
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
@ -633,7 +655,8 @@ namespace SourceGit.ViewModels
var stashes = new Commands.QueryStashes(FullPath).Result(); var stashes = new Commands.QueryStashes(FullPath).Result();
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
if (_stashesPage != null) _stashesPage.Stashes = stashes; if (_stashesPage != null)
_stashesPage.Stashes = stashes;
OnPropertyChanged(nameof(StashesCount)); OnPropertyChanged(nameof(StashesCount));
}); });
} }
@ -642,9 +665,12 @@ namespace SourceGit.ViewModels
{ {
var config = new Commands.Config(_fullpath).ListAll(); var config = new Commands.Config(_fullpath).ListAll();
var gitFlow = new Models.GitFlow(); var gitFlow = new Models.GitFlow();
if (config.ContainsKey("gitflow.prefix.feature")) gitFlow.Feature = config["gitflow.prefix.feature"]; if (config.TryGetValue("gitflow.prefix.feature", out var feature))
if (config.ContainsKey("gitflow.prefix.release")) gitFlow.Release = config["gitflow.prefix.release"]; gitFlow.Feature = feature;
if (config.ContainsKey("gitflow.prefix.hotfix")) gitFlow.Hotfix = config["gitflow.prefix.hotfix"]; if (config.TryGetValue("gitflow.prefix.release", out var release))
gitFlow.Release = release;
if (config.TryGetValue("gitflow.prefix.hotfix", out var hotfix))
gitFlow.Hotfix = hotfix;
Dispatcher.UIThread.Invoke(() => Dispatcher.UIThread.Invoke(() =>
{ {
GitFlow = gitFlow; GitFlow = gitFlow;
@ -660,7 +686,8 @@ namespace SourceGit.ViewModels
return; return;
} }
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(this, current)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(this, current));
} }
public void CreateNewTag() public void CreateNewTag()
@ -672,17 +699,20 @@ namespace SourceGit.ViewModels
return; return;
} }
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateTag(this, current)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateTag(this, current));
} }
public void AddRemote() public void AddRemote()
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new AddRemote(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new AddRemote(this));
} }
public void AddSubmodule() public void AddSubmodule()
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new AddSubmodule(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new AddSubmodule(this));
} }
public ContextMenu CreateContextMenuForGitFlow() public ContextMenu CreateContextMenuForGitFlow()
@ -696,7 +726,8 @@ namespace SourceGit.ViewModels
startFeature.Header = App.Text("GitFlow.StartFeature"); startFeature.Header = App.Text("GitFlow.StartFeature");
startFeature.Click += (o, e) => startFeature.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Feature)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Feature));
e.Handled = true; e.Handled = true;
}; };
@ -704,7 +735,8 @@ namespace SourceGit.ViewModels
startRelease.Header = App.Text("GitFlow.StartRelease"); startRelease.Header = App.Text("GitFlow.StartRelease");
startRelease.Click += (o, e) => startRelease.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Release)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Release));
e.Handled = true; e.Handled = true;
}; };
@ -712,7 +744,8 @@ namespace SourceGit.ViewModels
startHotfix.Header = App.Text("GitFlow.StartHotfix"); startHotfix.Header = App.Text("GitFlow.StartHotfix");
startHotfix.Click += (o, e) => startHotfix.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Hotfix)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowStart(this, Models.GitFlowBranchType.Hotfix));
e.Handled = true; e.Handled = true;
}; };
@ -726,7 +759,8 @@ namespace SourceGit.ViewModels
init.Header = App.Text("GitFlow.Init"); init.Header = App.Text("GitFlow.Init");
init.Click += (o, e) => init.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new InitGitFlow(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new InitGitFlow(this));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(init); menu.Items.Add(init);
@ -744,7 +778,8 @@ namespace SourceGit.ViewModels
push.IsEnabled = Remotes.Count > 0; push.IsEnabled = Remotes.Count > 0;
push.Click += (_, e) => push.Click += (_, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Push(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Push(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -756,7 +791,8 @@ namespace SourceGit.ViewModels
discard.IsEnabled = _workingCopy.Count > 0; discard.IsEnabled = _workingCopy.Count > 0;
discard.Click += (o, e) => discard.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Discard(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Discard(this));
e.Handled = true; e.Handled = true;
}; };
@ -772,7 +808,8 @@ namespace SourceGit.ViewModels
fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0; fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0;
fastForward.Click += (o, e) => fastForward.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Merge(this, upstream, branch.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Merge(this, upstream, branch.Name));
e.Handled = true; e.Handled = true;
}; };
@ -781,7 +818,8 @@ namespace SourceGit.ViewModels
pull.Icon = App.CreateMenuIcon("Icons.Pull"); pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.Click += (o, e) => pull.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Pull(this, null)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Pull(this, null));
e.Handled = true; e.Handled = true;
}; };
@ -800,7 +838,8 @@ namespace SourceGit.ViewModels
checkout.Icon = App.CreateMenuIcon("Icons.Check"); checkout.Icon = App.CreateMenuIcon("Icons.Check");
checkout.Click += (o, e) => checkout.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Checkout(this, branch.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Checkout(this, branch.Name));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(checkout); menu.Items.Add(checkout);
@ -814,7 +853,8 @@ namespace SourceGit.ViewModels
fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0; fastForward.IsEnabled = !string.IsNullOrEmpty(branch.UpstreamTrackStatus) && branch.UpstreamTrackStatus.IndexOf('↑') < 0;
fastForward.Click += (o, e) => fastForward.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new FastForwardWithoutCheckout(this, branch, upstream)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new FastForwardWithoutCheckout(this, branch, upstream));
e.Handled = true; e.Handled = true;
}; };
@ -830,7 +870,8 @@ namespace SourceGit.ViewModels
merge.Icon = App.CreateMenuIcon("Icons.Merge"); merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.Click += (o, e) => merge.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Merge(this, branch.Name, current.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Merge(this, branch.Name, current.Name));
e.Handled = true; e.Handled = true;
}; };
@ -839,7 +880,8 @@ namespace SourceGit.ViewModels
rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
rebase.Click += (o, e) => rebase.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Rebase(this, current, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Rebase(this, current, branch));
e.Handled = true; e.Handled = true;
}; };
@ -855,7 +897,8 @@ namespace SourceGit.ViewModels
finish.Icon = App.CreateMenuIcon("Icons.Flow"); finish.Icon = App.CreateMenuIcon("Icons.Flow");
finish.Click += (o, e) => finish.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new GitFlowFinish(this, branch, type)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new GitFlowFinish(this, branch, type));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(new MenuItem() { Header = "-" }); menu.Items.Add(new MenuItem() { Header = "-" });
@ -867,7 +910,8 @@ namespace SourceGit.ViewModels
rename.Icon = App.CreateMenuIcon("Icons.Rename"); rename.Icon = App.CreateMenuIcon("Icons.Rename");
rename.Click += (o, e) => rename.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new RenameBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new RenameBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -877,7 +921,8 @@ namespace SourceGit.ViewModels
delete.IsEnabled = !branch.IsCurrent; delete.IsEnabled = !branch.IsCurrent;
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -886,7 +931,8 @@ namespace SourceGit.ViewModels
createBranch.Header = App.Text("CreateBranch"); createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, e) => createBranch.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -895,7 +941,8 @@ namespace SourceGit.ViewModels
createTag.Header = App.Text("CreateTag"); createTag.Header = App.Text("CreateTag");
createTag.Click += (o, e) => createTag.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateTag(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateTag(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -910,7 +957,8 @@ namespace SourceGit.ViewModels
var remoteBranches = new List<Models.Branch>(); var remoteBranches = new List<Models.Branch>();
foreach (var b in Branches) foreach (var b in Branches)
{ {
if (!b.IsLocal) remoteBranches.Add(b); if (!b.IsLocal)
remoteBranches.Add(b);
} }
if (remoteBranches.Count > 0) if (remoteBranches.Count > 0)
@ -924,7 +972,8 @@ namespace SourceGit.ViewModels
var upstream = b.FullName.Replace("refs/remotes/", ""); var upstream = b.FullName.Replace("refs/remotes/", "");
var target = new MenuItem(); var target = new MenuItem();
target.Header = upstream; target.Header = upstream;
if (branch.Upstream == b.FullName) target.Icon = App.CreateMenuIcon("Icons.Check"); if (branch.Upstream == b.FullName)
target.Icon = App.CreateMenuIcon("Icons.Check");
target.Click += (o, e) => target.Click += (o, e) =>
{ {
@ -959,7 +1008,8 @@ namespace SourceGit.ViewModels
archive.Header = App.Text("Archive"); archive.Header = App.Text("Archive");
archive.Click += (o, e) => archive.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Archive(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Archive(this, branch));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(archive); menu.Items.Add(archive);
@ -987,7 +1037,8 @@ namespace SourceGit.ViewModels
fetch.Icon = App.CreateMenuIcon("Icons.Fetch"); fetch.Icon = App.CreateMenuIcon("Icons.Fetch");
fetch.Click += (o, e) => fetch.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Fetch(this, remote)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Fetch(this, remote));
e.Handled = true; e.Handled = true;
}; };
@ -996,7 +1047,8 @@ namespace SourceGit.ViewModels
prune.Icon = App.CreateMenuIcon("Icons.Clear2"); prune.Icon = App.CreateMenuIcon("Icons.Clear2");
prune.Click += (o, e) => prune.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new PruneRemote(this, remote)); if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new PruneRemote(this, remote));
e.Handled = true; e.Handled = true;
}; };
@ -1005,7 +1057,8 @@ namespace SourceGit.ViewModels
edit.Icon = App.CreateMenuIcon("Icons.Edit"); edit.Icon = App.CreateMenuIcon("Icons.Edit");
edit.Click += (o, e) => edit.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new EditRemote(this, remote)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new EditRemote(this, remote));
e.Handled = true; e.Handled = true;
}; };
@ -1014,7 +1067,8 @@ namespace SourceGit.ViewModels
delete.Icon = App.CreateMenuIcon("Icons.Clear"); delete.Icon = App.CreateMenuIcon("Icons.Clear");
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteRemote(this, remote)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteRemote(this, remote));
e.Handled = true; e.Handled = true;
}; };
@ -1051,13 +1105,16 @@ namespace SourceGit.ViewModels
{ {
if (b.IsLocal && b.Upstream == branch.FullName) if (b.IsLocal && b.Upstream == branch.FullName)
{ {
if (b.IsCurrent) return; if (b.IsCurrent)
if (PopupHost.CanCreatePopup()) PopupHost.ShowAndStartPopup(new Checkout(this, b.Name)); return;
if (PopupHost.CanCreatePopup())
PopupHost.ShowAndStartPopup(new Checkout(this, b.Name));
return; return;
} }
} }
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
menu.Items.Add(checkout); menu.Items.Add(checkout);
@ -1070,7 +1127,8 @@ namespace SourceGit.ViewModels
pull.Icon = App.CreateMenuIcon("Icons.Pull"); pull.Icon = App.CreateMenuIcon("Icons.Pull");
pull.Click += (o, e) => pull.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Pull(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Pull(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1079,7 +1137,8 @@ namespace SourceGit.ViewModels
merge.Icon = App.CreateMenuIcon("Icons.Merge"); merge.Icon = App.CreateMenuIcon("Icons.Merge");
merge.Click += (o, e) => merge.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Merge(this, $"{branch.Remote}/{branch.Name}", current.Name)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Merge(this, $"{branch.Remote}/{branch.Name}", current.Name));
e.Handled = true; e.Handled = true;
}; };
@ -1088,7 +1147,8 @@ namespace SourceGit.ViewModels
rebase.Icon = App.CreateMenuIcon("Icons.Rebase"); rebase.Icon = App.CreateMenuIcon("Icons.Rebase");
rebase.Click += (o, e) => rebase.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Rebase(this, current, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Rebase(this, current, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1103,7 +1163,8 @@ namespace SourceGit.ViewModels
delete.Icon = App.CreateMenuIcon("Icons.Clear"); delete.Icon = App.CreateMenuIcon("Icons.Clear");
delete.Click += (o, e) => delete.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1112,7 +1173,8 @@ namespace SourceGit.ViewModels
createBranch.Header = App.Text("CreateBranch"); createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, e) => createBranch.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1121,7 +1183,8 @@ namespace SourceGit.ViewModels
createTag.Header = App.Text("CreateTag"); createTag.Header = App.Text("CreateTag");
createTag.Click += (o, e) => createTag.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateTag(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateTag(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1130,7 +1193,8 @@ namespace SourceGit.ViewModels
archive.Header = App.Text("Archive"); archive.Header = App.Text("Archive");
archive.Click += (o, e) => archive.Click += (o, e) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Archive(this, branch)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Archive(this, branch));
e.Handled = true; e.Handled = true;
}; };
@ -1161,7 +1225,8 @@ namespace SourceGit.ViewModels
createBranch.Header = App.Text("CreateBranch"); createBranch.Header = App.Text("CreateBranch");
createBranch.Click += (o, ev) => createBranch.Click += (o, ev) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateBranch(this, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateBranch(this, tag));
ev.Handled = true; ev.Handled = true;
}; };
@ -1171,7 +1236,8 @@ namespace SourceGit.ViewModels
pushTag.IsEnabled = Remotes.Count > 0; pushTag.IsEnabled = Remotes.Count > 0;
pushTag.Click += (o, ev) => pushTag.Click += (o, ev) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new PushTag(this, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new PushTag(this, tag));
ev.Handled = true; ev.Handled = true;
}; };
@ -1180,7 +1246,8 @@ namespace SourceGit.ViewModels
deleteTag.Icon = App.CreateMenuIcon("Icons.Clear"); deleteTag.Icon = App.CreateMenuIcon("Icons.Clear");
deleteTag.Click += (o, ev) => deleteTag.Click += (o, ev) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteTag(this, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteTag(this, tag));
ev.Handled = true; ev.Handled = true;
}; };
@ -1189,7 +1256,8 @@ namespace SourceGit.ViewModels
archive.Header = App.Text("Archive"); archive.Header = App.Text("Archive");
archive.Click += (o, ev) => archive.Click += (o, ev) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new Archive(this, tag)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new Archive(this, tag));
ev.Handled = true; ev.Handled = true;
}; };
@ -1255,7 +1323,8 @@ namespace SourceGit.ViewModels
rm.Icon = App.CreateMenuIcon("Icons.Clear"); rm.Icon = App.CreateMenuIcon("Icons.Clear");
rm.Click += (o, ev) => rm.Click += (o, ev) =>
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteSubmodule(this, submodule)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteSubmodule(this, submodule));
ev.Handled = true; ev.Handled = true;
}; };

View file

@ -40,11 +40,16 @@ namespace SourceGit.ViewModels
_repo = repo; _repo = repo;
_cached = new Commands.Config(repo.FullPath).ListAll(); _cached = new Commands.Config(repo.FullPath).ListAll();
if (_cached.ContainsKey("user.name")) UserName = _cached["user.name"]; if (_cached.TryGetValue("user.name", out var name))
if (_cached.ContainsKey("user.email")) UserEmail = _cached["user.email"]; UserName = name;
if (_cached.ContainsKey("commit.gpgsign")) GPGSigningEnabled = _cached["commit.gpgsign"] == "true"; if (_cached.TryGetValue("user.email", out var email))
if (_cached.ContainsKey("user.signingkey")) GPGUserSigningKey = _cached["user.signingkey"]; UserEmail = email;
if (_cached.ContainsKey("http.proxy")) HttpProxy = _cached["http.proxy"]; if (_cached.TryGetValue("commit.gpgsign", out var gpgsign))
GPGSigningEnabled = gpgsign == "true";
if (_cached.TryGetValue("user.signingkey", out var signingKey))
GPGUserSigningKey = signingKey;
if (_cached.TryGetValue("http.proxy", out var proxy))
HttpProxy = proxy;
View = new Views.RepositoryConfigure() { DataContext = this }; View = new Views.RepositoryConfigure() { DataContext = this };
} }
@ -62,9 +67,9 @@ namespace SourceGit.ViewModels
private void SetIfChanged(string key, string value) private void SetIfChanged(string key, string value)
{ {
bool changed = false; bool changed = false;
if (_cached.ContainsKey(key)) if (_cached.TryGetValue(key, out var old))
{ {
changed = value != _cached[key]; changed = old != value;
} }
else if (!string.IsNullOrEmpty(value)) else if (!string.IsNullOrEmpty(value))
{ {

View file

@ -57,29 +57,34 @@ namespace SourceGit.ViewModels
public void Edit() public void Edit()
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new EditRepositoryNode(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new EditRepositoryNode(this));
} }
public void AddSubFolder() public void AddSubFolder()
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new CreateGroup(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new CreateGroup(this));
} }
public void OpenInFileManager() public void OpenInFileManager()
{ {
if (!IsRepository) return; if (!IsRepository)
return;
Native.OS.OpenInFileManager(_id); Native.OS.OpenInFileManager(_id);
} }
public void OpenTerminal() public void OpenTerminal()
{ {
if (!IsRepository) return; if (!IsRepository)
return;
Native.OS.OpenTerminal(_id); Native.OS.OpenTerminal(_id);
} }
public void Delete() public void Delete()
{ {
if (PopupHost.CanCreatePopup()) PopupHost.ShowPopup(new DeleteRepositoryNode(this)); if (PopupHost.CanCreatePopup())
PopupHost.ShowPopup(new DeleteRepositoryNode(this));
} }
private string _id = string.Empty; private string _id = string.Empty;

View file

@ -129,9 +129,12 @@ namespace SourceGit.ViewModels
public void Cleanup() public void Cleanup()
{ {
_repo = null; _repo = null;
if (_changes != null) _changes.Clear(); if (_changes != null)
if (_visibleChanges != null) _visibleChanges.Clear(); _changes.Clear();
if (_changeTree != null) _changeTree.Clear(); if (_visibleChanges != null)
_visibleChanges.Clear();
if (_changeTree != null)
_changeTree.Clear();
_selectedChange = null; _selectedChange = null;
_selectedNode = null; _selectedNode = null;
_searchFilter = null; _searchFilter = null;
@ -141,7 +144,8 @@ namespace SourceGit.ViewModels
public void NavigateTo(string commitSHA) public void NavigateTo(string commitSHA)
{ {
var repo = Preference.FindRepository(_repo); var repo = Preference.FindRepository(_repo);
if (repo != null) repo.NavigateToCommit(commitSHA); if (repo != null)
repo.NavigateToCommit(commitSHA);
} }
public void ClearSearchFilter() public void ClearSearchFilter()
@ -192,7 +196,8 @@ namespace SourceGit.ViewModels
private void RefreshVisible() private void RefreshVisible()
{ {
if (_changes == null) return; if (_changes == null)
return;
if (string.IsNullOrEmpty(_searchFilter)) if (string.IsNullOrEmpty(_searchFilter))
{ {

View file

@ -28,7 +28,8 @@ namespace SourceGit.ViewModels
public override Task<bool> Sure() public override Task<bool> Sure()
{ {
if (_message == Head.FullMessage) return null; if (_message == Head.FullMessage)
return null;
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
ProgressDescription = $"Editing head commit message ..."; ProgressDescription = $"Editing head commit message ...";

View file

@ -41,7 +41,8 @@ namespace SourceGit.ViewModels
return Task.Run(() => return Task.Run(() =>
{ {
var succ = new Commands.Reset(_repo.FullPath, Parent.SHA, "--soft").Exec(); var succ = new Commands.Reset(_repo.FullPath, Parent.SHA, "--soft").Exec();
if (succ) succ = new Commands.Commit(_repo.FullPath, _message, true).Exec(); if (succ)
succ = new Commands.Commit(_repo.FullPath, _message, true).Exec();
CallUIThread(() => _repo.SetWatcherEnabled(true)); CallUIThread(() => _repo.SetWatcherEnabled(true));
return succ; return succ;
}); });

View file

@ -49,7 +49,8 @@ namespace SourceGit.ViewModels
} }
} }
if (jobs.Count == 0) return null; if (jobs.Count == 0)
return null;
_repo.SetWatcherEnabled(false); _repo.SetWatcherEnabled(false);
ProgressDescription = $"Stash changes ..."; ProgressDescription = $"Stash changes ...";

Some files were not shown because too many files have changed in this diff Show more