diff options
Diffstat (limited to 'org.eclipse.jgit.test')
191 files changed, 27674 insertions, 0 deletions
diff --git a/org.eclipse.jgit.test/.classpath b/org.eclipse.jgit.test/.classpath new file mode 100644 index 0000000000..cb944bd388 --- /dev/null +++ b/org.eclipse.jgit.test/.classpath @@ -0,0 +1,11 @@ +<?xml version="1.0" encoding="UTF-8"?> +<classpath> + <classpathentry excluding="**/*.idx|**/*.pack" kind="src" path="tst"/> + <classpathentry kind="src" path="tst-rsrc"/> + <classpathentry kind="src" path="exttst"/> + <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/> + <classpathentry combineaccessrules="false" kind="src" path="/org.eclipse.jgit"/> + <classpathentry kind="con" path="org.eclipse.jdt.junit.JUNIT_CONTAINER/3.8.1"/> + <classpathentry kind="lib" path="/org.eclipse.jgit/lib/jsch-0.1.37.jar" sourcepath="/org.eclipse.jgit/lib/jsch-0.1.37.zip"/> + <classpathentry kind="output" path="bin"/> +</classpath> diff --git a/org.eclipse.jgit.test/.gitignore b/org.eclipse.jgit.test/.gitignore new file mode 100644 index 0000000000..9d7d1382b7 --- /dev/null +++ b/org.eclipse.jgit.test/.gitignore @@ -0,0 +1,3 @@ +bin +tst/todopack +trash diff --git a/org.eclipse.jgit.test/.project b/org.eclipse.jgit.test/.project new file mode 100644 index 0000000000..a7242a0684 --- /dev/null +++ b/org.eclipse.jgit.test/.project @@ -0,0 +1,17 @@ +<?xml version="1.0" encoding="UTF-8"?> +<projectDescription> + <name>org.eclipse.jgit.test</name> + <comment></comment> + <projects> + </projects> + <buildSpec> + <buildCommand> + <name>org.eclipse.jdt.core.javabuilder</name> + <arguments> + </arguments> + </buildCommand> + </buildSpec> + <natures> + <nature>org.eclipse.jdt.core.javanature</nature> + </natures> +</projectDescription> diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 0000000000..6a9621db1d --- /dev/null +++ b/org.eclipse.jgit.test/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,6 @@ +#Sat Dec 20 21:21:24 CET 2008 +eclipse.preferences.version=1 +encoding//tst-rsrc/org/eclipse/jgit/patch/testGetText_BothISO88591.patch=ISO-8859-1 +encoding//tst-rsrc/org/eclipse/jgit/patch/testGetText_Convert.patch=ISO-8859-1 +encoding//tst-rsrc/org/eclipse/jgit/patch/testGetText_DiffCc.patch=ISO-8859-1 +encoding/<project>=UTF-8 diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.core.runtime.prefs new file mode 100644 index 0000000000..72987c2521 --- /dev/null +++ b/org.eclipse.jgit.test/.settings/org.eclipse.core.runtime.prefs @@ -0,0 +1,3 @@ +#Mon Mar 24 18:55:56 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000000..8bfa5f141a --- /dev/null +++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,320 @@ +#Tue Feb 05 00:01:29 CET 2008 +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5 +org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve +org.eclipse.jdt.core.compiler.compliance=1.5 +org.eclipse.jdt.core.compiler.debug.lineNumber=generate +org.eclipse.jdt.core.compiler.debug.localVariable=generate +org.eclipse.jdt.core.compiler.debug.sourceFile=generate +org.eclipse.jdt.core.compiler.doc.comment.support=enabled +org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=warning +org.eclipse.jdt.core.compiler.problem.assertIdentifier=error +org.eclipse.jdt.core.compiler.problem.autoboxing=warning +org.eclipse.jdt.core.compiler.problem.deprecation=warning +org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled +org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled +org.eclipse.jdt.core.compiler.problem.discouragedReference=warning +org.eclipse.jdt.core.compiler.problem.emptyStatement=warning +org.eclipse.jdt.core.compiler.problem.enumIdentifier=error +org.eclipse.jdt.core.compiler.problem.fallthroughCase=warning +org.eclipse.jdt.core.compiler.problem.fieldHiding=warning +org.eclipse.jdt.core.compiler.problem.finalParameterBound=warning +org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=error +org.eclipse.jdt.core.compiler.problem.forbiddenReference=error +org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=error +org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=warning +org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=warning +org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=error +org.eclipse.jdt.core.compiler.problem.invalidJavadoc=error +org.eclipse.jdt.core.compiler.problem.invalidJavadocTags=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsDeprecatedRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsNotVisibleRef=enabled +org.eclipse.jdt.core.compiler.problem.invalidJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.localVariableHiding=warning +org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=error +org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocComments=ignore +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=public +org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled +org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=private +org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore +org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning +org.eclipse.jdt.core.compiler.problem.noEffectAssignment=error +org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=error +org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore +org.eclipse.jdt.core.compiler.problem.nullReference=warning +org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning +org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore +org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=error +org.eclipse.jdt.core.compiler.problem.potentialNullReference=warning +org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore +org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning +org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled +org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=error +org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled +org.eclipse.jdt.core.compiler.problem.typeParameterHiding=warning +org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=warning +org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=warning +org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=warning +org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=error +org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=error +org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled +org.eclipse.jdt.core.compiler.problem.unusedImport=error +org.eclipse.jdt.core.compiler.problem.unusedLabel=error +org.eclipse.jdt.core.compiler.problem.unusedLocal=error +org.eclipse.jdt.core.compiler.problem.unusedParameter=warning +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled +org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled +org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=error +org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=error +org.eclipse.jdt.core.compiler.source=1.5 +org.eclipse.jdt.core.formatter.align_type_members_on_columns=false +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_enum_constant=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_explicit_constructor_call=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_arguments_in_qualified_allocation_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_assignment=0 +org.eclipse.jdt.core.formatter.alignment_for_binary_expression=16 +org.eclipse.jdt.core.formatter.alignment_for_compact_if=16 +org.eclipse.jdt.core.formatter.alignment_for_conditional_expression=80 +org.eclipse.jdt.core.formatter.alignment_for_enum_constants=0 +org.eclipse.jdt.core.formatter.alignment_for_expressions_in_array_initializer=16 +org.eclipse.jdt.core.formatter.alignment_for_multiple_fields=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_parameters_in_method_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_selector_in_method_invocation=16 +org.eclipse.jdt.core.formatter.alignment_for_superclass_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_enum_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_superinterfaces_in_type_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_constructor_declaration=16 +org.eclipse.jdt.core.formatter.alignment_for_throws_clause_in_method_declaration=16 +org.eclipse.jdt.core.formatter.blank_lines_after_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_after_package=1 +org.eclipse.jdt.core.formatter.blank_lines_before_field=1 +org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0 +org.eclipse.jdt.core.formatter.blank_lines_before_imports=1 +org.eclipse.jdt.core.formatter.blank_lines_before_member_type=1 +org.eclipse.jdt.core.formatter.blank_lines_before_method=1 +org.eclipse.jdt.core.formatter.blank_lines_before_new_chunk=1 +org.eclipse.jdt.core.formatter.blank_lines_before_package=0 +org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=1 +org.eclipse.jdt.core.formatter.brace_position_for_annotation_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_anonymous_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_array_initializer=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_block_in_case=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_constructor_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_constant=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_enum_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_method_declaration=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_switch=end_of_line +org.eclipse.jdt.core.formatter.brace_position_for_type_declaration=end_of_line +org.eclipse.jdt.core.formatter.comment.clear_blank_lines=false +org.eclipse.jdt.core.formatter.comment.format_comments=true +org.eclipse.jdt.core.formatter.comment.format_header=false +org.eclipse.jdt.core.formatter.comment.format_html=true +org.eclipse.jdt.core.formatter.comment.format_source_code=true +org.eclipse.jdt.core.formatter.comment.indent_parameter_description=true +org.eclipse.jdt.core.formatter.comment.indent_root_tags=true +org.eclipse.jdt.core.formatter.comment.insert_new_line_before_root_tags=insert +org.eclipse.jdt.core.formatter.comment.insert_new_line_for_parameter=insert +org.eclipse.jdt.core.formatter.comment.line_length=80 +org.eclipse.jdt.core.formatter.compact_else_if=true +org.eclipse.jdt.core.formatter.continuation_indentation=2 +org.eclipse.jdt.core.formatter.continuation_indentation_for_array_initializer=2 +org.eclipse.jdt.core.formatter.format_guardian_clause_on_one_line=false +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_annotation_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_constant_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_enum_declaration_header=true +org.eclipse.jdt.core.formatter.indent_body_declarations_compare_to_type_header=true +org.eclipse.jdt.core.formatter.indent_breaks_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_empty_lines=false +org.eclipse.jdt.core.formatter.indent_statements_compare_to_block=true +org.eclipse.jdt.core.formatter.indent_statements_compare_to_body=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_cases=true +org.eclipse.jdt.core.formatter.indent_switchstatements_compare_to_switch=false +org.eclipse.jdt.core.formatter.indentation.size=4 +org.eclipse.jdt.core.formatter.insert_new_line_after_annotation=insert +org.eclipse.jdt.core.formatter.insert_new_line_after_opening_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_at_end_of_file_if_missing=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_catch_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_closing_brace_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_else_in_if_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_finally_in_try_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_before_while_in_do_statement=do not insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_annotation_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_block=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_method_body=insert +org.eclipse.jdt.core.formatter.insert_new_line_in_empty_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_after_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_after_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_at_in_annotation_type_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_angle_bracket_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_after_closing_paren_in_cast=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_case=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_colon_in_labeled_statement=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_allocation_expression=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_annotation=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_constructor_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_constant_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_enum_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_explicitconstructorcall_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_increments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_for_inits=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_declaration_throws=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_method_invocation_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_field_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_multiple_local_declarations=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_parameterized_type_reference=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_superinterfaces=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_arguments=insert +org.eclipse.jdt.core.formatter.insert_space_after_comma_in_type_parameters=insert +org.eclipse.jdt.core.formatter.insert_space_after_ellipsis=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_opening_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_after_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_after_semicolon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_after_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_and_in_type_parameter=insert +org.eclipse.jdt.core.formatter.insert_space_before_assignment_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_at_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_binary_operator=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_cast=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_catch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_if=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_switch=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_synchronized=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_closing_paren_in_while=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_assert=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_case=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_default=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_colon_in_labeled_statement=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_constructor_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_constant_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_enum_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_explicitconstructorcall_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_increments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_for_inits=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_declaration_throws=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_method_invocation_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_field_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_multiple_local_declarations=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_superinterfaces=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_comma_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_ellipsis=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_parameterized_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_arguments=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_angle_bracket_in_type_parameters=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_annotation_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_anonymous_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_array_initializer=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_block=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_constructor_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_constant=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_enum_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_method_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_brace_in_type_declaration=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_bracket_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_catch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_for=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_if=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_parenthesized_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_switch=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_synchronized=insert +org.eclipse.jdt.core.formatter.insert_space_before_opening_paren_in_while=insert +org.eclipse.jdt.core.formatter.insert_space_before_parenthesized_expression_in_return=insert +org.eclipse.jdt.core.formatter.insert_space_before_postfix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_prefix_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_conditional=insert +org.eclipse.jdt.core.formatter.insert_space_before_question_in_wildcard=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_semicolon_in_for=do not insert +org.eclipse.jdt.core.formatter.insert_space_before_unary_operator=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_brackets_in_array_type_reference=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_braces_in_array_initializer=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_brackets_in_array_allocation_expression=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_annotation_type_member_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_constructor_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_enum_constant=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_declaration=do not insert +org.eclipse.jdt.core.formatter.insert_space_between_empty_parens_in_method_invocation=do not insert +org.eclipse.jdt.core.formatter.keep_else_statement_on_same_line=false +org.eclipse.jdt.core.formatter.keep_empty_array_initializer_on_one_line=false +org.eclipse.jdt.core.formatter.keep_imple_if_on_one_line=false +org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false +org.eclipse.jdt.core.formatter.lineSplit=80 +org.eclipse.jdt.core.formatter.number_of_blank_lines_at_beginning_of_method_body=0 +org.eclipse.jdt.core.formatter.number_of_empty_lines_to_preserve=1 +org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=true +org.eclipse.jdt.core.formatter.tabulation.char=tab +org.eclipse.jdt.core.formatter.tabulation.size=4 +org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false diff --git a/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs new file mode 100644 index 0000000000..fce94cf0c2 --- /dev/null +++ b/org.eclipse.jgit.test/.settings/org.eclipse.jdt.ui.prefs @@ -0,0 +1,10 @@ +#Thu Dec 20 01:31:04 CET 2007 +eclipse.preferences.version=1 +formatter_profile=_JGit +formatter_settings_version=10 +internal.default.compliance=default +org.eclipse.jdt.ui.ignorelowercasenames=true +org.eclipse.jdt.ui.importorder=java;javax;org;com; +org.eclipse.jdt.ui.ondemandthreshold=99 +org.eclipse.jdt.ui.staticondemandthreshold=99 +org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/> diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/SpeedTestBase.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/SpeedTestBase.java new file mode 100644 index 0000000000..b53a4e4304 --- /dev/null +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/SpeedTestBase.java @@ -0,0 +1,116 @@ +/* + * Copyright (C) 2008, Google Inc. + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +/** + * Base class for performance unit test. + */ +public abstract class SpeedTestBase extends TestCase { + + /** + * The time used by native git as this is our reference. + */ + protected long nativeTime; + + /** + * Reference to the location of the Linux kernel repo. + */ + protected String kernelrepo; + + /** + * Prepare test by running a test against the Linux kernel repo first. + * + * @param refcmd + * git command to execute + * + * @throws Exception + */ + protected void prepare(String[] refcmd) throws Exception { + try { + BufferedReader bufferedReader = new BufferedReader(new FileReader("kernel.ref")); + try { + kernelrepo = bufferedReader.readLine(); + } finally { + bufferedReader.close(); + } + timeNativeGit(kernelrepo, refcmd); + nativeTime = timeNativeGit(kernelrepo, refcmd); + } catch (Exception e) { + System.out.println("Create a file named kernel.ref and put the path to the Linux kernels repository there"); + throw e; + } + } + + private static long timeNativeGit(String kernelrepo, String[] refcmd) throws IOException, + InterruptedException, Exception { + long start = System.currentTimeMillis(); + Process p = Runtime.getRuntime().exec(refcmd, null, new File(kernelrepo,"..")); + InputStream inputStream = p.getInputStream(); + InputStream errorStream = p.getErrorStream(); + byte[] buf=new byte[1024*1024]; + for (;;) + if (inputStream.read(buf) < 0) + break; + if (p.waitFor()!=0) { + int c; + while ((c=errorStream.read())!=-1) + System.err.print((char)c); + throw new Exception("git log failed"); + } + inputStream.close(); + errorStream.close(); + long stop = System.currentTimeMillis(); + return stop - start; + } +} diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0005_ShallowSpeedTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0005_ShallowSpeedTest.java new file mode 100644 index 0000000000..97b1cf97d7 --- /dev/null +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0005_ShallowSpeedTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; + +import junit.textui.TestRunner; + +public class T0005_ShallowSpeedTest extends SpeedTestBase { + + protected void setUp() throws Exception { + prepare(new String[] { "git", "rev-list", "365bbe0d0caaf2ba74d56556827babf0bc66965d" }); + } + + public void testShallowHistoryScan() throws IOException { + long start = System.currentTimeMillis(); + Repository db = new Repository(new File(kernelrepo)); + Commit commit = db.mapCommit("365bbe0d0caaf2ba74d56556827babf0bc66965d"); + int n = 1; + for (;;) { + ObjectId[] parents = commit.getParentIds(); + if (parents.length == 0) + break; + ObjectId parentId = parents[0]; + commit = db.mapCommit(parentId); + commit.getCommitId().name(); + ++n; + } + assertEquals(12275, n); + long stop = System.currentTimeMillis(); + long time = stop - start; + System.out.println("native="+nativeTime); + System.out.println("jgit="+time); + // ~0.750s (hot cache), ok + /* +native=1795 +jgit=722 + */ + // native git seems to run SLOWER than jgit here, at roughly half the speed + // creating the git process is not the issue here, btw. + long factor10 = (nativeTime*150/time+50)/100; + assertEquals(3, factor10); + } + + public static void main(String[] args) { + TestRunner.run(T0005_ShallowSpeedTest.class); + } +} diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0006_DeepSpeedTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0006_DeepSpeedTest.java new file mode 100644 index 0000000000..8843ae35b3 --- /dev/null +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/lib/T0006_DeepSpeedTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; + +import junit.textui.TestRunner; + +public class T0006_DeepSpeedTest extends SpeedTestBase { + + protected void setUp() throws Exception { + prepare(new String[] { "git", "rev-list", "365bbe0d0caaf2ba74d56556827babf0bc66965d","--","net/netfilter/nf_queue.c" }); + } + + public void testDeepHistoryScan() throws IOException { + long start = System.currentTimeMillis(); + Repository db = new Repository(new File(kernelrepo)); + Commit commit = db.mapCommit("365bbe0d0caaf2ba74d56556827babf0bc66965d"); + int n = 1; + for (;;) { + ObjectId[] parents = commit.getParentIds(); + if (parents.length == 0) + break; + ObjectId parentId = parents[0]; + commit = db.mapCommit(parentId); + TreeEntry m = commit.getTree().findBlobMember("net/netfilter/nf_queue.c"); + if (m != null) + commit.getCommitId().name(); + ++n; + } + + assertEquals(12275, n); + long stop = System.currentTimeMillis(); + long time = stop - start; + System.out.println("native="+nativeTime); + System.out.println("jgit="+time); + /* + native=1355 + jgit=5449 + */ + // This is not an exact factor, but we'd expect native git to perform this + // about 4 times quicker. If for some reason we find jgit to be faster than + // this the cause should be found and secured. + long factor = (time*110/nativeTime+50)/100; + assertEquals(4, factor); + } + + public static void main(String[] args) { + TestRunner.run(T0006_DeepSpeedTest.class); + } +} diff --git a/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java new file mode 100644 index 0000000000..60d3853d85 --- /dev/null +++ b/org.eclipse.jgit.test/exttst/org/eclipse/jgit/patch/EGitPatchHistoryTest.java @@ -0,0 +1,227 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.BufferedReader; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.UnsupportedEncodingException; +import java.util.HashMap; +import java.util.HashSet; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.util.MutableInteger; +import org.eclipse.jgit.util.RawParseUtils; +import org.eclipse.jgit.util.TemporaryBuffer; + +public class EGitPatchHistoryTest extends TestCase { + public void testParseHistory() throws Exception { + final NumStatReader numstat = new NumStatReader(); + numstat.read(); + + final HashMap<String, HashMap<String, StatInfo>> stats = numstat.stats; + assertEquals(1211, stats.size()); + + new PatchReader(stats).read(); + } + + static class StatInfo { + int added, deleted; + } + + static class PatchReader extends CommitReader { + final HashSet<String> offBy1; + + final HashMap<String, HashMap<String, StatInfo>> stats; + + int errors; + + PatchReader(final HashMap<String, HashMap<String, StatInfo>> s) + throws IOException { + super(new String[] { "-p" }); + stats = s; + + offBy1 = new HashSet<String>(); + offBy1.add("9bda5ece6806cd797416eaa47c7b927cc6e9c3b2"); + } + + @Override + void onCommit(String cid, byte[] buf) { + final HashMap<String, StatInfo> files = stats.remove(cid); + assertNotNull("No files for " + cid, files); + + final Patch p = new Patch(); + p.parse(buf, 0, buf.length - 1); + assertEquals("File count " + cid, files.size(), p.getFiles().size()); + if (!p.getErrors().isEmpty()) { + for (final FormatError e : p.getErrors()) { + System.out.println("error " + e.getMessage()); + System.out.println(" at " + e.getLineText()); + } + dump(buf); + fail("Unexpected error in " + cid); + } + + for (final FileHeader fh : p.getFiles()) { + final String fileName; + if (fh.getChangeType() != FileHeader.ChangeType.DELETE) + fileName = fh.getNewName(); + else + fileName = fh.getOldName(); + final StatInfo s = files.remove(fileName); + final String nid = fileName + " in " + cid; + assertNotNull("No " + nid, s); + int added = 0, deleted = 0; + for (final HunkHeader h : fh.getHunks()) { + added += h.getOldImage().getLinesAdded(); + deleted += h.getOldImage().getLinesDeleted(); + } + + if (s.added == added) { + // + } else if (s.added == added + 1 && offBy1.contains(cid)) { + // + } else { + dump(buf); + assertEquals("Added diff in " + nid, s.added, added); + } + + if (s.deleted == deleted) { + // + } else if (s.deleted == deleted + 1 && offBy1.contains(cid)) { + // + } else { + dump(buf); + assertEquals("Deleted diff in " + nid, s.deleted, deleted); + } + } + assertTrue("Missed files in " + cid, files.isEmpty()); + } + + private static void dump(final byte[] buf) { + String str; + try { + str = new String(buf, 0, buf.length - 1, "ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + System.out.println("<<" + str + ">>"); + } + } + + static class NumStatReader extends CommitReader { + final HashMap<String, HashMap<String, StatInfo>> stats = new HashMap<String, HashMap<String, StatInfo>>(); + + NumStatReader() throws IOException { + super(new String[] { "--numstat" }); + } + + @Override + void onCommit(String commitId, byte[] buf) { + final HashMap<String, StatInfo> files = new HashMap<String, StatInfo>(); + final MutableInteger ptr = new MutableInteger(); + while (ptr.value < buf.length) { + if (buf[ptr.value] == '\n') + break; + final StatInfo i = new StatInfo(); + i.added = RawParseUtils.parseBase10(buf, ptr.value, ptr); + i.deleted = RawParseUtils.parseBase10(buf, ptr.value + 1, ptr); + final int eol = RawParseUtils.nextLF(buf, ptr.value); + final String name = RawParseUtils.decode(Constants.CHARSET, + buf, ptr.value + 1, eol - 1); + files.put(name, i); + ptr.value = eol; + } + stats.put(commitId, files); + } + } + + static abstract class CommitReader { + private Process proc; + + CommitReader(final String[] args) throws IOException { + final String[] realArgs = new String[3 + args.length + 1]; + realArgs[0] = "git"; + realArgs[1] = "log"; + realArgs[2] = "--pretty=format:commit %H"; + System.arraycopy(args, 0, realArgs, 3, args.length); + realArgs[3 + args.length] = "a4b98ed15ea5f165a7aa0f2fd2ea6fcce6710925"; + + proc = Runtime.getRuntime().exec(realArgs); + proc.getOutputStream().close(); + proc.getErrorStream().close(); + } + + void read() throws IOException, InterruptedException { + final BufferedReader in = new BufferedReader(new InputStreamReader( + proc.getInputStream(), "ISO-8859-1")); + String commitId = null; + TemporaryBuffer buf = null; + for (;;) { + String line = in.readLine(); + if (line == null) + break; + if (line.startsWith("commit ")) { + if (buf != null) { + buf.close(); + onCommit(commitId, buf.toByteArray()); + buf.destroy(); + } + commitId = line.substring("commit ".length()); + buf = new TemporaryBuffer(); + } else if (buf != null) { + buf.write(line.getBytes("ISO-8859-1")); + buf.write('\n'); + } + } + in.close(); + assertEquals(0, proc.waitFor()); + proc = null; + } + + abstract void onCommit(String commitId, byte[] buf); + } +} diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests (Java 6).launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests (Java 6).launch new file mode 100644 index 0000000000..9a9ca124d3 --- /dev/null +++ b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests (Java 6).launch @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.test"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/exttst"/> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch new file mode 100644 index 0000000000..6735fb0a26 --- /dev/null +++ b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-External-Tests.launch @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.test"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/exttst"/> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 6).launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 6).launch new file mode 100644 index 0000000000..a0aecf920c --- /dev/null +++ b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests (Java 6).launch @@ -0,0 +1,21 @@ +<?xml version="1.0" encoding="UTF-8" standalone="no"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.test/tst"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="2"/> +</listAttribute> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.6"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests.launch b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests.launch new file mode 100644 index 0000000000..bff41ecf07 --- /dev/null +++ b/org.eclipse.jgit.test/org.eclipse.jgit.core--All-Tests.launch @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="UTF-8"?> +<launchConfiguration type="org.eclipse.jdt.junit.launchconfig"> +<booleanAttribute key="org.eclipse.jdt.junit.KEEPRUNNING_ATTR" value="false"/> +<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value=""/> +<stringAttribute key="org.eclipse.jdt.junit.TESTNAME" value=""/> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_TYPES"> +<listEntry value="4"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="org.eclipse.jgit.test"/> +<listAttribute key="org.eclipse.debug.ui.favoriteGroups"> +<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/> +<listEntry value="org.eclipse.debug.ui.launchGroup.run"/> +</listAttribute> +<listAttribute key="org.eclipse.debug.core.MAPPED_RESOURCE_PATHS"> +<listEntry value="/org.eclipse.jgit.test"/> +</listAttribute> +<stringAttribute key="org.eclipse.jdt.junit.CONTAINER" value="=org.eclipse.jgit.test/tst"/> +<booleanAttribute key="org.eclipse.debug.core.appendEnvironmentVariables" value="true"/> +<stringAttribute key="org.eclipse.jdt.junit.TEST_KIND" value="org.eclipse.jdt.junit.loader.junit3"/> +</launchConfiguration> diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E.patch new file mode 100644 index 0000000000..9b8fa98cf7 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E.patch @@ -0,0 +1,6 @@ +diff --git a/E b/E +index e69de29..7898192 100644 +--- a/E ++++ b/E +@@ -0,0 +1 @@ ++a diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PostImage new file mode 100644 index 0000000000..7898192261 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PostImage @@ -0,0 +1 @@ +a diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PreImage new file mode 100644 index 0000000000..e69de29bb2 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/E_PreImage diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X.patch new file mode 100644 index 0000000000..e5363eb204 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X.patch @@ -0,0 +1,24 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -2,2 +2,3 @@ a + b ++c + d +@@ -16,4 +17,2 @@ p + q +-r +-s + t +@@ -22,4 +21,8 @@ v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PostImage new file mode 100644 index 0000000000..2d44096024 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PostImage @@ -0,0 +1,28 @@ +a +b +c +d +e +f +g +h +i +j +k +l +m +n +o +p +q +t +u +v +w +0 +1 +2 +3 +4 +5 +z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PreImage new file mode 100644 index 0000000000..a3648a1eba --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/X_PreImage @@ -0,0 +1,25 @@ +a +b +d +e +f +g +h +i +j +k +l +m +n +o +p +q +r +s +t +u +v +w +x +y +z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y.patch new file mode 100644 index 0000000000..a2c9a0bb45 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y.patch @@ -0,0 +1,8 @@ +diff --git a/Y b/Y +index 2e65efe..7898192 100644 +--- a/Y ++++ b/Y +@@ -1 +1 @@ +-a +\ No newline at end of file ++a diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PostImage new file mode 100644 index 0000000000..7898192261 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PostImage @@ -0,0 +1 @@ +a diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PreImage new file mode 100644 index 0000000000..2e65efe2a1 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Y_PreImage @@ -0,0 +1 @@ +a
\ No newline at end of file diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z.patch new file mode 100644 index 0000000000..35a06d6473 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z.patch @@ -0,0 +1,8 @@ +diff --git a/Z b/Z +index 7898192..2e65efe 100644 +--- a/Z ++++ b/Z +@@ -1 +1 @@ +-a ++a +\ No newline at end of file diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PostImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PostImage new file mode 100644 index 0000000000..2e65efe2a1 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PostImage @@ -0,0 +1 @@ +a
\ No newline at end of file diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PreImage b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PreImage new file mode 100644 index 0000000000..7898192261 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/Z_PreImage @@ -0,0 +1 @@ +a diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext0.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext0.out new file mode 100644 index 0000000000..d36e3fa0b3 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext0.out @@ -0,0 +1,18 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -2,0 +3 @@ ++c +@@ -17,2 +17,0 @@ +-r +-s +@@ -23,2 +22,6 @@ +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext1.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext1.out new file mode 100644 index 0000000000..d0d847d608 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext1.out @@ -0,0 +1,24 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -2,2 +2,3 @@ + b ++c + d +@@ -16,4 +17,2 @@ + q +-r +-s + t +@@ -22,4 +21,8 @@ + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext10.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext10.out new file mode 100644 index 0000000000..1d4f242779 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext10.out @@ -0,0 +1,37 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -1,25 +1,28 @@ + a + b ++c + d + e + f + g + h + i + j + k + l + m + n + o + p + q +-r +-s + t + u + v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext100.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext100.out new file mode 100644 index 0000000000..1d4f242779 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext100.out @@ -0,0 +1,37 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -1,25 +1,28 @@ + a + b ++c + d + e + f + g + h + i + j + k + l + m + n + o + p + q +-r +-s + t + u + v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext3.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext3.out new file mode 100644 index 0000000000..2564016648 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext3.out @@ -0,0 +1,30 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -1,5 +1,6 @@ + a + b ++c + d + e + f +@@ -14,12 +15,14 @@ + o + p + q +-r +-s + t + u + v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext5.out b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext5.out new file mode 100644 index 0000000000..3073c5f09e --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/diff/testContext5.out @@ -0,0 +1,34 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -1,7 +1,8 @@ + a + b ++c + d + e + f + g + h +@@ -12,14 +13,16 @@ + m + n + o + p + q +-r +-s + t + u + v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/.gitattributes b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/.gitattributes new file mode 100644 index 0000000000..b38f87f9e3 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/.gitattributes @@ -0,0 +1 @@ +*.patch -crlf diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testEditList_Types.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testEditList_Types.patch new file mode 100644 index 0000000000..e5363eb204 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testEditList_Types.patch @@ -0,0 +1,24 @@ +diff --git a/X b/X +index a3648a1..2d44096 100644 +--- a/X ++++ b/X +@@ -2,2 +2,3 @@ a + b ++c + d +@@ -16,4 +17,2 @@ p + q +-r +-s + t +@@ -22,4 +21,8 @@ v + w +-x +-y ++0 ++1 ++2 ++3 ++4 ++5 + z diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_BodyTooLong.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_BodyTooLong.patch new file mode 100644 index 0000000000..9506198b1d --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_BodyTooLong.patch @@ -0,0 +1,17 @@ +diff --git a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +index da7e704..34ce04a 100644 +--- a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java ++++ b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +@@ -109,4 +109,11 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig + .getStringList("my", null, "somename"))); + checkFile(cfgFile, "[my]\n\tsomename = value1\n\tsomename = value2\n"); + } ++ ++ public void test006_readCaseInsensitive() throws IOException { ++ final File path = writeTrashFile("config_001", "[Foo]\nBar\n"); ++ RepositoryConfig repositoryConfig = new RepositoryConfig(null, path); ++BAD LINE ++ assertEquals(true, repositoryConfig.getBoolean("foo", null, "bar", false)); ++ assertEquals("", repositoryConfig.getString("foo", null, "bar")); ++ } + } diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_CcTruncatedOld.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_CcTruncatedOld.patch new file mode 100644 index 0000000000..1bbcfb54de --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_CcTruncatedOld.patch @@ -0,0 +1,24 @@ +commit 1a56639bbea8e8cbfbe5da87746de97f9217ce9b +Date: Tue May 13 00:43:56 2008 +0200 + ... + +diff --cc org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +index 169356b,dd8c317..fd85931 +mode 100644,100644..100755 +--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java ++++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +@@@ -55,12 -163,13 +163,15 @@@ public class UIText extends NLS + + /** */ + public static String ResourceHistory_toggleCommentWrap; ++ + /** */ + + /** */ + public static String ResourceHistory_toggleRevDetail; + /** */ + public static String ResourceHistory_toggleRevComment; + /** */ + public static String ResourceHistory_toggleTooltips; + + +commit 1a56639bbea8e8cbfbe5da87746de97f9217ce9b diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_DisconnectedHunk.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_DisconnectedHunk.patch new file mode 100644 index 0000000000..3235970412 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_DisconnectedHunk.patch @@ -0,0 +1,30 @@ +From: A. U. Thor + +@@ -109,4 +109,11 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig + .getStringList("my", null, "somename"))); + checkFile(cfgFile, "[my]\n\tsomename = value1\n\tsomename = value2\n"); + } ++ ++ public void test006_readCaseInsensitive() throws IOException { ++ final File path = writeTrashFile("config_001", "[Foo]\nBar\n"); ++ RepositoryConfig repositoryConfig = new RepositoryConfig(null, path); ++ assertEquals(true, repositoryConfig.getBoolean("foo", null, "bar", false)); ++ assertEquals("", repositoryConfig.getString("foo", null, "bar")); ++ } + } +diff --git a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +index 45c2f8a..3291bba 100644 +--- a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java ++++ b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +@@ -236,9 +236,9 @@ protected boolean getBoolean(final String section, String subsection, + return defaultValue; + + n = n.toLowerCase(); +- if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equals(n) || "true".equals(n) || "1".equals(n)) { ++ if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equalsIgnoreCase(n) || "true".equalsIgnoreCase(n) || "1".equals(n)) { + return true; +- } else if ("no".equals(n) || "false".equals(n) || "0".equals(n)) { ++ } else if ("no".equalsIgnoreCase(n) || "false".equalsIgnoreCase(n) || "0".equalsIgnoreCase(n)) { + return false; + } else { + throw new IllegalArgumentException("Invalid boolean value: " diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GarbageBetweenFiles.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GarbageBetweenFiles.patch new file mode 100644 index 0000000000..9f6fd6b8f6 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GarbageBetweenFiles.patch @@ -0,0 +1,33 @@ +diff --git a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +index da7e704..34ce04a 100644 +--- a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java ++++ b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +@@ -109,4 +109,11 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig + .getStringList("my", null, "somename"))); + checkFile(cfgFile, "[my]\n\tsomename = value1\n\tsomename = value2\n"); + } ++ ++ public void test006_readCaseInsensitive() throws IOException { ++ final File path = writeTrashFile("config_001", "[Foo]\nBar\n"); ++ RepositoryConfig repositoryConfig = new RepositoryConfig(null, path); ++ assertEquals(true, repositoryConfig.getBoolean("foo", null, "bar", false)); ++ assertEquals("", repositoryConfig.getString("foo", null, "bar")); ++ } + } +I AM NOT HERE +diff --git a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +index 45c2f8a..3291bba 100644 +--- a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java ++++ b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +@@ -236,9 +236,9 @@ protected boolean getBoolean(final String section, String subsection, + return defaultValue; + + n = n.toLowerCase(); +- if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equals(n) || "true".equals(n) || "1".equals(n)) { ++ if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equalsIgnoreCase(n) || "true".equalsIgnoreCase(n) || "1".equals(n)) { + return true; +- } else if ("no".equals(n) || "false".equals(n) || "0".equals(n)) { ++ } else if ("no".equalsIgnoreCase(n) || "false".equalsIgnoreCase(n) || "0".equalsIgnoreCase(n)) { + return false; + } else { + throw new IllegalArgumentException("Invalid boolean value: " diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GitBinaryNoForwardHunk.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GitBinaryNoForwardHunk.patch new file mode 100644 index 0000000000..e3f33075ae --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_GitBinaryNoForwardHunk.patch @@ -0,0 +1,10 @@ + create mode 100644 org.spearce.egit.ui/icons/toolbar/pushe.png + +diff --git a/org.spearce.egit.ui/icons/toolbar/fetchd.png b/org.spearce.egit.ui/icons/toolbar/fetchd.png +new file mode 100644 +index 0000000000000000000000000000000000000000..4433c543f2a52b586a3ed5e31b138244107bc239 +GIT binary patch + +diff --git a/org.spearce.egit.ui/icons/toolbar/fetche.png b/org.spearce.egit.ui/icons/toolbar/fetche.png +new file mode 100644 +index 0000000000000000000000000000000000000000..0ffeb419e6ab302caa5e58661854b33853dc43dc diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedNew.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedNew.patch new file mode 100644 index 0000000000..f10a433be8 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedNew.patch @@ -0,0 +1,15 @@ +diff --git a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +index 45c2f8a..3291bba 100644 +--- a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java ++++ b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +@@ -236,9 +236,9 @@ protected boolean getBoolean(final String section, String subsection, + return defaultValue; + + n = n.toLowerCase(); +- if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equals(n) || "true".equals(n) || "1".equals(n)) { + return true; +- } else if ("no".equals(n) || "false".equals(n) || "0".equals(n)) { ++ } else if ("no".equalsIgnoreCase(n) || "false".equalsIgnoreCase(n) || "0".equalsIgnoreCase(n)) { + return false; + } else { + throw new IllegalArgumentException("Invalid boolean value: " diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedOld.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedOld.patch new file mode 100644 index 0000000000..42363c61c8 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testError_TruncatedOld.patch @@ -0,0 +1,15 @@ +diff --git a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +index 45c2f8a..3291bba 100644 +--- a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java ++++ b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +@@ -236,9 +236,9 @@ protected boolean getBoolean(final String section, String subsection, + return defaultValue; + + n = n.toLowerCase(); +- if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equals(n) || "true".equals(n) || "1".equals(n)) { ++ if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equalsIgnoreCase(n) || "true".equalsIgnoreCase(n) || "1".equals(n)) { + return true; ++ } else if ("no".equalsIgnoreCase(n) || "false".equalsIgnoreCase(n) || "0".equalsIgnoreCase(n)) { + return false; + } else { + throw new IllegalArgumentException("Invalid boolean value: " diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_BothISO88591.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_BothISO88591.patch new file mode 100644 index 0000000000..8224fcc21d --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_BothISO88591.patch @@ -0,0 +1,21 @@ +diff --git a/X b/X +index 014ef30..8c80a36 100644 +--- a/X ++++ b/X +@@ -1,7 +1,7 @@ + a + b + c +-Ångström ++line 4 Ångström + d + e + f +@@ -13,6 +13,6 @@ k + l + m + n +-Ångström ++Ångström; line 16 + o + p diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_Convert.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_Convert.patch new file mode 100644 index 0000000000..a43fef584d --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_Convert.patch @@ -0,0 +1,21 @@ +diff --git a/X b/X +index 014ef30..209db0d 100644 +--- a/X ++++ b/X +@@ -1,7 +1,7 @@ + a + b + c +-Ångström ++Ã…ngström + d + e + f +@@ -13,6 +13,6 @@ k + l + m + n +-Ångström ++Ã…ngström + o + p diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_DiffCc.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_DiffCc.patch new file mode 100644 index 0000000000..3f74a52234 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_DiffCc.patch @@ -0,0 +1,13 @@ +diff --cc X +index bdfc9f4,209db0d..474bd69 +--- a/X ++++ b/X +@@@ -1,7 -1,7 +1,7 @@@ + a +--b + c + +test Ångström ++ Ã…ngström + d + e + f diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_NoBinary.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_NoBinary.patch new file mode 100644 index 0000000000..e4968dc4eb --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testGetText_NoBinary.patch @@ -0,0 +1,4 @@ +diff --git a/org.spearce.egit.ui/icons/toolbar/fetchd.png b/org.spearce.egit.ui/icons/toolbar/fetchd.png +new file mode 100644 +index 0000000..4433c54 +Binary files /dev/null and b/org.spearce.egit.ui/icons/toolbar/fetchd.png differ diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_AddNoNewline.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_AddNoNewline.patch new file mode 100644 index 0000000000..3060952e33 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_AddNoNewline.patch @@ -0,0 +1,20 @@ +From ca4719a4b2d93a469f61d1ddfb3e39ecbabfcd69 Mon Sep 17 00:00:00 2001 +From: Shawn O. Pearce <sop@google.com> +Date: Fri, 12 Dec 2008 12:35:14 -0800 +Subject: [PATCH] introduce no lf again + +--- + a | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/a b/a +index f2ad6c7..c59d9b6 100644 +--- a/a ++++ b/a +@@ -1 +1 @@ +-c ++d +\ No newline at end of file +-- +1.6.1.rc2.306.ge5d5e + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcDeleteFile.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcDeleteFile.patch new file mode 100644 index 0000000000..2654e09799 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcDeleteFile.patch @@ -0,0 +1,12 @@ +commit 740709ece2412856c0c3eabd4dc4a4cf115b0de6 +Merge: 5c19b43... 13a2c0d... +Author: Shawn O. Pearce <sop@google.com> +Date: Fri Dec 12 13:26:52 2008 -0800 + + Merge branch 'b' into d + +diff --cc a +index 7898192,2e65efe..0000000 +deleted file mode 100644,100644 +--- a/a ++++ /dev/null diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcNewFile.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcNewFile.patch new file mode 100644 index 0000000000..1a9b7b0ee3 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_CcNewFile.patch @@ -0,0 +1,14 @@ +commit 6cb8160a4717d51fd3cc0baf721946daa60cf921 +Merge: 5c19b43... 13a2c0d... +Author: Shawn O. Pearce <sop@google.com> +Date: Fri Dec 12 13:26:52 2008 -0800 + + Merge branch 'b' into d + +diff --cc d +index 0000000,0000000..4bcfe98 +new file mode 100644 +--- /dev/null ++++ b/d +@@@ -1,0 -1,0 +1,1 @@@ +++d diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_ConfigCaseInsensitive.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_ConfigCaseInsensitive.patch new file mode 100644 index 0000000000..bfb9b15dce --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_ConfigCaseInsensitive.patch @@ -0,0 +1,67 @@ +From ce9b593ddf2530613f6da9d7f7e4a5ff93da8b36 Mon Sep 17 00:00:00 2001 +From: Robin Rosenberg <robin.rosenberg@dewire.com> +Date: Mon, 13 Oct 2008 00:50:59 +0200 +Subject: [PATCH] git config file is case insensitive + +Keys are now always compared with ignore case rules. + +Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com> +Signed-off-by: Shawn O. Pearce <spearce@spearce.org> +--- + .../org/spearce/jgit/lib/RepositoryConfigTest.java | 7 +++++++ + .../src/org/spearce/jgit/lib/RepositoryConfig.java | 8 ++++---- + 2 files changed, 11 insertions(+), 4 deletions(-) + +diff --git a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +index da7e704..34ce04a 100644 +--- a/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java ++++ b/org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java +@@ -109,4 +109,11 @@ assertTrue(Arrays.equals(values.toArray(), repositoryConfig + .getStringList("my", null, "somename"))); + checkFile(cfgFile, "[my]\n\tsomename = value1\n\tsomename = value2\n"); + } ++ ++ public void test006_readCaseInsensitive() throws IOException { ++ final File path = writeTrashFile("config_001", "[Foo]\nBar\n"); ++ RepositoryConfig repositoryConfig = new RepositoryConfig(null, path); ++ assertEquals(true, repositoryConfig.getBoolean("foo", null, "bar", false)); ++ assertEquals("", repositoryConfig.getString("foo", null, "bar")); ++ } + } +diff --git a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +index 45c2f8a..3291bba 100644 +--- a/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java ++++ b/org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java +@@ -236,9 +236,9 @@ protected boolean getBoolean(final String section, String subsection, + return defaultValue; + + n = n.toLowerCase(); +- if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equals(n) || "true".equals(n) || "1".equals(n)) { ++ if (MAGIC_EMPTY_VALUE.equals(n) || "yes".equalsIgnoreCase(n) || "true".equalsIgnoreCase(n) || "1".equals(n)) { + return true; +- } else if ("no".equals(n) || "false".equals(n) || "0".equals(n)) { ++ } else if ("no".equalsIgnoreCase(n) || "false".equalsIgnoreCase(n) || "0".equalsIgnoreCase(n)) { + return false; + } else { + throw new IllegalArgumentException("Invalid boolean value: " +@@ -300,7 +300,7 @@ public String getString(final String section, String subsection, final String na + final Set<String> result = new HashSet<String>(); + + for (final Entry e : entries) { +- if (section.equals(e.base) && e.extendedBase != null) ++ if (section.equalsIgnoreCase(e.base) && e.extendedBase != null) + result.add(e.extendedBase); + } + if (baseConfig != null) +@@ -954,7 +954,7 @@ private static boolean eq(final String a, final String b) { + return true; + if (a == null || b == null) + return false; +- return a.equals(b); ++ return a.equalsIgnoreCase(b); + } + } + } +-- +1.6.1.rc2.299.gead4c + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_FixNoNewline.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_FixNoNewline.patch new file mode 100644 index 0000000000..e8af2e719a --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_FixNoNewline.patch @@ -0,0 +1,20 @@ +From 1beb3ec1fe68ff18b0287396096442e12c34787a Mon Sep 17 00:00:00 2001 +From: Shawn O. Pearce <sop@google.com> +Date: Fri, 12 Dec 2008 12:29:45 -0800 +Subject: [PATCH] make c and add lf + +--- + a | 2 +- + 1 files changed, 1 insertions(+), 1 deletions(-) + +diff --git a/a b/a +index 2e65efe..f2ad6c7 100644 +--- a/a ++++ b/a +@@ -1 +1 @@ +-a +\ No newline at end of file ++c +-- +1.6.1.rc2.306.ge5d5e + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryDelta.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryDelta.patch new file mode 100644 index 0000000000..5b2c9c6260 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryDelta.patch @@ -0,0 +1,21 @@ +From 7e49721ad0efdec3a81e20bc58e385ea5d2b87b7 Mon Sep 17 00:00:00 2001 +From: Shawn O. Pearce <sop@google.com> +Date: Fri, 12 Dec 2008 12:45:17 -0800 +Subject: [PATCH] make zero have a 3 + +--- + zero.bin | Bin 4096 -> 4096 bytes + 1 files changed, 0 insertions(+), 0 deletions(-) + +diff --git a/zero.bin b/zero.bin +index 08e7df176454f3ee5eeda13efa0adaa54828dfd8..d70d8710b6d32ff844af0ee7c247e4b4b051867f 100644 +GIT binary patch +delta 12 +TcmZorXi%6C%4ociaTPxR8IA+R + +delta 11 +ScmZorXi(Uguz-JJK>`37u>@iO + +-- +1.6.1.rc2.306.ge5d5e + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryLiteral.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryLiteral.patch new file mode 100644 index 0000000000..ab7b235919 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_GitBinaryLiteral.patch @@ -0,0 +1,135 @@ +From 8363f12135a7d0ff0b5fea7d5a35d294c0479518 Mon Sep 17 00:00:00 2001 +From: Robin Rosenberg <robin.rosenberg.lists@dewire.com> +Date: Tue, 23 Sep 2008 22:19:19 +0200 +Subject: [PATCH] Push and fetch icons for the toolbar + +Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com> +Signed-off-by: Shawn O. Pearce <spearce@spearce.org> +--- + org.spearce.egit.ui/icons/toolbar/fetchd.png | Bin 0 -> 359 bytes + org.spearce.egit.ui/icons/toolbar/fetche.png | Bin 0 -> 393 bytes + org.spearce.egit.ui/icons/toolbar/pushd.png | Bin 0 -> 372 bytes + org.spearce.egit.ui/icons/toolbar/pushe.png | Bin 0 -> 404 bytes + org.spearce.egit.ui/plugin.xml | 32 ++++++++++++++----------- + 5 files changed, 18 insertions(+), 14 deletions(-) + create mode 100644 org.spearce.egit.ui/icons/toolbar/fetchd.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/fetche.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/pushd.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/pushe.png + +diff --git a/org.spearce.egit.ui/icons/toolbar/fetchd.png b/org.spearce.egit.ui/icons/toolbar/fetchd.png +new file mode 100644 +index 0000000000000000000000000000000000000000..4433c543f2a52b586a3ed5e31b138244107bc239 +GIT binary patch +literal 359 +zcmV-t0hs=YP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0003lNkl<ZIE|%~ +zF{;8q6h+U7BBn4qm_`dxuy6}@!NzsCfLTKp;5yPsN=p|I(rKe&p~M74Bq5ObRRW{% +zje4sYc=ybGk2gYV%`a+{hvjnl6{!Lo4hNJ{A44jDl#(C_K2BmJ09dV7A3>VW2}+n! +zO1rKr0DRxqm&=7b&q>piUayDaIKlvw2}+e_&-3(PFkmzq(Q380-|r+zg6Da9KA(#Q +zPa2QMl^Gz*GK3HmMPby1VQ9_(U^bf>W`H=3+3)uhMZxuY<#al++wJIfyXFi47K?>p +z2GCj~rNp*vI-L&fb{osGh@!|$@ci;S2_arv_(sil1xb<+1Odb0kjLY}`F!ShJaW6; +z>Lr*?r);;|7ihoV2SC*MjhoFzuh;A9KAB9aMXCk(Pk$Loi}X0uxcmSB002ovPDHLk +FV1lxPoI3yj + +literal 0 +HcmV?d00001 + +diff --git a/org.spearce.egit.ui/icons/toolbar/fetche.png b/org.spearce.egit.ui/icons/toolbar/fetche.png +new file mode 100644 +index 0000000000000000000000000000000000000000..0ffeb419e6ab302caa5e58661854b33853dc43dc +GIT binary patch +literal 393 +zcmV;40e1e0P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0003{Nkl<ZIE|%} +z%Su8~6o$WjJd|h&)kLg8qatclklHDbhzOh%4SI>*L3{^aqJcvRqCsRQ6~SndH7ExK +zk=KcyE?#y6(aupYt$(ujUi|ChXYD1Vl>A3Z=W-tL|B2KE=%pm#uoxNA1!yxqxEMW& +zB>{jQO^yT+ogtn_{8Ep$Aq3h-C?o|y>g-6?-!e46K4}{7I2X6^?w$w$wKqXWo#uE< +zlN$@u$mIiCW0N$hIYc2#Jf_L5pe_`875HfeP>nhW1zLv1R!iSvNdTZ7`q(*62#YbV +zQhB;#V#z_Hl;tD;jPm%3!!_Fv=xqj&EpW_lqPo^m>_wFE9KxQ3t1@8v1#@h(gk?2k +zU%h_@BTD_vVB{6b=^Lij^3<ya#!DI7eU*yg9xg#(&qL<HX{n_QH=dOmU|OU>Dkk>j +n^=YB|UiI3T3toz$0fY1nZ1068v8@+b00000NkvXXu0mjfWwNMg + +literal 0 +HcmV?d00001 + +diff --git a/org.spearce.egit.ui/icons/toolbar/pushd.png b/org.spearce.egit.ui/icons/toolbar/pushd.png +new file mode 100644 +index 0000000000000000000000000000000000000000..22c3f7bf17b8b5a931c7527d768af13607b03bce +GIT binary patch +literal 372 +zcmV-)0gL{LP)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV0003yNkl<ZIE|%~ +zF{%PF6h%)&8w)Kgg)~~o6c%=-wG$iH;R0NP3veAG$Sh>A(?&%>K?5S92zkHxGyeyN +zQSnxRymxZ%OQJ-CZ<LQ0VHnEcaNzNHaJ${8)oOIRUG)l}M1;v?B8^6aVzEe}P~dX8 +zV6A1h+tKg$Ga)&E`~8km3g?`+IiJs8M#ur2PA68Y70x-1$0OVAmgRCusZ@FoAR=h3 +zDVNJsDix~LD)oBZD;$r<sngD7(Utm(zh18y4u?;WOu&C>t%;)O$w?l-T1yl~1VO;{ +zdS$=gv)ODopU<8HfZ1#YAcMg`B@Q~B4vWRYJJDL}%|UCO8Yd6XZnu?)$aFeQidwCf +z_mE--u|}hjN&o=H7-fukIg4hqnKXNVchu|kh_lCf`xbzwX88RJ-{>O;Y5D>6^@Sy# +SDlMe|0000<MNUMnLSTZnn4{zX + +literal 0 +HcmV?d00001 + +diff --git a/org.spearce.egit.ui/icons/toolbar/pushe.png b/org.spearce.egit.ui/icons/toolbar/pushe.png +new file mode 100644 +index 0000000000000000000000000000000000000000..1f99f0a702983d674f15eedae5f1218f0a30b5a0 +GIT binary patch +literal 404 +zcmV;F0c-w=P)<h;3K|Lk000e1NJLTq000mG000mO1^@s6AM^iV00047Nkl<ZIE|%~ +z%Su8~6o$WjJO~|4C>w|sG%6%VHSk(UL<B+v4SI>*L41dvA&3Z?G>L*BB*n0rWDTl8 +zL8Pb?Jzc!)CSJ}#$rF8}#a?Uu`(JCbg_M&2pmu`H$+oP&=V*R^(bPY1%&ibu+ZV$G +zgp`tt<A@B;jw3Z6E&C{q>NBF4=c=f%6i@vsq5!CR9fSfc-IT0lZ>^0`E2vbS?r{1v +z8l^m+g%^~^H#FDePyq!%wm_SSqPmu`yJKk6QAXzdroz+R(7<gg074jZz1Vo3Dy2y# +zMW2W=)MJ~7I|%3fPE-KBpis_UGqzZuUe(cG%h>L#RCJHY0YK_74TR+C&ZX!&h^>3c +zJvdA^W^@l;f6eS*z&I*^D|{frVpE>&7273F76LY=;y1$BWF(Q0qALI}5jqkZAq&fh +y^_oorR)}l`>CE22@+$y+&Cvb}|KU##2Jr)k?t0Dap2#Es0000<MNUMnLSTZgH?cGT + +literal 0 +HcmV?d00001 + +diff --git a/org.spearce.egit.ui/plugin.xml b/org.spearce.egit.ui/plugin.xml +index 7c98688..ee8a5a0 100644 +--- a/org.spearce.egit.ui/plugin.xml ++++ b/org.spearce.egit.ui/plugin.xml +@@ -272,22 +272,26 @@ + </separator> + </menu> + <action +- class="org.spearce.egit.ui.internal.actions.FetchAction" +- id="org.spearce.egit.ui.actionfetch" +- label="%FetchAction_label" +- style="push" +- menubarPath="org.spearce.egit.ui.gitmenu/repo" +- toolbarPath="org.spearce.egit.ui" +- tooltip="%FetchAction_tooltip"> ++ class="org.spearce.egit.ui.internal.actions.FetchAction" ++ disabledIcon="icons/toolbar/fetchd.png" ++ icon="icons/toolbar/fetche.png" ++ id="org.spearce.egit.ui.actionfetch" ++ label="%FetchAction_label" ++ menubarPath="org.spearce.egit.ui.gitmenu/repo" ++ style="push" ++ toolbarPath="org.spearce.egit.ui" ++ tooltip="%FetchAction_tooltip"> + </action> + <action +- class="org.spearce.egit.ui.internal.actions.PushAction" +- id="org.spearce.egit.ui.actionpush" +- label="%PushAction_label" +- style="push" +- menubarPath="org.spearce.egit.ui.gitmenu/repo" +- toolbarPath="org.spearce.egit.ui" +- tooltip="%PushAction_tooltip"> ++ class="org.spearce.egit.ui.internal.actions.PushAction" ++ disabledIcon="icons/toolbar/pushd.png" ++ icon="icons/toolbar/pushe.png" ++ id="org.spearce.egit.ui.actionpush" ++ label="%PushAction_label" ++ menubarPath="org.spearce.egit.ui.gitmenu/repo" ++ style="push" ++ toolbarPath="org.spearce.egit.ui" ++ tooltip="%PushAction_tooltip"> + </action> + <action + class="org.spearce.egit.ui.internal.actions.BranchAction" +-- +1.6.1.rc2.306.ge5d5e + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_NoBinary.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_NoBinary.patch new file mode 100644 index 0000000000..684b13c824 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_NoBinary.patch @@ -0,0 +1,83 @@ +From 8363f12135a7d0ff0b5fea7d5a35d294c0479518 Mon Sep 17 00:00:00 2001 +From: Robin Rosenberg <robin.rosenberg.lists@dewire.com> +Date: Tue, 23 Sep 2008 22:19:19 +0200 +Subject: [PATCH] Push and fetch icons for the toolbar + +Signed-off-by: Robin Rosenberg <robin.rosenberg@dewire.com> +Signed-off-by: Shawn O. Pearce <spearce@spearce.org> +--- + org.spearce.egit.ui/icons/toolbar/fetchd.png | Bin 0 -> 359 bytes + org.spearce.egit.ui/icons/toolbar/fetche.png | Bin 0 -> 393 bytes + org.spearce.egit.ui/icons/toolbar/pushd.png | Bin 0 -> 372 bytes + org.spearce.egit.ui/icons/toolbar/pushe.png | Bin 0 -> 404 bytes + org.spearce.egit.ui/plugin.xml | 32 ++++++++++++++----------- + 5 files changed, 18 insertions(+), 14 deletions(-) + create mode 100644 org.spearce.egit.ui/icons/toolbar/fetchd.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/fetche.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/pushd.png + create mode 100644 org.spearce.egit.ui/icons/toolbar/pushe.png + +diff --git a/org.spearce.egit.ui/icons/toolbar/fetchd.png b/org.spearce.egit.ui/icons/toolbar/fetchd.png +new file mode 100644 +index 0000000..4433c54 +Binary files /dev/null and b/org.spearce.egit.ui/icons/toolbar/fetchd.png differ +diff --git a/org.spearce.egit.ui/icons/toolbar/fetche.png b/org.spearce.egit.ui/icons/toolbar/fetche.png +new file mode 100644 +index 0000000..0ffeb41 +Binary files /dev/null and b/org.spearce.egit.ui/icons/toolbar/fetche.png differ +diff --git a/org.spearce.egit.ui/icons/toolbar/pushd.png b/org.spearce.egit.ui/icons/toolbar/pushd.png +new file mode 100644 +index 0000000..22c3f7b +Binary files /dev/null and b/org.spearce.egit.ui/icons/toolbar/pushd.png differ +diff --git a/org.spearce.egit.ui/icons/toolbar/pushe.png b/org.spearce.egit.ui/icons/toolbar/pushe.png +new file mode 100644 +index 0000000..1f99f0a +Binary files /dev/null and b/org.spearce.egit.ui/icons/toolbar/pushe.png differ +diff --git a/org.spearce.egit.ui/plugin.xml b/org.spearce.egit.ui/plugin.xml +index 7c98688..ee8a5a0 100644 +--- a/org.spearce.egit.ui/plugin.xml ++++ b/org.spearce.egit.ui/plugin.xml +@@ -272,22 +272,26 @@ + </separator> + </menu> + <action +- class="org.spearce.egit.ui.internal.actions.FetchAction" +- id="org.spearce.egit.ui.actionfetch" +- label="%FetchAction_label" +- style="push" +- menubarPath="org.spearce.egit.ui.gitmenu/repo" +- toolbarPath="org.spearce.egit.ui" +- tooltip="%FetchAction_tooltip"> ++ class="org.spearce.egit.ui.internal.actions.FetchAction" ++ disabledIcon="icons/toolbar/fetchd.png" ++ icon="icons/toolbar/fetche.png" ++ id="org.spearce.egit.ui.actionfetch" ++ label="%FetchAction_label" ++ menubarPath="org.spearce.egit.ui.gitmenu/repo" ++ style="push" ++ toolbarPath="org.spearce.egit.ui" ++ tooltip="%FetchAction_tooltip"> + </action> + <action +- class="org.spearce.egit.ui.internal.actions.PushAction" +- id="org.spearce.egit.ui.actionpush" +- label="%PushAction_label" +- style="push" +- menubarPath="org.spearce.egit.ui.gitmenu/repo" +- toolbarPath="org.spearce.egit.ui" +- tooltip="%PushAction_tooltip"> ++ class="org.spearce.egit.ui.internal.actions.PushAction" ++ disabledIcon="icons/toolbar/pushd.png" ++ icon="icons/toolbar/pushe.png" ++ id="org.spearce.egit.ui.actionpush" ++ label="%PushAction_label" ++ menubarPath="org.spearce.egit.ui.gitmenu/repo" ++ style="push" ++ toolbarPath="org.spearce.egit.ui" ++ tooltip="%PushAction_tooltip"> + </action> + <action + class="org.spearce.egit.ui.internal.actions.BranchAction" +-- +1.6.1.rc2.306.ge5d5e + diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_OneFileCc.patch b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_OneFileCc.patch new file mode 100644 index 0000000000..c096b330af --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/patch/testParse_OneFileCc.patch @@ -0,0 +1,27 @@ +commit 1a56639bbea8e8cbfbe5da87746de97f9217ce9b +Date: Tue May 13 00:43:56 2008 +0200 + ... + +diff --cc org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +index 169356b,dd8c317..fd85931 +mode 100644,100644..100755 +--- a/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java ++++ b/org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java +@@@ -55,12 -163,13 +163,15 @@@ public class UIText extends NLS + + /** */ + public static String ResourceHistory_toggleCommentWrap; ++ + /** */ + + public static String ResourceHistory_toggleCommentFill; + + /** */ + public static String ResourceHistory_toggleRevDetail; ++ + /** */ + public static String ResourceHistory_toggleRevComment; ++ + /** */ + public static String ResourceHistory_toggleTooltips; + + +commit 1a56639bbea8e8cbfbe5da87746de97f9217ce9b diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/all_packed_objects.txt b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/all_packed_objects.txt new file mode 100644 index 0000000000..a97f662455 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/all_packed_objects.txt @@ -0,0 +1,96 @@ +4b825dc642cb6eb9a060e54bf8d69288fbee4904 tree 0 9 7782 +540a36d136cf413e4b064c2b0e0a4db60f77feab commit 191 131 339 +5b6e7c66c276e7610d4a73c70ec1a1f7c1003259 blob 11 40 516 1 6ff87c4664981e4397625791c8ea3bbb5f2279a3 +6ff87c4664981e4397625791c8ea3bbb5f2279a3 blob 18787 7180 556 +82c6b885ff600be425b4ea96dee75dca255b69e7 commit 245 166 12 +902d5476fa249b7abc9d84c611577a81381f0327 tree 35 46 7736 +aabf2ffaec9b497f0950352b3e582d73035c2035 tree 35 46 470 +c59759f143fb1fe21c197981df75a7ee00290799 commit 240 161 178 +02ba32d3649e510002c21651936b7077aa75ffa9 tree 122 127 3806 +0966a434eb1a025db6b71485ab63a3bfbea520b6 commit 287 197 2611 +09efc7e59a839528ac7bda9fa020dc9101278680 tree 68 71 5497 +0a3d7772488b6b106fb62813c4d6d627918d9181 tree 98 95 3367 +1004d0d7ac26fbf63050a234c9b88a46075719d3 tree 68 72 3504 +10da5895682013006950e7da534b705252b03be6 blob 6 15 3591 +1203b03dc816ccbb67773f28b3c19318654b0bc8 commit 222 152 758 +15fae9e651043de0fd1deef588aa3fbf5a7a41c6 blob 6 15 3474 +16f9ec009e5568c435f473ba3a1df732d49ce8c3 blob 3 12 4196 +1fd7d579fb6ae3fe942dc09c2c783443d04cf21e blob 6 15 3678 +20a8ade77639491ea0bd667bf95de8abf3a434c8 tree 66 77 5663 +2675188fd86978d5bc4d7211698b2118ae3bf658 tree 68 72 4124 +2c349335b7f797072cf729c4f3bb0914ecb6dec9 commit 221 154 2457 +2cc3f4155a8eda5c3f1bc85de0988c0155c8cc1c tree 68 72 4717 +30a7b072d441dbfcfe0266b1c5fce94c22c447da tree 38 48 5784 +42e4e7c5e507e113ebbb7801b16b52cf867b7ce1 commit 184 133 1407 +49322bb17d3acc9146f98c97d078513228bbf3c0 commit 338 223 12 +49c5f851406e8004b816b8170f6f18e30ee877b9 tree 68 72 3606 +55a1a760df4b86a02094a904dfa511deb5655905 blob 6 15 3693 +58be4659bb571194ed4562d04b359d26216f526e commit 226 156 2962 +59706a11bde2b9899a278838ef20a97e8f8795d2 commit 222 153 1692 +5f25aaf573e7a094697987a927b833e088134674 tree 66 76 5184 +6020a3b8d5d636e549ccbd0c53e2764684bb3125 tree 122 126 3241 +62b15c9ddac853efbb00f59123f484b05b06d8b3 tree 28 37 4431 +6462e7d8024396b14d7651e2ec11e2bbf07a05c4 commit 221 153 1254 +6c83a9d0a09ce6d12292314ed3d9e1f60e39feb0 tree 66 76 5587 +6c8b137b1c652731597c89668f417b8695f28dd7 commit 172 123 3118 +6db9c2ebf75590eef973081736730a9ea169a0c4 commit 222 152 2153 +6e1475206e57110fcef4b92320436c1e9872a322 commit 282 192 566 +7f822839a2fe9760f386cbbbcb3f92c5fe81def7 commit 222 152 1540 +81e462df7c747d5b8783af18bf83bffbef8dc2bc tree 34 45 5139 +8230f48330e0055d9e0bc5a2a77718f6dd9324b8 blob 10 19 5568 +82b1d08466e9505f8666b778744f9a3471a70c81 blob 20 22 3708 +82fb2e7873759b74c41020a00abaea9c378a7a15 tree 66 76 4801 +835da11381dee94c71a04164cdaa533d0673e4e5 tree 34 45 4468 +83834a7afdaa1a1260568567f6ad90020389f664 commit 282 192 1062 +83d2f0431bcdc9c2fd2c17b828143be6ee4fbe80 commit 221 155 1998 +856ec208ae6cadac25a6d74f19b12bb27a24fe24 tree 66 76 5260 +86265c33b19b2be71bdd7b8cb95823f2743d03a8 tree 94 102 4208 +86cec6b57d80fda40300fb0d667965a5c3c3572f blob 6 15 3576 +8d6a2f2af0b2b96f320dd62fb6d9916fd2497dd9 tree 66 77 5420 +8f50ba15d49353813cc6e20298002c0d17b0a9ee tree 94 102 4961 +9188910f5d18434c2c8a3d78e8bef1a469c5626e tree 68 72 3933 +965361132e2f15897c9fd6c727beb5753057c38a blob 6 15 3489 +968a4b6caa8b55a68098e0495fbd9e75a7d05efa tree 68 72 4310 +a288d2cc3ee7d82f482e70ae7b6fedb4a039dd09 tree 28 37 4394 +a33a091b7c8de98b3a2ad2f21f88ea86f395d787 tree 94 102 4615 +a4e0e50de469ac6e2fdf2ee81808f253d5b78fd3 tree 68 72 5336 +ac7e7e44c1885efb472ad54a78327d66bfc4ecef commit 221 154 2808 +acd0220f06f7e4db50ea5ba242f0dfed297b27af tree 94 102 4513 +ae9304576a6ec3419b231b2b9c8e33a06f97f9fb blob 3 12 4382 +b9877f83f4c2ba0c3dd8fb2f6b5f04a0aaf18594 tree 66 76 5063 +bab66b48f836ed950c99134ef666436fb07a09a0 commit 222 152 910 +be9b45333b66013bde1c7314efc50fabd9b39c6d tree 7 18 4005 1 02ba32d3649e510002c21651936b7077aa75ffa9 +c070ad8c08840c8116da865b2d65593a6bb9cd2a commit 282 192 235 +c17b9ee9d0501fecadfac3b60ca485b14f5dbe98 tree 38 49 5832 +c1827f07e114c20547dc6a7296588870a4b5b62c blob 3 12 5408 +c9c6af7f78bc47490dbf3e822cf2f3c24d4b9061 blob 3 12 4949 +cd4bcfc27da62c6b840de700be1c60a7e69952a5 tree 66 76 3730 +d0114ab8ac326bab30e3a657a0397578c5a1af88 commit 84 95 427 1 c070ad8c08840c8116da865b2d65593a6bb9cd2a +d31f5a60d406e831d056b8ac2538d515100c2df2 commit 221 153 1845 +d4b9b11fc8006af3b05cf2b4611077ed6a9b8c07 tree 68 72 4877 +d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 commit 222 152 2305 +da0f8ed91a8f2f0f067b3bdf26265d5ca48cf82c blob 3 12 3462 +e4ff0b72cb0994dbf7a9da260aeb461c9d882bb5 tree 34 44 5740 +e6bfff5c1d0f0ecd501552b43a1e13d8008abc31 blob 3 12 4789 +f2aacb9368806d6502a03aa9da0834d4b50b9f0e tree 94 101 4023 +f73b95671f326616d66b2afb3bdfcdbbce110b44 commit 33 44 522 2 d0114ab8ac326bab30e3a657a0397578c5a1af88 +17768080a2318cd89bba4c8b87834401e2095703 tag 140 132 12 +032c063ce34486359e3ee3d4f9e5c225b9e1a4c2 tag 152 138 12 +1170b77a48d3ea2d58b043648b1ec63d606e3efa tag 150 138 971 +214cae792433672d28b3aeb9f75c1ae84fd54628 tag 150 136 1109 +8dfd42699e7b10e568fa1eaebe249e33e98da81e tag 150 138 833 +a773cd2d9dbca00d08793dac0d7002a49f0428c0 tag 150 138 422 +bf5123bb77c7b5a379f7de9c1293558e3e24dfb8 tag 150 135 287 +d54e006ebbef94b7d3a5cd56d154f1e6f08efb94 tag 150 137 560 +dd144af286452bfd6a1ea02b0d3745bcdb555e9d tag 150 137 150 +efee904c794b943a06931c76c576dd552212e8bc tag 150 136 697 +8bbde7aacf771a9afb6992434f1ae413e010c6d8 tag 630 436 1187 +fd608fbe625a2b456d9f15c2b1dc41f252057dd7 blob 1512 1175 12 +06b8692d5c4f29a6bc4987e1bec04e9bb2ec54a2 tree 29 40 330 +164bf8c9e69a5c192acd28e95aefd9a5d6f254df blob 7 16 370 +175d5b80bd9768884d8fced02e9bd33488174396 commit 56 68 160 1 47d3697c3747e8184e0dc479ccbd01e359023577 +3d2770618bb1132e59c314dea328b83ac7c83232 tree 29 40 488 +3df983efd6acdf73dfc7b451a2e30f7ed42e7736 blob 5 14 528 +47d3697c3747e8184e0dc479ccbd01e359023577 commit 217 148 12 +5e28f2d1ee99ddf4595a7a1ff31efa1a107c11e7 tree 94 102 386 +737d98fe75742dd9a8f4bce5e176e7f8d99d9de3 tree 94 102 228 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/create-second-pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/create-second-pack new file mode 100755 index 0000000000..7241fa694c --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/create-second-pack @@ -0,0 +1,166 @@ +#!/bin/bash -ex + +export GIT_COMMITTER_NAME="A U Thor" +export GIT_AUTHOR_NAME="A U Thor" +export GIT_COMMITTER_EMAIL="a.u.thor@example.com" +export GIT_AUTHOR_EMAIL="a.u.thor@example.com" + +test_tick () { + # from git/t/test-lib.sh + if test -z "${test_tick+set}" + then + test_tick=1112911993 + else + test_tick=$(($test_tick + 60)) + fi + GIT_COMMITTER_DATE="$test_tick -0700" + GIT_AUTHOR_DATE="$test_tick -0700" + export GIT_COMMITTER_DATE GIT_AUTHOR_DATE +} + +git_commit () { + test_tick + git commit "$@" +} + +git_merge () { + test_tick + git merge "$@" + +} + +test_tick +rm -rf .git *.txt ? +git init +echo "On master" >>master.txt +git add master.txt +git_commit -a -m "On master" + +echo "On master" >>master.txt +git_commit -a -m "On master again" + +git checkout -b a 6c8b137b1c652731597c89668f417b8695f28dd7 +mkdir a + +echo a1 >>a/a1.txt +git add a/a1.txt +git_commit -a -m "First a/a1" + +echo a2 >>a/a2.txt +git add a/a2.txt +git_commit -a -m "First a/a2" + +git merge master + +echo a1 >>a/a1.txt +git add a/a1.txt +git_commit -a -m "Second a/a1" +git branch pa + +echo a2 >>a/a2.txt +git add a/a2.txt +git_commit -a -m "Second a/a2" + +git checkout -b b 58be4659bb571194ed4562d04b359d26216f526e + +mkdir b +echo b1 >>b/b1.txt +git add b/b1.txt +git_commit -a -m "First b/b1" + +echo b2 >>b/b2.txt +git add b/b2.txt +git_commit -a -m "First b/b2" + +git merge a + +echo b1 >>b/b1.txt +git add b/b1.txt +git_commit -a -m "Second b/b1" + +echo b2 >>b/b2.txt +git add b/b2.txt +git_commit -a -m "Second b/b2" + +rm -rf a b c master.txt +mkdir c +rm -f ./git/index +echo ref: refs/heads/c >.git/HEAD + +echo c1 >>c/c1.txt +git add c/c1.txt +git_commit -a -m "First c/c1, no parent" + +echo c2 >>c/c2.txt +git add c/c2.txt +git_commit -a -m "First c/c2" + +git_merge a + +echo c1 >>c/c1.txt +git add c/c2.txt +git_commit -a -m "Second c/c1" + +echo c2 >>c/c2.txt +git add c/c2.txt +git_commit -a -m "Second c/c2" + +git_merge b + +git checkout -b d a + +echo "a1" >>a/a1 +git add a/a1 +git_commit -a -m "Third a/a1" + +git checkout -b e a + +echo "a1" >>a/a1 +git add a/a1 +git_commit -a -m "Fourth a/a1" + +git checkout master + +git_merge c d e + +git repack -d + +git tag A a +git tag -a -m "An annotated tag" B a^ + +git repack -d + +Bnth=B +for nth in 2nd 3rd 4th 5th 6th 7th 8th 9th 10th; do + git tag -a -m "An $nth level annotated tag" "B$nth" "$Bnth" + Bnth="B$nth" +done + +git repack -d + +git checkout -b f a +mkdir f +echo "an eff" >f/f +git add f/f +git commit -m "An eff" +git checkout -b g a +mkdir f +echo "an F" >f/f +git add f/f +git commit -m "An F" + +git repack -d + +git checkout -b symlink master +ln -s c/c1.txt symlink.txt +git add symlink.txt +git_commit -m "A symlink" + +git checkout -b gitlink master +git submodule add "$(pwd)/.git" submodule +git_commit -m "A gitlink" + +git repack -d +git pack-refs --all + +gitk --all master diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.index b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.index Binary files differnew file mode 100644 index 0000000000..215da649e1 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.index diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lsfiles b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lsfiles new file mode 100644 index 0000000000..27fe5c2347 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lsfiles @@ -0,0 +1,1437 @@ +100644 6b9c715d21d5486e59083fb6071566aa6ecd4d42 0 .gitattributes +100644 a213e8e25bb2442326e86cbfb9ef56319f482869 0 .gitignore +100644 373476bdc03f718b4c01471dd9996ee4497f43a8 0 .mailmap +100644 9651afc89d5e789abd9cedaa4f3b92dde7dd1412 0 .project +100644 6ff87c4664981e4397625791c8ea3bbb5f2279a3 0 COPYING +100644 ddb030137d54ef3fb0ee01d973ec5cee4bb2b2b3 0 Documentation/.gitattributes +100644 d8edd904065fbc4bd06365ce378f57d4cd8f9f0d 0 Documentation/.gitignore +100644 f628c1f3b7b706f9d585b96041e5a4b12bc0f62c 0 Documentation/CodingGuidelines +100644 62269e39c4edf95b2cf2e6a60bff2a33b239b07e 0 Documentation/Makefile +100644 fea3f9935b7794ce86f04d22c9d68fb9d537167d 0 Documentation/RelNotes-1.5.0.1.txt +100644 b061e50ff05b5e13211bb315e240974e898de32c 0 Documentation/RelNotes-1.5.0.2.txt +100644 cd500f96bfd73e288577b05cfdfe337d7f2b85bb 0 Documentation/RelNotes-1.5.0.3.txt +100644 feefa5dfd4eee5f493fcf3091ec0de116d414fc1 0 Documentation/RelNotes-1.5.0.4.txt +100644 eeec3d73d01a0e9f61df666bad8a48a4f423438a 0 Documentation/RelNotes-1.5.0.5.txt +100644 c02015ad5fdb1953ad1a8cf5b0edd7ef7c04fbac 0 Documentation/RelNotes-1.5.0.6.txt +100644 670ad32b85678c938709b47c37d6caacbb5ebe29 0 Documentation/RelNotes-1.5.0.7.txt +100644 daf4bdb0d7bb24319810fe0e73aa317663448c93 0 Documentation/RelNotes-1.5.0.txt +100644 91471213bdec8d95209db256f594b0e1b3f3ec2a 0 Documentation/RelNotes-1.5.1.1.txt +100644 d88456306c503d9e604ffbb699fb7cadacb2e733 0 Documentation/RelNotes-1.5.1.2.txt +100644 876408b65a0e0841567a2c9b97c6f6e62cb86b81 0 Documentation/RelNotes-1.5.1.3.txt +100644 df2f66ccb5d2a6a038d1fcf9306e7ed7aae05f39 0 Documentation/RelNotes-1.5.1.4.txt +100644 b0ab8eb371ccb05346781e63c5ec4b71dab8be34 0 Documentation/RelNotes-1.5.1.5.txt +100644 55f3ac13e3c242acc4bb1b873272d7d8ff4ef84d 0 Documentation/RelNotes-1.5.1.6.txt +100644 daed3672709f6b94478fc6ad425897abe3433c9a 0 Documentation/RelNotes-1.5.1.txt +100644 ebf20e22a74284f7085a5027f588ba295fb767d0 0 Documentation/RelNotes-1.5.2.1.txt +100644 f6393f8a94f454f4f7b5cc5bb42881b6662cadff 0 Documentation/RelNotes-1.5.2.2.txt +100644 addb22955b4e4e5344f7f139076a798cb50024ff 0 Documentation/RelNotes-1.5.2.3.txt +100644 75cff475f6546402dc3486c43e0b6e7557ae621e 0 Documentation/RelNotes-1.5.2.4.txt +100644 e8281c72a0b997e90cba2c9a2c4153f8607a7b76 0 Documentation/RelNotes-1.5.2.5.txt +100644 6195715dc78a26ce9ac452bd64852455fb79137c 0 Documentation/RelNotes-1.5.2.txt +100644 7ff546c743b3ac2e75610473e496d93e44a6dbe9 0 Documentation/RelNotes-1.5.3.1.txt +100644 4bbde3cab4dc6dc0815aeae5a0a79f88ab784b23 0 Documentation/RelNotes-1.5.3.2.txt +100644 d2138469511d3dc111d81b9354f100ed344d9524 0 Documentation/RelNotes-1.5.3.3.txt +100644 b04b3a45a5629cf852c970ac995bfb80bde846d2 0 Documentation/RelNotes-1.5.3.4.txt +100644 7ff1d5d0d100fc632208f4cbb67189ecbf58e9a4 0 Documentation/RelNotes-1.5.3.5.txt +100644 069a2b2cf9e9f28a2f9e6dc0817723a38b25f475 0 Documentation/RelNotes-1.5.3.6.txt +100644 2f690616c8327f8c86477998358ee0dd17ee467f 0 Documentation/RelNotes-1.5.3.7.txt +100644 0e3ff58a46f3cc2b987f9c3216e4844bab2317a5 0 Documentation/RelNotes-1.5.3.8.txt +100644 d03894b92645f2dd0d7cb464d3ab1905d8cb62ed 0 Documentation/RelNotes-1.5.3.txt +100644 d4e44b8b09d7176c137d826d5de305bd6822e862 0 Documentation/RelNotes-1.5.4.1.txt +100644 21d0df59fbb08ab148e275e21f0ed182c5aab1a1 0 Documentation/RelNotes-1.5.4.2.txt +100644 b0fc67fb2ade1c7e318d309ee4d55d37964021f3 0 Documentation/RelNotes-1.5.4.3.txt +100644 89fa6d03bc038d6210e94d7fe9fbbffdbc84d883 0 Documentation/RelNotes-1.5.4.4.txt +100644 02823413987d5a10364d936327e3a1cfb38cbac2 0 Documentation/RelNotes-1.5.4.5.txt +100644 3e3c3e55a31fd7f6d51e1aa5a1d57532484dacaf 0 Documentation/RelNotes-1.5.4.6.txt +100644 f1323b61746ee5d7f2a9d2fc3835c2cd75e76434 0 Documentation/RelNotes-1.5.4.txt +100644 7de419708f77fff6f61e749b917b5fcecbe9a292 0 Documentation/RelNotes-1.5.5.1.txt +100644 391a7b02eaf32d930e7c9c274dfd2a2edf081f75 0 Documentation/RelNotes-1.5.5.2.txt +100644 f22f98b734f82101d47a6aa2453d5374d5dd8175 0 Documentation/RelNotes-1.5.5.3.txt +100644 2d0279ecce622aab935e8e25914a5bd132fa95f3 0 Documentation/RelNotes-1.5.5.4.txt +100644 30fa3615c77d6198a5a08ebd8e8c63f4cd21b295 0 Documentation/RelNotes-1.5.5.5.txt +100644 29322124881bf65c3ee6f5d613251b09f4a98d9a 0 Documentation/RelNotes-1.5.5.txt +100644 4864b16445f3ca1854cee608f7c15f5a6e0933d8 0 Documentation/RelNotes-1.5.6.1.txt +100644 5902a85a78610ec38f4cf160ccd3c01267b4f9a1 0 Documentation/RelNotes-1.5.6.2.txt +100644 942611299d59abd4bdd820e1258662067a304d62 0 Documentation/RelNotes-1.5.6.3.txt +100644 d8968f1ecbd930463858870ee872efd8cb672bab 0 Documentation/RelNotes-1.5.6.4.txt +100644 e143d8d61be1bb2fac024b5d5f270b33f4f898d4 0 Documentation/RelNotes-1.5.6.txt +100644 2542cf53d2e40b06afe918fcf1cd35de19126d9e 0 Documentation/RelNotes-1.6.0.txt +100644 841bead9db18a025638570c10cac72bcf4791f68 0 Documentation/SubmittingPatches +100644 40d43b78ee9d6c3827bcf631c1f41f54d0e3dfbc 0 Documentation/asciidoc.conf +100644 5428111d732cb38dbb257ddfa860ebd04088b4e9 0 Documentation/blame-options.txt +100755 ba4205e0302a267a5da6bef504f3e69eb0c4aa6d 0 Documentation/build-docdep.perl +100644 6a361a21367bfed4ae325049556f2e82e7e1dbe4 0 Documentation/callouts.xsl +100755 dbc133cd3c1f19dd507014477e68b8ada78eab5e 0 Documentation/cat-texi.perl +100755 04f99778d81def42e9e129b2f5b2b0551a0c760f 0 Documentation/cmd-list.perl +100644 61c376057c0f2b9510bf6f1b2beb42f9859b7f46 0 Documentation/config.txt +100644 400cbb3b1c120b93278472678ee7bdb87a74f95b 0 Documentation/diff-format.txt +100644 517e1eba3c56907ebcb1d478dceb184e53fceda4 0 Documentation/diff-generate-patch.txt +100644 cba90fd27c6a1baaca884328e96adc8a6da8fc36 0 Documentation/diff-options.txt +100644 b878b385c6967f4c64ba30bdfe8f9bd24bef91e3 0 Documentation/docbook-xsl.css +100644 9a6912c641edf52083b8996fdce3a0be2f4dba45 0 Documentation/docbook.xsl +100644 e598cdda45cf0b953a106d6786765b3316e2cc16 0 Documentation/everyday.txt +100644 d313795fdbc420e3395adc42aebe82fabda037d4 0 Documentation/fetch-options.txt +100755 ff7d78f620a35fb66c47e50c4eceecff00b643b3 0 Documentation/fix-texi.perl +100644 2b6d6c86547b2cec370d34b14ddef25264404892 0 Documentation/git-add.txt +100644 c45c53ec2404725394563a9fba40f31cd314adb2 0 Documentation/git-am.txt +100644 8b6b56a54409dd586047a1a6cdf1138e8bb0e77b 0 Documentation/git-annotate.txt +100644 feb51f124ac8a806e65d41f6274c58de64d2991f 0 Documentation/git-apply.txt +100644 c7a6e3ec050b7ceeec79d468b5ffa123314c8f5d 0 Documentation/git-archimport.txt +100644 41cbf9c0819872a322321455b8a5cb805efcc26b 0 Documentation/git-archive.txt +100644 c7981efcd9b86287bbea9ddcaf187a9bd48c77eb 0 Documentation/git-bisect.txt +100644 fba374d652723161c3683d1be98c08ba573057cc 0 Documentation/git-blame.txt +100644 6103d62fe3dca23c78b16dbdbb5ba231a6b39bf7 0 Documentation/git-branch.txt +100644 1b66ab743c64d980a43a028d57ca2f6505d97845 0 Documentation/git-bundle.txt +100644 d35e8a04fe28b095b5405ae2e0b09e3ab448bf63 0 Documentation/git-cat-file.txt +100644 2b821f2a1d70fa108ce279135fd5028453a04fd9 0 Documentation/git-check-attr.txt +100644 034223cc5ace81dd0b63da44d79db5e83a1d492a 0 Documentation/git-check-ref-format.txt +100644 62d84836b8a0d77c2a6ea534566ff8462b0eb37a 0 Documentation/git-checkout-index.txt +100644 5aa69c0e12a6756fd6f79c117008a373f65ba5f5 0 Documentation/git-checkout.txt +100644 837fb08b7971a8b948dd7d039bab4a3c2e54cac7 0 Documentation/git-cherry-pick.txt +100644 74d14c4e7fc88e702e4781b22eb8ed5ce0480c6f 0 Documentation/git-cherry.txt +100644 670cb02b6cc035e4fbcf1a1016f66b7a85cd4ef7 0 Documentation/git-citool.txt +100644 7dcc1ba58c3879cb14ce243a4af00bca9e850799 0 Documentation/git-clean.txt +100644 26fd1b111798461b9150f1416721aa460f1ea525 0 Documentation/git-clone.txt +100644 feec58400b64c65c8f96f2d1834016455c89829e 0 Documentation/git-commit-tree.txt +100644 0e25bb862704eee4a22fe5349c04823d14ea9cba 0 Documentation/git-commit.txt +100644 28e1861094a1689cdb042df6b1d788620ffdf213 0 Documentation/git-config.txt +100644 75a8da1ca906aee4cc6a7d0c3ff19862b8e0fc2f 0 Documentation/git-count-objects.txt +100644 2da8588f4fd6edb842a9824181165b3f043ec87b 0 Documentation/git-cvsexportcommit.txt +100644 b7a8c10b8709108c1c8a0d14f661c179c2b4f22c 0 Documentation/git-cvsimport.txt +100644 c2d3c90d27084e7de7e0f7c37b40f130f6960244 0 Documentation/git-cvsserver.txt +100644 4ba4b75c1126d87c48935e7697e05f0d5210ad2d 0 Documentation/git-daemon.txt +100644 7fdda04bae34790eb2345427dda746e8bf097c1a 0 Documentation/git-describe.txt +100644 5c8c1d95a89b15e936816f486a8114cbc6788fb9 0 Documentation/git-diff-files.txt +100644 26920d4f63cd213ff17ab28d8dd0dbea94482147 0 Documentation/git-diff-index.txt +100644 8c8f35b7a762d42d3c45ff9f4eee1cb32d3917b6 0 Documentation/git-diff-tree.txt +100644 c53eba557d0a242a0d8553d9569ce8b2eb86331b 0 Documentation/git-diff.txt +100644 b974e2115b01f17f0ac809b691baf2f4e4d32169 0 Documentation/git-fast-export.txt +100644 c2f483a8d2aed8dc017f3172e2d5fff4bed2c450 0 Documentation/git-fast-import.txt +100644 47448da22eeebf51fe5829717df2dc7129a9b17e 0 Documentation/git-fetch-pack.txt +100644 d3164c5c88db6b9e02a4186c398e19c425bc204b 0 Documentation/git-fetch.txt +100644 7ba9dab5e6c0b32f927d24de800e17b71a06b84b 0 Documentation/git-filter-branch.txt +100644 1c24796d66d5aeaeeccfd152c69cddba1953fd6c 0 Documentation/git-fmt-merge-msg.txt +100644 727d84e6735417baa82fe7abff5b6945f6d6cef4 0 Documentation/git-for-each-ref.txt +100644 010d9e432231f41a179023df2e85610583b572cf 0 Documentation/git-format-patch.txt +100644 965a8279c1b17df6fbf82f4fbcadbd254049a7d5 0 Documentation/git-fsck-objects.txt +100644 d5a76472196a5e67bc6e62411d90377ec3b46e3a 0 Documentation/git-fsck.txt +100644 7086eea74a38b036130f61db362bae209a065e47 0 Documentation/git-gc.txt +100644 84f23ee525336fc2bdd289991b97eafecddc14b2 0 Documentation/git-get-tar-commit-id.txt +100644 fa4d133c1bccc088d3c8da65bce4e15cafd394aa 0 Documentation/git-grep.txt +100644 0e650f497bd456e633334a91bd929053a08eb0d3 0 Documentation/git-gui.txt +100644 ac928e198e75595a6fcd4e83b89aaf68987bd420 0 Documentation/git-hash-object.txt +100644 f414583fc48e85e4785fbf5f9431bb81a96ccd9d 0 Documentation/git-help.txt +100644 e7c796155fdd0ad644decf5dc488c6d780a2d164 0 Documentation/git-http-fetch.txt +100644 aef383e0b142bd603b77620cad720c102d70c4b7 0 Documentation/git-http-push.txt +100644 b3d8da33ee64730794821440c287f30c4bb85789 0 Documentation/git-imap-send.txt +100644 4b5c743c1e5f11281e2b9df7508d57e9878ee5d2 0 Documentation/git-index-pack.txt +100644 1fd0ff2610a1375bcf0defe2a234b2dee1a7997a 0 Documentation/git-init-db.txt +100644 71749c09d309f4cae2da9788969359d2620224a9 0 Documentation/git-init.txt +100644 22da21a54f625c434216945889127ec283d3d09f 0 Documentation/git-instaweb.txt +100644 05cbac56aced6ad27f36fe63f8f536e794794f9f 0 Documentation/git-log.txt +100644 602b8d5d4de8f7649cb88e6622108c012f484933 0 Documentation/git-lost-found.txt +100644 9f85d60b5fb6d6ae1b4d8c2e65a6131cbe21450b 0 Documentation/git-ls-files.txt +100644 abe7bf9ff9eb9a3ddb1924938de071291520797a 0 Documentation/git-ls-remote.txt +100644 4c7262f1cd82ca8d9ea6be638d23b18d9bba3738 0 Documentation/git-ls-tree.txt +100644 31eccea5bc0697ee461503734942429c2133ef3f 0 Documentation/git-mailinfo.txt +100644 5cc94ec53daf3057f57c993983d659543962abec 0 Documentation/git-mailsplit.txt +100644 1a7ecbf8f39381b0c7b2da513dfa26eacec15cf6 0 Documentation/git-merge-base.txt +100644 024ec015a3a3e0d3677a82e082e72a36c4572827 0 Documentation/git-merge-file.txt +100644 ff088c5c294527dd97c542012483aafe3ca64314 0 Documentation/git-merge-index.txt +100644 dc8a96adb00c0b674e12e071a4a56f89bfe8583d 0 Documentation/git-merge-one-file.txt +100644 dbb0c18668ff0fb60c31c12b02c27d92b430c24a 0 Documentation/git-merge-tree.txt +100644 2db88809898592c691166427efdd106d844d42d9 0 Documentation/git-merge.txt +100644 31570b1e27af6a603df98868c627da08d91c17cc 0 Documentation/git-mergetool.txt +100644 8bcc11443dce7322ac5b0fa70e07b2465f762615 0 Documentation/git-mktag.txt +100644 af19f06ed738bdecc7ab9a72a5c9a216b816f4c2 0 Documentation/git-mktree.txt +100644 9c5660275b326661bf7dc9a5162e5177b8a62b0f 0 Documentation/git-mv.txt +100644 6e77ab135353aaf713b638a70701717db1706c2c 0 Documentation/git-name-rev.txt +100644 8c354bd47014825de71243d73158b6b080ecb350 0 Documentation/git-pack-objects.txt +100644 5f9435e59b49fec1e37c65f1bfdc38be3704c4e5 0 Documentation/git-pack-redundant.txt +100644 a5244d35f49f10b7954d8fa52164663e3d167d4b 0 Documentation/git-pack-refs.txt +100644 cd43069874d59504627211e011250a3554aeee5a 0 Documentation/git-parse-remote.txt +100644 477785e13418e1971156f5210015da4ab9d77cab 0 Documentation/git-patch-id.txt +100644 8282a5e82b6e897ac501ef05c982d5e69415363f 0 Documentation/git-peek-remote.txt +100644 b5f26cee132622185457d92522fb932302dec97d 0 Documentation/git-prune-packed.txt +100644 54f1dab38de9e01d8452753ac6028875b91d5f6b 0 Documentation/git-prune.txt +100644 7578623edba9e2ddc5232f1a981bcb297182638d 0 Documentation/git-pull.txt +100644 050c3ddae2732fdf4cb9f3b0f798e3d2d190fa4e 0 Documentation/git-push.txt +100644 d4037de5124010e9c90dcc97e8b64e6011dbed21 0 Documentation/git-quiltimport.txt +100644 6f4b9b017f7b504a2b9e909639a61b1ef7750af0 0 Documentation/git-read-tree.txt +100644 59c1b021a6c410e1097df21d6d47365aec6689e2 0 Documentation/git-rebase.txt +100644 6b2f8c4de7c32927f270e561362d4766193986fa 0 Documentation/git-receive-pack.txt +100644 d99236e14d5238c936304029bd48efc6ac9dd024 0 Documentation/git-reflog.txt +100644 25ff8f9dcbe0db52675338f1429e9169052b9cf1 0 Documentation/git-relink.txt +100644 bb99810ec76f93ff1cdc59aacdf592c64419701a 0 Documentation/git-remote.txt +100644 38ac60947bc6c4cbfc8aae70a92f9163fefed442 0 Documentation/git-repack.txt +100644 e5bdb5533e61687874ad36d30534b2ac9e58d7cb 0 Documentation/git-repo-config.txt +100644 19335fddae2b706cd785258a8c02a5595c525667 0 Documentation/git-request-pull.txt +100644 89f321b414212a555f1e0fb0ff0ce6f4c180fd06 0 Documentation/git-rerere.txt +100644 6abaeac28cb70bcff809c803d732f79630c8046f 0 Documentation/git-reset.txt +100644 fd1de92e34b459cdc89928e1561ee6934cd63c19 0 Documentation/git-rev-list.txt +100644 2921da320d2b84df4d15ec2745e6d94093dd6907 0 Documentation/git-rev-parse.txt +100644 98cfa3c0d0f27e0cb603f07c76285f85ef07a771 0 Documentation/git-revert.txt +100644 4d0c495bc3ecb5482165a46956efe73dfdc5ee72 0 Documentation/git-rm.txt +100644 afbb294a7faadc7ff6d4039246dc1c085575cd4f 0 Documentation/git-send-email.txt +100644 399821832c2a5cd6a718a7dc37a87e6b5bc0b213 0 Documentation/git-send-pack.txt +100644 18f14b5be89b4e0240f59b13313308f3c09d012c 0 Documentation/git-sh-setup.txt +100644 ff420f8f8c52eb598976a134916000da9b8f3976 0 Documentation/git-shell.txt +100644 7ccf31ccc401fd35a0ed65667be001805436249b 0 Documentation/git-shortlog.txt +100644 d3f258869f5d441bea16b46d8030eb64ecb7df99 0 Documentation/git-show-branch.txt +100644 e3285aacfd310cc269cdb03aa9243c939c24def7 0 Documentation/git-show-index.txt +100644 9a4389981ca067633d773e28393a1d72ac6552ae 0 Documentation/git-show-ref.txt +100644 1642cfd8236a5b57420f67da580b42066afaa4f6 0 Documentation/git-show.txt +100644 7d50d74cc9a945f0dd82b0c26509bf0392eff837 0 Documentation/git-stash.txt +100644 84f60f3407499c40a8e0caadf9d40ed5e9b8386b 0 Documentation/git-status.txt +100644 7508c0e42d2cd50ac522fc80a3a866411b7b51c5 0 Documentation/git-stripspace.txt +100644 35efeefb3056ac69cf02689dc338956340e9efc9 0 Documentation/git-submodule.txt +100644 f230125a81baab9f13bf84e3543b63fc77a8e827 0 Documentation/git-svn.txt +100644 210fde03a12cd757769f81754e789a2a5934f02c 0 Documentation/git-symbolic-ref.txt +100644 046ab3542bab4048fe07c8a6718d63f9cd9e3791 0 Documentation/git-tag.txt +100644 a5d9558dd1eabd71e838026721d707c5f1ecc369 0 Documentation/git-tar-tree.txt +100644 a96403cb8cb720dbf094b06a0dc0b430147298fc 0 Documentation/git-tools.txt +100644 995db9feadf68df6f22de745d90790a145128e44 0 Documentation/git-unpack-file.txt +100644 36d1038056101a459a33e32b6729d75e03f127ce 0 Documentation/git-unpack-objects.txt +100644 1d9d81a702d26706047ae6ea29b4ca62ebe59460 0 Documentation/git-update-index.txt +100644 9639f705afafab6fcf0cd21ad2693627ab42f66d 0 Documentation/git-update-ref.txt +100644 35d27b0c7f0e4b7a1d0851140958e71fabb0e6bc 0 Documentation/git-update-server-info.txt +100644 bbd7617587084b0c66fd8e0b9f623cac50be2c03 0 Documentation/git-upload-archive.txt +100644 b8e49dce4a19a4d7083459468f27c273c1d91fea 0 Documentation/git-upload-pack.txt +100644 3647dd6c8f9c74a688f7a143119386ba89a8f13d 0 Documentation/git-var.txt +100644 c8611632d1d501d57eb7000de0ec3c3b36810b80 0 Documentation/git-verify-pack.txt +100644 ba837df4bc66e2b828fcd49c94f35957c27322df 0 Documentation/git-verify-tag.txt +100644 36afad8d4e0d67a8d9dd33d3bc590789e9f6604d 0 Documentation/git-web--browse.txt +100644 cadfbd90403766d44598c8d96d89dc5a0e4e2ef8 0 Documentation/git-whatchanged.txt +100644 26d3850e7317c22dcf0999e0c4a6afe9a5ea2e03 0 Documentation/git-write-tree.txt +100644 44ea35e949dbbc0e5785ba2831072059881058f8 0 Documentation/git.txt +100644 d7b41142d2c843bc5460f03c73c609b1c53ff4a6 0 Documentation/gitattributes.txt +100644 29e5929db22257346a2bed16cbd5ca6531698676 0 Documentation/gitcli.txt +100644 49179b0a00fad1ecda1fdf0537ccbce77f5fc494 0 Documentation/gitcore-tutorial.txt +100644 aaa7ef737a4c190c60e37e2849ce42f3bdb5dda7 0 Documentation/gitcvs-migration.txt +100644 2bdbc3d4f6a97c1a1d970f0c5f27222ef9e31274 0 Documentation/gitdiffcore.txt +100644 565719ed5f8516e17229ec11bbec5e1354580397 0 Documentation/gitglossary.txt +100644 046a2a7fe7cf8ec301d3a20f7ebc587a09d210e3 0 Documentation/githooks.txt +100644 59321a2e82b1e141746d94c439452b52b84994ad 0 Documentation/gitignore.txt +100644 e02ecf57444df14d61d82dcf2f9e0c3f6b990b91 0 Documentation/gitk.txt +100644 f8d122a8b90ca7cb4920768ca23fd9a27574ffdf 0 Documentation/gitmodules.txt +100644 a969b3fbc3efc99ce490455b93c8bfb912994e2e 0 Documentation/gitrepository-layout.txt +100644 660904686c656fd00078aa272d0b9a5a198e1833 0 Documentation/gittutorial-2.txt +100644 48d1454a90cf9453e5e3c9fa01b3dbc369a58f1f 0 Documentation/gittutorial.txt +100644 9b4a4f45e900a96c4ddeb214816877f39cca15a5 0 Documentation/glossary-content.txt +100755 34aa30c5b9ffc617e1519878317c2ae83bed6a6a 0 Documentation/howto-index.sh +100644 4357e269131fad960367534ae4161fe078fee30a 0 Documentation/howto/maintain-git.txt +100644 554909fe08de380aa02f2bf37f0f3b43b0233f4b 0 Documentation/howto/rebase-and-edit.txt +100644 d214d4bf9d0e539c6bf58ba24dcd12aabbaea1d8 0 Documentation/howto/rebase-from-internal-branch.txt +100644 48c67568d3418b2d6608f362f4b76e02ec450abc 0 Documentation/howto/rebuild-from-update-hook.txt +100644 323b513ed0e0ce8b749672f589a375073a050b97 0 Documentation/howto/recover-corrupted-blob-object.txt +100644 e70d8a31e7b05e8efc70c6a56f476324065d57a6 0 Documentation/howto/revert-branch-rebase.txt +100644 6d3eb8ed00e1779efce8abe201d37c8cff07ec29 0 Documentation/howto/separating-topic-branches.txt +100644 40327486084ac02874faff70fd100b619af83214 0 Documentation/howto/setup-git-server-over-http.txt +100644 697d9188850e9a685045da5bd37844b02978752d 0 Documentation/howto/update-hook-example.txt +100644 4e2f75cb6167633c97ec1981d2b6659368cc0170 0 Documentation/howto/use-git-daemon.txt +100644 0953a50b693307976977c81a4c0b611fd5dfb490 0 Documentation/howto/using-merge-subtree.txt +100644 fb0d7da56b902217f8f1f4d4bc85186d6bf0dc4c 0 Documentation/i18n.txt +100755 35f440876ed182de319b6d3f0b8296b1a1ede29d 0 Documentation/install-doc-quick.sh +100755 2135a8ee1f4f56a8c799437949ba76d7526164c0 0 Documentation/install-webdoc.sh +100644 4065a3a27a38be73132b9f509e1d63546b3fddef 0 Documentation/manpage-1.72.xsl +100644 48ce747cf4dad592d642735856eb156e93d6cf30 0 Documentation/merge-config.txt +100644 007909a82fe77325e46c54799d00dc78493a47f9 0 Documentation/merge-options.txt +100644 1276f858ade29bec40716d19cf56fe6e3882fc25 0 Documentation/merge-strategies.txt +100644 c11d4957714db202a012209e2437b9e050a28ae0 0 Documentation/pretty-formats.txt +100644 6d66c74cc11e6622892061f8328d04dfe38f87bf 0 Documentation/pretty-options.txt +100644 00a8d210476089257be3d09ac8a16d1f8e1dd8dc 0 Documentation/pull-fetch-param.txt +100644 3aa38097e6350a02c50873d5c670e108003fab22 0 Documentation/rev-list-options.txt +100644 8aa891daee050f03cf265a6ea991ff9ebb60815e 0 Documentation/technical/.gitignore +100644 43dbe09f735525b0a1549ccfb4de2f2ca87252a0 0 Documentation/technical/api-allocation-growing.txt +100644 7ede1e64e5d40ec8f742e900d7273d6f961605e2 0 Documentation/technical/api-builtin.txt +100644 1d52a6ce14416c7308f6c2c5d6a3dd2a43184e91 0 Documentation/technical/api-decorate.txt +100644 20b0241d30026747391fa4b6b38de5cf959cee70 0 Documentation/technical/api-diff.txt +100644 5bbd18f0206604416c3833b7541a5b55b7e63976 0 Documentation/technical/api-directory-listing.txt +100644 9d97eaa9dee99eef7e66072c4c51cfff3000bba3 0 Documentation/technical/api-gitattributes.txt +100644 a69cc8964d585db41b1907a8ce7cb8d0a9511ef2 0 Documentation/technical/api-grep.txt +100644 c784d3edcb2537b84bfb5db3da55faaf45995155 0 Documentation/technical/api-hash.txt +100644 e9559790a32185b1d4ac8ae72881f4f63f082538 0 Documentation/technical/api-history-graph.txt +100644 adbdbf5d75d8e17e38e1ba0e3694b4ff210f5799 0 Documentation/technical/api-in-core-index.txt +100644 af7cc2e395f1399830f9eacc52468376b216fb86 0 Documentation/technical/api-index-skel.txt +100755 9c3f4131b8586408acd81d1e60912b51688575ed 0 Documentation/technical/api-index.sh +100644 dd894043ae8b04269b3aa2108f96cb935217181d 0 Documentation/technical/api-lockfile.txt +100644 03bb0e950dd1616b00f950f83263835c57bfa70a 0 Documentation/technical/api-object-access.txt +100644 539863b1f920f8f34ad9272907cbacbd35a7fcbd 0 Documentation/technical/api-parse-options.txt +100644 e8a1bce94e05f06c5b2aa51d2b610fb9da15d0bb 0 Documentation/technical/api-quote.txt +100644 073b22bd83badb5aada47e061bb29e48d5f95518 0 Documentation/technical/api-remote.txt +100644 996da0503acfa3e3a0ed0f57a951d0fbc1500fb8 0 Documentation/technical/api-revision-walking.txt +100644 75aa5d49234ec36857a7c8d2f3900001af5cbcde 0 Documentation/technical/api-run-command.txt +100644 4f63a04d7db0e7b578c5034c2856ba95a7ef5739 0 Documentation/technical/api-setup.txt +100644 a9668e5f2d2b1a7ffac45e4111ca6d8a4818af2b 0 Documentation/technical/api-strbuf.txt +100644 293bb15d206e71f57e906b33ca27ee05e3429521 0 Documentation/technical/api-string-list.txt +100644 e3ddf912841298d6317a682a29cbaf628e86f156 0 Documentation/technical/api-tree-walking.txt +100644 6296ecad1d65511f943fcd82ded188954a33b052 0 Documentation/technical/api-xdiff-interface.txt +100644 1803e64e465fa4f8f0fe520fc0fd95d0c9def5bd 0 Documentation/technical/pack-format.txt +100644 103eb5d989349c8e7e0147920b2e218caba9daf9 0 Documentation/technical/pack-heuristics.txt +100644 9cd48b48597f9b7e822fc3d81e0bc556d6631b02 0 Documentation/technical/pack-protocol.txt +100644 6bdf034b3af55c8d881fee9153d5cd1824660692 0 Documentation/technical/racy-git.txt +100644 681efe42190fa28f8e6bc8f1eb569bfcf160ed4b 0 Documentation/technical/send-pack-pipeline.txt +100644 559263af485f139d6c33d982bed9342aa4110e50 0 Documentation/technical/shallow.txt +100644 24c84100b0790be22330464e01ea876e5d30fc9a 0 Documentation/technical/trivial-merge.txt +100644 504ae8a53bca42d7c9ec560b65ddfe14699387a4 0 Documentation/urls-remotes.txt +100644 fa34c6747194aaecf9e8124462129b8bbc9ae7d4 0 Documentation/urls.txt +100644 339b30919e6cd9791a5cc30b93395a88fb5e9d96 0 Documentation/user-manual.conf +100644 00256ca57cc7453ef4a0dce90169078ee96e95e3 0 Documentation/user-manual.txt +100755 cb7cd4b53827fa6820e84b1318572d0115b3b17f 0 GIT-VERSION-GEN +100644 7d0c2c2f865d6ed969038e7543dbeb8933723ec3 0 INSTALL +100644 52c67c1a472455dcce5c19a21bbfd0520ff7dd26 0 Makefile +100644 548142c327a6790ff8821d67c2ee1eff7a656b52 0 README +120000 b9a53c3416991b66e1d35c2bbf663b48340b0041 0 RelNotes +100644 0d561246e0a958d9a7284409b1900a82876eebf3 0 abspath.c +100644 ccb1108c94436035d0da8b1d6f08f859b68294a3 0 alias.c +100644 216c23a6f854c614d38c743cd7687a37f304161b 0 alloc.c +100644 13029619e5ec34bac4ba61a6fc08800ab36f4a1b 0 archive-tar.c +100644 cf285044e3576d0127c3215cb1253443d67517dc 0 archive-zip.c +100644 f834b5f51f4cf5d3b73d21dfd99198caef3b19f8 0 archive.c +100644 0b15b35143fffcc13764e4e668ee452b191cc609 0 archive.h +100644 9e3ae038e818f4e21bc50f864fc5204f6fa44daa 0 arm/sha1.c +100644 3952646349cf9d033177e69ba9433652a378c0e9 0 arm/sha1.h +100644 8c1cb99fb403875af85e4d1524d21f7eb818f59b 0 arm/sha1_arm.S +100644 17f6a4dca521d9690377f2e93a0192d8a874d2ad 0 attr.c +100644 f1c2038b0923d3130937eef965667204a8634e6d 0 attr.h +100644 b88270f90844095b3d352cc4213cbebd95a7f420 0 base85.c +100644 bd7d078e1ae5fe4ce0a16fda62a2c1743237941b 0 blob.c +100644 ea5d9e9f8b63be2c7048d19ee53feb06b0795c80 0 blob.h +100644 b1e59f2196b933ab7169a30efc5d1d340f8f9c5c 0 branch.c +100644 9f0c2a2c1fab9a312f436880956da0973c68ead8 0 branch.h +100644 fc3f96eaefff91e4e85adb92162716939f0ecd72 0 builtin-add.c +100644 fc43eed36b55e4966796490b8c0a02fae790229c 0 builtin-annotate.c +100644 2216a0bf7cd53adc31346f66a3b9786a1d688bad 0 builtin-apply.c +100644 22445acbfc5279f391ac6afa855b21064ec54535 0 builtin-archive.c +100644 8b6b09b10b8f9dcda0b7224f31c860bb803945f0 0 builtin-blame.c +100644 b1a2ad7a6b3b150cda8d031a87352a4daedc40ea 0 builtin-branch.c +100644 ac476e7a4b45fc55b6b6d1e4d02be0c35aba2c7b 0 builtin-bundle.c +100644 7441a56acdbefdd8044a406f4d756ce8a4f06644 0 builtin-cat-file.c +100644 cb783fc77e75515a02ed2268dfb37ee3bbd03749 0 builtin-check-attr.c +100644 fe04be77a9312c11fa054897c5982fa6c74b8e5e 0 builtin-check-ref-format.c +100644 71ebabf9903bd90b7da59c47f1c0819b5f25c538 0 builtin-checkout-index.c +100644 411cc513c65ba854221ad52dd6aeaaac7d213c9d 0 builtin-checkout.c +100644 48bf29f40a5e06fd588b34c468535e04abcf206b 0 builtin-clean.c +100644 e086a40b41810c30a4f5228daa4e38857dae84d5 0 builtin-clone.c +100644 7a9a309be0543da7d27e7710ef82271f2582e0a9 0 builtin-commit-tree.c +100644 f7c053a0106c2e42833d0d7c7255b7b636d09a93 0 builtin-commit.c +100644 91fdc4985d8e64fae12209174dd4aa2d887793e5 0 builtin-config.c +100644 91b5487478998e39bb8ae4a5cb667360cff82c9a 0 builtin-count-objects.c +100644 ec404c839b6542deb4e15ca342fd3c0afbbedd2e 0 builtin-describe.c +100644 9bf10bb37e2f56ec2a10239d7419db8fbb641745 0 builtin-diff-files.c +100644 17d851b29ee5de33e01745eabcd5cd735c30b352 0 builtin-diff-index.c +100644 415cb1612f5322da89850874ba81885e41808678 0 builtin-diff-tree.c +100644 7ffea975059f9e13b07ca680e6707ffc14973f90 0 builtin-diff.c +100644 070971616dbb12d005c5c9a1f82cc5b0c5391f62 0 builtin-fast-export.c +100644 7460ab7fce2a4e6a7e014f448819140e2204ccb7 0 builtin-fetch--tool.c +100644 273239af3be61736ee4ff484d628950c4de7311a 0 builtin-fetch-pack.c +100644 7eec4a0e43ad5760f1060a7d5bcf2a5083015130 0 builtin-fetch.c +100644 df02ba7afdd615492361a1897a9dedd6ab233c96 0 builtin-fmt-merge-msg.c +100644 445039e19c75e4c9321f7ee64289ef8201a25c14 0 builtin-for-each-ref.c +100644 6eb7da88d3e8591a8c544acc61a42e00babff120 0 builtin-fsck.c +100644 fac200e0b08360625afc81b02913128c9b87f486 0 builtin-gc.c +100644 631129ddfd0ffe06f919882d22cfc494d9553f50 0 builtin-grep.c +100644 3a062487a7eacd01ed824b46a9124dd343cd2e60 0 builtin-http-fetch.c +100644 baf0d09ac4ea372b4015d399560a133b401b55cc 0 builtin-init-db.c +100644 f4975cf35f7f1555739f7657ee62ed983d18cb84 0 builtin-log.c +100644 e8d568eed7ab700bc338af8f589d2f61e81f323c 0 builtin-ls-files.c +100644 c21b841e7c5e8d27a6e66e7f70786d77aa4653b5 0 builtin-ls-remote.c +100644 d25767a1f7eb0a8b45bc1eed6b9aa95de0847f18 0 builtin-ls-tree.c +100644 f974b9df968c74c5d62d58b2a09493e6abb4322e 0 builtin-mailinfo.c +100644 71f3b3b8741e505fc652e6c74c75972f19211f71 0 builtin-mailsplit.c +100644 3382b1382a7dcbd525126a35209072da4b4d8041 0 builtin-merge-base.c +100644 3605960c2d9692514a6df0f344f3c3269cf1de3c 0 builtin-merge-file.c +100644 8f5bbaf402e020e308e7af9cedb7df1b2ec5a2b7 0 builtin-merge-ours.c +100644 43e55bf90154c51b94527b2ab7eb7c60fe36e9ec 0 builtin-merge-recursive.c +100644 dde0c7ed33118ff8d0cc421e8a0366e342c6d011 0 builtin-merge.c +100644 4f65b5ae9baf66953e79886fd93fe31786b24d36 0 builtin-mv.c +100644 85612c4dcb719b460623204046e35486e9d9fe97 0 builtin-name-rev.c +100644 2dadec1630c266bbaf42e84810f7059ed5c43b1e 0 builtin-pack-objects.c +100644 34246df4ec946273d9f42e6f0848b02d8510beea 0 builtin-pack-refs.c +100644 10cb8df8457fd5f2ba9be62ecd0f9384e21c3e63 0 builtin-prune-packed.c +100644 947de8cf258c73d8a327ef3a1daed417ba533f1b 0 builtin-prune.c +100644 c1ed68d938f67343c6938cfef54d5ff69a522a63 0 builtin-push.c +100644 72a6de302f88728af17ce5c5c6983c5267afc6f6 0 builtin-read-tree.c +100644 0c34e378199064e87aa09caf0fa0a2346333ec69 0 builtin-reflog.c +100644 54d1c3e3d16b2cebcff0c6c57d98756e48472b67 0 builtin-remote.c +100644 dd4573fe8dcd9dc8edd5a7d41bc8daa83034ee7e 0 builtin-rerere.c +100644 c24c21909194014b467c86fd3598796e7db576b3 0 builtin-reset.c +100644 893762c80f4910fadf2d6df414bd835cccb7faaa 0 builtin-rev-list.c +100644 9aa049ec170b0125fddde29adda3c720c8a7b8ee 0 builtin-rev-parse.c +100644 e9da870d22c14c32a0e0a6cb71b933c79a2d8b53 0 builtin-revert.c +100644 ee8247b08cd007f73d5dfffa560a9efe33d327b9 0 builtin-rm.c +100644 7588d22885d0af24ae80f1d687ccd097fe365021 0 builtin-send-pack.c +100644 d03f14fdad3d17dde06734d78ddb4aade6ed4f2b 0 builtin-shortlog.c +100644 233eed499d0b8790781326ff0455bdc7f09fe4d4 0 builtin-show-branch.c +100644 add16004f11375b1ad2b97f9b1bf1ced5c437f81 0 builtin-show-ref.c +100644 c0b21301ba4c126a49ed38b6983756b99a25aae0 0 builtin-stripspace.c +100644 bfc78bb3f6eff2f8e39649b9649ae7263f143ad9 0 builtin-symbolic-ref.c +100644 325b1b2632e44121c23bc6df556bf3aa4e32ba04 0 builtin-tag.c +100644 f4bea4a322c26a54734286073c5e67444555c2d9 0 builtin-tar-tree.c +100644 a8918666655bb91f952ccdac18715bd9ba4a09f2 0 builtin-unpack-objects.c +100644 38eb53ccba2b97a0fccf50d6ba0b7424fe2d1bcb 0 builtin-update-index.c +100644 56a0b1b39cf4c4fc51dbbff256240655bc36a038 0 builtin-update-ref.c +100644 a9b02fa32f372a6810867c10560a20d58b5b2a91 0 builtin-upload-archive.c +100644 f4ac595695b1fff1317ff7d14ea9427780327aea 0 builtin-verify-pack.c +100644 729a1593e61d87ad4596f07e7faedac81de64e81 0 builtin-verify-tag.c +100644 52a3c015ff8e4611522bd41078bdb2934d288d35 0 builtin-write-tree.c +100644 f3502d305e4f65e9707fe8b738f64be6e49f7f84 0 builtin.h +100644 00b2aabefca49b634f49143523ee31556baa7777 0 bundle.c +100644 e2aedd60d6ad1482bb6da173c853e6ba4805c8d7 0 bundle.h +100644 5f8ee87bb1c446341b640c2f978a658d6bfcfcd0 0 cache-tree.c +100644 cf8b790874c4a4f5890b360c237ccdd4a5a03de4 0 cache-tree.h +100644 2475de9fa837596303284157e08b3080d64351ee 0 cache.h +100755 d6fe6cf1749ebcd6189fa36cbb4e14a532d2d17b 0 check-builtins.sh +100644 00d92a16631a80ff8ec4e995dafcd3e55434fad5 0 check-racy.c +100755 a1c4c3e8d845e8e791d7df0c1387e1b2262b5ecf 0 check_bindir +100644 fc0b72ad59b13e4bd86372e5e81b4f400c99d26e 0 color.c +100644 6cf5c88aaf8d0e38e2853e6fd212e3cdd6c180cb 0 color.h +100644 9f80a1c5e3a461afd11966625589684d61187911 0 combine-diff.c +100644 3583a33ee90647d8e6ded02643eb75753760d94f 0 command-list.txt +100644 dc0c5bfdab7296bf7febb6f1b1aad64550838c15 0 commit.c +100644 77de9621d9c926c6fb8a2bf9ca81c6c376a2ad41 0 commit.h +100644 1f4ead5f981688ee9e29ae2ee281e3904c9131f6 0 compat/fnmatch.c +100644 cc3ec379400e9334a37cf3f07a61a77f264da885 0 compat/fnmatch.h +100644 b5ca142fedf2ac0e0cedde1011ab385f65010fdf 0 compat/fopen.c +100644 069c555da47ea168eea937fcc2d788294bf92ef5 0 compat/hstrerror.c +100644 f44498258d4c2a0ebd1379ed818d9d04b56f0761 0 compat/inet_ntop.c +100644 4078fc0877ca99c82152acdd6b7a9eef70a9f8a4 0 compat/inet_pton.c +100644 cd0d8773641f2fdc808d8b246a8dd2bcd0e5814d 0 compat/memmem.c +100644 772cad510d5d260fdf33b4f7d6ff79f9f3367b05 0 compat/mingw.c +100644 290a9e6f822df97984b9f769508aab36419eaf02 0 compat/mingw.h +100644 34d4b49818b0896b9db19b2b1387f142cbbbd42b 0 compat/mkdtemp.c +100644 c9d46d174259f42a3e2a2eb073475aba517044be 0 compat/mmap.c +100644 978cac4ec91e6bb2f81539d85422bb37e4941a51 0 compat/pread.c +100644 d93dce2cf8fa33bd1fbefe131d2e41a6b954da61 0 compat/qsort.c +100644 87b33e46697b9a5dd9a9e8391ca3607f7e2ff569 0 compat/regex.c +100644 6eb64f14020db0a20ba596de5b58b3c552157f16 0 compat/regex.h +100644 3a22ea7b751efb768d72afa2f97fd963e10eec7e 0 compat/setenv.c +100644 580966e56a3455b9970b7eef33143c1e9c57d41c 0 compat/snprintf.c +100644 26896deca64c531f57b4c48ea92134f876b8e537 0 compat/strcasestr.c +100644 4024c360301ebe7d58ac5b84dcbb692341b649ed 0 compat/strlcpy.c +100644 5541353a77a22d48ccebd20ede2f510ae20d1492 0 compat/strtoumax.c +100644 eb29f5e0849370afe90c400271fea12e0f9090aa 0 compat/unsetenv.c +100644 e2d96dfe6f75213de567174261d9aeba3e663d9d 0 compat/winansi.c +100644 53f04a076a7275965090edd4ca2a34652c4f5679 0 config.c +100644 b776149531025c85f5665d971e6e072f0cc64893 0 config.mak.in +100644 7c2856efc92ca55e3cf03fcf1c72ffb70318f7c3 0 configure.ac +100644 574f42fa47ffa69328217eb25afee6f85db9595e 0 connect.c +100644 05f291c1f1d3d1018f390618816f94d0cd58951b 0 contrib/README +100644 fada5ce909876168f68a85c8ca9a8bc269048acb 0 contrib/blameview/README +100755 1dec00137b2dd8a888a962edd62f01aad89e4186 0 contrib/blameview/blameview.perl +100755 30d870187e64e33ed430dc1fab1ea37036a07f58 0 contrib/completion/git-completion.bash +100644 4009a151deceb45030fb26c5bfcf1b75a423a493 0 contrib/continuous/cidaemon +100644 b8f5a609af464f3af8b624246cc69eb335ce81d1 0 contrib/continuous/post-receive-cinotify +100644 90e7900e6d7aff2fadf9ba04f8d982733493411c 0 contrib/convert-objects/convert-objects.c +100644 9718abf86d8cd36ddae1eae8cf2337e35b927959 0 contrib/convert-objects/git-convert-objects.txt +100644 c531d9867f6c223be1daf0f6da7538feb11966d8 0 contrib/emacs/.gitignore +100644 a48540a92b4aa5140a87469b36c1f9b3d8e46e7f 0 contrib/emacs/Makefile +100644 4fa70c5ad47fcd717d9cbdb23a8142f89227f630 0 contrib/emacs/git-blame.el +100644 c1cf1cbcc014e5d6c01a1c33efa2d7bd3b76df88 0 contrib/emacs/git.el +100644 b8f6be5c0af64dfbe7e136f984404f22aea68130 0 contrib/emacs/vc-git.el +100755 1a7689a48f07a6ed2bb156f745bfea19a10e3eb9 0 contrib/examples/git-checkout.sh +100755 01c95e9fe8a19afcf331ed5ffd47eea478886213 0 contrib/examples/git-clean.sh +100755 547228e13ce60e575d0b4a10a322edfff6c0622c 0 contrib/examples/git-clone.sh +100755 2c4a4062a5317c51601fc4c644c96a7f75e1ef2c 0 contrib/examples/git-commit.sh +100755 e44af2c86d8e7e44bc79aafcc8ccef3806804720 0 contrib/examples/git-fetch.sh +100755 1597e9f33f5e001995085639a448f1214010b561 0 contrib/examples/git-gc.sh +100755 fec70bbf88c614a2dadfc40950fdd7abdf7f2c63 0 contrib/examples/git-ls-remote.sh +100755 29dba4ba3a57c15bd430bd23c1cebe78e6dc03be 0 contrib/examples/git-merge-ours.sh +100755 e9588eec33ba5b64d186ff048bb040c18c57e6bc 0 contrib/examples/git-merge.sh +100755 36bd54c985080f8dd5558a3e7a4e19ede9fbab93 0 contrib/examples/git-remote.perl +100755 4f692091e73bf633cf986ba2c9bed38bc2c78538 0 contrib/examples/git-rerere.perl +100755 bafeb52cd113ad8a07ffd1912191f2bc17a7ef7a 0 contrib/examples/git-reset.sh +100755 0ee1bd898ecbb725d13385408b4ed4bcb413f503 0 contrib/examples/git-resolve.sh +100755 49f00321b28833c24ebb78ea2104f34091d43017 0 contrib/examples/git-revert.sh +100755 a13bb6afec2fe5e0b5249523ec8c62d8e517de88 0 contrib/examples/git-svnimport.perl +100644 71aad8b45bd4c5f59c2ce3746cb3299821729c2a 0 contrib/examples/git-svnimport.txt +100755 e9f3a228af472c932f6cec5fa25ae49cd841b239 0 contrib/examples/git-tag.sh +100755 0902a5c21adc4123e36856f73acc1409e17eb0ac 0 contrib/examples/git-verify-tag.sh +100755 f9fef6db28dbba0ef67589f05eeb937760d2facf 0 contrib/fast-import/git-import.perl +100755 0ca7718d0518db2e559ecd17eb6f7f57338b80fd 0 contrib/fast-import/git-import.sh +100755 6ae0429c2dde435f8ae33991ad10f40485aefdc6 0 contrib/fast-import/git-p4 +100644 9f97e884f5c3cae9e89164c9590959ba487a89bd 0 contrib/fast-import/git-p4.bat +100644 b16a8384bcfbfe33dc33e1076c64f5d36e75e803 0 contrib/fast-import/git-p4.txt +100755 23aeb257b9557cb146586868084ce1b20d7e7ac8 0 contrib/fast-import/import-tars.perl +100755 c674fa2d1b5c6ab47ebb5e828c427c6d47bb50fc 0 contrib/fast-import/import-zips.py +100755 4c99dfb9038ca034d86b72cbe342373d12ae8cc6 0 contrib/gitview/gitview +100644 77c29de305fabc518edf060b0e6634d9c5c9f71e 0 contrib/gitview/gitview.txt +100755 7b03204ed18500756ba55818f0808b52db68d048 0 contrib/hg-to-git/hg-to-git.py +100644 91f8fe6410c06308b6dce47ca28f4c1b8536c5bb 0 contrib/hg-to-git/hg-to-git.txt +100644 41368950d6b29121089ee9239b8e07ece209a31e 0 contrib/hooks/post-receive-email +100644 0096f57b7e09f33108d7177405d02eec05811c03 0 contrib/hooks/pre-auto-gc-battery +100644 dab7c8e3a1829b31f2b10eafe8becf0f067b5a05 0 contrib/hooks/setgitperms.perl +100644 d18b317b2f018d1d1a5a9677a7bdaf8956d65186 0 contrib/hooks/update-paranoid +100644 b9892b679320d17c1e9812633d892a7e057865aa 0 contrib/p4import/README +100644 0f3d97b67eef3108728265e26f5d79c4526d11ac 0 contrib/p4import/git-p4import.py +100644 9967587fe6bef0cf7cc3e93467bd179f6f58b032 0 contrib/p4import/git-p4import.txt +100644 f2b08b4f4a5ea29ac6125f5717fa661e11b7d5f9 0 contrib/patches/docbook-xsl-manpages-charmap.patch +100755 1cda19f66af96fa828de81cbb21817abca0c06ea 0 contrib/remotes2config.sh +100755 e27fd088be1bd3ecc3da116d5f32ce10d89897ac 0 contrib/stats/git-common-hash +100755 4b852e2455bab324e3bd16e02ec712fbacbf34b0 0 contrib/stats/mailmap.pl +100755 f4a7b62cd9f1a397118b95792c04c2f70f910f9e 0 contrib/stats/packinfo.pl +100644 39f96aa115e0a20024d2f41138db6b2b8c6d5320 0 contrib/thunderbird-patch-inline/README +100755 cc518f3c890158d29e751e008436e0c3790746ee 0 contrib/thunderbird-patch-inline/appp.sh +100644 9e7881fea923e47c3c35028ebbc00bce395d4005 0 contrib/vim/README +100644 332121b40e9c54de9f55362cb57760136039e9fd 0 contrib/vim/syntax/gitcommit.vim +100755 7959eab902d28bb3307c542514ca4c5f49deee0f 0 contrib/workdir/git-new-workdir +100644 78efed800d4d64898d438d9590b01be008cfcd36 0 convert.c +100644 e54d15aced7595ccb11423b0de121db9051ad1f3 0 copy.c +100644 ace64f165e4a01fb99892e9b89e7df791a7f4ca1 0 csum-file.c +100644 72c9487f4fd9fcab5e02fc2dc6afd3cb7f9c036a 0 csum-file.h +100644 ee06eb7f48f1d3e818b3037369b4e056fe7e5be7 0 ctype.c +100644 4540e8df5ab8bc8ff66549144d7db2928e12199b 0 daemon.c +100644 35a52576c53e5e1406d40ed4402b8834a29b9f0e 0 date.c +100644 d9668d2ef94c73e4a7a5602011ff13a9fd9d8c6a 0 decorate.c +100644 1fa4ad9beb08f23888814b99183487ab85378bfd 0 decorate.h +100644 40ccf5a1e95f62d840a006274f7024fa43208b1c 0 delta.h +100644 a4e28df714b4834e5efe42fa3abb647711913d71 0 diff-delta.c +100644 e7eaff9a68ccbcc692522c9956f0dae9af45f3f1 0 diff-lib.c +100644 7d68b7f1bef1039b4996e662fb17968c4e3e3e79 0 diff-no-index.c +100644 cbf25473c594abfd1fc13473108dc9c15e2f1d15 0 diff.c +100644 50fb5ddb0bec02b0cd5498d6ecc37d44bf874476 0 diff.h +100644 31cdcfe8bcdae7df65b0387071846299a14bb7be 0 diffcore-break.c +100644 e670f8512558c38d9a9d6e754cfc609b042b1195 0 diffcore-delta.c +100644 23e93852d8c701760d56e7e728dba7c08367fbe8 0 diffcore-order.c +100644 af9fffe6e8e145b066157da8791c749257e7c8e9 0 diffcore-pickaxe.c +100644 1b2ebb40014d820fe4fb679509ab694d453be7b4 0 diffcore-rename.c +100644 cc96c20734bf4184970f5381416637cf6e45ea13 0 diffcore.h +100644 29d1d5ba31def46ba8b55905dc60773cc6cc167e 0 dir.c +100644 2df15defb6720a742282f24721233c4816deceb6 0 dir.h +100644 1f73f1ea7dfa6a14dedf384c99751e86c8121ff4 0 dump-cache-tree.c +100644 eebc3e95fe0c7e61f7c29fa5412ea9d4a5900f92 0 editor.c +100644 222aaa374b8268828e9d529a8afacb8830acc281 0 entry.c +100644 0c6d11f6a0c6fa5dbab2f36c4b4ad4de5aba4ac9 0 environment.c +100644 ce6741eb682b59ad638c7bee6ca31e2fcd53f281 0 exec_cmd.c +100644 594f961387240c221020c9ea0bccd8a39ff69595 0 exec_cmd.h +100644 7089e6f9e6c5fa9142f468e54afe7d33a6d2eec7 0 fast-import.c +100644 8bd9c32561e79d194d27fa10cc98a26aa2cb673c 0 fetch-pack.h +100755 63dfa4c475ae3632fc5cfd093d949a41683a5458 0 fixup-builtins +100644 797e3178ae279f444d2efa7e3758652ad0898dd7 0 fsck.c +100644 990ee02335a2e2693e32baa82b259c23843f2aa0 0 fsck.h +100755 a2913c2a2cd1ec158157ada3e2deb666892b734b 0 generate-cmdlist.sh +100755 da768ee7acc22e6480f0a067e109239561d43927 0 git-add--interactive.perl +100755 6aa819280ef99ccbbdeefde037e99fae3e6f0110 0 git-am.sh +100755 98f3ede566a6cb0c902ce84795f7de8f8afbe633 0 git-archimport.perl +100755 3cac20db79e1e408a321b0e9d272501985a3c49b 0 git-bisect.sh +100644 cf89cdf4598b3796724a85aa707f740245155cdc 0 git-compat-util.h +100755 6d9f0ef0f989133422cf8c0302e63dab15a999d5 0 git-cvsexportcommit.perl +100755 e2664ef01308fd0fb65d47b25e0ae73a65aa6262 0 git-cvsimport.perl +100755 b0a805c688f59af29e1f25b514d73f3991285dee 0 git-cvsserver.perl +100755 182822a24e214fe7e93a2df68fdda3dd40b5896d 0 git-filter-branch.sh +100644 6483b21cbfc73601602d628a2c609d3ca84f9e53 0 git-gui/.gitignore +100755 0ab478ef90aba9048a2de785d538da16e1bae431 0 git-gui/GIT-VERSION-GEN +100644 55765c8a3aa6b3702b230e8efe3c2ab47a6e73e5 0 git-gui/Makefile +100755 14b2d9aacd1d28084f195365b434747df2ddc95d 0 git-gui/git-gui.sh +100644 241ab892cd5b731f07571acf7a0ca3150a763f4f 0 git-gui/lib/about.tcl +100644 b6e42cbc8fe0a49c301335f78cc2941bd9d59870 0 git-gui/lib/blame.tcl +100644 777eeb79c1355ec49ce175cc5c33a13df6e41c97 0 git-gui/lib/branch.tcl +100644 6603703ea163d830c7de1478aa2dd737c4d9d499 0 git-gui/lib/branch_checkout.tcl +100644 3817771b944cc363205b86c91f7b4801c1d568f9 0 git-gui/lib/branch_create.tcl +100644 ef1930b4911591566be4561b8c17c24e1cfbfaad 0 git-gui/lib/branch_delete.tcl +100644 166538808f461275075e2b03c56ddc15b5813e1a 0 git-gui/lib/branch_rename.tcl +100644 ab470d12648c1dd3560b411e70ea210cc4381e3e 0 git-gui/lib/browser.tcl +100644 caca88831b7066c573917542d24a52e832dcff34 0 git-gui/lib/checkout_op.tcl +100644 56443b042c62bc10765aaf6484ad1077a843cb30 0 git-gui/lib/choose_font.tcl +100644 318078615862adab052d0d0f637f82176a0a785a 0 git-gui/lib/choose_repository.tcl +100644 c8821c146386f850c0794df70f605cd9f18dcff3 0 git-gui/lib/choose_rev.tcl +100644 dc2141192a21e7416268cc94beda78d6ceb8f86f 0 git-gui/lib/class.tcl +100644 40a710355751836e78b65101592b753266f507ca 0 git-gui/lib/commit.tcl +100644 c112464ec367a2db707a3f28ff6c588aefe7985f 0 git-gui/lib/console.tcl +100644 a18ac8b4308d8263a0688058524282b72bafe77a 0 git-gui/lib/database.tcl +100644 abe82992b6529cf49983029d85348df5d27ceaf5 0 git-gui/lib/date.tcl +100644 52b79e4a1f476c2ee9b65087f66a352a25ed0903 0 git-gui/lib/diff.tcl +100644 7f06b0d47f0fa214c98644757f99f8a036b9689e 0 git-gui/lib/encoding.tcl +100644 75650157e551e34dab650d89f3fa6d25afc91d6a 0 git-gui/lib/error.tcl +100644 334cfa5a1a59c320e86789ccf4ed3320584a0215 0 git-gui/lib/git-gui.ico +100644 3c1fce7475d362d1880d915ff4bdf168fda28593 0 git-gui/lib/index.tcl +100644 5ff76692f5eeeb51bcca0905385f51963d1e6531 0 git-gui/lib/logo.tcl +100644 5c01875b051305b5b40a17ac7a2245f69081f41b 0 git-gui/lib/merge.tcl +100644 ffb3f00ff0a992254804cc047b5a63ce82aa5bd9 0 git-gui/lib/option.tcl +100644 0e86ddac0981fbb575a7dd5294ddaed29f7c3917 0 git-gui/lib/remote.tcl +100644 c7b81486984d46a9dca59867c406a8e247d76313 0 git-gui/lib/remote_branch_delete.tcl +100644 38c3151b05c732d919943e44629bfc0a8c9fb617 0 git-gui/lib/shortcut.tcl +100644 78f344f08f34842c134b6b0e22b6eb8c49b1dbbd 0 git-gui/lib/spellcheck.tcl +100644 51d4177551b911c35cfd8004a36fca4259367d24 0 git-gui/lib/status_bar.tcl +100644 8e6a9d0a6010cf5efee069a2d488124bcbdb54cd 0 git-gui/lib/transport.tcl +100644 d7f93d045d1a2b3a14d2fdb4907697622b5973a8 0 git-gui/lib/win32.tcl +100644 117923f8860bb8f0f04c1664d8cbe38804a59831 0 git-gui/lib/win32_shortcut.js +100644 ddbe6334a258dae46b6c333d53590f3b920a9cab 0 git-gui/macosx/AppMain.tcl +100644 b3bf15fa1c1a41265460664417caf47265553a4f 0 git-gui/macosx/Info.plist +100644 77d88a77a7669667335cf6fd5767c8b40f3ce6e7 0 git-gui/macosx/git-gui.icns +100644 a89cf4496990737117d7558a7465f68aa058e465 0 git-gui/po/.gitignore +100644 5e77a7d7d2d9e82311c1573035fa020c8d08b38c 0 git-gui/po/README +100644 f20955c18520bf2b0cc8826da9e1dc93a5624ac3 0 git-gui/po/de.po +100644 89b6d51ea011d5b0fc8a343ffdda078d659571cb 0 git-gui/po/fr.po +100644 813199f782968cb0949d24119145e8b3e4a174cd 0 git-gui/po/git-gui.pot +100644 749aa2e7ec1b02e6af3427516b1197f77bd48795 0 git-gui/po/glossary/Makefile +100644 35764d1d22da45e90638b2db3e0bfbcb332e8696 0 git-gui/po/glossary/de.po +100644 27c006abb2adca055ebf7e44ce9a4ec351af19c5 0 git-gui/po/glossary/fr.po +100644 40eb3e9c07a4d39091972655d8a99110fd361be5 0 git-gui/po/glossary/git-gui-glossary.pot +100644 9b31f69152025e484ddf467d7884c2bf2140a894 0 git-gui/po/glossary/git-gui-glossary.txt +100644 bb46b48d6b84446a23c14af88c339fda7e417718 0 git-gui/po/glossary/it.po +100755 49bf7c5365130ec290948ee8abba28d757774381 0 git-gui/po/glossary/txt-to-pot.sh +100644 158835b5c1c9364735167e618af62272c8bb7a8d 0 git-gui/po/glossary/zh_cn.po +100644 28760ed97838d39effd035ab4f1159c0085221f8 0 git-gui/po/hu.po +100644 11cc79bb5ec9c8f1a158ceb457157705b04d4adf 0 git-gui/po/it.po +100644 28e6d6246b5a07bc0dfe29dde4727be0cf0ba40c 0 git-gui/po/ja.po +100644 b7c4bf3fdffb3d04b8c01b25e99a706e499de0d1 0 git-gui/po/po2msg.sh +100644 db55b3e0a69813cba16932212ee1b2ce0f5b2b9a 0 git-gui/po/ru.po +100644 4da687bb41f5471eaa6dd49c2ffae1eaa053ec68 0 git-gui/po/sv.po +100644 d2c686667163ec4cd83045efd429e3413564290e 0 git-gui/po/zh_cn.po +100644 53c3a94686813936445efbb055dc4f02885c70e9 0 git-gui/windows/git-gui.sh +100755 0843372b57371b62cd68f2818f634209f55d5395 0 git-instaweb.sh +100755 9cedaf80ceac1d4100adf3cfb152c76c7f945e4d 0 git-lost-found.sh +100755 645e1147dc886f2b1ca6d2020b44db746b082bf0 0 git-merge-octopus.sh +100755 e1eb9632660146396a0b5f3f2a410d8cb027ff9d 0 git-merge-one-file.sh +100755 93bcfc2f5dce418d00f26257788932d5c738785c 0 git-merge-resolve.sh +100755 94187c306ccb05d977f2bb35e81828130ab49a61 0 git-mergetool.sh +100755 695a4094bb4230341618bd6f16d0bea9bff2e826 0 git-parse-remote.sh +100755 75c36100a2f858bcf2663d2b4560654787963175 0 git-pull.sh +100755 cebaee1cc9dfc28d80173583b144a480be2f9bfd 0 git-quiltimport.sh +100755 4e334ba41dad3067394b79c15ebfe610b2d3e178 0 git-rebase--interactive.sh +100755 412e135c3ae88d76b5bdf3f08083b153da220a95 0 git-rebase.sh +100755 937c69a74858a8a3c63bb41a23705b579df1b3a3 0 git-relink.perl +100755 683960b04d6b743e687b2eb640d2b0e00ccfd313 0 git-repack.sh +100755 073a314c8043e0ff30afde65e012e356ff0d186f 0 git-request-pull.sh +100755 d2fd89907688a044ffe0d2520744e00a9b33c942 0 git-send-email.perl +100755 dbdf209ec0e7d6468c199d1905c3e7788a9cd246 0 git-sh-setup.sh +100755 d4609ed66e56dc6021c800d60286bec38615ff39 0 git-stash.sh +100755 b40f876a2ca9fe985cedc622ab28a9f461edc5ab 0 git-submodule.sh +100755 cf6dbbc42773fef394c27cd87109b69c3144753c 0 git-svn.perl +100755 384148a59fc492d8fb1d6ea4fc4532aa1e5ffc22 0 git-web--browse.sh +100644 37b1d76a08ca59f3de54e11890dce962403cf8d3 0 git.c +100644 c6492e5be2763eab81358424ff625a34a5ff2fba 0 git.spec.in +100644 e1b6045605865cbfc4ae0d57039111d5df825649 0 gitk-git/Makefile +100644 fddcb45817ed6839ba95965d7e57e9a2e04ae30a 0 gitk-git/gitk +100644 e358dd1903352f5cd65ac77e777ae14d6887adc0 0 gitk-git/po/.gitignore +100644 b9867bf8e05d06f7effb9919f00879f77690e185 0 gitk-git/po/de.po +100644 2cb148624723adf82fd7f4a361133dbc8909db93 0 gitk-git/po/es.po +100644 d0f4c2e19ac15b10c01d6df968f823914cdbba4a 0 gitk-git/po/it.po +100644 c63248e3752b8b479f75ad2fe772dd40f684be54 0 gitk-git/po/po2msg.sh +100644 f6b080df4cf313edaba241eb54c232e9f282a38c 0 gitk-git/po/sv.po +100644 26967e201aca8ea1c799e6b21cad468484753779 0 gitweb/INSTALL +100644 825162a0b6dce8c354de67a30abfbad94d29fdde 0 gitweb/README +100644 de637c0608090162a6ce6b51d5f9bfe512cf8bcf 0 gitweb/git-favicon.png +100644 16ae8d5382de5ffe63b54139245143513a87446e 0 gitweb/git-logo.png +100644 aa0eeca24786dbd5143354fc3bb5e8cdb3ef831f 0 gitweb/gitweb.css +100755 90cd99bf916135e5c0a9e1bd7d5e9ff45555c489 0 gitweb/gitweb.perl +100644 e2633f8376eb7b12706dcd4c698e2b3f6be2b433 0 graph.c +100644 eab4e3daba9812293d4e005c3ebe28f9a97744ce 0 graph.h +100644 f67d6716ea5f42c3384a7a4cb2eb973b02785fba 0 grep.c +100644 d252dd25f81526d9b8663b4d3c9585d69a901397 0 grep.h +100644 46c06a9552dac5475afc607c3fe2bf00801eb055 0 hash-object.c +100644 1cd4c9d5c0945994b84bb25edd6e4685cf76b5c5 0 hash.c +100644 69e33a47b9861df9ac12c354eae180b4f8fea857 0 hash.h +100644 3cb19628965685ce59a5377b81bef975851996e8 0 help.c +100644 68052888570af7d09535db8831b8cf3ef2881589 0 http-push.c +100644 9dc6b27b457a2979a95018679a0b885e6fb62d9a 0 http-walker.c +100644 1108ab4a3101fb4768cad420ccfdb52d87890a18 0 http.c +100644 905b4629a47789705c13745fd56ce0c91adea41b 0 http.h +100644 b35504a8d25594a8d243ae7490733eae5a262712 0 ident.c +100644 1ec131092109aa3fbed3cd20f10b56a864584a94 0 imap-send.c +100644 52064befdbbbdf671bd08e369a133d4f1fee03c1 0 index-pack.c +100644 7f03bd99c5b66afa6cc7fa11a2430301a3042656 0 interpolate.c +100644 77407e67dca97eb85274c69e2e7469e1d4d40b3b 0 interpolate.h +100644 c8b8375e4983794e601ba69a1c217a3c711835e9 0 list-objects.c +100644 0f41391ecc00eac324ea76de7654781c4fce094e 0 list-objects.h +100644 9837c842a3f215ebee7cbe9690e42e216fb5c76c 0 ll-merge.c +100644 5388422d091ede134d42406291989c49553f7428 0 ll-merge.h +100644 4023797b00fe21ecbabe3407ef8a12fca0690607 0 lockfile.c +100644 bd8b9e45ab46b8664c8b7016b33bee22f86c9e0d 0 log-tree.c +100644 59ba4c48b7966db34c6345a445ab0b10e235ac83 0 log-tree.h +100644 88fc6f394684436967002ca477eac1e084537348 0 mailmap.c +100644 6e48f83cedd13e24d50cddf47f037791ddc5ad4b 0 mailmap.h +100644 0fd6df7d6ed839eaed536bc332312c2688a6bbad 0 match-trees.c +100644 2a939c9dd835a7e7946eb1548e4cf637ae3ca329 0 merge-file.c +100644 7491c56ad25332fb4aae6a075bf0577a1d800c3b 0 merge-index.c +100644 f37630a8ad07709ae106ddde44a34daf6bad8b16 0 merge-recursive.h +100644 02fc10f7e622ba1c53065e7cf4563ff10af0c41f 0 merge-tree.c +100644 0b34341f711a903d4a12fe96dc6ef63e55fb2f5b 0 mktag.c +100644 e0da110a98d3a7376dc78df71fabc10fc5664296 0 mktree.c +100644 3f06b835675206912777a774d91c3ba611fa5a06 0 mozilla-sha1/sha1.c +100644 16f2d3d43ca8bee1eeb306308277bef8c707a972 0 mozilla-sha1/sha1.h +100644 0031d78e8c98a32d61cd0dc0f939a033e24ed890 0 name-hash.c +100644 50b6528001fe4bafdfe70126dc2078860c3d1969 0 object.c +100644 036bd66fe9b6591e959e6df51160e636ab1a682e 0 object.h +100644 f596bf2db5e0a0065e6856b8caa3ded8a134f74d 0 pack-check.c +100644 25b81a445c8fafe0c00ce30082b7d9a7c22ccf1e 0 pack-redundant.c +100644 848d311c2b2c651dbb14893c260584f00c639357 0 pack-refs.c +100644 518acfb370ad72be18399a3ac5e8ca17880281c9 0 pack-refs.h +100644 cd300bdff5b524a4d509ba5276e9ef21f443013d 0 pack-revindex.c +100644 36a514a6cf600e7e77794e50998a9d160e30c8e9 0 pack-revindex.h +100644 a8f02699366c87de960d7637e9f69c26c2241693 0 pack-write.c +100644 76e6aa2aad06545e7c44fc2c1e117ea668356ccf 0 pack.h +100644 6b5c9e44b4ded338ddb344ae454d83a685b7569a 0 pager.c +100644 71a7acf4e22bd12c0919f277410d6ec52dd5efc8 0 parse-options.c +100644 bc317e7512af7a1cc86641a651ae5415d28e71c4 0 parse-options.h +100644 ed9db81fa82c812c9ffa07f5a40540dbb15da0d3 0 patch-delta.c +100644 9349bc5580456b378d41da7cc2518e4fa9a7e81a 0 patch-id.c +100644 3be5d3165e0009761a0ca69e15e4a9132c6cfaff 0 patch-ids.c +100644 c8c7ca110ad34def12a3594a1560b3c3052eb701 0 patch-ids.h +100644 9df447bd6dcfaddf7f05fe5f0b624700ff1f40d7 0 path.c +100644 98b24772c7ebe838d513d8e24f3c8acff7839cb9 0 perl/.gitignore +100644 d99e7782002e01079b3866003cc8555b7e130e3f 0 perl/Git.pm +100644 b8547db2c64ac1242725b5f71fb646b5bca38ef3 0 perl/Makefile +100644 320253eb8e91eb1d914aa4e34f7d3af4649b9b39 0 perl/Makefile.PL +100644 11e9cd9a02eb3f85a9150c6fb06d1fc76abd9b09 0 perl/private-Error.pm +100644 f5d00863a6234c16db33637d19fefd2014780e87 0 pkt-line.c +100644 9df653f6f5afe720870658d7093bddbf3e66beaf 0 pkt-line.h +100644 738e36c1e81def4822ccc2a66bc2761402a07f26 0 ppc/sha1.c +100644 c3c51aa4d487f2e85c02b0257c1f0b57d6158d76 0 ppc/sha1.h +100644 f132696ee72bf4a2e3d608a24322a6839f9a03a8 0 ppc/sha1ppc.S +100644 33ef34a4119812674726254fee3f391fb5734fdb 0 pretty.c +100644 55a8687ad15788f8ea5a5beb463d216908f618b2 0 progress.c +100644 611e4c4d42d8d1164add09f926ad5b2ce088db5e 0 progress.h +100644 6a520855d6c418ecb1384ef9571b122b134af1af 0 quote.c +100644 c5eea6f18e2dfabd071b73e6507c34c2b7b5e39f 0 quote.h +100644 3b1c18ff9b9060d0dd437ce89aedb8871c66c54c 0 reachable.c +100644 40751810b64f8bbf9c0a633472a0ef27d23ed1a5 0 reachable.h +100644 2c03ec3069decb20f7557af4ac7dbe295f2dcf9c 0 read-cache.c +100644 d44c19e6b577023dcbaa188a0e67130ff4e5bd9a 0 receive-pack.c +100644 f751fdc8d832cae54647c1a70d888e979d324fd8 0 reflog-walk.c +100644 7ca1438f4d74b652f962c6bdfddd08fe0d75802d 0 reflog-walk.h +100644 39a3b23804d2da715c564459bf320be23d41c1bf 0 refs.c +100644 06ad26055661a9b9e475d0f8a7bd6d1cfb42e792 0 refs.h +100644 f61a3ab399aa6960fb8eba050321cea4a3b05344 0 remote.c +100644 091b1d041f8a4d255f59bfc001e098e692dbc15c 0 remote.h +100644 323e493dafee46c0d3f95e3c4cd9c4c9b463bbef 0 rerere.c +100644 f9b03862fe78b560ee606637be3b1ce972a2cc14 0 rerere.h +100644 3897fec53170c50921eb1952bc4bdf9c08480638 0 revision.c +100644 f64e8ce7ff999e9fe4a01205ae51775827484ed4 0 revision.h +100644 a3b28a64dc2d1b888b0ba2a135be10fe04651201 0 run-command.c +100644 5203a9ebb10b14bd06862abafed0ab73d7514a3d 0 run-command.h +100644 8ff1dc35390083c3648c4ee5790f35633d956069 0 send-pack.h +100644 c1c073b2f05a48772a45602cdc711eef6e211695 0 server-info.c +100644 6cf909463d4ad3681a2f35269db9dc944f4389c2 0 setup.c +100644 da357479cf19aad4bebc64f874c76fdf8566712b 0 sha1-lookup.c +100644 3249a81b3d664afc89c98e6d9dd6b512092a82f9 0 sha1-lookup.h +100644 e281c14f01d37ab7623998c2990914aca49a7a3b 0 sha1_file.c +100644 4fb77f8863ec075de38b84171d3ef039a00cee4c 0 sha1_name.c +100644 4d90eda19efe0a80c1cb39e8897ab3ed5e6fcf56 0 shallow.c +100644 6a48de05ff80f86050715ef3dab87a48b0a86ac9 0 shell.c +100644 bc02cc29ef0d5f640ab390614def995f30fe4691 0 shortlog.h +100644 45bb535773fd9c36f73502df9462f7de800009c8 0 show-index.c +100644 b6777812cb92c1c169ee395164d53a0c2e6eceb2 0 sideband.c +100644 a84b6917c7a17b5f8a922540801e98d46aa24431 0 sideband.h +100644 720737d856b694bc5239f0c18af372959c99e744 0 strbuf.c +100644 eba7ba423a2d3a383ef93f663c95695438269edf 0 strbuf.h +100644 ddd83c8c76112cecd5d23668aaca467601855a72 0 string-list.c +100644 4d6a7051fe5bccf04a0d0c32a90e5cf9c00dba3c 0 string-list.h +100644 5a5e781a15d7d9cb60797958433eca896b31ec85 0 symlinks.c +100644 1b97c5465b7d9e4404e11668b44c5c507a302d4a 0 t/.gitattributes +100644 b27e280083867ac03c4abc188f0f37291eb123a0 0 t/.gitignore +100644 0d65cedaa6566a6dd654753cb574c9ee64b1c90b 0 t/Makefile +100644 8f12d48fe8b4ffe4a4b37dcd16ce58e50837433f 0 t/README +100755 d5bab75d7da49ebb53e368d67f6b867f5417a125 0 t/aggregate-results.sh +100644 cacb273afff1fbddf152bb440451fa141589cf33 0 t/annotate-tests.sh +100644 4bddeb591ecc17ec532164d0d6cf1ad1a54eb996 0 t/diff-lib.sh +100644 a841df2a9e3a9ed64e81ab7b9778e59cfc714cad 0 t/lib-git-svn.sh +100644 dc473dfb53d5ffafee72738a55caf21732fa4fb1 0 t/lib-httpd.sh +100644 4717c2d33b70af6527f8951ec8a414e8caf87095 0 t/lib-httpd/apache.conf +100644 6dab2579cbf9658c3ac2bd55c8a66333d67eda47 0 t/lib-httpd/ssl.cnf +100644 168329adbc4edeedc98501575ccc9b9c81f0c061 0 t/lib-read-tree-m-3way.sh +100755 70df15cbd8339b552a56a95ca0c0893138550201 0 t/t0000-basic.sh +100755 620da5b32041b1ad69bfdcb6d139f2705386a5ff 0 t/t0001-init.sh +100755 4db4ac44c9611398db46dfbe2688c95e3b03605b 0 t/t0002-gitfile.sh +100755 3d8e06a20fade230136d50736a2f621d3c96002c 0 t/t0003-attributes.sh +100755 63e1217e7162435c3da8ec7984b5f6a53b3a10e2 0 t/t0004-unwritable.sh +100755 e45a9e40e432524454e94a041599b201a092879a 0 t/t0010-racy-git.sh +100755 1be7446d8d9f8a46b463f2474a8c25bdd33044d2 0 t/t0020-crlf.sh +100755 8fc39d77cec6168dae930beef785597dace24aa3 0 t/t0021-conversion.sh +100755 7d1ce2d0563b3734d754c171d21580075264bbb2 0 t/t0022-crlf-rename.sh +100755 6f8a4347d5397b8b396db800c12c6e045a0d2b7c 0 t/t0023-crlf-am.sh +100755 ccb0a3cb61be3bb591033564b221726a4cd3968d 0 t/t0030-stripspace.sh +100755 03dbe00102626e05c37e45d8a3b1364b99644942 0 t/t0040-parse-options.sh +100755 b177174ef53e7689cc8c18b134afdbe90be72744 0 t/t0050-filesystem.sh +100755 6e7501f352ee97636280357da54c50d73ceb0138 0 t/t0060-path-utils.sh +100755 807fb83af8c65304f1dae2ee35ba0f2909ddf465 0 t/t1000-read-tree-m-3way.sh +100755 4b44e131b27df0cc6a73590b045c2eb87b104f59 0 t/t1001-read-tree-m-2way.sh +100755 aa9dd580a658ffd980ec9689b01f7964580661f2 0 t/t1002-read-tree-m-u-2way.sh +100755 8c6d67edda1468ba0f1c7afc6d13ea3a7bbe0a90 0 t/t1003-read-tree-prefix.sh +100755 570d3729bd2312a8d9cf90f3d2e1121a58f43de6 0 t/t1004-read-tree-m-u-wf.sh +100755 b0d31f5a9bb8b3474665147327d94ad5067fa206 0 t/t1005-read-tree-reset.sh +100755 d8b7f2ffbcc0427b1ae9d48feb4387f580e81d61 0 t/t1006-cat-file.sh +100755 1ec0535138c72bbd1e497c35c21bc5ea46b0315f 0 t/t1007-hash-object.sh +100755 fc386ba033ac165a5f4a9fca0c6c6f5db49a314e 0 t/t1020-subdirectory.sh +100755 7f7fc36734d96de96801c59af41024db97dc614d 0 t/t1100-commit-tree-options.sh +100755 09a8199335cbdf96f8aba75d47a321f0cfb828d9 0 t/t1200-tutorial.sh +100755 64567fb94d5c3f9587b643333212cdb37a4661ac 0 t/t1300-repo-config.sh +100755 dc85e8b60a5c10e57047d1692e383f177e2c478d 0 t/t1301-shared-repo.sh +100755 8d305b43725f8cf60e7ee802df1923feb98eeae5 0 t/t1302-repo-version.sh +100755 f98f4c51796e6f7a7181568a134e21ecd9dc2c4f 0 t/t1303-wacky-config.sh +100755 b31e4b1ac66e56d67ba48ab213c4ef9c32f05ea8 0 t/t1400-update-ref.sh +100755 73f830db2374e751fb46e25b345e860979b9dd05 0 t/t1410-reflog.sh +100755 dc9e402c55574d981e161d4e38e74617c411f46d 0 t/t1420-lost-found.sh +100755 85da4caa7ed1b8bcaca7b21e218f2d1839d2db82 0 t/t1500-rev-parse.sh +100755 2ee88d8a069288d0d9f6931231162e04d6b0917a 0 t/t1501-worktree.sh +100755 997002d4c40dd8e66e3be5a701e3d99bab1c57c4 0 t/t1502-rev-parse-parseopt.sh +100755 95244c9bcf54de8cb3584b4022e53a84051d496f 0 t/t1503-rev-parse-verify.sh +100755 91b704a3a4ce6771071d19bd84aa228856fe6875 0 t/t1504-ceiling-dirs.sh +100755 f7e1a735ec8699616280a086f59dc50c078bfaa7 0 t/t2000-checkout-cache-clash.sh +100755 ef007532b15108d72445f7c95a2906a3039fbbbb 0 t/t2001-checkout-cache-clash.sh +100755 70361c806e1baf1b26810983374c53eb49ea2f2d 0 t/t2002-checkout-cache-u.sh +100755 71894b37439bd1b9c72194cbbabe37680d2f9743 0 t/t2003-checkout-cache-mkdir.sh +100755 39133b8c7a4b56cb7273cec607ea89081a426eff 0 t/t2004-checkout-cache-temp.sh +100755 a84c5a6af9e69ffec7689827ce1ba653a658a73f 0 t/t2005-checkout-index-symlinks.sh +100755 0526fce163fc13273daf035a0920a6b53a3acefb 0 t/t2007-checkout-symlink.sh +100755 3e098ab31e1944abe8e5815c0f219947620b6618 0 t/t2008-checkout-subdir.sh +100755 f3c21520877e271506be13b5cabad5e7906f0c91 0 t/t2009-checkout-statinfo.sh +100755 7cc0a3582ef1bb1598bc5dfc5334bfbe006c3f5a 0 t/t2010-checkout-ambiguous.sh +100755 88f268b9d7a696a06f5ce560c1e8ed0f3d8dc3a3 0 t/t2050-git-dir-relative.sh +100755 6ef2dcfd8afece86aaf6345630179af179eb2ed9 0 t/t2100-update-cache-badpath.sh +100755 59b560bfdf240e87516aadd6a31a2fe84e85d49a 0 t/t2101-update-index-reupdate.sh +100755 19d0894d260787d37a43199d7a3f6c3aa37d32aa 0 t/t2102-update-index-symlinks.sh +100755 332694e7d38083fad18b3e53e4def268d54e9423 0 t/t2103-update-index-ignore-missing.sh +100755 f57a6e077c3b85dcdedc3f4813150feebc8e647d 0 t/t2200-add-update.sh +100755 d24c7d9e5fce0e9c0f8ef5576dab86ffdbc11331 0 t/t2201-add-update-typechange.sh +100755 6a8151064c8256bd03a90460eb1bd6970428f2f0 0 t/t2202-add-addremove.sh +100755 bc0a3513920cab41e4335b8c1b5163e25e8354d3 0 t/t3000-ls-files-others.sh +100755 1caeacafa7ae70506e626498d274dbfa25f1b036 0 t/t3001-ls-files-others-exclude.sh +100755 8704b04e1b4150357a7a01c91ac59bb1f22cbb8e 0 t/t3002-ls-files-dashpath.sh +100755 ec1404063701eef04667d5ffbbb4bdc8051c773b 0 t/t3010-ls-files-killed-modified.sh +100755 af8c4121abfc28b7e289b39936df45bd5b82cf22 0 t/t3020-ls-files-error-unmatch.sh +100755 aff360303ae2a304bff4799def6906defdb85843 0 t/t3030-merge-recursive.sh +100755 f6973e96a59916c6048222bfa0064aec5dea3746 0 t/t3040-subprojects-basic.sh +100755 4261e9641e00fb3b543384b6a8dbbcc1a214b598 0 t/t3050-subprojects-fetch.sh +100755 3ce501bb9794900b99fbbf2f2ccfbb330f7947a7 0 t/t3060-ls-files-with-tree.sh +100755 6e6a2542a22712006ae23874069c55943a3cba27 0 t/t3100-ls-tree-restrict.sh +100755 4dd7d12bac62eae23516686c0ece0edf037f0317 0 t/t3101-ls-tree-dirname.sh +100755 7a83fbfe4f6b47dc5dbaa3df59c8633ae5c2c8f8 0 t/t3200-branch.sh +100755 f86f4bc5ebcc0e36ddb4071a6aeb855e1039faa6 0 t/t3201-branch-contains.sh +100755 7fe4a6ecb05df0fbfb825fbb08207f7672e1775f 0 t/t3202-show-branch-octopus.sh +100755 c2dec1c6320a0f9b555e3cd38d164c4e3efcb51e 0 t/t3210-pack-refs.sh +100755 0574ef1f101df172a30755726b0ea1b6c2ef5f7d 0 t/t3300-funny-names.sh +100755 91bb5e1d9eea0b2f1ff7a1120d97ca2876a8f277 0 t/t3400-rebase.sh +100755 166ddb1447db4c33a79f0e9aea21cb00e8a151f2 0 t/t3401-rebase-partial.sh +100755 7b7d07269ae35f56dd02a223f350ae0da97bae85 0 t/t3402-rebase-merge.sh +100755 0d33c71daa557e68268dfb2279a02fe2afca1ed7 0 t/t3403-rebase-skip.sh +100755 ffe3dd97b7b1c056d854e28795e1313ce1633452 0 t/t3404-rebase-interactive.sh +100755 e5ad67c643ffee9b79fce813673732faa950714f 0 t/t3405-rebase-malformed.sh +100755 539108094345e3e0ba4cf03fc20a5ca6486fa230 0 t/t3406-rebase-message.sh +100755 4de550a632e6ead08c9629e80901e4735c53f55c 0 t/t3407-rebase-abort.sh +100755 e12cd578e8663ad8717aecde310bb0b6a500c2a2 0 t/t3408-rebase-multi-line.sh +100755 4911c48378a137471d2ad56747ceed11d0115be5 0 t/t3500-cherry.sh +100755 6da212825a447866364979c2fb10778b6bbc02d5 0 t/t3501-revert-cherry-pick.sh +100755 0ab52da902c8d602e9c4d64660aa4a7e8e35544f 0 t/t3502-cherry-pick-merge.sh +100755 b0faa299183df5fe06ccaf383bce47cbb9a0cf89 0 t/t3503-cherry-pick-root.sh +100755 79c06adf1f035cf727771974b2f9713da9d2fb8c 0 t/t3600-rm.sh +100755 7d123d17fc156c61a8e85a399c3762e8075485de 0 t/t3700-add.sh +100755 e95663d8e66d5b94e574a6b956625fccfd341a05 0 t/t3701-add-interactive.sh +100755 c851db8ca9373a890ede7c230710690d5b4b4165 0 t/t3800-mktag.sh +100755 883281dbd6c02ea7b2d90336c2629eafacee0257 0 t/t3900-i18n-commit.sh +100644 ee31e1973829739baebbdc1ba0a56391adb2fe2f 0 t/t3900/1-UTF-8.txt +100644 63f4f8f121dffe43c1902d1a7357b6303072714d 0 t/t3900/2-UTF-8.txt +100644 546f2aac01b67e39d19de601f5586097b34a8325 0 t/t3900/EUCJP.txt +100644 74b533042f6d1dfd5cb8fae5a538a43938c2df8d 0 t/t3900/ISO-2022-JP.txt +100644 7cbef0ee6f430c611134a06a6dd6c12fbea589d5 0 t/t3900/ISO-8859-1.txt +100755 38c21a6a7fa9a643030f68fd6dd1269b9c640608 0 t/t3901-8859-1.txt +100755 235f372832cb32aefff0a00c4f2ac0e19de2e55d 0 t/t3901-i18n-patch.sh +100755 5f5205cd022ba3a96eb8e5eb73292bd0d4a8ab87 0 t/t3901-utf8.txt +100755 fe4fb5116ac4c482c357f0af3f0a34da27cee237 0 t/t3902-quoted.sh +100755 8d4804b65818f7fc55f0c0736fde673ac7512a8a 0 t/t3903-stash.sh +100755 c44b27aeb24816a346f0aa84d70546a0ffd83b2a 0 t/t4000-diff-format.sh +100755 a32692417db73444dbdc143e6908b7371be79d42 0 t/t4001-diff-rename.sh +100755 a4cfde6b2927a4655f582d7e92dad4568f7b5f89 0 t/t4002-diff-basic.sh +100755 8b1f875286b25b5fc1a527b5b0281f866724a82d 0 t/t4003-diff-rename-1.sh +100755 3d25be7a6709cdd23e0d583a8f1a3e19a3927cd8 0 t/t4004-diff-rename-symlink.sh +100755 66300173124eee8480e7214322faf8bc493ad940 0 t/t4005-diff-rename-2.sh +100755 4e92fce1d00a55cfbc39e55b53f95cc309e96ff2 0 t/t4006-diff-mode.sh +100755 104a4e1492b65a64d061e1ce1df0b0a2a49fb20e 0 t/t4007-rename-3.sh +100755 26c2e4aa65c539c527ae8e2d71b5abb40c21fbbd 0 t/t4008-diff-break-rewrite.sh +100755 d2b45e7b8fb3902cb740e0df582f92195a295f24 0 t/t4009-diff-rename-4.sh +100755 ad3d9e48454d2e72afce682df009cdaaee9ba3c5 0 t/t4010-diff-pathspec.sh +100755 c6d13693ba45b594704c2ef55d40540ee3f9c25f 0 t/t4011-diff-symlink.sh +100755 eced1f30fb8475739aef52230bbb79946a0f76d8 0 t/t4012-diff-binary.sh +100755 9337b81064bbdbe4e7f590830b458c48226c4a17 0 t/t4013-diff-various.sh +100644 78f8970e2be272114368ee28ca2d55f345a6494a 0 t/t4013/diff.config_format.subjectprefix_DIFFERENT_PREFIX +100644 3a9f78a09df1bb12aefbb2b5fb75fd0b9455ed06 0 t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_master +100644 a61ad8cb130093ed63bba5335a0b283f9136177e 0 t/t4013/diff.diff-tree_--cc_--patch-with-stat_--summary_side +100644 49f23b9215c3179d8923915ee2e497ccbc53875a 0 t/t4013/diff.diff-tree_--cc_--patch-with-stat_master +100644 cc6eb3b3d50f2d620df7116bf64992a4dd42b736 0 t/t4013/diff.diff-tree_--cc_--stat_--summary_master +100644 50362be7bf851759885ad17847f5913e5dfb0b3c 0 t/t4013/diff.diff-tree_--cc_--stat_--summary_side +100644 fae7f33255faef186aa7b987c29adfe33d0365f1 0 t/t4013/diff.diff-tree_--cc_--stat_master +100644 5ecb4e14ae4718bb26dbe5657abd5660dc45914e 0 t/t4013/diff.diff-tree_--cc_master +100644 fc177ab3f24c7eddc71d76b803515f7314d9b136 0 t/t4013/diff.diff-tree_--patch-with-raw_initial +100644 bd905b1c573056f92d7f3b11ad4898d19fd0e5f8 0 t/t4013/diff.diff-tree_--patch-with-stat_initial +100644 7bb8b45e3eea89b4015cabb70d34483352b40f1a 0 t/t4013/diff.diff-tree_--pretty=oneline_--patch-with-raw_initial +100644 cbdde4f400fe96ea565dcf28b6b474c2218b6104 0 t/t4013/diff.diff-tree_--pretty=oneline_--patch-with-stat_initial +100644 cd79f1a0ff23a4399416d85737f312e0b8652a38 0 t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-raw_initial +100644 d5c333a378c9407abf179d6cc3f5233ca8b5f116 0 t/t4013/diff.diff-tree_--pretty=oneline_--root_--patch-with-stat_initial +100644 3c5092c6993f454dc7392a3846b93cc3fa47f7e5 0 t/t4013/diff.diff-tree_--pretty=oneline_--root_-p_initial +100644 08920ac658b07ed83376bdd492020f7787ad1ad5 0 t/t4013/diff.diff-tree_--pretty=oneline_--root_initial +100644 94b76bfef159a0d8e2d7c48194110cb8465545c2 0 t/t4013/diff.diff-tree_--pretty=oneline_-p_initial +100644 d50970d5745278a47da683aa20968a912493cb01 0 t/t4013/diff.diff-tree_--pretty=oneline_initial +100644 3a85316d8a3416e2f280e01d02e0bf3cfce13cc8 0 t/t4013/diff.diff-tree_--pretty_--patch-with-raw_initial +100644 2e08239a46a72e76aad4e38940cdc822ca511793 0 t/t4013/diff.diff-tree_--pretty_--patch-with-stat_initial +100644 4d30e7eddc05aa561b43519b031f89de8a30fd98 0 t/t4013/diff.diff-tree_--pretty_--patch-with-stat_side +100644 a3203bd19bd74f1308ca75396fd9a3cfa2064ac8 0 t/t4013/diff.diff-tree_--pretty_--root_--patch-with-raw_initial +100644 7dfa6af3c97b1ad469135bb9a9f3c1f8d6d4b60d 0 t/t4013/diff.diff-tree_--pretty_--root_--patch-with-stat_initial +100644 43bfce253eaf451e2f0a19042c9cbb8879c6fef1 0 t/t4013/diff.diff-tree_--pretty_--root_--stat_--summary_initial +100644 9154aa4d4700b4a7c1e4c205f43694c198419ece 0 t/t4013/diff.diff-tree_--pretty_--root_--stat_initial +100644 ccdaafb3772e80571441f5e4263f79a7b8bc5bfd 0 t/t4013/diff.diff-tree_--pretty_--root_--summary_-r_initial +100644 58e5f74aeae880c69776bfa8e51bc9e5fe2463cf 0 t/t4013/diff.diff-tree_--pretty_--root_--summary_initial +100644 d0411f64ec5d104de3169da28453276880984917 0 t/t4013/diff.diff-tree_--pretty_--root_-p_initial +100644 94e32eabb1f82eb614f1a92d64d0ada403a4df16 0 t/t4013/diff.diff-tree_--pretty_--root_initial +100644 c22983ac4ae05a8c8d9591c91c0a44bc8f42052e 0 t/t4013/diff.diff-tree_--pretty_--stat_--summary_initial +100644 8fdcfb4c0ad64bc92ddda2418cb5f7fa1138cc7a 0 t/t4013/diff.diff-tree_--pretty_--stat_initial +100644 9bc2c4fbad20e42dd0a007eaa23c5994eb675588 0 t/t4013/diff.diff-tree_--pretty_--summary_initial +100644 3c9942faf4b1a1e6d8c3bbbab5627a32ecc96be6 0 t/t4013/diff.diff-tree_--pretty_-p_initial +100644 b993aa7b893c9ba6c276045a400fe0a849265fcd 0 t/t4013/diff.diff-tree_--pretty_-p_side +100644 14715bf7d08ff7696da2572544092f6be9029e18 0 t/t4013/diff.diff-tree_--pretty_initial +100644 e9b6e1c10211c4fb60262a55a28a503c3ed9bb47 0 t/t4013/diff.diff-tree_--pretty_side +100644 5aa84b2a866262a4e6b2d496e7da5b6f7b9d4d88 0 t/t4013/diff.diff-tree_--root_--abbrev_initial +100644 d295e475ddc626dc18381a5c5e839d3b2c26126e 0 t/t4013/diff.diff-tree_--root_--patch-with-raw_initial +100644 1562b627085ff0ad8ffaea61cc42ed39a9d94fc8 0 t/t4013/diff.diff-tree_--root_--patch-with-stat_initial +100644 3219c72fcbce5ee5a1c2b4e7bb87e696db9a0b18 0 t/t4013/diff.diff-tree_--root_-p_initial +100644 0c5361688c54c2599e240252ce70e4fad457c924 0 t/t4013/diff.diff-tree_--root_-r_--abbrev=4_initial +100644 c7b460faf6900e5730a08ab3b90bfda8e1ad48ca 0 t/t4013/diff.diff-tree_--root_-r_--abbrev_initial +100644 eed435e175d40a3f6fa8b3a0a534936360e86eea 0 t/t4013/diff.diff-tree_--root_-r_initial +100644 ddf6b068abe26f7516c37ceb1dca1d646343a499 0 t/t4013/diff.diff-tree_--root_initial +100644 b8e4aa2530717abc7d7b8bea62f12d615dfcd759 0 t/t4013/diff.diff-tree_-c_--abbrev_master +100644 ac9f641fb48272f25f3385dfbbd05777564f16bc 0 t/t4013/diff.diff-tree_-c_--stat_--summary_master +100644 2afcca11f4d0c4db6e259e85540e4d90f8c76a10 0 t/t4013/diff.diff-tree_-c_--stat_--summary_side +100644 c2fe6a98c5f9818f9caf5e0a314aee45831e5329 0 t/t4013/diff.diff-tree_-c_--stat_master +100644 e2d2bb26114ac886fbf2467dc7a33ec8cfab5daf 0 t/t4013/diff.diff-tree_-c_master +100644 b60bea039d991675e9d1480d5089c416aa68200a 0 t/t4013/diff.diff-tree_-p_-m_master +100644 e20ce883702ae0e430350ae849b28c44a081487f 0 t/t4013/diff.diff-tree_-p_initial +100644 b182875fb2fb3f0020dbf49fd9fd4c80e016e651 0 t/t4013/diff.diff-tree_-p_master +100644 c5a3aa5aa4688cb354bff44cbb6062ef8259a617 0 t/t4013/diff.diff-tree_-r_--abbrev=4_initial +100644 0b689b773c67dfef103d95c55ee9958f1b8f32ed 0 t/t4013/diff.diff-tree_-r_--abbrev_initial +100644 1765d83ce461d78e59cf7d505ec63331a7c70577 0 t/t4013/diff.diff-tree_-r_initial +100644 b49fc5345730346ab50142f55a1b8796545ead89 0 t/t4013/diff.diff-tree_initial +100644 fe9226f8a12323c3a36ff2c0c2fd9938852575c8 0 t/t4013/diff.diff-tree_master +100644 a88e66f81774579c511b6cd546f5043a9c975c36 0 t/t4013/diff.diff_--abbrev_initial..side +100644 d0d96aaa91eec7f5a6cb833e43bbd3ec89efad98 0 t/t4013/diff.diff_--name-status_dir2_dir +100644 6a47584777a65cff71e2ebfac8c8f12944de17bb 0 t/t4013/diff.diff_--no-index_--name-status_dir2_dir +100644 3590dc79a65af7299c4b56fd632489920b62f0fb 0 t/t4013/diff.diff_--patch-with-raw_-r_initial..side +100644 b21d5dc6f391fe977cc7c9b9c6badf9b261c5f72 0 t/t4013/diff.diff_--patch-with-raw_initial..side +100644 9ed317a198c71fcec0b44a7b736b61550eed9394 0 t/t4013/diff.diff_--patch-with-stat_-r_initial..side +100644 8b50629e668a385179eb9586b472c51237492232 0 t/t4013/diff.diff_--patch-with-stat_initial..side +100644 0517b5d63129f44275b16f51819d9c08bf37d430 0 t/t4013/diff.diff_--stat_initial..side +100644 245220d3f9b475b4281395639d85122feaa7948d 0 t/t4013/diff.diff_-r_--stat_initial..side +100644 5bb2fe2f280d2def45c113b5c0daa7ab789faed0 0 t/t4013/diff.diff_-r_initial..side +100644 c8adaf595863e66fb9ae061cd20176c981316372 0 t/t4013/diff.diff_initial..side +100644 43346b9ba443fe22b56f0874a7cc885461d2aa81 0 t/t4013/diff.format-patch_--attach_--stdout_initial..master +100644 d7490a9fd729890c80a4b8fc3da0783997f81a04 0 t/t4013/diff.format-patch_--attach_--stdout_initial..master^ +100644 38f790290a41311e490c493bdaf71774853cc861 0 t/t4013/diff.format-patch_--attach_--stdout_initial..side +100644 fca5cce373767d96fd68a17a196889c8c9ea172f 0 t/t4013/diff.format-patch_--inline_--stdout_--subject-prefix=TESTCASE_initial..master +100644 6d6fac390849c964e75b56e48808a78dd3428ce1 0 t/t4013/diff.format-patch_--inline_--stdout_initial..master +100644 18a1110def4bbe25c0bd7020d35df589ef6f528f 0 t/t4013/diff.format-patch_--inline_--stdout_initial..master^ +100644 4f258b8858df79ecf475514b69df904e83e29ffa 0 t/t4013/diff.format-patch_--inline_--stdout_initial..master^^ +100644 e86dce69a3a78d5cfe5cd82067df0381b0f635bd 0 t/t4013/diff.format-patch_--inline_--stdout_initial..side +100644 8dab4bf93ebd5f3e5ee6e899890d6e53af9ab967 0 t/t4013/diff.format-patch_--stdout_--cover-letter_-n_initial..master^ +100644 8b88ca49276695aead0083ad49c53715874e11dc 0 t/t4013/diff.format-patch_--stdout_initial..master +100644 47a4b88637d4dc8650f0480278ae67b907eb5080 0 t/t4013/diff.format-patch_--stdout_initial..master^ +100644 e7650884755b993661ef14fbc812edd7c2710702 0 t/t4013/diff.format-patch_--stdout_initial..side +100644 3ceb8e73c5d4e963a2c08eddf41197431ad52178 0 t/t4013/diff.log_--patch-with-stat_--summary_master_--_dir_ +100644 43d77761f988b7f43f46a5d8fd85d406ef9caa42 0 t/t4013/diff.log_--patch-with-stat_master +100644 5187a26816723476b049c44bb3801816e8672cdf 0 t/t4013/diff.log_--patch-with-stat_master_--_dir_ +100644 c9640976a8f3bd724004f945b00d71f43f00c8ea 0 t/t4013/diff.log_--root_--cc_--patch-with-stat_--summary_master +100644 ad050af55ffa6983bc08ef5919dd20229584fd59 0 t/t4013/diff.log_--root_--patch-with-stat_--summary_master +100644 628c6c03bc6195268c3e7e003478fd042ef36db2 0 t/t4013/diff.log_--root_--patch-with-stat_master +100644 5d4e0f13b59652b170c0b2498319f970d071f774 0 t/t4013/diff.log_--root_-c_--patch-with-stat_--summary_master +100644 217a2eb203718b91ccd79a04e0369f4c5d2905aa 0 t/t4013/diff.log_--root_-p_master +100644 e17ccfc2340eadbb8c393de0aa2793f6f899ba56 0 t/t4013/diff.log_--root_master +100644 5e3243897294d1fc4193c1de3fec95ce58ab22af 0 t/t4013/diff.log_-SF_-p_master +100644 c1599f2f520090b0717d951a69ade5a9960f8038 0 t/t4013/diff.log_-SF_master +100644 f8fefef2c3869337ba048d5cd6d95169dc60cf00 0 t/t4013/diff.log_-p_master +100644 e9d9e7b40a08d803901ac001e4bf9f0c37ad8b15 0 t/t4013/diff.log_master +100644 221b46a7cc2c174ec605cab02211de97bf84f010 0 t/t4013/diff.show_--patch-with-raw_side +100644 377f2b7b7a34a1e83bbcf0f2d72981685a678c24 0 t/t4013/diff.show_--patch-with-stat_--summary_side +100644 fb14c530d2dd79730320badff2547ebf755bd350 0 t/t4013/diff.show_--patch-with-stat_side +100644 8c89136c4d84091da3f2b9f6eaf582112f90a9ba 0 t/t4013/diff.show_--root_initial +100644 5bd597762869443cfd91ba8ebdaeff6e8b515ebf 0 t/t4013/diff.show_--stat_--summary_side +100644 3b22327e48122187af12db46027f17526c8e9caf 0 t/t4013/diff.show_--stat_side +100644 4c4066ae48e213b6a0f4bf51226c4322ac9348c4 0 t/t4013/diff.show_initial +100644 9e6e1f27105ca50262e5eb3f2ff132b46c12fe45 0 t/t4013/diff.show_master +100644 530a073b19d75e37aeb241200b6b306e6803ca09 0 t/t4013/diff.show_side +100644 6a467cccc190449049b7baed2dde0a2f9027e663 0 t/t4013/diff.whatchanged_--patch-with-stat_--summary_master_--_dir_ +100644 1e1bbe19638eeeffb4e656239545ea91fda3dbf2 0 t/t4013/diff.whatchanged_--patch-with-stat_master +100644 13789f169b6803ba71680470197c50b51795e4e4 0 t/t4013/diff.whatchanged_--patch-with-stat_master_--_dir_ +100644 5facf2543db0135ceb3aafdc5ffe0395b429f44c 0 t/t4013/diff.whatchanged_--root_--cc_--patch-with-stat_--summary_master +100644 02911535870b012720c9ae095499c61e6e242c7e 0 t/t4013/diff.whatchanged_--root_--patch-with-stat_--summary_master +100644 9b0349cd555eb17836b8c056d7aae8cf1eabe537 0 t/t4013/diff.whatchanged_--root_--patch-with-stat_master +100644 10f6767e498b0d5bdadd73067e4ef2dd5f028e89 0 t/t4013/diff.whatchanged_--root_-c_--patch-with-stat_--summary_master +100644 ebf1f0661e07bd06098d1609a5a22b8e9bbae436 0 t/t4013/diff.whatchanged_--root_-p_master +100644 a405cb6138857d3a1bc1b590aa55565c34770e4c 0 t/t4013/diff.whatchanged_--root_master +100644 f39da84822845984e0f431cf84e71fc48853a3c8 0 t/t4013/diff.whatchanged_-SF_-p_master +100644 0499321d0ebf57fc2d583afd46ce7813a1ba9fde 0 t/t4013/diff.whatchanged_-SF_master +100644 f18d43209c0a90d2d6fd474e849690f1b2120cfe 0 t/t4013/diff.whatchanged_-p_master +100644 cd3bcc2c7269c17ff25504c8b7ca02b55ba8d8ed 0 t/t4013/diff.whatchanged_master +100755 7fe853c20d1111e40371a3796d82bb8485f5ebcf 0 t/t4014-format-patch.sh +100755 a27fccc8dce431169ce41f7137fb75f44149719c 0 t/t4015-diff-whitespace.sh +100755 f07035ab7ec72557be7a0cba9ea286bcbaa79da9 0 t/t4016-diff-quote.sh +100755 60dd2014d5ae5d5e9e168b8b60278d90ef93cc53 0 t/t4017-diff-retval.sh +100755 e747e842272df5935f863f78ccfc3b311f64228b 0 t/t4017-quiet.sh +100755 833d6cbcfc063f336d97689ae4e547cf5e956b69 0 t/t4018-diff-funcname.sh +100755 0d9cbb62615c0d94da784f63907989988b0e8151 0 t/t4019-diff-wserror.sh +100755 637b4e19d52e81cf1472a4ed9dcfb0c9ff00da2b 0 t/t4020-diff-external.sh +100644 db2f89090c1c4de05e4f82ea39ea118fccfd48dd 0 t/t4020/diff.NUL +100755 43d64bbd826049c5a0a8cf365ed5cb3f4489752c 0 t/t4021-format-patch-numbered.sh +100755 ba43f185494630c50fc2a168df8dcd45c0b2421b 0 t/t4021-format-patch-signer-mime.sh +100755 bf996fc414d3b5ea16488a8b274973a8347b29cb 0 t/t4022-diff-rewrite.sh +100755 4dbfc6e8b751a6c93b1f9dfee8ce649235c98c93 0 t/t4023-diff-rename-typechange.sh +100755 c4d733f5db6a4d390762505b770954cdbf6cc82f 0 t/t4024-diff-optimize-common.sh +100755 7a3dbc1ea22fd19a54da8949abc368c112377b19 0 t/t4025-hunk-header.sh +100755 b61e5169f4e9e8d9f87b9ea16e71dfcf1fb9f340 0 t/t4026-color.sh +100755 ba6679c6e4032bb12e4206226f95770946ece8cc 0 t/t4027-diff-submodule.sh +100755 204ba673cb58f905f2f35ff5b83294b2a2943f48 0 t/t4028-format-patch-mime-headers.sh +100755 e0c67740a5ef85aaa3edc9a4514da72c92ce30ec 0 t/t4100-apply-stat.sh +100644 540e64db85575e10fe02b3b85af6a353999aab8f 0 t/t4100/t-apply-1.expect +100644 90ab54f0f586c87ace077be87fba396c8f2781a0 0 t/t4100/t-apply-1.patch +100644 d1e6459749fe3dd4635c9136ccbb148a85405676 0 t/t4100/t-apply-2.expect +100644 f5c7d601fc955b15d15012a5b49df83364b6ebf4 0 t/t4100/t-apply-2.patch +100644 912a552a7a67be283c963da84bf044fa779fe633 0 t/t4100/t-apply-3.expect +100644 90cdbaa5bb62a4adfa0a5eb3f6fe223b9de50e7b 0 t/t4100/t-apply-3.patch +100644 1ec028b3d05d79fab29d2ac61027c8ef00bf8401 0 t/t4100/t-apply-4.expect +100644 4a56ab5cf416e2144b5dbdbe06d10b51255fabe2 0 t/t4100/t-apply-4.patch +100644 b387df15d4fc81574ac18f41174205c86a6ad503 0 t/t4100/t-apply-5.expect +100644 5f6ddc105950eac20bcacb7987fabff015320ee3 0 t/t4100/t-apply-5.patch +100644 1c343d459eb8fc129f53d3a13f0e0ffa79058139 0 t/t4100/t-apply-6.expect +100644 a72729a712038dc64f55d154eb9a94713e3269c9 0 t/t4100/t-apply-6.patch +100644 1283164d9909164c2428bc1a08cbff1d819fe71c 0 t/t4100/t-apply-7.expect +100644 07c6589e74fa5afbff9bdfd8d7b7b41f873a005b 0 t/t4100/t-apply-7.patch +100644 eef7f2e65cc3e2192935b9bde3ea001244b6db18 0 t/t4100/t-apply-8.expect +100644 5ca13e65949047b5a1e8170422519cd69418da88 0 t/t4100/t-apply-8.patch +100644 eef7f2e65cc3e2192935b9bde3ea001244b6db18 0 t/t4100/t-apply-9.expect +100644 875d57d567e2b807587a7e4d2a9bb7771225e28c 0 t/t4100/t-apply-9.patch +100755 da8abcf36418dbd2e9d8ec85871c245991f96fda 0 t/t4101-apply-nonl.sh +100644 1010a88f4727373c20e7ab46515a79b9d3cd9675 0 t/t4101/diff.0-1 +100644 36460a243ac10e256df270cec10a7498a0a32009 0 t/t4101/diff.0-2 +100644 b281c43e5b5f4926e365cbd168e43420e8a4a63a 0 t/t4101/diff.0-3 +100644 f0a2e92770870d78d32bef7fe2ed63ad4ca105de 0 t/t4101/diff.1-0 +100644 2a440a5ce2adae53a23363a3cd3b6af5ff915fd0 0 t/t4101/diff.1-2 +100644 61aff975b69f49430ccb0b6ebd14193fd9f78b4e 0 t/t4101/diff.1-3 +100644 c2e71ee344d032ee38bf325099ed6386f180f287 0 t/t4101/diff.2-0 +100644 a66d9fd3a137b22edf5a49cf811970fc85c985d9 0 t/t4101/diff.2-1 +100644 5633c831de0bb2d5d482acc89c32bb3cb39d02d7 0 t/t4101/diff.2-3 +100644 10b1a41edf734aef77feb4a5f40cf358a8f48db3 0 t/t4101/diff.3-0 +100644 c799c60fb9d460ff24160082a9c1346c0751dd4b 0 t/t4101/diff.3-1 +100644 f8d1ba6dc24669ff19530e0d3ed064db2c8e7077 0 t/t4101/diff.3-2 +100755 d42abff1ad59343fa1c84bded9a82c3212370da0 0 t/t4102-apply-rename.sh +100755 7da0b4bb8bfa96765b9f6eaa1693e2e24e82d335 0 t/t4103-apply-binary.sh +100755 e7e2913de745cc9f7639103757933f6238fdd564 0 t/t4104-apply-boundary.sh +100755 3266e394003958b62509b7bfe6652abd03fdfcb7 0 t/t4105-apply-fuzz.sh +100755 ac58083fe224100987800e9b5ee3e388d9b4d97c 0 t/t4109-apply-multifrag.sh +100644 1db5ff10501497459d07e227f02764576a6010e1 0 t/t4109/expect-1 +100644 bc52924112ba857784169157d3f650eb35a931ba 0 t/t4109/expect-2 +100644 cd2a475feb2280a24b05870c00f0693dd1de605b 0 t/t4109/expect-3 +100644 1d411fc3ccebe33ee086cfeaea7cea1beb041a6a 0 t/t4109/patch1.patch +100644 8c6b06d536a06d786f0752ec2aa2a7fae22c8926 0 t/t4109/patch2.patch +100644 d696c55a752ac61b86691192d46da2566e299830 0 t/t4109/patch3.patch +100644 4b085909b160a093e9edb4f91de87f7637f218b5 0 t/t4109/patch4.patch +100755 09f58112e0229a41ea2a5d2ea6e8c23d2523298d 0 t/t4110-apply-scan.sh +100644 87cc493ec8a0f6f042a5df3c302433c6e45d8dd3 0 t/t4110/expect +100644 56139080dc157ab9e58dec01399c40362a9e710e 0 t/t4110/patch1.patch +100644 04974247ec927d9b25bf0b30c372e4669321dad0 0 t/t4110/patch2.patch +100644 26bd4427f808bb1d0929833f2784e384e35ab961 0 t/t4110/patch3.patch +100644 9ffb9c2d7ecd2e87eb3a92ed99be90beba3e16be 0 t/t4110/patch4.patch +100644 c5ac6914f987d3a41266dca735d872e4c131d02c 0 t/t4110/patch5.patch +100755 f9ad183758c28ff648890d1bd4bbd599562cd795 0 t/t4112-apply-renames.sh +100755 66fa51591eb7ee8f102fd86e30e54af2da3ea310 0 t/t4113-apply-ending.sh +100755 55334927abb33864a55f8ff49fd0c0c94a3c1769 0 t/t4114-apply-typechange.sh +100755 9ace578f17a07aafc050ccaf935aef8a4a3cab4e 0 t/t4115-apply-symlink.sh +100755 2298ece8019d79ef718ef658bdac74493d265b92 0 t/t4116-apply-reverse.sh +100755 e9ccd161ee96a5bdbb4bf77de406ea51dacfb5de 0 t/t4117-apply-reject.sh +100755 f92e259cc6f251ec6f89edee3fc16720f264d82f 0 t/t4118-apply-empty-context.sh +100755 3c73a783a7e908070308fb1f972f6b5d152e12a4 0 t/t4119-apply-config.sh +100755 83d4ba679850c2ae2548bcfcce3f22227fcde8c7 0 t/t4120-apply-popt.sh +100755 aff551a1d787477eb2db34d96217f66ca03c435d 0 t/t4121-apply-diffs.sh +100755 841773f75fc085d07836b39b3775f49bde5d8d19 0 t/t4122-apply-symlink-inside.sh +100755 984157f03b9744aa491c888fab9e6aef95dfdc6b 0 t/t4123-apply-shrink.sh +100755 85f3da2b98a881647837323e3af0378ce59a9db5 0 t/t4124-apply-ws-rule.sh +100755 3b471b641ba2d3274dd1ab89948485ff8ce4dfdb 0 t/t4125-apply-ws-fuzz.sh +100755 ceb6a79fe0c8ca5b26a9e148215556f2aa344eb9 0 t/t4126-apply-empty.sh +100755 1f859dd908cb298bf89a13822e8fc19882060689 0 t/t4127-apply-same-fn.sh +100755 2dd0c75f964b690977e40a3a8235cc324dc6826e 0 t/t4128-apply-root.sh +100755 6e6aaf59364456e21bb1deda960edb5295a71131 0 t/t4150-am.sh +100755 7d86cdff64522f588a3d3e781cf2b272087cfd88 0 t/t4151-am-abort.sh +100755 b68ab11f2915789cd04ac6bd43363aeab2079198 0 t/t4200-rerere.sh +100755 405b97119175a1c0fa75a9db30c6b1ab076cc44e 0 t/t4201-shortlog.sh +100755 4c8af45f834d034529c2a627768a0a3e6f1aac8d 0 t/t4202-log.sh +100755 e395ff4e341bacea21cc5cd909304b7bb4fcb044 0 t/t5000-tar-tree.sh +100755 e9f3e72c7ee5584d956d46126956c641a7d53905 0 t/t5100-mailinfo.sh +100644 f5892c9da73eae30d7629ca5e7f0ba6a4c621c73 0 t/t5100/0010 +100644 8c052777e0d216e84bb8464b1ceaff1bc7721154 0 t/t5100/info0001 +100644 49bb0fec85323c8c19182bc2a50ceb64ce8307fb 0 t/t5100/info0002 +100644 bd0d1221aa34973159390642efc67773a6bfef17 0 t/t5100/info0003 +100644 616c3092a28223d9aa1b3c68aa0bd49fc394dd85 0 t/t5100/info0004 +100644 46a46fc77283fe31bd583444f76ae2cb7085a35a 0 t/t5100/info0005 +100644 8c052777e0d216e84bb8464b1ceaff1bc7721154 0 t/t5100/info0006 +100644 49bb0fec85323c8c19182bc2a50ceb64ce8307fb 0 t/t5100/info0007 +100644 e8a295138317864b814b24af63ad3cf9c64cf79a 0 t/t5100/info0008 +100644 2a66321c8032cc0ee0cba25486e57f790d1f6ce8 0 t/t5100/info0009 +100644 1791241e46dc44994c58b365e339c093704a6006 0 t/t5100/info0010 +100644 b275a9a9b21c762814ed09c0d3a6eb103aa59370 0 t/t5100/msg0001 +100644 e2546ec7332b6b0483f4951906a40436da6383e0 0 t/t5100/msg0002 +100644 1ac68101b135f4aaf6dacd4bcc0b7586a29d6584 0 t/t5100/msg0003 +100644 6f8ba3b8e0e504d0aa343e45fffc044a211cc7ca 0 t/t5100/msg0004 +100644 dd94cd7b9f52247fd33a891e4fdd9b715c7f59b7 0 t/t5100/msg0005 +100644 b275a9a9b21c762814ed09c0d3a6eb103aa59370 0 t/t5100/msg0006 +100644 71b23c0236bddbedabfbdb982e4e73c5e266da28 0 t/t5100/msg0007 +100644 a80ecb97ef9dabb6d25d24d42212dabd5eab6249 0 t/t5100/msg0008 +100644 9ffe1314891f0998bf90f6c6b1e02c56c405e2f2 0 t/t5100/msg0009 +100644 a96c230092340037ef1c99ae91f24096eceacf44 0 t/t5100/msg0010 +100644 d7d680f631b14ea75adf34ba5052043be311e72f 0 t/t5100/nul-b64.expect +100644 16540d961f8e6eb791300e085d2d6e82e01bd2c4 0 t/t5100/nul-b64.in +100644 3d40691787b855cc0133514a19052492eb853d21 0 t/t5100/nul-plain +100644 8ce155167d51de1868fdd2395c312c46b9cc2c63 0 t/t5100/patch0001 +100644 8ce155167d51de1868fdd2395c312c46b9cc2c63 0 t/t5100/patch0002 +100644 8ce155167d51de1868fdd2395c312c46b9cc2c63 0 t/t5100/patch0003 +100644 196458e44e1974188cc1d1523a92c2bbef1ed506 0 t/t5100/patch0004 +100644 7d24b24af83c861a1dc615c19cbaa392fdd69dec 0 t/t5100/patch0005 +100644 8ce155167d51de1868fdd2395c312c46b9cc2c63 0 t/t5100/patch0006 +100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 t/t5100/patch0007 +100644 e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 0 t/t5100/patch0008 +100644 65615c34af6ea70a53102e6bbef4bd60344cbf1c 0 t/t5100/patch0009 +100644 f055481d567212b7b43e7ca8251351b3f83b143b 0 t/t5100/patch0010 +100644 aba57f922b33b6ab708afbbf82c7e56f6e37bb8d 0 t/t5100/sample.mbox +100755 645583f9d729cb04ea7bd9638b0c49c48128822e 0 t/t5300-pack-object.sh +100755 073ac0c6f9dd3d06474b1b81c8c7b622dcfee663 0 t/t5301-sliding-window.sh +100755 0639772ac4e1e2c6563e793b16c2c10faf06758a 0 t/t5302-pack-index.sh +100755 31b20b21d23c2066fd124bf6a33dbdc689930170 0 t/t5303-pack-corruption-resilience.sh +100755 9fd9d0700033027921c90290cedc0a31d71c7733 0 t/t5304-prune.sh +100755 fb471a08c698b431cd2440e9d4f0e77e2fef6b08 0 t/t5305-include-tag.sh +100755 68c2ae688c2b7ff96ec927622f92fd512e7beefe 0 t/t5400-send-pack.sh +100755 ee769d6695ee91120671c485924d804f14c80424 0 t/t5401-update-hooks.sh +100755 1394047a8dc3e87476e223db42936d59845f803b 0 t/t5402-post-merge-hook.sh +100755 823239a251f9ba9607649382d595db1b6cc6dcb2 0 t/t5403-post-checkout-hook.sh +100755 c24003565d635722f07333bb662c8e102d577c9e 0 t/t5404-tracking-branches.sh +100755 86abc6227105e27fdb9ad99e34193efb90a6242f 0 t/t5405-send-pack-rewind.sh +100755 59e80a5ea253607bf83ac4eed670744df950eb81 0 t/t5406-remote-rejects.sh +100755 362cf7e928090fb3752936317f78a4d128810127 0 t/t5500-fetch-pack.sh +100755 16eadd6b68664884836976aafb6dcbb582603c09 0 t/t5502-quickfetch.sh +100755 4074e23ffa2c7a93fdbd4a367e273118224b9038 0 t/t5503-tagfollow.sh +100755 be9ee9326fc4590dcc875e31b6cf64b800451bc5 0 t/t5505-remote.sh +100755 13d1d826c20293c26c739c70c0a36ed48bbb41d1 0 t/t5510-fetch.sh +100755 22ba380034775e7584a33ca606294af34f568443 0 t/t5511-refspec.sh +100755 1dd8eed5bb3cb0f320a8f0780452e52fa7d8da16 0 t/t5512-ls-remote.sh +100755 9e7486274b3f0079cb993acbd03e90afc5638e38 0 t/t5513-fetch-track.sh +100755 8becbc3f38fde02371ebbcd9a39a320a1c00c290 0 t/t5515-fetch-merge-logic.sh +100644 2e0414f6c3d006ac6f06b884a13397c67f6b7df1 0 t/t5515/fetch.br-branches-default +100644 ca2cc1d1b44e3edc8cd42e2e77d0f85658a52195 0 t/t5515/fetch.br-branches-default-merge +100644 7d947cd80f9cf656024206f1ea31da0d9f10f493 0 t/t5515/fetch.br-branches-default-merge_branches-default +100644 ec39c54b7e242ddbeec76f55b98f555d562aa271 0 t/t5515/fetch.br-branches-default-octopus +100644 6bf42e24b67b526bac49e3cdb287e32513f4a6c4 0 t/t5515/fetch.br-branches-default-octopus_branches-default +100644 4a2bf3c95ca474417d1dd54d1ac0bcc02bb5f402 0 t/t5515/fetch.br-branches-default_branches-default +100644 12ac8d20fba1c8a9402b92aa71e2e6797101a042 0 t/t5515/fetch.br-branches-one +100644 b4b3b35ce0e2f46a16b015a74b771eb90ed3ebad 0 t/t5515/fetch.br-branches-one-merge +100644 2ecef384eb7d823104581bfe2b4bd240b449e5df 0 t/t5515/fetch.br-branches-one-merge_branches-one +100644 96e3029416b46ab4192d3e4aaa285a02489e4054 0 t/t5515/fetch.br-branches-one-octopus +100644 55e0bad621cde0c93e6a6fb92dc259c61986aba5 0 t/t5515/fetch.br-branches-one-octopus_branches-one +100644 281fa09d481a2d04788d5c1b0a67b8f569203ebc 0 t/t5515/fetch.br-branches-one_branches-one +100644 e2fa9c8654647e46baa89d24501b050209aefdc1 0 t/t5515/fetch.br-config-explicit +100644 ec1a7231aa7875df2cebd32411bad4861c233dcd 0 t/t5515/fetch.br-config-explicit-merge +100644 54f689151ff1006561309f6f7ca5e3523f8626c4 0 t/t5515/fetch.br-config-explicit-merge_config-explicit +100644 7011dfc18140aade896592c853bec85567d4ccc8 0 t/t5515/fetch.br-config-explicit-octopus +100644 bdad51f87163b51c378aaa1ca9bed8fe4a461af1 0 t/t5515/fetch.br-config-explicit-octopus_config-explicit +100644 1b237dde6e03b9bb1f4b9ad0b5ab75ae31127b57 0 t/t5515/fetch.br-config-explicit_config-explicit +100644 e75ec2f72b4420cf27bcb959ab83518d93e115b1 0 t/t5515/fetch.br-config-glob +100644 ce8f739a0d5f53d24d1408e0e39719c0411e3c0d 0 t/t5515/fetch.br-config-glob-merge +100644 5817bed8f88fcc11b9d5e67ce0863249339eeb2c 0 t/t5515/fetch.br-config-glob-merge_config-glob +100644 938e532db25e684599b39d1c862680a1caf8ea23 0 t/t5515/fetch.br-config-glob-octopus +100644 c9225bf6ff060118ae85b5c666085b3a558db16e 0 t/t5515/fetch.br-config-glob-octopus_config-glob +100644 a6c20f92ce6e708f915b285310a94b7080eab1e3 0 t/t5515/fetch.br-config-glob_config-glob +100644 83534d2ec85e30dee5c32b8d385dd717cf4930a2 0 t/t5515/fetch.br-remote-explicit +100644 a9064dd65a0e569cc3e7ce5ae2368313f6bfa7ec 0 t/t5515/fetch.br-remote-explicit-merge +100644 732a37e4d358f0239687770b28c109051c438070 0 t/t5515/fetch.br-remote-explicit-merge_remote-explicit +100644 ecf020d9298e7a031833e9986f2deb787712cb89 0 t/t5515/fetch.br-remote-explicit-octopus +100644 af7753101140d43e2a592ec37b88d57d53d45bde 0 t/t5515/fetch.br-remote-explicit-octopus_remote-explicit +100644 51fae567c8765fc6f447d7ee93a9796e022663a5 0 t/t5515/fetch.br-remote-explicit_remote-explicit +100644 94e6ad31e301a87b52160f2287b54051e27b4e18 0 t/t5515/fetch.br-remote-glob +100644 09362e25af564342ccb5ed9507caa103676aedf6 0 t/t5515/fetch.br-remote-glob-merge +100644 e2eabec62e12b29be2b8cd0c8e6d0cc9ad042f4d 0 t/t5515/fetch.br-remote-glob-merge_remote-glob +100644 b08e0461954dcedc90df43c03302e3d4257c6f4b 0 t/t5515/fetch.br-remote-glob-octopus +100644 d4d547c84733f0faacc85c88c7b7fa138933e4a6 0 t/t5515/fetch.br-remote-glob-octopus_remote-glob +100644 646dbc877008edae3644ceef92fd5bed990eb784 0 t/t5515/fetch.br-remote-glob_remote-glob +100644 65ce6d99e2631fd777de10e11b3a58db5859c29a 0 t/t5515/fetch.br-unconfig +100644 8258c808689d883b97867b3d07ca89e08146de12 0 t/t5515/fetch.br-unconfig_--tags_.._.git +100644 284bb1fb613cafff208741069aea2d4041ec07cd 0 t/t5515/fetch.br-unconfig_.._.git +100644 11eb5a6ef22d52b794dd7a0a3e29d2ff515791c2 0 t/t5515/fetch.br-unconfig_.._.git_one +100644 f02bab2fb4a1e07c6128fb899bf42183d1f0965e 0 t/t5515/fetch.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file +100644 3f1be224b8b46ba18bb45ffdbc155d9bd312376c 0 t/t5515/fetch.br-unconfig_.._.git_one_two +100644 85de41109ecfb6fd4ac3a1b3b15489b83506a63c 0 t/t5515/fetch.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file +100644 0da2337f1b95b2011524b3d047a291747bd80305 0 t/t5515/fetch.br-unconfig_.._.git_tag_tag-one_tag_tag-three +100644 fc7041eefc2150417abc504e25f9d82049b3102e 0 t/t5515/fetch.br-unconfig_branches-default +100644 e94cde745b58aeb360e2db064466260f2362cf87 0 t/t5515/fetch.br-unconfig_branches-one +100644 01a283e70d9d10373c363d1fe15b39949bba8d89 0 t/t5515/fetch.br-unconfig_config-explicit +100644 3a556c5e964785046cc43e9c13351818f436b857 0 t/t5515/fetch.br-unconfig_config-glob +100644 db216dfa562e894999c565d44d43abb6c6dd562e 0 t/t5515/fetch.br-unconfig_remote-explicit +100644 aee65c204d1b1468adaee9d41dc5c0a47a3ae999 0 t/t5515/fetch.br-unconfig_remote-glob +100644 950fd078db7ccbe27825183cb0236a0dcc45139a 0 t/t5515/fetch.master +100644 0e59950c7b5e18521b59a17d3aaddc3a314a6f9c 0 t/t5515/fetch.master_--tags_.._.git +100644 66d1aaddae6cb34d83bbd0e728fbe89fd26227b1 0 t/t5515/fetch.master_.._.git +100644 35deddbd2ca6c28c7a50dfc28c3da09b79b7b6a6 0 t/t5515/fetch.master_.._.git_one +100644 82868524ca40041b243e146064f4451d6899f3c4 0 t/t5515/fetch.master_.._.git_one_tag_tag-one_tag_tag-three-file +100644 35ec5782c8a6076a76cf314fb5021da8a641e782 0 t/t5515/fetch.master_.._.git_one_two +100644 2e133eff296d291045e86fe6a8cba958106b9aae 0 t/t5515/fetch.master_.._.git_tag_tag-one-tree_tag_tag-three-file +100644 92b18b40ccc883bede4d2067aa4bf7a529d2f059 0 t/t5515/fetch.master_.._.git_tag_tag-one_tag_tag-three +100644 603d6d23312b6a58d95a685803d8b19f0e0ac4e2 0 t/t5515/fetch.master_branches-default +100644 fe9bb0b7982951ccf85934e42ff7c9620e2312b4 0 t/t5515/fetch.master_branches-one +100644 4be97c75752571d46aef0283f164abea025a1be8 0 t/t5515/fetch.master_config-explicit +100644 cb0726ff8d7ea9e801497b564b680710c2a273af 0 t/t5515/fetch.master_config-glob +100644 44a1ca84296079356eabc3fd37d04529a3492409 0 t/t5515/fetch.master_remote-explicit +100644 724e8db0a533248cab6784696c90db02ca1435f3 0 t/t5515/fetch.master_remote-glob +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default-merge +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default-merge_branches-default +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default-octopus +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default-octopus_branches-default +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-branches-default_branches-default +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one-merge +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one-merge_branches-one +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one-octopus +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one-octopus_branches-one +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-branches-one_branches-one +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit-merge +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit-merge_config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit-octopus +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit-octopus_config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-explicit_config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob-merge +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob-merge_config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob-octopus +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob-octopus_config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-config-glob_config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit-merge +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit-merge_remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit-octopus +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit-octopus_remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-explicit_remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob-merge +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob-merge_remote-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob-octopus +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob-octopus_remote-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-remote-glob_remote-glob +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.br-unconfig +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.br-unconfig_--tags_.._.git +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.br-unconfig_.._.git +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.br-unconfig_.._.git_one +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.br-unconfig_.._.git_one_tag_tag-one_tag_tag-three-file +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.br-unconfig_.._.git_one_two +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.br-unconfig_.._.git_tag_tag-one-tree_tag_tag-three-file +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.br-unconfig_.._.git_tag_tag-one_tag_tag-three +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.br-unconfig_branches-default +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.br-unconfig_branches-one +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-unconfig_config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-unconfig_config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-unconfig_remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.br-unconfig_remote-glob +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.master +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.master_--tags_.._.git +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.master_.._.git +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.master_.._.git_one +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.master_.._.git_one_tag_tag-one_tag_tag-three-file +100644 70962eaac152f7063e965da7c6a61abee410e0bc 0 t/t5515/refs.master_.._.git_one_two +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.master_.._.git_tag_tag-one-tree_tag_tag-three-file +100644 13e4ad2e4602154808a384fe298497b220ac9d6a 0 t/t5515/refs.master_.._.git_tag_tag-one_tag_tag-three +100644 21917c1e5dba7133d451403984f754f445657908 0 t/t5515/refs.master_branches-default +100644 8a705a5df252f6f9d4cd32b1557a221ca4f7dc6f 0 t/t5515/refs.master_branches-one +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.master_config-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.master_config-glob +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.master_remote-explicit +100644 9bbbfd9fc5332911f35826763b821d2eeb758d6f 0 t/t5515/refs.master_remote-glob +100755 f0030ad00e4a6478fcb3ccfc503e576bd58003bd 0 t/t5516-fetch-push.sh +100755 ea49dedbf8867694d83cd550c8212ff107361920 0 t/t5517-push-mirror.sh +100755 c6bc65faa06adeaced0733064fb09eb82add585e 0 t/t5518-fetch-exit-status.sh +100755 997b2db827c4f37512c6b5d2f861e12105e2a32d 0 t/t5520-pull.sh +100755 1a15817cd5f8e838812723ad14dbec59a108680c 0 t/t5530-upload-pack-error.sh +100755 f8c17cd96cc86ca8f2db2ff51467f712d65f8956 0 t/t5540-http-push.sh +100755 3c013e2b6aa5c659c80134baf43c99e0d89e2e38 0 t/t5600-clone-fail-cleanup.sh +100755 d785b3df78e8507d81ffa03ff694846791edfc87 0 t/t5601-clone.sh +100755 8367a6845f6ea3cdbc2f4f0e096144975fa3aef2 0 t/t5602-clone-remote-exec.sh +100755 1c109160690d273451f7a089be42e45f36a3b5bb 0 t/t5700-clone-reference.sh +100755 8dfaaa456e115e85e36c438bb998d8053534104e 0 t/t5701-clone-local.sh +100755 328e4d9a339101d04bb22e441a8955f6c2e1f260 0 t/t5702-clone-options.sh +100755 ef7127c1b3943a494692ac8027ec321608a31b9c 0 t/t5710-info-alternate.sh +100755 f55627b641682e72d58a2282639ca589b38fa744 0 t/t6000lib.sh +100755 b2131cdacd93e0b62f4ef8fdc62b6a81c6aef6fc 0 t/t6001-rev-list-graft.sh +100755 8f5de097ecd703ae5f6f889ecb735f7277f361be 0 t/t6002-rev-list-bisect.sh +100755 5daa0be8cc856bff513905bc6583854e0b5ae53a 0 t/t6003-rev-list-topo-order.sh +100755 5dabf1c5e354c28cc593bd0ea8e4b0d5f0d56d67 0 t/t6004-rev-list-path-optim.sh +100755 0b64822bf621dee5c9544f76013c0342412eaee6 0 t/t6005-rev-list-count.sh +100755 9176484db2f78122f71c0f11889e01382effcfb9 0 t/t6006-rev-list-format.sh +100755 4b8611ce2092f9062aeaeb62ce19a9121d5be537 0 t/t6007-rev-list-cherry-pick-file.sh +100755 c4af9ca0a7edf6230dc6ca8ec10848545971fce7 0 t/t6008-rev-list-submodule.sh +100755 c8a96a9a994badde602c8bf7a7decda048a00525 0 t/t6009-rev-list-parent.sh +100755 b6e57b2426728cce308a57315247cd2a66cabf4a 0 t/t6010-merge-base.sh +100755 e51eb41f4b9575d2b51d8d4d255ff5ab7a0889ad 0 t/t6011-rev-list-with-bad-commit.sh +100755 a19d49de28c457d1a5726400d25c1f731506a05f 0 t/t6020-merge-df.sh +100755 331b9b07d4eedb07377de605ebb87691427b7bb4 0 t/t6021-merge-criss-cross.sh +100755 e3f7ae8120aa2a46b25dd3830597cb863a5f5e20 0 t/t6022-merge-rename.sh +100755 f674c48cab3e80d63b5a5831c667b8e08b542905 0 t/t6023-merge-file.sh +100755 65be95fbaaef4861189a7fc6b3a25bb6d7feb0a7 0 t/t6023-merge-rename-nocruft.sh +100755 802d0d06ebddec9db6e3a109e689b3974f1e0ff1 0 t/t6024-recursive-merge.sh +100755 fc58456a11eef7ecb4cf60d37a9e9d5cbe13f970 0 t/t6025-merge-symlinks.sh +100755 56fc34176859b81137b4d88af90398b9a74a18f7 0 t/t6026-merge-attr.sh +100755 92ca1f0f8ccabe6f01159ea3e4a73683387ec4a3 0 t/t6027-merge-binary.sh +100755 f8f3e3ff2c00df468f5703a4e0ac31f52e42e06d 0 t/t6028-merge-up-to-date.sh +100755 5bbfa44e8d9ee3eebb18eb07e93380c802741a18 0 t/t6029-merge-subtree.sh +100755 244fda62a5cd34d778cf0789961654eaa37fe589 0 t/t6030-bisect-porcelain.sh +100755 8073e0c3efb2ac01e4a81e722fc357bcab13f5d4 0 t/t6031-merge-recursive.sh +100755 eac5ebac24a0174fa20625a19835861573147a26 0 t/t6032-merge-large-rename.sh +100755 75d9602de4d4238b4182956127540525f711d33f 0 t/t6033-merge-crlf.sh +100755 aac212e936331db9a596fda0c4a9c0382e123797 0 t/t6040-tracking-info.sh +100755 919552a2fc5544c130268befca322a6e6a8081c3 0 t/t6101-rev-parse-parents.sh +100755 2fb672c3b43a9efe4cb9c85465f6b33f23724e48 0 t/t6120-describe.sh +100755 bc74349416d858834c43f6c648daa95c8b9f3a7a 0 t/t6200-fmt-merge-msg.sh +100755 a3c8941c726d77fd993a3cfcd7fde4e9aa43da74 0 t/t6300-for-each-ref.sh +100755 910a28c7e29b6dd8bd30d1ccb156681b44e51bca 0 t/t7001-mv.sh +100755 c8b4f65f380f3941c75bd6ed52975777d2b28d67 0 t/t7002-grep.sh +100755 a0ab096c8fdee153a89a1428f85c9bf107badada 0 t/t7003-filter-branch.sh +100755 bc7ce2cbbb712f890245688da03be96146a1d9ed 0 t/t7004-tag.sh +100644 83855fa4e1c6c37afe550c17afa1e7971042ded5 0 t/t7004/pubring.gpg +100644 8fed1339ed0a744e5663f4a5e6b6ac9bae3d8524 0 t/t7004/random_seed +100644 d831cd9eb3eee613d3c0e1a71093ae01ea7347e3 0 t/t7004/secring.gpg +100644 abace962b8bf84be688a6f27e4ebd0ee7052f210 0 t/t7004/trustdb.gpg +100755 2d919d69ef110408b820c76185d6b8da63ea183e 0 t/t7005-editor.sh +100755 d8a7c798525728ddc8fc5fa9bd8335d8d1f0a710 0 t/t7010-setup.sh +100755 0d9874bfd7082f9ef16c1f6b3ff8a848a19d8937 0 t/t7101-reset.sh +100755 29f5678b4c93485ad492fa865a5da58a3cc05b7c 0 t/t7102-reset.sh +100755 cdecebe456c7a9cf30465b112a24ce7bcf76f344 0 t/t7103-reset-bare.sh +100755 f136ee7bb5300966c0c3c9d2250dc81763db9feb 0 t/t7104-reset.sh +100755 9ad5d635a2881c920fff8e524aea0ed931f68e6c 0 t/t7201-co.sh +100755 2b51c0d7d8ab727a5fb0be8338938f1d3b2eb6a3 0 t/t7300-clean.sh +100755 cbc0c34ce2487959ef0e8f89f7c2a5d4a68be826 0 t/t7400-submodule-basic.sh +100755 bf12dbdeef6e307850a91eb6be5ebe537b2de0c8 0 t/t7401-submodule-summary.sh +100755 f919c8d34de41b2ec3fe08c217dd2c6276cf8472 0 t/t7402-submodule-rebase.sh +100755 d89f91a6fb7fa12d41cc4a346829bff7cbd3e76b 0 t/t7500-commit.sh +100755 a72e65c8910f71b8ea562ef5ed641c54fbd89a8e 0 t/t7500/add-comments +100755 2fa3d86a108d1fc410d82173809066db0b32b062 0 t/t7500/add-content +100755 e1d856af6d8b59fed20e3beb272006612ba4e8a5 0 t/t7500/add-signed-off +100755 0edd9ddf73b7053c21595ce1ac1dd157c77d1bca 0 t/t7501-commit.sh +100755 f1112639b698faca38b2c8fc743e422d14dc15f6 0 t/t7502-commit.sh +100755 38a48b57c70a888838cfa114be843e1d4aea00d8 0 t/t7502-status.sh +100755 b06909599564a1c8afa027b0f9c71ef6bb61d6e4 0 t/t7503-pre-commit-hook.sh +100755 47680e6df41c2bc14f23514b010a8aefb3fedcd7 0 t/t7504-commit-msg-hook.sh +100755 cd6c7c834218fd4c46c49396b79da1ddeef42772 0 t/t7505-prepare-commit-msg-hook.sh +100755 a75130cdbb55be157c915f4fc1397227a78441ec 0 t/t7506-status-submodule.sh +100755 5eeb6c2b2708d582a6e86cd2e06e2b00b7b7b391 0 t/t7600-merge.sh +100755 55aa6b5f2716255b2b5aa74f1cac9d285de6d6a8 0 t/t7601-merge-pull-config.sh +100755 fcb8285746420ed721713d9c8e527d23cafb05cf 0 t/t7602-merge-octopus-many.sh +100755 17b19dc11f2b1a5d26a16f447733880f3cf30d26 0 t/t7603-merge-reduce-heads.sh +100755 6081677d234f1fcb88b6b9160f707ebf0274f38a 0 t/t7604-merge-custom-message.sh +100755 ee21a107fd99e35b9d6325a040b7549b7a6c2502 0 t/t7605-merge-resolve.sh +100755 9285071c473dcfe7d37845d01ba20226b5ab585d 0 t/t7610-mergetool.sh +100755 31c340fd389ed2688bb94a29acbf892be6f0c564 0 t/t7701-repack-unpack-unreachable.sh +100755 eabec2e06e2f97fc1790cd4ce30a80e402d4a205 0 t/t8001-annotate.sh +100755 92ece30fa94784bdad8ae50fc370487e60bbcb5c 0 t/t8002-blame.sh +100755 966bb0a61a89ed63dec085338d3c45f766a7f777 0 t/t8003-blame.sh +100755 ba19ac127e630c01e009fa6eda1fac0086d7184d 0 t/t8004-blame.sh +100755 1c857cf4ab6e359d7009d2c6b5018bb61c916e93 0 t/t9001-send-email.sh +100755 843a5013b96c675a629bd7f738eca220861e6ff8 0 t/t9100-git-svn-basic.sh +100755 f420796c31db2746b71ba9d7090f37363eba214a 0 t/t9101-git-svn-props.sh +100755 0e7ce34b9b1e254873a2700cf58095318b49b15c 0 t/t9102-git-svn-deep-rmdir.sh +100755 9ffd8458ef9d58fa5d3c42fd61f4629219b4d80a 0 t/t9103-git-svn-tracked-directory-removed.sh +100755 4d964e2db7cc3c96fc64911bd58c4f2f9679a6cd 0 t/t9104-git-svn-follow-parent.sh +100755 63230367bb1566384e66e1b5ddd6a68e1ae98c8f 0 t/t9105-git-svn-commit-diff.sh +100755 83896e96876d8cca24496c7cb278732a308e3d92 0 t/t9106-git-svn-commit-diff-clobber.sh +100755 bc37db9d62071ba92463276524675964c3e91593 0 t/t9106-git-svn-dcommit-clobber-series.sh +100755 d9b553ad55b1f7024af0689a450a9c6c65dcb034 0 t/t9107-git-svn-migrate.sh +100755 f6f71d0545c869a7216eb0e81f260085f6ffdec1 0 t/t9108-git-svn-glob.sh +100755 04d2a65c087de78fa8126b68774673532497276e 0 t/t9110-git-svn-use-svm-props.sh +100644 cc799c238de91a2b466735d678a0bc7415ebefc2 0 t/t9110/svm.dump +100755 a8d74dcd3aba7c462d46ea33c722d4307d24bded 0 t/t9111-git-svn-use-svnsync-props.sh +100644 499fa9594fafe5d45a32005c189634b6a3048777 0 t/t9111/svnsync.dump +100755 d470a920e4864ab0c494da1261fe835ff80474eb 0 t/t9112-git-svn-md5less-file.sh +100755 8da8ce58eb1b29210a6ac95fdd3a3fcb547ca36f 0 t/t9113-git-svn-dcommit-new-file.sh +100755 61d7781616eed4374c014cabd75a297c2baa348d 0 t/t9114-git-svn-dcommit-merge.sh +100755 f0fbd3aff7e63f64f8ba388db805013c43b4b22c 0 t/t9115-git-svn-dcommit-funky-renames.sh +100644 42422f791ea4240495e0b9cb5173bb7a27989958 0 t/t9115/funky-names.dump +100755 4b2cc878f685e65b2ccd5d8153efb533320d6ee9 0 t/t9116-git-svn-log.sh +100755 7a689bb1cd1d9daa1f17c0dcaaafa4d68ebd78fa 0 t/t9117-git-svn-init-clone.sh +100755 3281cbd3472a8da58c4f6f0f3965b5810705b0e9 0 t/t9118-git-svn-funky-branch-names.sh +100755 cc619115931cb74a85a171ade915ca2c47639c9b 0 t/t9119-git-svn-info.sh +100755 5979e133b9d5b9d85ddca31a40763ed4fb6feba3 0 t/t9120-git-svn-clone-with-percent-escapes.sh +100755 99230b08107102836f752c14e1b0a67804b35ea3 0 t/t9121-git-svn-fetch-renamed-dir.sh +100644 5f9127be92616ea8fb8ace1cff80a37037cb15ec 0 t/t9121/renamed-dir.dump +100755 1190576a658d08a680e177b748cfc5e69caa3ddb 0 t/t9122-git-svn-author.sh +100755 c18878fad16a6565fe846cc958417fea73289dce 0 t/t9123-git-svn-rebuild-with-rewriteroot.sh +100755 8223c5909e6ff6936cb0ccf4d0badfe43491af46 0 t/t9124-git-svn-dcommit-auto-props.sh +100755 3e32e84e6cd32413f98b5189f869bfb8f0a7f354 0 t/t9200-git-cvsexportcommit.sh +100755 1fc06c5a23b50d54c33755a9fce4ddd9ed3b9c79 0 t/t9300-fast-import.sh +100755 c19b4a2bab586b21da43c7a838ba85626f913568 0 t/t9301-fast-export.sh +100755 4b91f8d4c45dad075d69028c9c70aa9cb1959e2b 0 t/t9400-git-cvsserver-server.sh +100755 e27a1c5f85bbecac652ce8d224f8fc5e99b02a4e 0 t/t9401-git-cvsserver-crlf.sh +100755 ae7082be1d903e1f4d5758610d5166152f2847cc 0 t/t9500-gitweb-standalone-no-errors.sh +100755 0d7786a8c730d17fa194346f1da2978d23256da9 0 t/t9600-cvsimport.sh +100755 9706ee5773692bd8fcfbc9015ef062947c0a2da5 0 t/t9700-perl-git.sh +100755 4d2312548a81762918ac05b9a0014195b08ea532 0 t/t9700/test.pl +100644 11c027571b44c429b4f6fdca88bff9c3360c7545 0 t/test-lib.sh +100644 7b181d15cebb4c86a6ad7fed3dbf30ce2223b4c5 0 t/test4012.png +100644 7b181d15cebb4c86a6ad7fed3dbf30ce2223b4c5 0 t/test9200a.png +100644 ac22ccbd3ee9f03a3b38249ac8efdbe96b5da2cd 0 t/test9200b.png +100644 4470d2bf78e1fbb00d00e487f41daa4373cf48e1 0 tag.c +100644 7a0cb0070d46ba8c49d71029dc0704188805ea62 0 tag.h +100644 3467705e9b0e14a0230473186079e83a582e4345 0 tar.h +100644 6759ecbf98f8a90d96b4918c130babdd87889f69 0 templates/.gitignore +100644 9f3f1fc352dea624bd36e55802de190ead0ad9dd 0 templates/Makefile +100644 fae88709a636f3a06cc813dd64b28bfee7fa2073 0 templates/branches-- +100755 8b2a2fe84feaeaba56953d6d4d0d649b3cf755eb 0 templates/hooks--applypatch-msg.sample +100755 6ef1d29d09a10a5b6c3cbec0ac481931cd0d85fc 0 templates/hooks--commit-msg.sample +100755 22668216a3cec5a00d804dc5e9a904a10fd0fd09 0 templates/hooks--post-commit.sample +100755 18d2e0f72768c103d593cc2cf6d2b7a4bc8a9a01 0 templates/hooks--post-receive.sample +100755 5323b56b81b9dd3d7f9fb86d8892241becbb5e7e 0 templates/hooks--post-update.sample +100755 b1f187c2e9acaba942639bca90a63c5b4f058967 0 templates/hooks--pre-applypatch.sample +100755 0e49279c7f7b805c78f1bc4760a0d1c70a84a0d9 0 templates/hooks--pre-commit.sample +100755 be1b06e25043146f22261b55548229e6ab524b7c 0 templates/hooks--pre-rebase.sample +100755 365242499dcf0ee35c26ccb2917724d6e559be69 0 templates/hooks--prepare-commit-msg.sample +100755 93c605594fc06683088b934273873165215ccbb5 0 templates/hooks--update.sample +100644 2c87b72dff61f8394b3f1f32e21c1d936314ec2e 0 templates/info--exclude +100644 c6f25e80b8bcf0a21db2bea368b9e444c19bc0bf 0 templates/this--description +100644 90da448ebec3e5375b7725ba7f297c1c74199b87 0 test-chmtime.c +100644 62e8f2387a1cab97ec1c71d1993d082274e17bf5 0 test-date.c +100644 3d885ff37ee7fc43dec05dd827679d68cee5516b 0 test-delta.c +100644 8cefe6cfed87c8fe0c11d1263dae01639d2bd0f0 0 test-genrandom.c +100644 a3c4688778d9db28c83c9149c9cff1609b69b93f 0 test-match-trees.c +100644 2a79e729a4018ddb2da9ff633f4bf3b102fa8f88 0 test-parse-options.c +100644 a0bcb0e210523124fa977c8bf46667cf25d0335f 0 test-path-utils.c +100644 78d7e983a7a05ba0652132425a66477ef5773304 0 test-sha1.c +100755 0f0bc5d02f4dcbd67c6d405350e5aaeb39f44bfb 0 test-sha1.sh +100644 55e7e2904eb5f95cedaec2520ddd1d158ee93c7a 0 thread-utils.c +100644 cce4b77bd6452e2ec589d8c0dc0e8156352dd67b 0 thread-utils.h +100644 4713f9165c54405d51e81c3e90847120ee907e5d 0 trace.c +100644 6eb65b873afc9dfd457e974b63d88350bb8dc913 0 transport.c +100644 d0b52053fff9bc463438674232bffb6024f3b1fc 0 transport.h +100644 bbb126fc46cfb28a0bc92cc0842c0dc72017751d 0 tree-diff.c +100644 02e2aed7737207225f1b96eed774a1b75dd6d8d9 0 tree-walk.c +100644 42110a465f9a8c91d1bc643dfae7a9b9c32e3719 0 tree-walk.h +100644 03e782a9cabc0a12ed5baec0ef59c99f19dbc843 0 tree.c +100644 2ff01a4f839ecc2206fcc1c13fee9d5d202b1128 0 tree.h +100644 bcdc8bbb3b44a43aa43db6035a31478158e070af 0 unpack-file.c +100644 cba0aca062f201c5cd5f8799f2190d4a6f06e7c7 0 unpack-trees.c +100644 94e567265af9a69a30dd5c578439b6444e50004d 0 unpack-trees.h +100644 7e8209ea4b43995737b36bc58db47e7dd6eadb19 0 update-server-info.c +100644 c911e70c9aa47b70dac41b7f4de2f0b4b6c1f948 0 upload-pack.c +100644 a5fc4ec5fae66823266862fa0254474696c220e6 0 usage.c +100644 dc3735364f85273c2a119b994ddb405c09dc395c 0 utf8.c +100644 98cce1b038a908bec51ccd2f7e1c1f648cb429a1 0 utf8.h +100644 724ba87a7c9ccb16bc506fc3f25710a4b78e3006 0 var.c +100644 0e68ee6d2e2fb1b866ecec00c5f6446af366a62e 0 walker.c +100644 8a149e11084eeec4501b5b2c5d22e5266f4852e7 0 walker.h +100644 93562f03eef21b26945d2d9bbdc96818f4de6567 0 wrapper.c +100644 4c29255df1b637f93ab3d59e0dcab1fa3b40e10b 0 write_or_die.c +100644 7a7ff130a34942506e6068105ac5946c9404bf18 0 ws.c +100644 889e50f89fc24984f700d14f7033600fa9fdf642 0 wt-status.c +100644 78add09bd67c727babb61cd1eaa773bcd0c6e55e 0 wt-status.h +100644 61dc5c547019776b971dc89d009f628bbac134fd 0 xdiff-interface.c +100644 f7f791d96b9a34ef0f08db4b007c5309b9adc3d6 0 xdiff-interface.h +100644 413082e1fdf537d230a0f58940cee7466b965d0e 0 xdiff/xdiff.h +100644 1bad8462fb32cffdc9ff20a278d513e7a444b257 0 xdiff/xdiffi.c +100644 3e099dc445d6130f6a0ce2c6270a3b06d6ee119f 0 xdiff/xdiffi.h +100644 d3d9c845c6420e4881636d779c7029f900a0b067 0 xdiff/xemit.c +100644 440a7390fa4abb0411c336cfba616e3229484e86 0 xdiff/xemit.h +100644 526ccb344d231fb978f53b80deb17ec6c8fed368 0 xdiff/xinclude.h +100644 8ef232cfad12d706aaafe705bf16c546f3597182 0 xdiff/xmacros.h +100644 82b3573e7ada8c6df13ac24a78650b80af91ea73 0 xdiff/xmerge.c +100644 e87ab57c652b56b1a684e2a0a56885c1d1b27ef7 0 xdiff/xprepare.c +100644 8fb06a537451cbf3335ab4bdacb0f992e9744338 0 xdiff/xprepare.h +100644 2511aef8d89ab52be5ec6a5e46236b4b6bcd07ea 0 xdiff/xtypes.h +100644 d7974d1a3e612a235b0c8adfde08ba802e782b5a 0 xdiff/xutils.c +100644 d5de8292e05e7c36c4b68857c1cf9855e3d2f70a 0 xdiff/xutils.h diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lstree b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lstree new file mode 100644 index 0000000000..2d1fad46f0 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/gitgit.lstree @@ -0,0 +1,331 @@ +100644 blob 6b9c715d21d5486e59083fb6071566aa6ecd4d42 .gitattributes +100644 blob a213e8e25bb2442326e86cbfb9ef56319f482869 .gitignore +100644 blob 373476bdc03f718b4c01471dd9996ee4497f43a8 .mailmap +100644 blob 9651afc89d5e789abd9cedaa4f3b92dde7dd1412 .project +100644 blob 6ff87c4664981e4397625791c8ea3bbb5f2279a3 COPYING +040000 tree fe83e22f0c04b81c62a335ef09d59c23ff93d6ca Documentation +100755 blob cb7cd4b53827fa6820e84b1318572d0115b3b17f GIT-VERSION-GEN +100644 blob 7d0c2c2f865d6ed969038e7543dbeb8933723ec3 INSTALL +100644 blob 52c67c1a472455dcce5c19a21bbfd0520ff7dd26 Makefile +100644 blob 548142c327a6790ff8821d67c2ee1eff7a656b52 README +120000 blob b9a53c3416991b66e1d35c2bbf663b48340b0041 RelNotes +100644 blob 0d561246e0a958d9a7284409b1900a82876eebf3 abspath.c +100644 blob ccb1108c94436035d0da8b1d6f08f859b68294a3 alias.c +100644 blob 216c23a6f854c614d38c743cd7687a37f304161b alloc.c +100644 blob 13029619e5ec34bac4ba61a6fc08800ab36f4a1b archive-tar.c +100644 blob cf285044e3576d0127c3215cb1253443d67517dc archive-zip.c +100644 blob f834b5f51f4cf5d3b73d21dfd99198caef3b19f8 archive.c +100644 blob 0b15b35143fffcc13764e4e668ee452b191cc609 archive.h +040000 tree 36753f6455e2308e746447cde2c2113285bc9b02 arm +100644 blob 17f6a4dca521d9690377f2e93a0192d8a874d2ad attr.c +100644 blob f1c2038b0923d3130937eef965667204a8634e6d attr.h +100644 blob b88270f90844095b3d352cc4213cbebd95a7f420 base85.c +100644 blob bd7d078e1ae5fe4ce0a16fda62a2c1743237941b blob.c +100644 blob ea5d9e9f8b63be2c7048d19ee53feb06b0795c80 blob.h +100644 blob b1e59f2196b933ab7169a30efc5d1d340f8f9c5c branch.c +100644 blob 9f0c2a2c1fab9a312f436880956da0973c68ead8 branch.h +100644 blob fc3f96eaefff91e4e85adb92162716939f0ecd72 builtin-add.c +100644 blob fc43eed36b55e4966796490b8c0a02fae790229c builtin-annotate.c +100644 blob 2216a0bf7cd53adc31346f66a3b9786a1d688bad builtin-apply.c +100644 blob 22445acbfc5279f391ac6afa855b21064ec54535 builtin-archive.c +100644 blob 8b6b09b10b8f9dcda0b7224f31c860bb803945f0 builtin-blame.c +100644 blob b1a2ad7a6b3b150cda8d031a87352a4daedc40ea builtin-branch.c +100644 blob ac476e7a4b45fc55b6b6d1e4d02be0c35aba2c7b builtin-bundle.c +100644 blob 7441a56acdbefdd8044a406f4d756ce8a4f06644 builtin-cat-file.c +100644 blob cb783fc77e75515a02ed2268dfb37ee3bbd03749 builtin-check-attr.c +100644 blob fe04be77a9312c11fa054897c5982fa6c74b8e5e builtin-check-ref-format.c +100644 blob 71ebabf9903bd90b7da59c47f1c0819b5f25c538 builtin-checkout-index.c +100644 blob 411cc513c65ba854221ad52dd6aeaaac7d213c9d builtin-checkout.c +100644 blob 48bf29f40a5e06fd588b34c468535e04abcf206b builtin-clean.c +100644 blob e086a40b41810c30a4f5228daa4e38857dae84d5 builtin-clone.c +100644 blob 7a9a309be0543da7d27e7710ef82271f2582e0a9 builtin-commit-tree.c +100644 blob f7c053a0106c2e42833d0d7c7255b7b636d09a93 builtin-commit.c +100644 blob 91fdc4985d8e64fae12209174dd4aa2d887793e5 builtin-config.c +100644 blob 91b5487478998e39bb8ae4a5cb667360cff82c9a builtin-count-objects.c +100644 blob ec404c839b6542deb4e15ca342fd3c0afbbedd2e builtin-describe.c +100644 blob 9bf10bb37e2f56ec2a10239d7419db8fbb641745 builtin-diff-files.c +100644 blob 17d851b29ee5de33e01745eabcd5cd735c30b352 builtin-diff-index.c +100644 blob 415cb1612f5322da89850874ba81885e41808678 builtin-diff-tree.c +100644 blob 7ffea975059f9e13b07ca680e6707ffc14973f90 builtin-diff.c +100644 blob 070971616dbb12d005c5c9a1f82cc5b0c5391f62 builtin-fast-export.c +100644 blob 7460ab7fce2a4e6a7e014f448819140e2204ccb7 builtin-fetch--tool.c +100644 blob 273239af3be61736ee4ff484d628950c4de7311a builtin-fetch-pack.c +100644 blob 7eec4a0e43ad5760f1060a7d5bcf2a5083015130 builtin-fetch.c +100644 blob df02ba7afdd615492361a1897a9dedd6ab233c96 builtin-fmt-merge-msg.c +100644 blob 445039e19c75e4c9321f7ee64289ef8201a25c14 builtin-for-each-ref.c +100644 blob 6eb7da88d3e8591a8c544acc61a42e00babff120 builtin-fsck.c +100644 blob fac200e0b08360625afc81b02913128c9b87f486 builtin-gc.c +100644 blob 631129ddfd0ffe06f919882d22cfc494d9553f50 builtin-grep.c +100644 blob 3a062487a7eacd01ed824b46a9124dd343cd2e60 builtin-http-fetch.c +100644 blob baf0d09ac4ea372b4015d399560a133b401b55cc builtin-init-db.c +100644 blob f4975cf35f7f1555739f7657ee62ed983d18cb84 builtin-log.c +100644 blob e8d568eed7ab700bc338af8f589d2f61e81f323c builtin-ls-files.c +100644 blob c21b841e7c5e8d27a6e66e7f70786d77aa4653b5 builtin-ls-remote.c +100644 blob d25767a1f7eb0a8b45bc1eed6b9aa95de0847f18 builtin-ls-tree.c +100644 blob f974b9df968c74c5d62d58b2a09493e6abb4322e builtin-mailinfo.c +100644 blob 71f3b3b8741e505fc652e6c74c75972f19211f71 builtin-mailsplit.c +100644 blob 3382b1382a7dcbd525126a35209072da4b4d8041 builtin-merge-base.c +100644 blob 3605960c2d9692514a6df0f344f3c3269cf1de3c builtin-merge-file.c +100644 blob 8f5bbaf402e020e308e7af9cedb7df1b2ec5a2b7 builtin-merge-ours.c +100644 blob 43e55bf90154c51b94527b2ab7eb7c60fe36e9ec builtin-merge-recursive.c +100644 blob dde0c7ed33118ff8d0cc421e8a0366e342c6d011 builtin-merge.c +100644 blob 4f65b5ae9baf66953e79886fd93fe31786b24d36 builtin-mv.c +100644 blob 85612c4dcb719b460623204046e35486e9d9fe97 builtin-name-rev.c +100644 blob 2dadec1630c266bbaf42e84810f7059ed5c43b1e builtin-pack-objects.c +100644 blob 34246df4ec946273d9f42e6f0848b02d8510beea builtin-pack-refs.c +100644 blob 10cb8df8457fd5f2ba9be62ecd0f9384e21c3e63 builtin-prune-packed.c +100644 blob 947de8cf258c73d8a327ef3a1daed417ba533f1b builtin-prune.c +100644 blob c1ed68d938f67343c6938cfef54d5ff69a522a63 builtin-push.c +100644 blob 72a6de302f88728af17ce5c5c6983c5267afc6f6 builtin-read-tree.c +100644 blob 0c34e378199064e87aa09caf0fa0a2346333ec69 builtin-reflog.c +100644 blob 54d1c3e3d16b2cebcff0c6c57d98756e48472b67 builtin-remote.c +100644 blob dd4573fe8dcd9dc8edd5a7d41bc8daa83034ee7e builtin-rerere.c +100644 blob c24c21909194014b467c86fd3598796e7db576b3 builtin-reset.c +100644 blob 893762c80f4910fadf2d6df414bd835cccb7faaa builtin-rev-list.c +100644 blob 9aa049ec170b0125fddde29adda3c720c8a7b8ee builtin-rev-parse.c +100644 blob e9da870d22c14c32a0e0a6cb71b933c79a2d8b53 builtin-revert.c +100644 blob ee8247b08cd007f73d5dfffa560a9efe33d327b9 builtin-rm.c +100644 blob 7588d22885d0af24ae80f1d687ccd097fe365021 builtin-send-pack.c +100644 blob d03f14fdad3d17dde06734d78ddb4aade6ed4f2b builtin-shortlog.c +100644 blob 233eed499d0b8790781326ff0455bdc7f09fe4d4 builtin-show-branch.c +100644 blob add16004f11375b1ad2b97f9b1bf1ced5c437f81 builtin-show-ref.c +100644 blob c0b21301ba4c126a49ed38b6983756b99a25aae0 builtin-stripspace.c +100644 blob bfc78bb3f6eff2f8e39649b9649ae7263f143ad9 builtin-symbolic-ref.c +100644 blob 325b1b2632e44121c23bc6df556bf3aa4e32ba04 builtin-tag.c +100644 blob f4bea4a322c26a54734286073c5e67444555c2d9 builtin-tar-tree.c +100644 blob a8918666655bb91f952ccdac18715bd9ba4a09f2 builtin-unpack-objects.c +100644 blob 38eb53ccba2b97a0fccf50d6ba0b7424fe2d1bcb builtin-update-index.c +100644 blob 56a0b1b39cf4c4fc51dbbff256240655bc36a038 builtin-update-ref.c +100644 blob a9b02fa32f372a6810867c10560a20d58b5b2a91 builtin-upload-archive.c +100644 blob f4ac595695b1fff1317ff7d14ea9427780327aea builtin-verify-pack.c +100644 blob 729a1593e61d87ad4596f07e7faedac81de64e81 builtin-verify-tag.c +100644 blob 52a3c015ff8e4611522bd41078bdb2934d288d35 builtin-write-tree.c +100644 blob f3502d305e4f65e9707fe8b738f64be6e49f7f84 builtin.h +100644 blob 00b2aabefca49b634f49143523ee31556baa7777 bundle.c +100644 blob e2aedd60d6ad1482bb6da173c853e6ba4805c8d7 bundle.h +100644 blob 5f8ee87bb1c446341b640c2f978a658d6bfcfcd0 cache-tree.c +100644 blob cf8b790874c4a4f5890b360c237ccdd4a5a03de4 cache-tree.h +100644 blob 2475de9fa837596303284157e08b3080d64351ee cache.h +100755 blob d6fe6cf1749ebcd6189fa36cbb4e14a532d2d17b check-builtins.sh +100644 blob 00d92a16631a80ff8ec4e995dafcd3e55434fad5 check-racy.c +100755 blob a1c4c3e8d845e8e791d7df0c1387e1b2262b5ecf check_bindir +100644 blob fc0b72ad59b13e4bd86372e5e81b4f400c99d26e color.c +100644 blob 6cf5c88aaf8d0e38e2853e6fd212e3cdd6c180cb color.h +100644 blob 9f80a1c5e3a461afd11966625589684d61187911 combine-diff.c +100644 blob 3583a33ee90647d8e6ded02643eb75753760d94f command-list.txt +100644 blob dc0c5bfdab7296bf7febb6f1b1aad64550838c15 commit.c +100644 blob 77de9621d9c926c6fb8a2bf9ca81c6c376a2ad41 commit.h +040000 tree 3612b1a756de51eb5beb16e0c3b958e74f8bc53d compat +100644 blob 53f04a076a7275965090edd4ca2a34652c4f5679 config.c +100644 blob b776149531025c85f5665d971e6e072f0cc64893 config.mak.in +100644 blob 7c2856efc92ca55e3cf03fcf1c72ffb70318f7c3 configure.ac +100644 blob 574f42fa47ffa69328217eb25afee6f85db9595e connect.c +040000 tree ed65cee05eb473aca9cfae781f109d464dcbd711 contrib +100644 blob 78efed800d4d64898d438d9590b01be008cfcd36 convert.c +100644 blob e54d15aced7595ccb11423b0de121db9051ad1f3 copy.c +100644 blob ace64f165e4a01fb99892e9b89e7df791a7f4ca1 csum-file.c +100644 blob 72c9487f4fd9fcab5e02fc2dc6afd3cb7f9c036a csum-file.h +100644 blob ee06eb7f48f1d3e818b3037369b4e056fe7e5be7 ctype.c +100644 blob 4540e8df5ab8bc8ff66549144d7db2928e12199b daemon.c +100644 blob 35a52576c53e5e1406d40ed4402b8834a29b9f0e date.c +100644 blob d9668d2ef94c73e4a7a5602011ff13a9fd9d8c6a decorate.c +100644 blob 1fa4ad9beb08f23888814b99183487ab85378bfd decorate.h +100644 blob 40ccf5a1e95f62d840a006274f7024fa43208b1c delta.h +100644 blob a4e28df714b4834e5efe42fa3abb647711913d71 diff-delta.c +100644 blob e7eaff9a68ccbcc692522c9956f0dae9af45f3f1 diff-lib.c +100644 blob 7d68b7f1bef1039b4996e662fb17968c4e3e3e79 diff-no-index.c +100644 blob cbf25473c594abfd1fc13473108dc9c15e2f1d15 diff.c +100644 blob 50fb5ddb0bec02b0cd5498d6ecc37d44bf874476 diff.h +100644 blob 31cdcfe8bcdae7df65b0387071846299a14bb7be diffcore-break.c +100644 blob e670f8512558c38d9a9d6e754cfc609b042b1195 diffcore-delta.c +100644 blob 23e93852d8c701760d56e7e728dba7c08367fbe8 diffcore-order.c +100644 blob af9fffe6e8e145b066157da8791c749257e7c8e9 diffcore-pickaxe.c +100644 blob 1b2ebb40014d820fe4fb679509ab694d453be7b4 diffcore-rename.c +100644 blob cc96c20734bf4184970f5381416637cf6e45ea13 diffcore.h +100644 blob 29d1d5ba31def46ba8b55905dc60773cc6cc167e dir.c +100644 blob 2df15defb6720a742282f24721233c4816deceb6 dir.h +100644 blob 1f73f1ea7dfa6a14dedf384c99751e86c8121ff4 dump-cache-tree.c +100644 blob eebc3e95fe0c7e61f7c29fa5412ea9d4a5900f92 editor.c +100644 blob 222aaa374b8268828e9d529a8afacb8830acc281 entry.c +100644 blob 0c6d11f6a0c6fa5dbab2f36c4b4ad4de5aba4ac9 environment.c +100644 blob ce6741eb682b59ad638c7bee6ca31e2fcd53f281 exec_cmd.c +100644 blob 594f961387240c221020c9ea0bccd8a39ff69595 exec_cmd.h +100644 blob 7089e6f9e6c5fa9142f468e54afe7d33a6d2eec7 fast-import.c +100644 blob 8bd9c32561e79d194d27fa10cc98a26aa2cb673c fetch-pack.h +100755 blob 63dfa4c475ae3632fc5cfd093d949a41683a5458 fixup-builtins +100644 blob 797e3178ae279f444d2efa7e3758652ad0898dd7 fsck.c +100644 blob 990ee02335a2e2693e32baa82b259c23843f2aa0 fsck.h +100755 blob a2913c2a2cd1ec158157ada3e2deb666892b734b generate-cmdlist.sh +100755 blob da768ee7acc22e6480f0a067e109239561d43927 git-add--interactive.perl +100755 blob 6aa819280ef99ccbbdeefde037e99fae3e6f0110 git-am.sh +100755 blob 98f3ede566a6cb0c902ce84795f7de8f8afbe633 git-archimport.perl +100755 blob 3cac20db79e1e408a321b0e9d272501985a3c49b git-bisect.sh +100644 blob cf89cdf4598b3796724a85aa707f740245155cdc git-compat-util.h +100755 blob 6d9f0ef0f989133422cf8c0302e63dab15a999d5 git-cvsexportcommit.perl +100755 blob e2664ef01308fd0fb65d47b25e0ae73a65aa6262 git-cvsimport.perl +100755 blob b0a805c688f59af29e1f25b514d73f3991285dee git-cvsserver.perl +100755 blob 182822a24e214fe7e93a2df68fdda3dd40b5896d git-filter-branch.sh +040000 tree 320e89a01513e3630eb681d9524ff835d56f6690 git-gui +100755 blob 0843372b57371b62cd68f2818f634209f55d5395 git-instaweb.sh +100755 blob 9cedaf80ceac1d4100adf3cfb152c76c7f945e4d git-lost-found.sh +100755 blob 645e1147dc886f2b1ca6d2020b44db746b082bf0 git-merge-octopus.sh +100755 blob e1eb9632660146396a0b5f3f2a410d8cb027ff9d git-merge-one-file.sh +100755 blob 93bcfc2f5dce418d00f26257788932d5c738785c git-merge-resolve.sh +100755 blob 94187c306ccb05d977f2bb35e81828130ab49a61 git-mergetool.sh +100755 blob 695a4094bb4230341618bd6f16d0bea9bff2e826 git-parse-remote.sh +100755 blob 75c36100a2f858bcf2663d2b4560654787963175 git-pull.sh +100755 blob cebaee1cc9dfc28d80173583b144a480be2f9bfd git-quiltimport.sh +100755 blob 4e334ba41dad3067394b79c15ebfe610b2d3e178 git-rebase--interactive.sh +100755 blob 412e135c3ae88d76b5bdf3f08083b153da220a95 git-rebase.sh +100755 blob 937c69a74858a8a3c63bb41a23705b579df1b3a3 git-relink.perl +100755 blob 683960b04d6b743e687b2eb640d2b0e00ccfd313 git-repack.sh +100755 blob 073a314c8043e0ff30afde65e012e356ff0d186f git-request-pull.sh +100755 blob d2fd89907688a044ffe0d2520744e00a9b33c942 git-send-email.perl +100755 blob dbdf209ec0e7d6468c199d1905c3e7788a9cd246 git-sh-setup.sh +100755 blob d4609ed66e56dc6021c800d60286bec38615ff39 git-stash.sh +100755 blob b40f876a2ca9fe985cedc622ab28a9f461edc5ab git-submodule.sh +100755 blob cf6dbbc42773fef394c27cd87109b69c3144753c git-svn.perl +100755 blob 384148a59fc492d8fb1d6ea4fc4532aa1e5ffc22 git-web--browse.sh +100644 blob 37b1d76a08ca59f3de54e11890dce962403cf8d3 git.c +100644 blob c6492e5be2763eab81358424ff625a34a5ff2fba git.spec.in +040000 tree 615732133b5e3dcd80f5477f3ca94574e4430957 gitk-git +040000 tree e3fbfd0f5bfe5e8927abb7fe37a59585aef9a405 gitweb +100644 blob e2633f8376eb7b12706dcd4c698e2b3f6be2b433 graph.c +100644 blob eab4e3daba9812293d4e005c3ebe28f9a97744ce graph.h +100644 blob f67d6716ea5f42c3384a7a4cb2eb973b02785fba grep.c +100644 blob d252dd25f81526d9b8663b4d3c9585d69a901397 grep.h +100644 blob 46c06a9552dac5475afc607c3fe2bf00801eb055 hash-object.c +100644 blob 1cd4c9d5c0945994b84bb25edd6e4685cf76b5c5 hash.c +100644 blob 69e33a47b9861df9ac12c354eae180b4f8fea857 hash.h +100644 blob 3cb19628965685ce59a5377b81bef975851996e8 help.c +100644 blob 68052888570af7d09535db8831b8cf3ef2881589 http-push.c +100644 blob 9dc6b27b457a2979a95018679a0b885e6fb62d9a http-walker.c +100644 blob 1108ab4a3101fb4768cad420ccfdb52d87890a18 http.c +100644 blob 905b4629a47789705c13745fd56ce0c91adea41b http.h +100644 blob b35504a8d25594a8d243ae7490733eae5a262712 ident.c +100644 blob 1ec131092109aa3fbed3cd20f10b56a864584a94 imap-send.c +100644 blob 52064befdbbbdf671bd08e369a133d4f1fee03c1 index-pack.c +100644 blob 7f03bd99c5b66afa6cc7fa11a2430301a3042656 interpolate.c +100644 blob 77407e67dca97eb85274c69e2e7469e1d4d40b3b interpolate.h +100644 blob c8b8375e4983794e601ba69a1c217a3c711835e9 list-objects.c +100644 blob 0f41391ecc00eac324ea76de7654781c4fce094e list-objects.h +100644 blob 9837c842a3f215ebee7cbe9690e42e216fb5c76c ll-merge.c +100644 blob 5388422d091ede134d42406291989c49553f7428 ll-merge.h +100644 blob 4023797b00fe21ecbabe3407ef8a12fca0690607 lockfile.c +100644 blob bd8b9e45ab46b8664c8b7016b33bee22f86c9e0d log-tree.c +100644 blob 59ba4c48b7966db34c6345a445ab0b10e235ac83 log-tree.h +100644 blob 88fc6f394684436967002ca477eac1e084537348 mailmap.c +100644 blob 6e48f83cedd13e24d50cddf47f037791ddc5ad4b mailmap.h +100644 blob 0fd6df7d6ed839eaed536bc332312c2688a6bbad match-trees.c +100644 blob 2a939c9dd835a7e7946eb1548e4cf637ae3ca329 merge-file.c +100644 blob 7491c56ad25332fb4aae6a075bf0577a1d800c3b merge-index.c +100644 blob f37630a8ad07709ae106ddde44a34daf6bad8b16 merge-recursive.h +100644 blob 02fc10f7e622ba1c53065e7cf4563ff10af0c41f merge-tree.c +100644 blob 0b34341f711a903d4a12fe96dc6ef63e55fb2f5b mktag.c +100644 blob e0da110a98d3a7376dc78df71fabc10fc5664296 mktree.c +040000 tree 930c4b2743737c3dd8a58309fd66f019f08ab12f mozilla-sha1 +100644 blob 0031d78e8c98a32d61cd0dc0f939a033e24ed890 name-hash.c +100644 blob 50b6528001fe4bafdfe70126dc2078860c3d1969 object.c +100644 blob 036bd66fe9b6591e959e6df51160e636ab1a682e object.h +100644 blob f596bf2db5e0a0065e6856b8caa3ded8a134f74d pack-check.c +100644 blob 25b81a445c8fafe0c00ce30082b7d9a7c22ccf1e pack-redundant.c +100644 blob 848d311c2b2c651dbb14893c260584f00c639357 pack-refs.c +100644 blob 518acfb370ad72be18399a3ac5e8ca17880281c9 pack-refs.h +100644 blob cd300bdff5b524a4d509ba5276e9ef21f443013d pack-revindex.c +100644 blob 36a514a6cf600e7e77794e50998a9d160e30c8e9 pack-revindex.h +100644 blob a8f02699366c87de960d7637e9f69c26c2241693 pack-write.c +100644 blob 76e6aa2aad06545e7c44fc2c1e117ea668356ccf pack.h +100644 blob 6b5c9e44b4ded338ddb344ae454d83a685b7569a pager.c +100644 blob 71a7acf4e22bd12c0919f277410d6ec52dd5efc8 parse-options.c +100644 blob bc317e7512af7a1cc86641a651ae5415d28e71c4 parse-options.h +100644 blob ed9db81fa82c812c9ffa07f5a40540dbb15da0d3 patch-delta.c +100644 blob 9349bc5580456b378d41da7cc2518e4fa9a7e81a patch-id.c +100644 blob 3be5d3165e0009761a0ca69e15e4a9132c6cfaff patch-ids.c +100644 blob c8c7ca110ad34def12a3594a1560b3c3052eb701 patch-ids.h +100644 blob 9df447bd6dcfaddf7f05fe5f0b624700ff1f40d7 path.c +040000 tree 7f5daf8444afe10cabcfff7b46dcf101777301cb perl +100644 blob f5d00863a6234c16db33637d19fefd2014780e87 pkt-line.c +100644 blob 9df653f6f5afe720870658d7093bddbf3e66beaf pkt-line.h +040000 tree 6f6159f0245784352414ff38ffb68bae80f30bd6 ppc +100644 blob 33ef34a4119812674726254fee3f391fb5734fdb pretty.c +100644 blob 55a8687ad15788f8ea5a5beb463d216908f618b2 progress.c +100644 blob 611e4c4d42d8d1164add09f926ad5b2ce088db5e progress.h +100644 blob 6a520855d6c418ecb1384ef9571b122b134af1af quote.c +100644 blob c5eea6f18e2dfabd071b73e6507c34c2b7b5e39f quote.h +100644 blob 3b1c18ff9b9060d0dd437ce89aedb8871c66c54c reachable.c +100644 blob 40751810b64f8bbf9c0a633472a0ef27d23ed1a5 reachable.h +100644 blob 2c03ec3069decb20f7557af4ac7dbe295f2dcf9c read-cache.c +100644 blob d44c19e6b577023dcbaa188a0e67130ff4e5bd9a receive-pack.c +100644 blob f751fdc8d832cae54647c1a70d888e979d324fd8 reflog-walk.c +100644 blob 7ca1438f4d74b652f962c6bdfddd08fe0d75802d reflog-walk.h +100644 blob 39a3b23804d2da715c564459bf320be23d41c1bf refs.c +100644 blob 06ad26055661a9b9e475d0f8a7bd6d1cfb42e792 refs.h +100644 blob f61a3ab399aa6960fb8eba050321cea4a3b05344 remote.c +100644 blob 091b1d041f8a4d255f59bfc001e098e692dbc15c remote.h +100644 blob 323e493dafee46c0d3f95e3c4cd9c4c9b463bbef rerere.c +100644 blob f9b03862fe78b560ee606637be3b1ce972a2cc14 rerere.h +100644 blob 3897fec53170c50921eb1952bc4bdf9c08480638 revision.c +100644 blob f64e8ce7ff999e9fe4a01205ae51775827484ed4 revision.h +100644 blob a3b28a64dc2d1b888b0ba2a135be10fe04651201 run-command.c +100644 blob 5203a9ebb10b14bd06862abafed0ab73d7514a3d run-command.h +100644 blob 8ff1dc35390083c3648c4ee5790f35633d956069 send-pack.h +100644 blob c1c073b2f05a48772a45602cdc711eef6e211695 server-info.c +100644 blob 6cf909463d4ad3681a2f35269db9dc944f4389c2 setup.c +100644 blob da357479cf19aad4bebc64f874c76fdf8566712b sha1-lookup.c +100644 blob 3249a81b3d664afc89c98e6d9dd6b512092a82f9 sha1-lookup.h +100644 blob e281c14f01d37ab7623998c2990914aca49a7a3b sha1_file.c +100644 blob 4fb77f8863ec075de38b84171d3ef039a00cee4c sha1_name.c +100644 blob 4d90eda19efe0a80c1cb39e8897ab3ed5e6fcf56 shallow.c +100644 blob 6a48de05ff80f86050715ef3dab87a48b0a86ac9 shell.c +100644 blob bc02cc29ef0d5f640ab390614def995f30fe4691 shortlog.h +100644 blob 45bb535773fd9c36f73502df9462f7de800009c8 show-index.c +100644 blob b6777812cb92c1c169ee395164d53a0c2e6eceb2 sideband.c +100644 blob a84b6917c7a17b5f8a922540801e98d46aa24431 sideband.h +100644 blob 720737d856b694bc5239f0c18af372959c99e744 strbuf.c +100644 blob eba7ba423a2d3a383ef93f663c95695438269edf strbuf.h +100644 blob ddd83c8c76112cecd5d23668aaca467601855a72 string-list.c +100644 blob 4d6a7051fe5bccf04a0d0c32a90e5cf9c00dba3c string-list.h +100644 blob 5a5e781a15d7d9cb60797958433eca896b31ec85 symlinks.c +040000 tree 40b1d0c852cbaf154abff6e8f5e94537c1184548 t +100644 blob 4470d2bf78e1fbb00d00e487f41daa4373cf48e1 tag.c +100644 blob 7a0cb0070d46ba8c49d71029dc0704188805ea62 tag.h +100644 blob 3467705e9b0e14a0230473186079e83a582e4345 tar.h +040000 tree b9afb0508810e32cc63b582eb84bc72c8d2225cd templates +100644 blob 90da448ebec3e5375b7725ba7f297c1c74199b87 test-chmtime.c +100644 blob 62e8f2387a1cab97ec1c71d1993d082274e17bf5 test-date.c +100644 blob 3d885ff37ee7fc43dec05dd827679d68cee5516b test-delta.c +100644 blob 8cefe6cfed87c8fe0c11d1263dae01639d2bd0f0 test-genrandom.c +100644 blob a3c4688778d9db28c83c9149c9cff1609b69b93f test-match-trees.c +100644 blob 2a79e729a4018ddb2da9ff633f4bf3b102fa8f88 test-parse-options.c +100644 blob a0bcb0e210523124fa977c8bf46667cf25d0335f test-path-utils.c +100644 blob 78d7e983a7a05ba0652132425a66477ef5773304 test-sha1.c +100755 blob 0f0bc5d02f4dcbd67c6d405350e5aaeb39f44bfb test-sha1.sh +100644 blob 55e7e2904eb5f95cedaec2520ddd1d158ee93c7a thread-utils.c +100644 blob cce4b77bd6452e2ec589d8c0dc0e8156352dd67b thread-utils.h +100644 blob 4713f9165c54405d51e81c3e90847120ee907e5d trace.c +100644 blob 6eb65b873afc9dfd457e974b63d88350bb8dc913 transport.c +100644 blob d0b52053fff9bc463438674232bffb6024f3b1fc transport.h +100644 blob bbb126fc46cfb28a0bc92cc0842c0dc72017751d tree-diff.c +100644 blob 02e2aed7737207225f1b96eed774a1b75dd6d8d9 tree-walk.c +100644 blob 42110a465f9a8c91d1bc643dfae7a9b9c32e3719 tree-walk.h +100644 blob 03e782a9cabc0a12ed5baec0ef59c99f19dbc843 tree.c +100644 blob 2ff01a4f839ecc2206fcc1c13fee9d5d202b1128 tree.h +100644 blob bcdc8bbb3b44a43aa43db6035a31478158e070af unpack-file.c +100644 blob cba0aca062f201c5cd5f8799f2190d4a6f06e7c7 unpack-trees.c +100644 blob 94e567265af9a69a30dd5c578439b6444e50004d unpack-trees.h +100644 blob 7e8209ea4b43995737b36bc58db47e7dd6eadb19 update-server-info.c +100644 blob c911e70c9aa47b70dac41b7f4de2f0b4b6c1f948 upload-pack.c +100644 blob a5fc4ec5fae66823266862fa0254474696c220e6 usage.c +100644 blob dc3735364f85273c2a119b994ddb405c09dc395c utf8.c +100644 blob 98cce1b038a908bec51ccd2f7e1c1f648cb429a1 utf8.h +100644 blob 724ba87a7c9ccb16bc506fc3f25710a4b78e3006 var.c +100644 blob 0e68ee6d2e2fb1b866ecec00c5f6446af366a62e walker.c +100644 blob 8a149e11084eeec4501b5b2c5d22e5266f4852e7 walker.h +100644 blob 93562f03eef21b26945d2d9bbdc96818f4de6567 wrapper.c +100644 blob 4c29255df1b637f93ab3d59e0dcab1fa3b40e10b write_or_die.c +100644 blob 7a7ff130a34942506e6068105ac5946c9404bf18 ws.c +100644 blob 889e50f89fc24984f700d14f7033600fa9fdf642 wt-status.c +100644 blob 78add09bd67c727babb61cd1eaa773bcd0c6e55e wt-status.h +100644 blob 61dc5c547019776b971dc89d009f628bbac134fd xdiff-interface.c +100644 blob f7f791d96b9a34ef0f08db4b007c5309b9adc3d6 xdiff-interface.h +040000 tree 88b6f65753131f1f2c0dbceb1f37950e3494833a xdiff diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.idx Binary files differnew file mode 100644 index 0000000000..300c0cea48 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.pack Binary files differnew file mode 100644 index 0000000000..fca3460ed2 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx Binary files differnew file mode 100644 index 0000000000..84a6c0fbea --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2 Binary files differnew file mode 100644 index 0000000000..1d45fa811a --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack Binary files differnew file mode 100644 index 0000000000..99f4fdf232 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.idx Binary files differnew file mode 100755 index 0000000000..60331335d9 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.pack Binary files differnew file mode 100755 index 0000000000..203c157657 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-546ff360fe3488adb20860ce3436a2d6373d2796.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.idx Binary files differnew file mode 100644 index 0000000000..58b712f6c5 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.pack Binary files differnew file mode 100644 index 0000000000..0b0001020a --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.idx Binary files differnew file mode 100644 index 0000000000..a5aed7def2 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.pack Binary files differnew file mode 100644 index 0000000000..24f69429a0 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-cbdeda40019ae0e6e789088ea0f51f164f489d14.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx Binary files differnew file mode 100644 index 0000000000..3ff5423774 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2 b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2 Binary files differnew file mode 100644 index 0000000000..ccbf00e34f --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2 diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack Binary files differnew file mode 100644 index 0000000000..ef56d7e941 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.idx Binary files differnew file mode 100644 index 0000000000..d515f905f2 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.pack b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.pack Binary files differnew file mode 100644 index 0000000000..72712b20be --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa.pack diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-huge.idx b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-huge.idx Binary files differnew file mode 100644 index 0000000000..0a5bbfb6a6 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/pack-huge.idx diff --git a/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/packed-refs b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/packed-refs new file mode 100644 index 0000000000..82fb0d7b34 --- /dev/null +++ b/org.eclipse.jgit.test/tst-rsrc/org/eclipse/jgit/test/resources/packed-refs @@ -0,0 +1,36 @@ +# pack-refs with: peeled +6db9c2ebf75590eef973081736730a9ea169a0c4 refs/heads/a +7f822839a2fe9760f386cbbbcb3f92c5fe81def7 refs/heads/b +6e1475206e57110fcef4b92320436c1e9872a322 refs/heads/c +f73b95671f326616d66b2afb3bdfcdbbce110b44 refs/heads/d +d0114ab8ac326bab30e3a657a0397578c5a1af88 refs/heads/e +47d3697c3747e8184e0dc479ccbd01e359023577 refs/heads/f +175d5b80bd9768884d8fced02e9bd33488174396 refs/heads/g +175d5b80bd9768884d8fced02e9bd33488174396 refs/heads/prefix/a +68cb1f232964f3cd698afc1dafe583937203c587 refs/heads/gitlink +49322bb17d3acc9146f98c97d078513228bbf3c0 refs/heads/master +d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 refs/heads/pa +5ce00008cf3fb8f194f52742020bd40d78f3f1b3 refs/heads/symlink +6db9c2ebf75590eef973081736730a9ea169a0c4 refs/tags/A +17768080a2318cd89bba4c8b87834401e2095703 refs/tags/B +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +032c063ce34486359e3ee3d4f9e5c225b9e1a4c2 refs/tags/B10th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +214cae792433672d28b3aeb9f75c1ae84fd54628 refs/tags/B2nd +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +1170b77a48d3ea2d58b043648b1ec63d606e3efa refs/tags/B3rd +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +8dfd42699e7b10e568fa1eaebe249e33e98da81e refs/tags/B4th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +efee904c794b943a06931c76c576dd552212e8bc refs/tags/B5th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +d54e006ebbef94b7d3a5cd56d154f1e6f08efb94 refs/tags/B6th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +a773cd2d9dbca00d08793dac0d7002a49f0428c0 refs/tags/B7th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +bf5123bb77c7b5a379f7de9c1293558e3e24dfb8 refs/tags/B8th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +dd144af286452bfd6a1ea02b0d3745bcdb555e9d refs/tags/B9th +^d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864 +8bbde7aacf771a9afb6992434f1ae413e010c6d8 refs/tags/spearce-gpg-pub +^fd608fbe625a2b456d9f15c2b1dc41f252057dd7 diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterReflowTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterReflowTest.java new file mode 100644 index 0000000000..d9e50d20af --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/DiffFormatterReflowTest.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Johannes E. Schindelin <johannes.schindelin@gmx.de> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.diff; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.patch.FileHeader; +import org.eclipse.jgit.patch.Patch; +import org.eclipse.jgit.util.RawParseUtils; + +public class DiffFormatterReflowTest extends TestCase { + private RawText a; + + private RawText b; + + private FileHeader file; + + private ByteArrayOutputStream out; + + private DiffFormatter fmt; + + protected void setUp() throws Exception { + super.setUp(); + out = new ByteArrayOutputStream(); + fmt = new DiffFormatter(); + } + + public void testNegativeContextFails() throws IOException { + init("X"); + try { + fmt.setContext(-1); + fail("accepted negative context"); + } catch (IllegalArgumentException e) { + // pass + } + } + + public void testContext0() throws IOException { + init("X"); + fmt.setContext(0); + assertFormatted(); + } + + public void testContext1() throws IOException { + init("X"); + fmt.setContext(1); + assertFormatted(); + } + + public void testContext3() throws IOException { + init("X"); + fmt.setContext(3); + assertFormatted(); + } + + public void testContext5() throws IOException { + init("X"); + fmt.setContext(5); + assertFormatted(); + } + + public void testContext10() throws IOException { + init("X"); + fmt.setContext(10); + assertFormatted(); + } + + public void testContext100() throws IOException { + init("X"); + fmt.setContext(100); + assertFormatted(); + } + + public void testEmpty1() throws IOException { + init("E"); + assertFormatted("E.patch"); + } + + public void testNoNewLine1() throws IOException { + init("Y"); + assertFormatted("Y.patch"); + } + + public void testNoNewLine2() throws IOException { + init("Z"); + assertFormatted("Z.patch"); + } + + private void init(final String name) throws IOException { + a = new RawText(readFile(name + "_PreImage")); + b = new RawText(readFile(name + "_PostImage")); + file = parseTestPatchFile(name + ".patch").getFiles().get(0); + } + + private void assertFormatted() throws IOException { + assertFormatted(getName() + ".out"); + } + + private void assertFormatted(final String name) throws IOException { + fmt.format(out, file, a, b); + final String exp = RawParseUtils.decode(readFile(name)); + assertEquals(exp, RawParseUtils.decode(out.toByteArray())); + } + + private byte[] readFile(final String patchFile) throws IOException { + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final byte[] buf = new byte[1024]; + final ByteArrayOutputStream temp = new ByteArrayOutputStream(); + int n; + while ((n = in.read(buf)) > 0) + temp.write(buf, 0, n); + return temp.toByteArray(); + } finally { + in.close(); + } + } + + private Patch parseTestPatchFile(final String patchFile) throws IOException { + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java new file mode 100644 index 0000000000..5c2c3d0a22 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditListTest.java @@ -0,0 +1,127 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.diff; + +import java.util.Iterator; + +import junit.framework.TestCase; + +public class EditListTest extends TestCase { + public void testEmpty() { + final EditList l = new EditList(); + assertEquals(0, l.size()); + assertTrue(l.isEmpty()); + assertEquals("EditList[]", l.toString()); + + assertTrue(l.equals(l)); + assertTrue(l.equals(new EditList())); + assertFalse(l.equals("")); + assertEquals(l.hashCode(), new EditList().hashCode()); + } + + public void testAddOne() { + final Edit e = new Edit(1, 2, 1, 1); + final EditList l = new EditList(); + l.add(e); + assertEquals(1, l.size()); + assertFalse(l.isEmpty()); + assertSame(e, l.get(0)); + assertSame(e, l.iterator().next()); + + assertTrue(l.equals(l)); + assertFalse(l.equals(new EditList())); + + final EditList l2 = new EditList(); + l2.add(e); + assertTrue(l.equals(l2)); + assertTrue(l2.equals(l)); + assertEquals(l.hashCode(), l2.hashCode()); + } + + public void testAddTwo() { + final Edit e1 = new Edit(1, 2, 1, 1); + final Edit e2 = new Edit(8, 8, 8, 12); + final EditList l = new EditList(); + l.add(e1); + l.add(e2); + assertEquals(2, l.size()); + assertSame(e1, l.get(0)); + assertSame(e2, l.get(1)); + + final Iterator<Edit> i = l.iterator(); + assertSame(e1, i.next()); + assertSame(e2, i.next()); + + assertTrue(l.equals(l)); + assertFalse(l.equals(new EditList())); + + final EditList l2 = new EditList(); + l2.add(e1); + l2.add(e2); + assertTrue(l.equals(l2)); + assertTrue(l2.equals(l)); + assertEquals(l.hashCode(), l2.hashCode()); + } + + public void testSet() { + final Edit e1 = new Edit(1, 2, 1, 1); + final Edit e2 = new Edit(3, 4, 3, 3); + final EditList l = new EditList(); + l.add(e1); + assertSame(e1, l.get(0)); + assertSame(e1, l.set(0, e2)); + assertSame(e2, l.get(0)); + } + + public void testRemove() { + final Edit e1 = new Edit(1, 2, 1, 1); + final Edit e2 = new Edit(8, 8, 8, 12); + final EditList l = new EditList(); + l.add(e1); + l.add(e2); + l.remove(e1); + assertEquals(1, l.size()); + assertSame(e2, l.get(0)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java new file mode 100644 index 0000000000..6f3d21e558 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/EditTest.java @@ -0,0 +1,146 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Johannes E. Schindelin <johannes.schindelin@gmx.de> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.diff; + +import junit.framework.TestCase; + +public class EditTest extends TestCase { + public void testCreate() { + final Edit e = new Edit(1, 2, 3, 4); + assertEquals(1, e.getBeginA()); + assertEquals(2, e.getEndA()); + assertEquals(3, e.getBeginB()); + assertEquals(4, e.getEndB()); + } + + public void testCreateEmpty() { + final Edit e = new Edit(1, 3); + assertEquals(1, e.getBeginA()); + assertEquals(1, e.getEndA()); + assertEquals(3, e.getBeginB()); + assertEquals(3, e.getEndB()); + } + + public void testSwap() { + final Edit e = new Edit(1, 2, 3, 4); + e.swap(); + assertEquals(3, e.getBeginA()); + assertEquals(4, e.getEndA()); + assertEquals(1, e.getBeginB()); + assertEquals(2, e.getEndB()); + } + + public void testType_Insert() { + final Edit e = new Edit(1, 1, 1, 2); + assertSame(Edit.Type.INSERT, e.getType()); + } + + public void testType_Delete() { + final Edit e = new Edit(1, 2, 1, 1); + assertSame(Edit.Type.DELETE, e.getType()); + } + + public void testType_Replace() { + final Edit e = new Edit(1, 2, 1, 4); + assertSame(Edit.Type.REPLACE, e.getType()); + } + + public void testType_Empty() { + assertSame(Edit.Type.EMPTY, new Edit(1, 1, 2, 2).getType()); + assertSame(Edit.Type.EMPTY, new Edit(1, 2).getType()); + } + + public void testToString() { + final Edit e = new Edit(1, 2, 1, 4); + assertEquals("REPLACE(1-2,1-4)", e.toString()); + } + + public void testEquals1() { + final Edit e1 = new Edit(1, 2, 3, 4); + final Edit e2 = new Edit(1, 2, 3, 4); + + assertTrue(e1.equals(e1)); + assertTrue(e1.equals(e2)); + assertTrue(e2.equals(e1)); + assertEquals(e1.hashCode(), e2.hashCode()); + assertFalse(e1.equals("")); + } + + public void testNotEquals1() { + assertFalse(new Edit(1, 2, 3, 4).equals(new Edit(0, 2, 3, 4))); + } + + public void testNotEquals2() { + assertFalse(new Edit(1, 2, 3, 4).equals(new Edit(1, 0, 3, 4))); + } + + public void testNotEquals3() { + assertFalse(new Edit(1, 2, 3, 4).equals(new Edit(1, 2, 0, 4))); + } + + public void testNotEquals4() { + assertFalse(new Edit(1, 2, 3, 4).equals(new Edit(1, 2, 3, 0))); + } + + public void testExtendA() { + final Edit e = new Edit(1, 2, 1, 1); + + e.extendA(); + assertEquals(new Edit(1, 3, 1, 1), e); + + e.extendA(); + assertEquals(new Edit(1, 4, 1, 1), e); + } + + public void testExtendB() { + final Edit e = new Edit(1, 2, 1, 1); + + e.extendB(); + assertEquals(new Edit(1, 2, 1, 2), e); + + e.extendB(); + assertEquals(new Edit(1, 2, 1, 3), e); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java new file mode 100644 index 0000000000..5cb8bc3945 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/diff/RawTextTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Johannes E. Schindelin <johannes.schindelin@gmx.de> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.diff; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.util.RawParseUtils; + +public class RawTextTest extends TestCase { + public void testEmpty() { + final RawText r = new RawText(new byte[0]); + assertEquals(0, r.size()); + } + + public void testEquals() { + final RawText a = new RawText(Constants.encodeASCII("foo-a\nfoo-b\n")); + final RawText b = new RawText(Constants.encodeASCII("foo-b\nfoo-c\n")); + + assertEquals(2, a.size()); + assertEquals(2, b.size()); + + // foo-a != foo-b + assertFalse(a.equals(0, b, 0)); + assertFalse(b.equals(0, a, 0)); + + // foo-b == foo-b + assertTrue(a.equals(1, b, 0)); + assertTrue(b.equals(0, a, 1)); + } + + public void testWriteLine1() throws IOException { + final RawText a = new RawText(Constants.encodeASCII("foo-a\nfoo-b\n")); + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + a.writeLine(o, 0); + final byte[] r = o.toByteArray(); + assertEquals("foo-a", RawParseUtils.decode(r)); + } + + public void testWriteLine2() throws IOException { + final RawText a = new RawText(Constants.encodeASCII("foo-a\nfoo-b")); + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + a.writeLine(o, 1); + final byte[] r = o.toByteArray(); + assertEquals("foo-b", RawParseUtils.decode(r)); + } + + public void testWriteLine3() throws IOException { + final RawText a = new RawText(Constants.encodeASCII("a\n\nb\n")); + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + a.writeLine(o, 1); + final byte[] r = o.toByteArray(); + assertEquals("", RawParseUtils.decode(r)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java new file mode 100644 index 0000000000..cc37c2bf8b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBasicTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.io.File; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class DirCacheBasicTest extends RepositoryTestCase { + public void testReadMissing_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + assertFalse(idx.exists()); + + final DirCache dc = DirCache.read(db); + assertNotNull(dc); + assertEquals(0, dc.getEntryCount()); + } + + public void testReadMissing_TempIndex() throws Exception { + final File idx = new File(db.getDirectory(), "tmp_index"); + assertFalse(idx.exists()); + + final DirCache dc = DirCache.read(idx); + assertNotNull(dc); + assertEquals(0, dc.getEntryCount()); + } + + public void testLockMissing_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + final File lck = new File(db.getDirectory(), "index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + + final DirCache dc = DirCache.lock(db); + assertNotNull(dc); + assertFalse(idx.exists()); + assertTrue(lck.exists()); + assertEquals(0, dc.getEntryCount()); + + dc.unlock(); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + } + + public void testLockMissing_TempIndex() throws Exception { + final File idx = new File(db.getDirectory(), "tmp_index"); + final File lck = new File(db.getDirectory(), "tmp_index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + + final DirCache dc = DirCache.lock(idx); + assertNotNull(dc); + assertFalse(idx.exists()); + assertTrue(lck.exists()); + assertEquals(0, dc.getEntryCount()); + + dc.unlock(); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + } + + public void testWriteEmptyUnlock_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + final File lck = new File(db.getDirectory(), "index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + + final DirCache dc = DirCache.lock(db); + assertEquals(0, lck.length()); + dc.write(); + assertEquals(12 + 20, lck.length()); + + dc.unlock(); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + } + + public void testWriteEmptyCommit_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + final File lck = new File(db.getDirectory(), "index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + + final DirCache dc = DirCache.lock(db); + assertEquals(0, lck.length()); + dc.write(); + assertEquals(12 + 20, lck.length()); + + assertTrue(dc.commit()); + assertTrue(idx.exists()); + assertFalse(lck.exists()); + assertEquals(12 + 20, idx.length()); + } + + public void testWriteEmptyReadEmpty_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + final File lck = new File(db.getDirectory(), "index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + { + final DirCache dc = DirCache.lock(db); + dc.write(); + assertTrue(dc.commit()); + assertTrue(idx.exists()); + } + { + final DirCache dc = DirCache.read(db); + assertEquals(0, dc.getEntryCount()); + } + } + + public void testWriteEmptyLockEmpty_RealIndex() throws Exception { + final File idx = new File(db.getDirectory(), "index"); + final File lck = new File(db.getDirectory(), "index.lock"); + assertFalse(idx.exists()); + assertFalse(lck.exists()); + { + final DirCache dc = DirCache.lock(db); + dc.write(); + assertTrue(dc.commit()); + assertTrue(idx.exists()); + } + { + final DirCache dc = DirCache.lock(db); + assertEquals(0, dc.getEntryCount()); + assertTrue(idx.exists()); + assertTrue(lck.exists()); + dc.unlock(); + } + } + + public void testBuildThenClear() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + assertEquals(paths.length, dc.getEntryCount()); + dc.clear(); + assertEquals(0, dc.getEntryCount()); + } + + public void testFindOnEmpty() throws Exception { + final DirCache dc = DirCache.newInCore(); + final byte[] path = Constants.encode("a"); + assertEquals(-1, dc.findEntry(path, path.length)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java new file mode 100644 index 0000000000..03bb7f5e83 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderIteratorTest.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.util.Collections; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; + +public class DirCacheBuilderIteratorTest extends RepositoryTestCase { + public void testPathFilterGroup_DoesNotSkipTail() throws Exception { + final DirCache dc = DirCache.read(db); + + final FileMode mode = FileMode.REGULAR_FILE; + final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(mode); + } + { + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + } + + final int expIdx = 2; + final DirCacheBuilder b = dc.builder(); + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheBuildIterator(b)); + tw.setRecursive(true); + tw.setFilter(PathFilterGroup.createFromStrings(Collections + .singleton(paths[expIdx]))); + + assertTrue("found " + paths[expIdx], tw.next()); + final DirCacheIterator c = tw.getTree(0, DirCacheIterator.class); + assertNotNull(c); + assertEquals(expIdx, c.ptr); + assertSame(ents[expIdx], c.getDirCacheEntry()); + assertEquals(paths[expIdx], tw.getPathString()); + assertEquals(mode.getBits(), tw.getRawMode(0)); + assertSame(mode, tw.getFileMode(0)); + b.add(c.getDirCacheEntry()); + + assertFalse("no more entries", tw.next()); + + b.finish(); + assertEquals(ents.length, dc.getEntryCount()); + for (int i = 0; i < ents.length; i++) + assertSame(ents[i], dc.getEntry(i)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java new file mode 100644 index 0000000000..fe02a1b23e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheBuilderTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.io.File; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class DirCacheBuilderTest extends RepositoryTestCase { + public void testBuildEmpty() throws Exception { + { + final DirCache dc = DirCache.lock(db); + final DirCacheBuilder b = dc.builder(); + assertNotNull(b); + b.finish(); + dc.write(); + assertTrue(dc.commit()); + } + { + final DirCache dc = DirCache.read(db); + assertEquals(0, dc.getEntryCount()); + } + } + + public void testBuildOneFile_FinishWriteCommit() throws Exception { + final String path = "a-file-path"; + final FileMode mode = FileMode.REGULAR_FILE; + final long lastModified = 1218123387057L; + final int length = 1342; + final DirCacheEntry entOrig; + { + final DirCache dc = DirCache.lock(db); + final DirCacheBuilder b = dc.builder(); + assertNotNull(b); + + entOrig = new DirCacheEntry(path); + entOrig.setFileMode(mode); + entOrig.setLastModified(lastModified); + entOrig.setLength(length); + + assertNotSame(path, entOrig.getPathString()); + assertEquals(path, entOrig.getPathString()); + assertEquals(ObjectId.zeroId(), entOrig.getObjectId()); + assertEquals(mode.getBits(), entOrig.getRawMode()); + assertEquals(0, entOrig.getStage()); + assertEquals(lastModified, entOrig.getLastModified()); + assertEquals(length, entOrig.getLength()); + assertFalse(entOrig.isAssumeValid()); + b.add(entOrig); + + b.finish(); + assertEquals(1, dc.getEntryCount()); + assertSame(entOrig, dc.getEntry(0)); + + dc.write(); + assertTrue(dc.commit()); + } + { + final DirCache dc = DirCache.read(db); + assertEquals(1, dc.getEntryCount()); + + final DirCacheEntry entRead = dc.getEntry(0); + assertNotSame(entOrig, entRead); + assertEquals(path, entRead.getPathString()); + assertEquals(ObjectId.zeroId(), entOrig.getObjectId()); + assertEquals(mode.getBits(), entOrig.getRawMode()); + assertEquals(0, entOrig.getStage()); + assertEquals(lastModified, entOrig.getLastModified()); + assertEquals(length, entOrig.getLength()); + assertFalse(entOrig.isAssumeValid()); + } + } + + public void testBuildOneFile_Commit() throws Exception { + final String path = "a-file-path"; + final FileMode mode = FileMode.REGULAR_FILE; + final long lastModified = 1218123387057L; + final int length = 1342; + final DirCacheEntry entOrig; + { + final DirCache dc = DirCache.lock(db); + final DirCacheBuilder b = dc.builder(); + assertNotNull(b); + + entOrig = new DirCacheEntry(path); + entOrig.setFileMode(mode); + entOrig.setLastModified(lastModified); + entOrig.setLength(length); + + assertNotSame(path, entOrig.getPathString()); + assertEquals(path, entOrig.getPathString()); + assertEquals(ObjectId.zeroId(), entOrig.getObjectId()); + assertEquals(mode.getBits(), entOrig.getRawMode()); + assertEquals(0, entOrig.getStage()); + assertEquals(lastModified, entOrig.getLastModified()); + assertEquals(length, entOrig.getLength()); + assertFalse(entOrig.isAssumeValid()); + b.add(entOrig); + + assertTrue(b.commit()); + assertEquals(1, dc.getEntryCount()); + assertSame(entOrig, dc.getEntry(0)); + assertFalse(new File(db.getDirectory(), "index.lock").exists()); + } + { + final DirCache dc = DirCache.read(db); + assertEquals(1, dc.getEntryCount()); + + final DirCacheEntry entRead = dc.getEntry(0); + assertNotSame(entOrig, entRead); + assertEquals(path, entRead.getPathString()); + assertEquals(ObjectId.zeroId(), entOrig.getObjectId()); + assertEquals(mode.getBits(), entOrig.getRawMode()); + assertEquals(0, entOrig.getStage()); + assertEquals(lastModified, entOrig.getLastModified()); + assertEquals(length, entOrig.getLength()); + assertFalse(entOrig.isAssumeValid()); + } + } + + public void testFindSingleFile() throws Exception { + final String path = "a-file-path"; + final DirCache dc = DirCache.read(db); + final DirCacheBuilder b = dc.builder(); + assertNotNull(b); + + final DirCacheEntry entOrig = new DirCacheEntry(path); + assertNotSame(path, entOrig.getPathString()); + assertEquals(path, entOrig.getPathString()); + b.add(entOrig); + b.finish(); + + assertEquals(1, dc.getEntryCount()); + assertSame(entOrig, dc.getEntry(0)); + assertEquals(0, dc.findEntry(path)); + + assertEquals(-1, dc.findEntry("@@-before")); + assertEquals(0, real(dc.findEntry("@@-before"))); + + assertEquals(-2, dc.findEntry("a-zoo")); + assertEquals(1, real(dc.findEntry("a-zoo"))); + + assertSame(entOrig, dc.getEntry(path)); + } + + public void testAdd_InGitSortOrder() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + assertEquals(paths.length, dc.getEntryCount()); + for (int i = 0; i < paths.length; i++) { + assertSame(ents[i], dc.getEntry(i)); + assertEquals(paths[i], dc.getEntry(i).getPathString()); + assertEquals(i, dc.findEntry(paths[i])); + assertSame(ents[i], dc.getEntry(paths[i])); + } + } + + public void testAdd_ReverseGitSortOrder() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + + final DirCacheBuilder b = dc.builder(); + for (int i = ents.length - 1; i >= 0; i--) + b.add(ents[i]); + b.finish(); + + assertEquals(paths.length, dc.getEntryCount()); + for (int i = 0; i < paths.length; i++) { + assertSame(ents[i], dc.getEntry(i)); + assertEquals(paths[i], dc.getEntry(i).getPathString()); + assertEquals(i, dc.findEntry(paths[i])); + assertSame(ents[i], dc.getEntry(paths[i])); + } + } + + public void testBuilderClear() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a.b", "a/b", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + { + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + } + assertEquals(paths.length, dc.getEntryCount()); + { + final DirCacheBuilder b = dc.builder(); + b.finish(); + } + assertEquals(0, dc.getEntryCount()); + } + + private static int real(int eIdx) { + if (eIdx < 0) + eIdx = -(eIdx + 1); + return eIdx; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java new file mode 100644 index 0000000000..ab0c77110d --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheCGitCompatabilityTest.java @@ -0,0 +1,219 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.Map; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.util.JGitTestUtil; + +public class DirCacheCGitCompatabilityTest extends RepositoryTestCase { + private final File index = pathOf("gitgit.index"); + + public void testReadIndex_LsFiles() throws Exception { + final Map<String, CGitIndexRecord> ls = readLsFiles(); + final DirCache dc = new DirCache(index); + assertEquals(0, dc.getEntryCount()); + dc.read(); + assertEquals(ls.size(), dc.getEntryCount()); + { + final Iterator<CGitIndexRecord> rItr = ls.values().iterator(); + for (int i = 0; rItr.hasNext(); i++) + assertEqual(rItr.next(), dc.getEntry(i)); + } + } + + public void testTreeWalk_LsFiles() throws Exception { + final Map<String, CGitIndexRecord> ls = readLsFiles(); + final DirCache dc = new DirCache(index); + assertEquals(0, dc.getEntryCount()); + dc.read(); + assertEquals(ls.size(), dc.getEntryCount()); + { + final Iterator<CGitIndexRecord> rItr = ls.values().iterator(); + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.setRecursive(true); + tw.addTree(new DirCacheIterator(dc)); + while (rItr.hasNext()) { + final DirCacheIterator dcItr; + + assertTrue(tw.next()); + dcItr = tw.getTree(0, DirCacheIterator.class); + assertNotNull(dcItr); + + assertEqual(rItr.next(), dcItr.getDirCacheEntry()); + } + } + } + + private static void assertEqual(final CGitIndexRecord c, + final DirCacheEntry j) { + assertNotNull(c); + assertNotNull(j); + + assertEquals(c.path, j.getPathString()); + assertEquals(c.id, j.getObjectId()); + assertEquals(c.mode, j.getRawMode()); + assertEquals(c.stage, j.getStage()); + } + + public void testReadIndex_DirCacheTree() throws Exception { + final Map<String, CGitIndexRecord> cList = readLsFiles(); + final Map<String, CGitLsTreeRecord> cTree = readLsTree(); + final DirCache dc = new DirCache(index); + assertEquals(0, dc.getEntryCount()); + dc.read(); + assertEquals(cList.size(), dc.getEntryCount()); + + final DirCacheTree jTree = dc.getCacheTree(false); + assertNotNull(jTree); + assertEquals("", jTree.getNameString()); + assertEquals("", jTree.getPathString()); + assertTrue(jTree.isValid()); + assertEquals(ObjectId + .fromString("698dd0b8d0c299f080559a1cffc7fe029479a408"), jTree + .getObjectId()); + assertEquals(cList.size(), jTree.getEntrySpan()); + + final ArrayList<CGitLsTreeRecord> subtrees = new ArrayList<CGitLsTreeRecord>(); + for (final CGitLsTreeRecord r : cTree.values()) { + if (FileMode.TREE.equals(r.mode)) + subtrees.add(r); + } + assertEquals(subtrees.size(), jTree.getChildCount()); + + for (int i = 0; i < jTree.getChildCount(); i++) { + final DirCacheTree sj = jTree.getChild(i); + final CGitLsTreeRecord sc = subtrees.get(i); + assertEquals(sc.path, sj.getNameString()); + assertEquals(sc.path + "/", sj.getPathString()); + assertTrue(sj.isValid()); + assertEquals(sc.id, sj.getObjectId()); + } + } + + private File pathOf(final String name) { + return JGitTestUtil.getTestResourceFile(name); + } + + private Map<String, CGitIndexRecord> readLsFiles() throws Exception { + final LinkedHashMap<String, CGitIndexRecord> r = new LinkedHashMap<String, CGitIndexRecord>(); + final BufferedReader br = new BufferedReader(new InputStreamReader( + new FileInputStream(pathOf("gitgit.lsfiles")), "UTF-8")); + try { + String line; + while ((line = br.readLine()) != null) { + final CGitIndexRecord cr = new CGitIndexRecord(line); + r.put(cr.path, cr); + } + } finally { + br.close(); + } + return r; + } + + private Map<String, CGitLsTreeRecord> readLsTree() throws Exception { + final LinkedHashMap<String, CGitLsTreeRecord> r = new LinkedHashMap<String, CGitLsTreeRecord>(); + final BufferedReader br = new BufferedReader(new InputStreamReader( + new FileInputStream(pathOf("gitgit.lstree")), "UTF-8")); + try { + String line; + while ((line = br.readLine()) != null) { + final CGitLsTreeRecord cr = new CGitLsTreeRecord(line); + r.put(cr.path, cr); + } + } finally { + br.close(); + } + return r; + } + + private static class CGitIndexRecord { + final int mode; + + final ObjectId id; + + final int stage; + + final String path; + + CGitIndexRecord(final String line) { + final int tab = line.indexOf('\t'); + final int sp1 = line.indexOf(' '); + final int sp2 = line.indexOf(' ', sp1 + 1); + mode = Integer.parseInt(line.substring(0, sp1), 8); + id = ObjectId.fromString(line.substring(sp1 + 1, sp2)); + stage = Integer.parseInt(line.substring(sp2 + 1, tab)); + path = line.substring(tab + 1); + } + } + + private static class CGitLsTreeRecord { + final int mode; + + final ObjectId id; + + final String path; + + CGitLsTreeRecord(final String line) { + final int tab = line.indexOf('\t'); + final int sp1 = line.indexOf(' '); + final int sp2 = line.indexOf(' ', sp1 + 1); + mode = Integer.parseInt(line.substring(0, sp1), 8); + id = ObjectId.fromString(line.substring(sp2 + 1, tab)); + path = line.substring(tab + 1); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java new file mode 100644 index 0000000000..cdc659a21c --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheFindTest.java @@ -0,0 +1,92 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class DirCacheFindTest extends RepositoryTestCase { + public void testEntriesWithin() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + final int aFirst = 1; + final int aLast = 3; + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + assertEquals(paths.length, dc.getEntryCount()); + for (int i = 0; i < ents.length; i++) + assertSame(ents[i], dc.getEntry(i)); + + { + final DirCacheEntry[] aContents = dc.getEntriesWithin("a"); + assertNotNull(aContents); + assertEquals(aLast - aFirst + 1, aContents.length); + for (int i = aFirst, j = 0; i <= aLast; i++, j++) + assertSame(ents[i], aContents[j]); + } + { + final DirCacheEntry[] aContents = dc.getEntriesWithin("a/"); + assertNotNull(aContents); + assertEquals(aLast - aFirst + 1, aContents.length); + for (int i = aFirst, j = 0; i <= aLast; i++, j++) + assertSame(ents[i], aContents[j]); + } + + assertNotNull(dc.getEntriesWithin("a.")); + assertEquals(0, dc.getEntriesWithin("a.").length); + + assertNotNull(dc.getEntriesWithin("a0b")); + assertEquals(0, dc.getEntriesWithin("a0b.").length); + + assertNotNull(dc.getEntriesWithin("zoo")); + assertEquals(0, dc.getEntriesWithin("zoo.").length); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java new file mode 100644 index 0000000000..db9f684fed --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheIteratorTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.util.Collections; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; + +public class DirCacheIteratorTest extends RepositoryTestCase { + public void testEmptyTree_NoTreeWalk() throws Exception { + final DirCache dc = DirCache.read(db); + assertEquals(0, dc.getEntryCount()); + + final DirCacheIterator i = new DirCacheIterator(dc); + assertTrue(i.eof()); + } + + public void testEmptyTree_WithTreeWalk() throws Exception { + final DirCache dc = DirCache.read(db); + assertEquals(0, dc.getEntryCount()); + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(dc)); + assertFalse(tw.next()); + } + + public void testNoSubtree_NoTreeWalk() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final DirCacheIterator i = new DirCacheIterator(dc); + int pathIdx = 0; + for (; !i.eof(); i.next(1)) { + assertEquals(pathIdx, i.ptr); + assertSame(ents[pathIdx], i.getDirCacheEntry()); + pathIdx++; + } + assertEquals(paths.length, pathIdx); + } + + public void testNoSubtree_WithTreeWalk() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a0b" }; + final FileMode[] modes = { FileMode.EXECUTABLE_FILE, FileMode.GITLINK }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(modes[i]); + } + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final DirCacheIterator i = new DirCacheIterator(dc); + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(i); + int pathIdx = 0; + while (tw.next()) { + assertSame(i, tw.getTree(0, DirCacheIterator.class)); + assertEquals(pathIdx, i.ptr); + assertSame(ents[pathIdx], i.getDirCacheEntry()); + assertEquals(paths[pathIdx], tw.getPathString()); + assertEquals(modes[pathIdx].getBits(), tw.getRawMode(0)); + assertSame(modes[pathIdx], tw.getFileMode(0)); + pathIdx++; + } + assertEquals(paths.length, pathIdx); + } + + public void testSingleSubtree_NoRecursion() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(FileMode.REGULAR_FILE); + } + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final String[] expPaths = { "a.", "a", "a0b" }; + final FileMode[] expModes = { FileMode.REGULAR_FILE, FileMode.TREE, + FileMode.REGULAR_FILE }; + final int expPos[] = { 0, -1, 4 }; + + final DirCacheIterator i = new DirCacheIterator(dc); + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(i); + tw.setRecursive(false); + int pathIdx = 0; + while (tw.next()) { + assertSame(i, tw.getTree(0, DirCacheIterator.class)); + assertEquals(expModes[pathIdx].getBits(), tw.getRawMode(0)); + assertSame(expModes[pathIdx], tw.getFileMode(0)); + assertEquals(expPaths[pathIdx], tw.getPathString()); + + if (expPos[pathIdx] >= 0) { + assertEquals(expPos[pathIdx], i.ptr); + assertSame(ents[expPos[pathIdx]], i.getDirCacheEntry()); + } else { + assertSame(FileMode.TREE, tw.getFileMode(0)); + } + + pathIdx++; + } + assertEquals(expPaths.length, pathIdx); + } + + public void testSingleSubtree_Recursive() throws Exception { + final DirCache dc = DirCache.read(db); + + final FileMode mode = FileMode.REGULAR_FILE; + final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(mode); + } + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final DirCacheIterator i = new DirCacheIterator(dc); + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(i); + tw.setRecursive(true); + int pathIdx = 0; + while (tw.next()) { + final DirCacheIterator c = tw.getTree(0, DirCacheIterator.class); + assertNotNull(c); + assertEquals(pathIdx, c.ptr); + assertSame(ents[pathIdx], c.getDirCacheEntry()); + assertEquals(paths[pathIdx], tw.getPathString()); + assertEquals(mode.getBits(), tw.getRawMode(0)); + assertSame(mode, tw.getFileMode(0)); + pathIdx++; + } + assertEquals(paths.length, pathIdx); + } + + public void testTwoLevelSubtree_Recursive() throws Exception { + final DirCache dc = DirCache.read(db); + + final FileMode mode = FileMode.REGULAR_FILE; + final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(mode); + } + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(dc)); + tw.setRecursive(true); + int pathIdx = 0; + while (tw.next()) { + final DirCacheIterator c = tw.getTree(0, DirCacheIterator.class); + assertNotNull(c); + assertEquals(pathIdx, c.ptr); + assertSame(ents[pathIdx], c.getDirCacheEntry()); + assertEquals(paths[pathIdx], tw.getPathString()); + assertEquals(mode.getBits(), tw.getRawMode(0)); + assertSame(mode, tw.getFileMode(0)); + pathIdx++; + } + assertEquals(paths.length, pathIdx); + } + + public void testTwoLevelSubtree_FilterPath() throws Exception { + final DirCache dc = DirCache.read(db); + + final FileMode mode = FileMode.REGULAR_FILE; + final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) { + ents[i] = new DirCacheEntry(paths[i]); + ents[i].setFileMode(mode); + } + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + final TreeWalk tw = new TreeWalk(db); + for (int victimIdx = 0; victimIdx < paths.length; victimIdx++) { + tw.reset(); + tw.addTree(new DirCacheIterator(dc)); + tw.setFilter(PathFilterGroup.createFromStrings(Collections + .singleton(paths[victimIdx]))); + tw.setRecursive(tw.getFilter().shouldBeRecursive()); + assertTrue(tw.next()); + final DirCacheIterator c = tw.getTree(0, DirCacheIterator.class); + assertNotNull(c); + assertEquals(victimIdx, c.ptr); + assertSame(ents[victimIdx], c.getDirCacheEntry()); + assertEquals(paths[victimIdx], tw.getPathString()); + assertEquals(mode.getBits(), tw.getRawMode(0)); + assertSame(mode, tw.getFileMode(0)); + assertFalse(tw.next()); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java new file mode 100644 index 0000000000..ceaadf97b6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheLargePathTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.io.IOException; + +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class DirCacheLargePathTest extends RepositoryTestCase { + public void testPath_4090() throws Exception { + testLongPath(4090); + } + + public void testPath_4094() throws Exception { + testLongPath(4094); + } + + public void testPath_4095() throws Exception { + testLongPath(4095); + } + + public void testPath_4096() throws Exception { + testLongPath(4096); + } + + public void testPath_16384() throws Exception { + testLongPath(16384); + } + + private void testLongPath(final int len) throws CorruptObjectException, + IOException { + final String longPath = makeLongPath(len); + final String shortPath = "~~~ shorter-path"; + + final DirCacheEntry longEnt = new DirCacheEntry(longPath); + final DirCacheEntry shortEnt = new DirCacheEntry(shortPath); + assertEquals(longPath, longEnt.getPathString()); + assertEquals(shortPath, shortEnt.getPathString()); + + { + final DirCache dc1 = DirCache.lock(db); + { + final DirCacheBuilder b = dc1.builder(); + b.add(longEnt); + b.add(shortEnt); + assertTrue(b.commit()); + } + assertEquals(2, dc1.getEntryCount()); + assertSame(longEnt, dc1.getEntry(0)); + assertSame(shortEnt, dc1.getEntry(1)); + } + { + final DirCache dc2 = DirCache.read(db); + assertEquals(2, dc2.getEntryCount()); + + assertNotSame(longEnt, dc2.getEntry(0)); + assertEquals(longPath, dc2.getEntry(0).getPathString()); + + assertNotSame(shortEnt, dc2.getEntry(1)); + assertEquals(shortPath, dc2.getEntry(1).getPathString()); + } + } + + private static String makeLongPath(final int len) { + final StringBuilder r = new StringBuilder(len); + for (int i = 0; i < len; i++) + r.append('a' + (i % 26)); + return r.toString(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java new file mode 100644 index 0000000000..b84b240a74 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/dircache/DirCacheTreeTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.dircache; + +import java.io.IOException; + +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class DirCacheTreeTest extends RepositoryTestCase { + public void testEmptyCache_NoCacheTree() throws Exception { + final DirCache dc = DirCache.read(db); + assertNull(dc.getCacheTree(false)); + } + + public void testEmptyCache_CreateEmptyCacheTree() throws Exception { + final DirCache dc = DirCache.read(db); + final DirCacheTree tree = dc.getCacheTree(true); + assertNotNull(tree); + assertSame(tree, dc.getCacheTree(false)); + assertSame(tree, dc.getCacheTree(true)); + assertEquals("", tree.getNameString()); + assertEquals("", tree.getPathString()); + assertEquals(0, tree.getChildCount()); + assertEquals(0, tree.getEntrySpan()); + assertFalse(tree.isValid()); + } + + public void testEmptyCache_Clear_NoCacheTree() throws Exception { + final DirCache dc = DirCache.read(db); + final DirCacheTree tree = dc.getCacheTree(true); + assertNotNull(tree); + dc.clear(); + assertNull(dc.getCacheTree(false)); + assertNotSame(tree, dc.getCacheTree(true)); + } + + public void testSingleSubtree() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a/b", "a/c", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + final int aFirst = 1; + final int aLast = 3; + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + assertNull(dc.getCacheTree(false)); + final DirCacheTree root = dc.getCacheTree(true); + assertNotNull(root); + assertSame(root, dc.getCacheTree(true)); + assertEquals("", root.getNameString()); + assertEquals("", root.getPathString()); + assertEquals(1, root.getChildCount()); + assertEquals(dc.getEntryCount(), root.getEntrySpan()); + assertFalse(root.isValid()); + + final DirCacheTree aTree = root.getChild(0); + assertNotNull(aTree); + assertSame(aTree, root.getChild(0)); + assertEquals("a", aTree.getNameString()); + assertEquals("a/", aTree.getPathString()); + assertEquals(0, aTree.getChildCount()); + assertEquals(aLast - aFirst + 1, aTree.getEntrySpan()); + assertFalse(aTree.isValid()); + } + + public void testTwoLevelSubtree() throws Exception { + final DirCache dc = DirCache.read(db); + + final String[] paths = { "a.", "a/b", "a/c/e", "a/c/f", "a/d", "a0b" }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + final int aFirst = 1; + final int aLast = 4; + final int acFirst = 2; + final int acLast = 3; + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + b.finish(); + + assertNull(dc.getCacheTree(false)); + final DirCacheTree root = dc.getCacheTree(true); + assertNotNull(root); + assertSame(root, dc.getCacheTree(true)); + assertEquals("", root.getNameString()); + assertEquals("", root.getPathString()); + assertEquals(1, root.getChildCount()); + assertEquals(dc.getEntryCount(), root.getEntrySpan()); + assertFalse(root.isValid()); + + final DirCacheTree aTree = root.getChild(0); + assertNotNull(aTree); + assertSame(aTree, root.getChild(0)); + assertEquals("a", aTree.getNameString()); + assertEquals("a/", aTree.getPathString()); + assertEquals(1, aTree.getChildCount()); + assertEquals(aLast - aFirst + 1, aTree.getEntrySpan()); + assertFalse(aTree.isValid()); + + final DirCacheTree acTree = aTree.getChild(0); + assertNotNull(acTree); + assertSame(acTree, aTree.getChild(0)); + assertEquals("c", acTree.getNameString()); + assertEquals("a/c/", acTree.getPathString()); + assertEquals(0, acTree.getChildCount()); + assertEquals(acLast - acFirst + 1, acTree.getEntrySpan()); + assertFalse(acTree.isValid()); + } + + /** + * We had bugs related to buffer size in the DirCache. This test creates an + * index larger than the default BufferedInputStream buffer size. This made + * the DirCache unable to read the extensions when index size exceeded the + * buffer size (in some cases at least). + * + * @throws CorruptObjectException + * @throws IOException + */ + public void testWriteReadTree() throws CorruptObjectException, IOException { + final DirCache dc = DirCache.lock(db); + + final String A = String.format("a%2000s", "a"); + final String B = String.format("b%2000s", "b"); + final String[] paths = { A + ".", A + "." + B, A + "/" + B, A + "0" + B }; + final DirCacheEntry[] ents = new DirCacheEntry[paths.length]; + for (int i = 0; i < paths.length; i++) + ents[i] = new DirCacheEntry(paths[i]); + + final DirCacheBuilder b = dc.builder(); + for (int i = 0; i < ents.length; i++) + b.add(ents[i]); + + b.commit(); + DirCache read = DirCache.read(db); + + assertEquals(paths.length, read.getEntryCount()); + assertEquals(1, read.getCacheTree(true).getChildCount()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java new file mode 100644 index 0000000000..752a1e2f68 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/fnmatch/FileNameMatcherTest.java @@ -0,0 +1,764 @@ +/* + * Copyright (C) 2008, Florian Koeberle <florianskarten@web.de> + * Copyright (C) 2008, Florian Köberle <florianskarten@web.de> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.fnmatch; + +import org.eclipse.jgit.errors.InvalidPatternException; +import org.eclipse.jgit.fnmatch.FileNameMatcher; + +import junit.framework.TestCase; + +public class FileNameMatcherTest extends TestCase { + + private void assertMatch(final String pattern, final String input, + final boolean matchExpected, final boolean appendCanMatchExpected) + throws InvalidPatternException { + final FileNameMatcher matcher = new FileNameMatcher(pattern, null); + matcher.append(input); + assertEquals(matchExpected, matcher.isMatch()); + assertEquals(appendCanMatchExpected, matcher.canAppendMatch()); + } + + private void assertFileNameMatch(final String pattern, final String input, + final char excludedCharacter, final boolean matchExpected, + final boolean appendCanMatchExpected) + throws InvalidPatternException { + final FileNameMatcher matcher = new FileNameMatcher(pattern, + new Character(excludedCharacter)); + matcher.append(input); + assertEquals(matchExpected, matcher.isMatch()); + assertEquals(appendCanMatchExpected, matcher.canAppendMatch()); + } + + public void testVerySimplePatternCase0() throws Exception { + assertMatch("", "", true, false); + } + + public void testVerySimplePatternCase1() throws Exception { + assertMatch("ab", "a", false, true); + } + + public void testVerySimplePatternCase2() throws Exception { + assertMatch("ab", "ab", true, false); + } + + public void testVerySimplePatternCase3() throws Exception { + assertMatch("ab", "ac", false, false); + } + + public void testVerySimplePatternCase4() throws Exception { + assertMatch("ab", "abc", false, false); + } + + public void testVerySimpleWirdcardCase0() throws Exception { + assertMatch("?", "a", true, false); + } + + public void testVerySimpleWildCardCase1() throws Exception { + assertMatch("??", "a", false, true); + } + + public void testVerySimpleWildCardCase2() throws Exception { + assertMatch("??", "ab", true, false); + } + + public void testVerySimpleWildCardCase3() throws Exception { + assertMatch("??", "abc", false, false); + } + + public void testVerySimpleStarCase0() throws Exception { + assertMatch("*", "", true, true); + } + + public void testVerySimpleStarCase1() throws Exception { + assertMatch("*", "a", true, true); + } + + public void testVerySimpleStarCase2() throws Exception { + assertMatch("*", "ab", true, true); + } + + public void testSimpleStarCase0() throws Exception { + assertMatch("a*b", "a", false, true); + } + + public void testSimpleStarCase1() throws Exception { + assertMatch("a*c", "ac", true, true); + } + + public void testSimpleStarCase2() throws Exception { + assertMatch("a*c", "ab", false, true); + } + + public void testSimpleStarCase3() throws Exception { + assertMatch("a*c", "abc", true, true); + } + + public void testManySolutionsCase0() throws Exception { + assertMatch("a*a*a", "aaa", true, true); + } + + public void testManySolutionsCase1() throws Exception { + assertMatch("a*a*a", "aaaa", true, true); + } + + public void testManySolutionsCase2() throws Exception { + assertMatch("a*a*a", "ababa", true, true); + } + + public void testManySolutionsCase3() throws Exception { + assertMatch("a*a*a", "aaaaaaaa", true, true); + } + + public void testManySolutionsCase4() throws Exception { + assertMatch("a*a*a", "aaaaaaab", false, true); + } + + public void testVerySimpleGroupCase0() throws Exception { + assertMatch("[ab]", "a", true, false); + } + + public void testVerySimpleGroupCase1() throws Exception { + assertMatch("[ab]", "b", true, false); + } + + public void testVerySimpleGroupCase2() throws Exception { + assertMatch("[ab]", "ab", false, false); + } + + public void testVerySimpleGroupRangeCase0() throws Exception { + assertMatch("[b-d]", "a", false, false); + } + + public void testVerySimpleGroupRangeCase1() throws Exception { + assertMatch("[b-d]", "b", true, false); + } + + public void testVerySimpleGroupRangeCase2() throws Exception { + assertMatch("[b-d]", "c", true, false); + } + + public void testVerySimpleGroupRangeCase3() throws Exception { + assertMatch("[b-d]", "d", true, false); + } + + public void testVerySimpleGroupRangeCase4() throws Exception { + assertMatch("[b-d]", "e", false, false); + } + + public void testVerySimpleGroupRangeCase5() throws Exception { + assertMatch("[b-d]", "-", false, false); + } + + public void testTwoGroupsCase0() throws Exception { + assertMatch("[b-d][ab]", "bb", true, false); + } + + public void testTwoGroupsCase1() throws Exception { + assertMatch("[b-d][ab]", "ca", true, false); + } + + public void testTwoGroupsCase2() throws Exception { + assertMatch("[b-d][ab]", "fa", false, false); + } + + public void testTwoGroupsCase3() throws Exception { + assertMatch("[b-d][ab]", "bc", false, false); + } + + public void testTwoRangesInOneGroupCase0() throws Exception { + assertMatch("[b-ce-e]", "a", false, false); + } + + public void testTwoRangesInOneGroupCase1() throws Exception { + assertMatch("[b-ce-e]", "b", true, false); + } + + public void testTwoRangesInOneGroupCase2() throws Exception { + assertMatch("[b-ce-e]", "c", true, false); + } + + public void testTwoRangesInOneGroupCase3() throws Exception { + assertMatch("[b-ce-e]", "d", false, false); + } + + public void testTwoRangesInOneGroupCase4() throws Exception { + assertMatch("[b-ce-e]", "e", true, false); + } + + public void testTwoRangesInOneGroupCase5() throws Exception { + assertMatch("[b-ce-e]", "f", false, false); + } + + public void testIncompleteRangesInOneGroupCase0() throws Exception { + assertMatch("a[b-]", "ab", true, false); + } + + public void testIncompleteRangesInOneGroupCase1() throws Exception { + assertMatch("a[b-]", "ac", false, false); + } + + public void testIncompleteRangesInOneGroupCase2() throws Exception { + assertMatch("a[b-]", "a-", true, false); + } + + public void testCombinedRangesInOneGroupCase0() throws Exception { + assertMatch("[a-c-e]", "b", true, false); + } + + /** + * The c belongs to the range a-c. "-e" is no valid range so d should not + * match. + * + * @throws Exception + * for some reasons + */ + public void testCombinedRangesInOneGroupCase1() throws Exception { + assertMatch("[a-c-e]", "d", false, false); + } + + public void testCombinedRangesInOneGroupCase2() throws Exception { + assertMatch("[a-c-e]", "e", true, false); + } + + public void testInversedGroupCase0() throws Exception { + assertMatch("[!b-c]", "a", true, false); + } + + public void testInversedGroupCase1() throws Exception { + assertMatch("[!b-c]", "b", false, false); + } + + public void testInversedGroupCase2() throws Exception { + assertMatch("[!b-c]", "c", false, false); + } + + public void testInversedGroupCase3() throws Exception { + assertMatch("[!b-c]", "d", true, false); + } + + public void testAlphaGroupCase0() throws Exception { + assertMatch("[[:alpha:]]", "d", true, false); + } + + public void testAlphaGroupCase1() throws Exception { + assertMatch("[[:alpha:]]", ":", false, false); + } + + public void testAlphaGroupCase2() throws Exception { + // \u00f6 = 'o' with dots on it + assertMatch("[[:alpha:]]", "\u00f6", true, false); + } + + public void test2AlphaGroupsCase0() throws Exception { + // \u00f6 = 'o' with dots on it + assertMatch("[[:alpha:]][[:alpha:]]", "a\u00f6", true, false); + assertMatch("[[:alpha:]][[:alpha:]]", "a1", false, false); + } + + public void testAlnumGroupCase0() throws Exception { + assertMatch("[[:alnum:]]", "a", true, false); + } + + public void testAlnumGroupCase1() throws Exception { + assertMatch("[[:alnum:]]", "1", true, false); + } + + public void testAlnumGroupCase2() throws Exception { + assertMatch("[[:alnum:]]", ":", false, false); + } + + public void testBlankGroupCase0() throws Exception { + assertMatch("[[:blank:]]", " ", true, false); + } + + public void testBlankGroupCase1() throws Exception { + assertMatch("[[:blank:]]", "\t", true, false); + } + + public void testBlankGroupCase2() throws Exception { + assertMatch("[[:blank:]]", "\r", false, false); + } + + public void testBlankGroupCase3() throws Exception { + assertMatch("[[:blank:]]", "\n", false, false); + } + + public void testBlankGroupCase4() throws Exception { + assertMatch("[[:blank:]]", "a", false, false); + } + + public void testCntrlGroupCase0() throws Exception { + assertMatch("[[:cntrl:]]", "a", false, false); + } + + public void testCntrlGroupCase1() throws Exception { + assertMatch("[[:cntrl:]]", String.valueOf((char) 7), true, false); + } + + public void testDigitGroupCase0() throws Exception { + assertMatch("[[:digit:]]", "0", true, false); + } + + public void testDigitGroupCase1() throws Exception { + assertMatch("[[:digit:]]", "5", true, false); + } + + public void testDigitGroupCase2() throws Exception { + assertMatch("[[:digit:]]", "9", true, false); + } + + public void testDigitGroupCase3() throws Exception { + // \u06f9 = EXTENDED ARABIC-INDIC DIGIT NINE + assertMatch("[[:digit:]]", "\u06f9", true, false); + } + + public void testDigitGroupCase4() throws Exception { + assertMatch("[[:digit:]]", "a", false, false); + } + + public void testDigitGroupCase5() throws Exception { + assertMatch("[[:digit:]]", "]", false, false); + } + + public void testGraphGroupCase0() throws Exception { + assertMatch("[[:graph:]]", "]", true, false); + } + + public void testGraphGroupCase1() throws Exception { + assertMatch("[[:graph:]]", "a", true, false); + } + + public void testGraphGroupCase2() throws Exception { + assertMatch("[[:graph:]]", ".", true, false); + } + + public void testGraphGroupCase3() throws Exception { + assertMatch("[[:graph:]]", "0", true, false); + } + + public void testGraphGroupCase4() throws Exception { + assertMatch("[[:graph:]]", " ", false, false); + } + + public void testGraphGroupCase5() throws Exception { + // \u00f6 = 'o' with dots on it + assertMatch("[[:graph:]]", "\u00f6", true, false); + } + + public void testLowerGroupCase0() throws Exception { + assertMatch("[[:lower:]]", "a", true, false); + } + + public void testLowerGroupCase1() throws Exception { + assertMatch("[[:lower:]]", "h", true, false); + } + + public void testLowerGroupCase2() throws Exception { + assertMatch("[[:lower:]]", "A", false, false); + } + + public void testLowerGroupCase3() throws Exception { + assertMatch("[[:lower:]]", "H", false, false); + } + + public void testLowerGroupCase4() throws Exception { + // \u00e4 = small 'a' with dots on it + assertMatch("[[:lower:]]", "\u00e4", true, false); + } + + public void testLowerGroupCase5() throws Exception { + assertMatch("[[:lower:]]", ".", false, false); + } + + public void testPrintGroupCase0() throws Exception { + assertMatch("[[:print:]]", "]", true, false); + } + + public void testPrintGroupCase1() throws Exception { + assertMatch("[[:print:]]", "a", true, false); + } + + public void testPrintGroupCase2() throws Exception { + assertMatch("[[:print:]]", ".", true, false); + } + + public void testPrintGroupCase3() throws Exception { + assertMatch("[[:print:]]", "0", true, false); + } + + public void testPrintGroupCase4() throws Exception { + assertMatch("[[:print:]]", " ", true, false); + } + + public void testPrintGroupCase5() throws Exception { + // \u00f6 = 'o' with dots on it + assertMatch("[[:print:]]", "\u00f6", true, false); + } + + public void testPunctGroupCase0() throws Exception { + assertMatch("[[:punct:]]", ".", true, false); + } + + public void testPunctGroupCase1() throws Exception { + assertMatch("[[:punct:]]", "@", true, false); + } + + public void testPunctGroupCase2() throws Exception { + assertMatch("[[:punct:]]", " ", false, false); + } + + public void testPunctGroupCase3() throws Exception { + assertMatch("[[:punct:]]", "a", false, false); + } + + public void testSpaceGroupCase0() throws Exception { + assertMatch("[[:space:]]", " ", true, false); + } + + public void testSpaceGroupCase1() throws Exception { + assertMatch("[[:space:]]", "\t", true, false); + } + + public void testSpaceGroupCase2() throws Exception { + assertMatch("[[:space:]]", "\r", true, false); + } + + public void testSpaceGroupCase3() throws Exception { + assertMatch("[[:space:]]", "\n", true, false); + } + + public void testSpaceGroupCase4() throws Exception { + assertMatch("[[:space:]]", "a", false, false); + } + + public void testUpperGroupCase0() throws Exception { + assertMatch("[[:upper:]]", "a", false, false); + } + + public void testUpperGroupCase1() throws Exception { + assertMatch("[[:upper:]]", "h", false, false); + } + + public void testUpperGroupCase2() throws Exception { + assertMatch("[[:upper:]]", "A", true, false); + } + + public void testUpperGroupCase3() throws Exception { + assertMatch("[[:upper:]]", "H", true, false); + } + + public void testUpperGroupCase4() throws Exception { + // \u00c4 = 'A' with dots on it + assertMatch("[[:upper:]]", "\u00c4", true, false); + } + + public void testUpperGroupCase5() throws Exception { + assertMatch("[[:upper:]]", ".", false, false); + } + + public void testXDigitGroupCase0() throws Exception { + assertMatch("[[:xdigit:]]", "a", true, false); + } + + public void testXDigitGroupCase1() throws Exception { + assertMatch("[[:xdigit:]]", "d", true, false); + } + + public void testXDigitGroupCase2() throws Exception { + assertMatch("[[:xdigit:]]", "f", true, false); + } + + public void testXDigitGroupCase3() throws Exception { + assertMatch("[[:xdigit:]]", "0", true, false); + } + + public void testXDigitGroupCase4() throws Exception { + assertMatch("[[:xdigit:]]", "5", true, false); + } + + public void testXDigitGroupCase5() throws Exception { + assertMatch("[[:xdigit:]]", "9", true, false); + } + + public void testXDigitGroupCase6() throws Exception { + assertMatch("[[:xdigit:]]", "Û¹", false, false); + } + + public void testXDigitGroupCase7() throws Exception { + assertMatch("[[:xdigit:]]", ".", false, false); + } + + public void testWordroupCase0() throws Exception { + assertMatch("[[:word:]]", "g", true, false); + } + + public void testWordroupCase1() throws Exception { + // \u00f6 = 'o' with dots on it + assertMatch("[[:word:]]", "\u00f6", true, false); + } + + public void testWordroupCase2() throws Exception { + assertMatch("[[:word:]]", "5", true, false); + } + + public void testWordroupCase3() throws Exception { + assertMatch("[[:word:]]", "_", true, false); + } + + public void testWordroupCase4() throws Exception { + assertMatch("[[:word:]]", " ", false, false); + } + + public void testWordroupCase5() throws Exception { + assertMatch("[[:word:]]", ".", false, false); + } + + public void testMixedGroupCase0() throws Exception { + assertMatch("[A[:lower:]C3-5]", "A", true, false); + } + + public void testMixedGroupCase1() throws Exception { + assertMatch("[A[:lower:]C3-5]", "C", true, false); + } + + public void testMixedGroupCase2() throws Exception { + assertMatch("[A[:lower:]C3-5]", "e", true, false); + } + + public void testMixedGroupCase3() throws Exception { + assertMatch("[A[:lower:]C3-5]", "3", true, false); + } + + public void testMixedGroupCase4() throws Exception { + assertMatch("[A[:lower:]C3-5]", "4", true, false); + } + + public void testMixedGroupCase5() throws Exception { + assertMatch("[A[:lower:]C3-5]", "5", true, false); + } + + public void testMixedGroupCase6() throws Exception { + assertMatch("[A[:lower:]C3-5]", "B", false, false); + } + + public void testMixedGroupCase7() throws Exception { + assertMatch("[A[:lower:]C3-5]", "2", false, false); + } + + public void testMixedGroupCase8() throws Exception { + assertMatch("[A[:lower:]C3-5]", "6", false, false); + } + + public void testMixedGroupCase9() throws Exception { + assertMatch("[A[:lower:]C3-5]", ".", false, false); + } + + public void testSpecialGroupCase0() throws Exception { + assertMatch("[[]", "[", true, false); + } + + public void testSpecialGroupCase1() throws Exception { + assertMatch("[]]", "]", true, false); + } + + public void testSpecialGroupCase2() throws Exception { + assertMatch("[]a]", "]", true, false); + } + + public void testSpecialGroupCase3() throws Exception { + assertMatch("[a[]", "[", true, false); + } + + public void testSpecialGroupCase4() throws Exception { + assertMatch("[a[]", "a", true, false); + } + + public void testSpecialGroupCase5() throws Exception { + assertMatch("[!]]", "]", false, false); + } + + public void testSpecialGroupCase6() throws Exception { + assertMatch("[!]]", "x", true, false); + } + + public void testSpecialGroupCase7() throws Exception { + assertMatch("[:]]", ":]", true, false); + } + + public void testSpecialGroupCase8() throws Exception { + assertMatch("[:]]", ":", false, true); + } + + public void testSpecialGroupCase9() throws Exception { + try { + assertMatch("[[:]", ":", true, true); + fail("InvalidPatternException expected"); + } catch (InvalidPatternException e) { + // expected + } + } + + public void testUnsupportedGroupCase0() throws Exception { + try { + assertMatch("[[=a=]]", "b", false, false); + fail("InvalidPatternException expected"); + } catch (InvalidPatternException e) { + assertTrue(e.getMessage().contains("[=a=]")); + } + } + + public void testUnsupportedGroupCase1() throws Exception { + try { + assertMatch("[[.a.]]", "b", false, false); + fail("InvalidPatternException expected"); + } catch (InvalidPatternException e) { + assertTrue(e.getMessage().contains("[.a.]")); + } + } + + public void testFilePathSimpleCase() throws Exception { + assertFileNameMatch("a/b", "a/b", '/', true, false); + } + + public void testFilePathCase0() throws Exception { + assertFileNameMatch("a*b", "a/b", '/', false, false); + } + + public void testFilePathCase1() throws Exception { + assertFileNameMatch("a?b", "a/b", '/', false, false); + } + + public void testFilePathCase2() throws Exception { + assertFileNameMatch("a*b", "a\\b", '\\', false, false); + } + + public void testFilePathCase3() throws Exception { + assertFileNameMatch("a?b", "a\\b", '\\', false, false); + } + + public void testReset() throws Exception { + final String pattern = "helloworld"; + final FileNameMatcher matcher = new FileNameMatcher(pattern, null); + matcher.append("helloworld"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + matcher.reset(); + matcher.append("hello"); + assertEquals(false, matcher.isMatch()); + assertEquals(true, matcher.canAppendMatch()); + matcher.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + matcher.append("to much"); + assertEquals(false, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + matcher.reset(); + matcher.append("helloworld"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + } + + public void testCreateMatcherForSuffix() throws Exception { + final String pattern = "helloworld"; + final FileNameMatcher matcher = new FileNameMatcher(pattern, null); + matcher.append("hello"); + final FileNameMatcher childMatcher = matcher.createMatcherForSuffix(); + assertEquals(false, matcher.isMatch()); + assertEquals(true, matcher.canAppendMatch()); + assertEquals(false, childMatcher.isMatch()); + assertEquals(true, childMatcher.canAppendMatch()); + matcher.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(false, childMatcher.isMatch()); + assertEquals(true, childMatcher.canAppendMatch()); + childMatcher.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(true, childMatcher.isMatch()); + assertEquals(false, childMatcher.canAppendMatch()); + childMatcher.reset(); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(false, childMatcher.isMatch()); + assertEquals(true, childMatcher.canAppendMatch()); + childMatcher.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(true, childMatcher.isMatch()); + assertEquals(false, childMatcher.canAppendMatch()); + } + + public void testCopyConstructor() throws Exception { + final String pattern = "helloworld"; + final FileNameMatcher matcher = new FileNameMatcher(pattern, null); + matcher.append("hello"); + final FileNameMatcher copy = new FileNameMatcher(matcher); + assertEquals(false, matcher.isMatch()); + assertEquals(true, matcher.canAppendMatch()); + assertEquals(false, copy.isMatch()); + assertEquals(true, copy.canAppendMatch()); + matcher.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(false, copy.isMatch()); + assertEquals(true, copy.canAppendMatch()); + copy.append("world"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(true, copy.isMatch()); + assertEquals(false, copy.canAppendMatch()); + copy.reset(); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(false, copy.isMatch()); + assertEquals(true, copy.canAppendMatch()); + copy.append("helloworld"); + assertEquals(true, matcher.isMatch()); + assertEquals(false, matcher.canAppendMatch()); + assertEquals(true, copy.isMatch()); + assertEquals(false, copy.canAppendMatch()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbreviatedObjectIdTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbreviatedObjectIdTest.java new file mode 100644 index 0000000000..45f8907da7 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/AbbreviatedObjectIdTest.java @@ -0,0 +1,351 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import junit.framework.TestCase; + +public class AbbreviatedObjectIdTest extends TestCase { + public void testEmpty_FromByteArray() { + final AbbreviatedObjectId i; + i = AbbreviatedObjectId.fromString(new byte[] {}, 0, 0); + assertNotNull(i); + assertEquals(0, i.length()); + assertFalse(i.isComplete()); + assertEquals("", i.name()); + } + + public void testEmpty_FromString() { + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(""); + assertNotNull(i); + assertEquals(0, i.length()); + assertFalse(i.isComplete()); + assertEquals("", i.name()); + } + + public void testFull_FromByteArray() { + final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final byte[] b = Constants.encodeASCII(s); + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(b, 0, + b.length); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertTrue(i.isComplete()); + assertEquals(s, i.name()); + + final ObjectId f = i.toObjectId(); + assertNotNull(f); + assertEquals(ObjectId.fromString(s), f); + assertEquals(f.hashCode(), i.hashCode()); + } + + public void testFull_FromString() { + final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertTrue(i.isComplete()); + assertEquals(s, i.name()); + + final ObjectId f = i.toObjectId(); + assertNotNull(f); + assertEquals(ObjectId.fromString(s), f); + assertEquals(f.hashCode(), i.hashCode()); + } + + public void test1_FromString() { + final String s = "7"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test2_FromString() { + final String s = "7b"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test3_FromString() { + final String s = "7b6"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test4_FromString() { + final String s = "7b6e"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test5_FromString() { + final String s = "7b6e8"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test6_FromString() { + final String s = "7b6e80"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test7_FromString() { + final String s = "7b6e806"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test8_FromString() { + final String s = "7b6e8067"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test9_FromString() { + final String s = "7b6e8067e"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void test17_FromString() { + final String s = "7b6e8067ec96acef9"; + final AbbreviatedObjectId i = AbbreviatedObjectId.fromString(s); + assertNotNull(i); + assertEquals(s.length(), i.length()); + assertFalse(i.isComplete()); + assertEquals(s, i.name()); + assertNull(i.toObjectId()); + } + + public void testEquals_Short() { + final String s = "7b6e8067"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s); + final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(s); + assertNotSame(a, b); + assertTrue(a.hashCode() == b.hashCode()); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + } + + public void testEquals_Full() { + final String s = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s); + final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(s); + assertNotSame(a, b); + assertTrue(a.hashCode() == b.hashCode()); + assertTrue(a.equals(b)); + assertTrue(b.equals(a)); + } + + public void testNotEquals_SameLength() { + final String sa = "7b6e8067"; + final String sb = "7b6e806e"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(sb); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + } + + public void testNotEquals_DiffLength() { + final String sa = "7b6e8067abcd"; + final String sb = "7b6e8067"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + final AbbreviatedObjectId b = AbbreviatedObjectId.fromString(sb); + assertFalse(a.equals(b)); + assertFalse(b.equals(a)); + } + + public void testPrefixCompare_Full() { + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(s1); + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "7b6e8067ec96acef9a4184b43210d583b6d2f99b"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "7b6e8067ec96acef9a4184b43210d583b6d2f999"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + public void testPrefixCompare_1() { + final String sa = "7"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "8b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "6b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + public void testPrefixCompare_7() { + final String sa = "7b6e806"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "7b6e8167ec86acef9a4184b43210d583b6d2f99a"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "7b6e8057eca6acef9a4184b43210d583b6d2f99a"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + public void testPrefixCompare_8() { + final String sa = "7b6e8067"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "7b6e8167ec86acef9a4184b43210d583b6d2f99a"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "7b6e8057eca6acef9a4184b43210d583b6d2f99a"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + public void testPrefixCompare_9() { + final String sa = "7b6e8067e"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "7b6e8167ec86acef9a4184b43210d583b6d2f99a"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "7b6e8057eca6acef9a4184b43210d583b6d2f99a"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } + + public void testPrefixCompare_17() { + final String sa = "7b6e8067ec96acef9"; + final AbbreviatedObjectId a = AbbreviatedObjectId.fromString(sa); + + final String s1 = "7b6e8067ec96acef9a4184b43210d583b6d2f99a"; + final ObjectId i1 = ObjectId.fromString(s1); + assertEquals(0, a.prefixCompare(i1)); + assertTrue(i1.startsWith(a)); + + final String s2 = "7b6e8067eca6acef9a4184b43210d583b6d2f99a"; + final ObjectId i2 = ObjectId.fromString(s2); + assertTrue(a.prefixCompare(i2) < 0); + assertFalse(i2.startsWith(a)); + + final String s3 = "7b6e8067ec86acef9a4184b43210d583b6d2f99a"; + final ObjectId i3 = ObjectId.fromString(s3); + assertTrue(a.prefixCompare(i3) > 0); + assertFalse(i3.startsWith(a)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java new file mode 100644 index 0000000000..644c7b366c --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConcurrentRepackTest.java @@ -0,0 +1,264 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.revwalk.RevObject; +import org.eclipse.jgit.revwalk.RevWalk; + +public class ConcurrentRepackTest extends RepositoryTestCase { + public void setUp() throws Exception { + WindowCacheConfig windowCacheConfig = new WindowCacheConfig(); + windowCacheConfig.setPackedGitOpenFiles(1); + WindowCache.reconfigure(windowCacheConfig); + super.setUp(); + } + + protected void tearDown() throws Exception { + super.tearDown(); + WindowCacheConfig windowCacheConfig = new WindowCacheConfig(); + WindowCache.reconfigure(windowCacheConfig); + } + + public void testObjectInNewPack() throws IncorrectObjectTypeException, + IOException { + // Create a new object in a new pack, and test that it is present. + // + final Repository eden = createNewEmptyRepo(); + final RevObject o1 = writeBlob(eden, "o1"); + pack(eden, o1); + assertEquals(o1.name(), parse(o1).name()); + } + + public void testObjectMovedToNewPack1() + throws IncorrectObjectTypeException, IOException { + // Create an object and pack it. Then remove that pack and put the + // object into a different pack file, with some other object. We + // still should be able to access the objects. + // + final Repository eden = createNewEmptyRepo(); + final RevObject o1 = writeBlob(eden, "o1"); + final File[] out1 = pack(eden, o1); + assertEquals(o1.name(), parse(o1).name()); + + final RevObject o2 = writeBlob(eden, "o2"); + pack(eden, o2, o1); + + // Force close, and then delete, the old pack. + // + whackCache(); + delete(out1); + + // Now here is the interesting thing. Will git figure the new + // object exists in the new pack, and not the old one. + // + assertEquals(o2.name(), parse(o2).name()); + assertEquals(o1.name(), parse(o1).name()); + } + + public void testObjectMovedWithinPack() + throws IncorrectObjectTypeException, IOException { + // Create an object and pack it. + // + final Repository eden = createNewEmptyRepo(); + final RevObject o1 = writeBlob(eden, "o1"); + final File[] out1 = pack(eden, o1); + assertEquals(o1.name(), parse(o1).name()); + + // Force close the old pack. + // + whackCache(); + + // Now overwrite the old pack in place. This method of creating a + // different pack under the same file name is partially broken. We + // should also have a different file name because the list of objects + // within the pack has been modified. + // + final RevObject o2 = writeBlob(eden, "o2"); + final PackWriter pw = new PackWriter(eden, NullProgressMonitor.INSTANCE); + pw.addObject(o2); + pw.addObject(o1); + write(out1, pw); + + // Try the old name, then the new name. The old name should cause the + // pack to reload when it opens and the index and pack mismatch. + // + assertEquals(o1.name(), parse(o1).name()); + assertEquals(o2.name(), parse(o2).name()); + } + + public void testObjectMovedToNewPack2() + throws IncorrectObjectTypeException, IOException { + // Create an object and pack it. Then remove that pack and put the + // object into a different pack file, with some other object. We + // still should be able to access the objects. + // + final Repository eden = createNewEmptyRepo(); + final RevObject o1 = writeBlob(eden, "o1"); + final File[] out1 = pack(eden, o1); + assertEquals(o1.name(), parse(o1).name()); + + final ObjectLoader load1 = db.openBlob(o1); + assertNotNull(load1); + + final RevObject o2 = writeBlob(eden, "o2"); + pack(eden, o2, o1); + + // Force close, and then delete, the old pack. + // + whackCache(); + delete(out1); + + // Now here is the interesting thing... can the loader we made + // earlier still resolve the object, even though its underlying + // pack is gone, but the object still exists. + // + final ObjectLoader load2 = db.openBlob(o1); + assertNotNull(load2); + assertNotSame(load1, load2); + + final byte[] data2 = load2.getCachedBytes(); + final byte[] data1 = load1.getCachedBytes(); + assertNotNull(data2); + assertNotNull(data1); + assertNotSame(data1, data2); // cache should be per-pack, not per object + assertTrue(Arrays.equals(data1, data2)); + assertEquals(load2.getType(), load1.getType()); + } + + private static void whackCache() { + final WindowCacheConfig config = new WindowCacheConfig(); + config.setPackedGitOpenFiles(1); + WindowCache.reconfigure(config); + } + + private RevObject parse(final AnyObjectId id) + throws MissingObjectException, IOException { + return new RevWalk(db).parseAny(id); + } + + private File[] pack(final Repository src, final RevObject... list) + throws IOException { + final PackWriter pw = new PackWriter(src, NullProgressMonitor.INSTANCE); + for (final RevObject o : list) { + pw.addObject(o); + } + + final ObjectId name = pw.computeName(); + final File packFile = fullPackFileName(name, ".pack"); + final File idxFile = fullPackFileName(name, ".idx"); + final File[] files = new File[] { packFile, idxFile }; + write(files, pw); + return files; + } + + private static void write(final File[] files, final PackWriter pw) + throws IOException { + final long begin = files[0].getParentFile().lastModified(); + FileOutputStream out; + + out = new FileOutputStream(files[0]); + try { + pw.writePack(out); + } finally { + out.close(); + } + + out = new FileOutputStream(files[1]); + try { + pw.writeIndex(out); + } finally { + out.close(); + } + + touch(begin, files[0].getParentFile()); + } + + private static void delete(final File[] list) { + final long begin = list[0].getParentFile().lastModified(); + for (final File f : list) { + f.delete(); + assertFalse(f + " was removed", f.exists()); + } + touch(begin, list[0].getParentFile()); + } + + private static void touch(final long begin, final File dir) { + while (begin >= dir.lastModified()) { + try { + Thread.sleep(25); + } catch (InterruptedException ie) { + // + } + dir.setLastModified(System.currentTimeMillis()); + } + } + + private File fullPackFileName(final ObjectId name, final String suffix) { + final File packdir = new File(db.getObjectsDirectory(), "pack"); + return new File(packdir, "pack-" + name.name() + suffix); + } + + private RevObject writeBlob(final Repository repo, final String data) + throws IOException { + final RevWalk revWalk = new RevWalk(repo); + final byte[] bytes = Constants.encode(data); + final ObjectWriter ow = new ObjectWriter(repo); + final ObjectId id = ow.writeBlob(bytes); + try { + parse(id); + fail("Object " + id.name() + " should not exist in test repository"); + } catch (MissingObjectException e) { + // Ok + } + return revWalk.lookupBlob(id); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java new file mode 100644 index 0000000000..96568ff232 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ConstantsEncodingTest.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.UnsupportedEncodingException; +import java.util.Arrays; + +import junit.framework.TestCase; + +public class ConstantsEncodingTest extends TestCase { + public void testEncodeASCII_SimpleASCII() + throws UnsupportedEncodingException { + final String src = "abc"; + final byte[] exp = { 'a', 'b', 'c' }; + final byte[] res = Constants.encodeASCII(src); + assertTrue(Arrays.equals(exp, res)); + assertEquals(src, new String(res, 0, res.length, "UTF-8")); + } + + public void testEncodeASCII_FailOnNonASCII() { + final String src = "ŪnÄcÅde̽"; + try { + Constants.encodeASCII(src); + fail("Incorrectly accepted a Unicode character"); + } catch (IllegalArgumentException err) { + assertEquals("Not ASCII string: " + src, err.getMessage()); + } + } + + public void testEncodeASCII_Number13() { + final long src = 13; + final byte[] exp = { '1', '3' }; + final byte[] res = Constants.encodeASCII(src); + assertTrue(Arrays.equals(exp, res)); + } + + public void testEncode_SimpleASCII() throws UnsupportedEncodingException { + final String src = "abc"; + final byte[] exp = { 'a', 'b', 'c' }; + final byte[] res = Constants.encode(src); + assertTrue(Arrays.equals(exp, res)); + assertEquals(src, new String(res, 0, res.length, "UTF-8")); + } + + public void testEncode_Unicode() throws UnsupportedEncodingException { + final String src = "ŪnÄcÅde̽"; + final byte[] exp = { (byte) 0xC5, (byte) 0xAA, 0x6E, (byte) 0xC4, + (byte) 0xAD, 0x63, (byte) 0xC5, (byte) 0x8D, 0x64, 0x65, + (byte) 0xCC, (byte) 0xBD }; + final byte[] res = Constants.encode(src); + assertTrue(Arrays.equals(exp, res)); + assertEquals(src, new String(res, 0, res.length, "UTF-8")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java new file mode 100644 index 0000000000..f871cc0524 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexDiffTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; + +public class IndexDiffTest extends RepositoryTestCase { + public void testAdded() throws IOException { + GitIndex index = new GitIndex(db); + writeTrashFile("file1", "file1"); + writeTrashFile("dir/subfile", "dir/subfile"); + Tree tree = new Tree(db); + + index.add(trash, new File(trash, "file1")); + index.add(trash, new File(trash, "dir/subfile")); + IndexDiff diff = new IndexDiff(tree, index); + diff.diff(); + assertEquals(2, diff.getAdded().size()); + assertTrue(diff.getAdded().contains("file1")); + assertTrue(diff.getAdded().contains("dir/subfile")); + assertEquals(0, diff.getChanged().size()); + assertEquals(0, diff.getModified().size()); + assertEquals(0, diff.getRemoved().size()); + } + + public void testRemoved() throws IOException { + GitIndex index = new GitIndex(db); + writeTrashFile("file2", "file2"); + writeTrashFile("dir/file3", "dir/file3"); + + Tree tree = new Tree(db); + tree.addFile("file2"); + tree.addFile("dir/file3"); + assertEquals(2, tree.memberCount()); + tree.findBlobMember("file2").setId(ObjectId.fromString("30d67d4672d5c05833b7192cc77a79eaafb5c7ad")); + Tree tree2 = (Tree) tree.findTreeMember("dir"); + tree2.findBlobMember("file3").setId(ObjectId.fromString("873fb8d667d05436d728c52b1d7a09528e6eb59b")); + tree2.setId(new ObjectWriter(db).writeTree(tree2)); + tree.setId(new ObjectWriter(db).writeTree(tree)); + + IndexDiff diff = new IndexDiff(tree, index); + diff.diff(); + assertEquals(2, diff.getRemoved().size()); + assertTrue(diff.getRemoved().contains("file2")); + assertTrue(diff.getRemoved().contains("dir/file3")); + assertEquals(0, diff.getChanged().size()); + assertEquals(0, diff.getModified().size()); + assertEquals(0, diff.getAdded().size()); + } + + public void testModified() throws IOException { + GitIndex index = new GitIndex(db); + + + index.add(trash, writeTrashFile("file2", "file2")); + index.add(trash, writeTrashFile("dir/file3", "dir/file3")); + + writeTrashFile("dir/file3", "changed"); + + Tree tree = new Tree(db); + tree.addFile("file2").setId(ObjectId.fromString("0123456789012345678901234567890123456789")); + tree.addFile("dir/file3").setId(ObjectId.fromString("0123456789012345678901234567890123456789")); + assertEquals(2, tree.memberCount()); + + Tree tree2 = (Tree) tree.findTreeMember("dir"); + tree2.setId(new ObjectWriter(db).writeTree(tree2)); + tree.setId(new ObjectWriter(db).writeTree(tree)); + IndexDiff diff = new IndexDiff(tree, index); + diff.diff(); + assertEquals(2, diff.getChanged().size()); + assertTrue(diff.getChanged().contains("file2")); + assertTrue(diff.getChanged().contains("dir/file3")); + assertEquals(1, diff.getModified().size()); + assertTrue(diff.getModified().contains("dir/file3")); + assertEquals(0, diff.getAdded().size()); + assertEquals(0, diff.getRemoved().size()); + assertEquals(0, diff.getMissing().size()); + } + + public void testUnchangedSimple() throws IOException { + GitIndex index = new GitIndex(db); + + index.add(trash, writeTrashFile("a.b", "a.b")); + index.add(trash, writeTrashFile("a.c", "a.c")); + index.add(trash, writeTrashFile("a=c", "a=c")); + index.add(trash, writeTrashFile("a=d", "a=d")); + + Tree tree = new Tree(db); + // got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin + tree.addFile("a.b").setId(ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851")); + tree.addFile("a.c").setId(ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca")); + tree.addFile("a=c").setId(ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714")); + tree.addFile("a=d").setId(ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2")); + + tree.setId(new ObjectWriter(db).writeTree(tree)); + + IndexDiff diff = new IndexDiff(tree, index); + diff.diff(); + assertEquals(0, diff.getChanged().size()); + assertEquals(0, diff.getAdded().size()); + assertEquals(0, diff.getRemoved().size()); + assertEquals(0, diff.getMissing().size()); + assertEquals(0, diff.getModified().size()); + } + + /** + * This test has both files and directories that involve + * the tricky ordering used by Git. + * + * @throws IOException + */ + public void testUnchangedComplex() throws IOException { + GitIndex index = new GitIndex(db); + + index.add(trash, writeTrashFile("a.b", "a.b")); + index.add(trash, writeTrashFile("a.c", "a.c")); + index.add(trash, writeTrashFile("a/b.b/b", "a/b.b/b")); + index.add(trash, writeTrashFile("a/b", "a/b")); + index.add(trash, writeTrashFile("a/c", "a/c")); + index.add(trash, writeTrashFile("a=c", "a=c")); + index.add(trash, writeTrashFile("a=d", "a=d")); + + Tree tree = new Tree(db); + // got the hash id'd from the data using echo -n a.b|git hash-object -t blob --stdin + tree.addFile("a.b").setId(ObjectId.fromString("f6f28df96c2b40c951164286e08be7c38ec74851")); + tree.addFile("a.c").setId(ObjectId.fromString("6bc0e647512d2a0bef4f26111e484dc87df7f5ca")); + tree.addFile("a/b.b/b").setId(ObjectId.fromString("8d840bd4e2f3a48ff417c8e927d94996849933fd")); + tree.addFile("a/b").setId(ObjectId.fromString("db89c972fc57862eae378f45b74aca228037d415")); + tree.addFile("a/c").setId(ObjectId.fromString("52ad142a008aeb39694bafff8e8f1be75ed7f007")); + tree.addFile("a=c").setId(ObjectId.fromString("06022365ddbd7fb126761319633bf73517770714")); + tree.addFile("a=d").setId(ObjectId.fromString("fa6414df3da87840700e9eeb7fc261dd77ccd5c2")); + + Tree tree3 = (Tree) tree.findTreeMember("a/b.b"); + tree3.setId(new ObjectWriter(db).writeTree(tree3)); + Tree tree2 = (Tree) tree.findTreeMember("a"); + tree2.setId(new ObjectWriter(db).writeTree(tree2)); + tree.setId(new ObjectWriter(db).writeTree(tree)); + + IndexDiff diff = new IndexDiff(tree, index); + diff.diff(); + assertEquals(0, diff.getChanged().size()); + assertEquals(0, diff.getAdded().size()); + assertEquals(0, diff.getRemoved().size()); + assertEquals(0, diff.getMissing().size()); + assertEquals(0, diff.getModified().size()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexTreeWalkerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexTreeWalkerTest.java new file mode 100644 index 0000000000..eb7b622d6c --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/IndexTreeWalkerTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.jgit.lib.GitIndex.Entry; + +public class IndexTreeWalkerTest extends RepositoryTestCase { + private ArrayList<String> treeOnlyEntriesVisited = new ArrayList<String>(); + private ArrayList<String> bothVisited = new ArrayList<String>(); + private ArrayList<String> indexOnlyEntriesVisited = new ArrayList<String>(); + + private class TestIndexTreeVisitor extends AbstractIndexTreeVisitor { + public void visitEntry(TreeEntry treeEntry, Entry indexEntry, File file) { + if (treeEntry == null) + indexOnlyEntriesVisited.add(indexEntry.getName()); + else if (indexEntry == null) + treeOnlyEntriesVisited.add(treeEntry.getFullName()); + else bothVisited.add(indexEntry.getName()); + } + } + + /* + * Need to think about what I really need to be able to do.... + * + * 1) Visit all entries in index and tree + * 2) Get all directories that exist in the index, but not in the tree + * -- I'm pretty sure that I don't need to do the other way around + * because I already + */ + + public void testTreeOnlyOneLevel() throws IOException { + GitIndex index = new GitIndex(db); + Tree tree = new Tree(db); + tree.addFile("foo"); + tree.addFile("bar"); + + new IndexTreeWalker(index, tree, trash, new TestIndexTreeVisitor()).walk(); + + assertTrue(treeOnlyEntriesVisited.get(0).equals("bar")); + assertTrue(treeOnlyEntriesVisited.get(1).equals("foo")); + } + + public void testIndexOnlyOneLevel() throws IOException { + GitIndex index = new GitIndex(db); + Tree tree = new Tree(db); + + index.add(trash, writeTrashFile("foo", "foo")); + index.add(trash, writeTrashFile("bar", "bar")); + new IndexTreeWalker(index, tree, trash, new TestIndexTreeVisitor()).walk(); + + assertTrue(indexOnlyEntriesVisited.get(0).equals("bar")); + assertTrue(indexOnlyEntriesVisited.get(1).equals("foo")); + } + + public void testBoth() throws IOException { + GitIndex index = new GitIndex(db); + Tree tree = new Tree(db); + + index.add(trash, writeTrashFile("a", "a")); + tree.addFile("b/b"); + index.add(trash, writeTrashFile("c", "c")); + tree.addFile("c"); + + new IndexTreeWalker(index, tree, trash, new TestIndexTreeVisitor()).walk(); + assertTrue(indexOnlyEntriesVisited.contains("a")); + assertTrue(treeOnlyEntriesVisited.contains("b/b")); + assertTrue(bothVisited.contains("c")); + + } + + public void testIndexOnlySubDirs() throws IOException { + GitIndex index = new GitIndex(db); + Tree tree = new Tree(db); + + index.add(trash, writeTrashFile("foo/bar/baz", "foobar")); + index.add(trash, writeTrashFile("asdf", "asdf")); + new IndexTreeWalker(index, tree, trash, new TestIndexTreeVisitor()).walk(); + + assertEquals("asdf", indexOnlyEntriesVisited.get(0)); + assertEquals("foo/bar/baz", indexOnlyEntriesVisited.get(1)); + } + + public void testLeavingTree() throws IOException { + GitIndex index = new GitIndex(db); + index.add(trash, writeTrashFile("foo/bar", "foo/bar")); + index.add(trash, writeTrashFile("foobar", "foobar")); + + new IndexTreeWalker(index, db.mapTree(index.writeTree()), trash, new AbstractIndexTreeVisitor() { + @Override + public void visitEntry(TreeEntry entry, Entry indexEntry, File f) { + if (entry == null || indexEntry == null) + fail(); + } + + @Override + public void finishVisitTree(Tree tree, int i, String curDir) + throws IOException { + if (tree.memberCount() == 0) + fail(); + if (i == 0) + fail(); + } + + }).walk(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/MockSystemReader.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/MockSystemReader.java new file mode 100644 index 0000000000..2e94632cee --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/MockSystemReader.java @@ -0,0 +1,97 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2009, Yann Simon <yann.simon.fr@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.util.HashMap; +import java.util.Map; +import java.util.TimeZone; + +import org.eclipse.jgit.util.SystemReader; + +class MockSystemReader extends SystemReader { + final Map<String, String> values = new HashMap<String, String>(); + + FileBasedConfig userGitConfig; + + MockSystemReader() { + init(Constants.OS_USER_NAME_KEY); + init(Constants.GIT_AUTHOR_NAME_KEY); + init(Constants.GIT_AUTHOR_EMAIL_KEY); + init(Constants.GIT_COMMITTER_NAME_KEY); + init(Constants.GIT_COMMITTER_EMAIL_KEY); + userGitConfig = new FileBasedConfig(null); + } + + private void init(final String n) { + values.put(n, n); + } + + public String getenv(String variable) { + return values.get(variable); + } + + public String getProperty(String key) { + return values.get(key); + } + + public FileBasedConfig openUserConfig() { + return userGitConfig; + } + + public String getHostname() { + return "fake.host.example.com"; + } + + @Override + public long getCurrentTime() { + return 1250379778668L; // Sat Aug 15 20:12:58 GMT-03:30 2009 + } + + @Override + public int getTimezone(long when) { + return TimeZone.getTimeZone("GMT-3:30").getOffset(when); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java new file mode 100644 index 0000000000..7c2676bc7d --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ObjectCheckerTest.java @@ -0,0 +1,1331 @@ +/* + * Copyright (C) 2008, Google Inc. + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import junit.framework.TestCase; + +import org.eclipse.jgit.errors.CorruptObjectException; + +public class ObjectCheckerTest extends TestCase { + private ObjectChecker checker; + + protected void setUp() throws Exception { + super.setUp(); + checker = new ObjectChecker(); + } + + public void testInvalidType() { + try { + checker.check(Constants.OBJ_BAD, new byte[0]); + fail("Did not throw CorruptObjectException"); + } catch (CorruptObjectException e) { + final String m = e.getMessage(); + assertEquals("Invalid object type: " + Constants.OBJ_BAD, m); + } + } + + public void testCheckBlob() throws CorruptObjectException { + // Any blob should pass... + checker.checkBlob(new byte[0]); + checker.checkBlob(new byte[1]); + + checker.check(Constants.OBJ_BLOB, new byte[0]); + checker.check(Constants.OBJ_BLOB, new byte[1]); + } + + public void testValidCommitNoParent() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + b.append("committer A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testValidCommitBlankAuthor() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author <> 0 +0000\n"); + b.append("committer <> 0 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testValidCommit1Parent() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + b.append("committer A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testValidCommit2Parent() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + b.append("committer A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testValidCommit128Parent() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + for (int i = 0; i < 128; i++) { + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + } + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + b.append("committer A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testValidCommitNormalTime() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + final String when = "1222757360 -0730"; + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> " + when + "\n"); + b.append("committer A. U. Thor <author@localhost> " + when + "\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkCommit(data); + checker.check(Constants.OBJ_COMMIT, data); + } + + public void testInvalidCommitNoTree1() { + final StringBuilder b = new StringBuilder(); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("no tree header", e.getMessage()); + } + } + + public void testInvalidCommitNoTree2() { + final StringBuilder b = new StringBuilder(); + + b.append("trie "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("no tree header", e.getMessage()); + } + } + + public void testInvalidCommitNoTree3() { + final StringBuilder b = new StringBuilder(); + + b.append("tree"); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("no tree header", e.getMessage()); + } + } + + public void testInvalidCommitNoTree4() { + final StringBuilder b = new StringBuilder(); + + b.append("tree\t"); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("no tree header", e.getMessage()); + } + } + + public void testInvalidCommitInvalidTree1() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("zzzzfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid tree", e.getMessage()); + } + } + + public void testInvalidCommitInvalidTree2() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append("z\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid tree", e.getMessage()); + } + } + + public void testInvalidCommitInvalidTree3() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9b"); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid tree", e.getMessage()); + } + } + + public void testInvalidCommitInvalidTree4() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid tree", e.getMessage()); + } + } + + public void testInvalidCommitInvalidParent1() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid parent", e.getMessage()); + } + } + + public void testInvalidCommitInvalidParent2() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("zzzzfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid parent", e.getMessage()); + } + } + + public void testInvalidCommitInvalidParent3() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid parent", e.getMessage()); + } + } + + public void testInvalidCommitInvalidParent4() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append("z\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + assertEquals("invalid parent", e.getMessage()); + } + } + + public void testInvalidCommitInvalidParent5() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("parent\t"); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("no author", e.getMessage()); + } + } + + public void testInvalidCommitNoAuthor() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("committer A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("no author", e.getMessage()); + } + } + + public void testInvalidCommitNoCommitter1() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("no committer", e.getMessage()); + } + } + + public void testInvalidCommitNoCommitter2() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <author@localhost> 1 +0000\n"); + b.append("\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("no committer", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor1() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor <foo 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor2() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author A. U. Thor foo> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor3() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor4() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author a <b> +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor5() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author a <b>\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor6() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author a <b> z"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidAuthor7() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author a <b> 1 z"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid author", e.getMessage()); + } + } + + public void testInvalidCommitInvalidCommitter() { + final StringBuilder b = new StringBuilder(); + + b.append("tree "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("author a <b> 1 +0000\n"); + b.append("committer a <"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkCommit(data); + fail("Did not catch corrupt object"); + } catch (CorruptObjectException e) { + // Yes, really, we complain about author not being + // found as the invalid parent line wasn't consumed. + assertEquals("invalid committer", e.getMessage()); + } + } + + public void testValidTag() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag test-tag\n"); + b.append("tagger A. U. Thor <author@localhost> 1 +0000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTag(data); + checker.check(Constants.OBJ_TAG, data); + } + + public void testInvalidTagNoObject1() { + final StringBuilder b = new StringBuilder(); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no object header", e.getMessage()); + } + } + + public void testInvalidTagNoObject2() { + final StringBuilder b = new StringBuilder(); + + b.append("object\t"); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no object header", e.getMessage()); + } + } + + public void testInvalidTagNoObject3() { + final StringBuilder b = new StringBuilder(); + + b.append("obejct "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no object header", e.getMessage()); + } + } + + public void testInvalidTagNoObject4() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("zz9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("invalid object", e.getMessage()); + } + } + + public void testInvalidTagNoObject5() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append(" \n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("invalid object", e.getMessage()); + } + } + + public void testInvalidTagNoObject6() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("invalid object", e.getMessage()); + } + } + + public void testInvalidTagNoType1() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no type header", e.getMessage()); + } + } + + public void testInvalidTagNoType2() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type\tcommit\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no type header", e.getMessage()); + } + } + + public void testInvalidTagNoType3() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("tpye commit\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no type header", e.getMessage()); + } + } + + public void testInvalidTagNoType4() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tag header", e.getMessage()); + } + } + + public void testInvalidTagNoTagHeader1() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tag header", e.getMessage()); + } + } + + public void testInvalidTagNoTagHeader2() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag\tfoo\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tag header", e.getMessage()); + } + } + + public void testInvalidTagNoTagHeader3() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tga foo\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tag header", e.getMessage()); + } + } + + public void testInvalidTagNoTagHeader4() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag foo"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tagger header", e.getMessage()); + } + } + + public void testInvalidTagNoTaggerHeader1() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag foo\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("no tagger header", e.getMessage()); + } + } + + public void testInvalidTagInvalidTaggerHeader1() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag foo\n"); + b.append("tagger \n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("invalid tagger", e.getMessage()); + } + } + + public void testInvalidTagInvalidTaggerHeader3() { + final StringBuilder b = new StringBuilder(); + + b.append("object "); + b.append("be9bfa841874ccc9f2ef7c48d0c76226f89b7189"); + b.append('\n'); + + b.append("type commit\n"); + b.append("tag foo\n"); + b.append("tagger a < 1 +000\n"); + + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTag(data); + fail("incorrectly accepted invalid tag"); + } catch (CorruptObjectException e) { + assertEquals("invalid tagger", e.getMessage()); + } + } + + public void testValidEmptyTree() throws CorruptObjectException { + checker.checkTree(new byte[0]); + checker.check(Constants.OBJ_TREE, new byte[0]); + } + + public void testValidTree1() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 regular-file"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTree2() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100755 executable"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTree3() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "40000 tree"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTree4() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "120000 symlink"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTree5() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "160000 git link"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTree6() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 .a"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting1() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 fooaaa"); + entry(b, "100755 foobar"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting2() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100755 fooaaa"); + entry(b, "100644 foobar"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting3() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "40000 a"); + entry(b, "100644 b"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting4() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "40000 b"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting5() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a.c"); + entry(b, "40000 a"); + entry(b, "100644 a0c"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting6() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "40000 a"); + entry(b, "100644 apple"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting7() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "40000 an orang"); + entry(b, "40000 an orange"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testValidTreeSorting8() throws CorruptObjectException { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100644 a0c"); + entry(b, "100644 b"); + final byte[] data = Constants.encodeASCII(b.toString()); + checker.checkTree(data); + } + + public void testInvalidTreeModeStartsWithZero1() { + final StringBuilder b = new StringBuilder(); + entry(b, "0 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("mode starts with '0'", e.getMessage()); + } + } + + public void testInvalidTreeModeStartsWithZero2() { + final StringBuilder b = new StringBuilder(); + entry(b, "0100644 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("mode starts with '0'", e.getMessage()); + } + } + + public void testInvalidTreeModeStartsWithZero3() { + final StringBuilder b = new StringBuilder(); + entry(b, "040000 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("mode starts with '0'", e.getMessage()); + } + } + + public void testInvalidTreeModeNotOctal1() { + final StringBuilder b = new StringBuilder(); + entry(b, "8 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid mode character", e.getMessage()); + } + } + + public void testInvalidTreeModeNotOctal2() { + final StringBuilder b = new StringBuilder(); + entry(b, "Z a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid mode character", e.getMessage()); + } + } + + public void testInvalidTreeModeNotSupportedMode1() { + final StringBuilder b = new StringBuilder(); + entry(b, "1 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid mode 1", e.getMessage()); + } + } + + public void testInvalidTreeModeNotSupportedMode2() { + final StringBuilder b = new StringBuilder(); + entry(b, "170000 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid mode " + 0170000, e.getMessage()); + } + } + + public void testInvalidTreeModeMissingName() { + final StringBuilder b = new StringBuilder(); + b.append("100644"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("truncated in mode", e.getMessage()); + } + } + + public void testInvalidTreeNameContainsSlash() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a/b"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("name contains '/'", e.getMessage()); + } + } + + public void testInvalidTreeNameIsEmpty() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 "); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("zero length name", e.getMessage()); + } + } + + public void testInvalidTreeNameIsDot() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 ."); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '.'", e.getMessage()); + } + } + + public void testInvalidTreeNameIsDotDot() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 .."); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("invalid name '..'", e.getMessage()); + } + } + + public void testInvalidTreeTruncatedInName() { + final StringBuilder b = new StringBuilder(); + b.append("100644 b"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("truncated in name", e.getMessage()); + } + } + + public void testInvalidTreeTruncatedInObjectId() { + final StringBuilder b = new StringBuilder(); + b.append("100644 b\0\1\2"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("truncated in object id", e.getMessage()); + } + } + + public void testInvalidTreeBadSorting1() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 foobar"); + entry(b, "100644 fooaaa"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("incorrectly sorted", e.getMessage()); + } + } + + public void testInvalidTreeBadSorting2() { + final StringBuilder b = new StringBuilder(); + entry(b, "40000 a"); + entry(b, "100644 a.c"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("incorrectly sorted", e.getMessage()); + } + } + + public void testInvalidTreeBadSorting3() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a0c"); + entry(b, "40000 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("incorrectly sorted", e.getMessage()); + } + } + + public void testInvalidTreeDuplicateNames1() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100644 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + public void testInvalidTreeDuplicateNames2() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100755 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + public void testInvalidTreeDuplicateNames3() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "40000 a"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + public void testInvalidTreeDuplicateNames4() { + final StringBuilder b = new StringBuilder(); + entry(b, "100644 a"); + entry(b, "100644 a.c"); + entry(b, "100644 a.d"); + entry(b, "100644 a.e"); + entry(b, "40000 a"); + entry(b, "100644 zoo"); + final byte[] data = Constants.encodeASCII(b.toString()); + try { + checker.checkTree(data); + fail("incorrectly accepted an invalid tree"); + } catch (CorruptObjectException e) { + assertEquals("duplicate entry names", e.getMessage()); + } + } + + private static void entry(final StringBuilder b, final String modeName) { + b.append(modeName); + b.append('\0'); + for (int i = 0; i < Constants.OBJECT_ID_LENGTH; i++) + b.append((char) i); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java new file mode 100644 index 0000000000..31de3d98ad --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexTestCase.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.util.Iterator; +import java.util.NoSuchElementException; + +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.lib.PackIndex.MutableEntry; + +public abstract class PackIndexTestCase extends RepositoryTestCase { + + PackIndex smallIdx; + + PackIndex denseIdx; + + public void setUp() throws Exception { + super.setUp(); + smallIdx = PackIndex.open(getFileForPack34be9032()); + denseIdx = PackIndex.open(getFileForPackdf2982f28()); + } + + /** + * Return file with appropriate index version for prepared pack. + * + * @return file with index + */ + public abstract File getFileForPack34be9032(); + + /** + * Return file with appropriate index version for prepared pack. + * + * @return file with index + */ + public abstract File getFileForPackdf2982f28(); + + /** + * Verify CRC32 support. + * + * @throws MissingObjectException + * @throws UnsupportedOperationException + */ + public abstract void testCRC32() throws MissingObjectException, + UnsupportedOperationException; + + /** + * Test contracts of Iterator methods and this implementation remove() + * limitations. + */ + public void testIteratorMethodsContract() { + Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator(); + while (iter.hasNext()) { + iter.next(); + } + + try { + iter.next(); + fail("next() unexpectedly returned element"); + } catch (NoSuchElementException x) { + // expected + } + + try { + iter.remove(); + fail("remove() shouldn't be implemented"); + } catch (UnsupportedOperationException x) { + // expected + } + } + + /** + * Test results of iterator comparing to content of well-known (prepared) + * small index. + */ + public void testIteratorReturnedValues1() { + Iterator<PackIndex.MutableEntry> iter = smallIdx.iterator(); + assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", iter.next() + .name()); + assertEquals("540a36d136cf413e4b064c2b0e0a4db60f77feab", iter.next() + .name()); + assertEquals("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259", iter.next() + .name()); + assertEquals("6ff87c4664981e4397625791c8ea3bbb5f2279a3", iter.next() + .name()); + assertEquals("82c6b885ff600be425b4ea96dee75dca255b69e7", iter.next() + .name()); + assertEquals("902d5476fa249b7abc9d84c611577a81381f0327", iter.next() + .name()); + assertEquals("aabf2ffaec9b497f0950352b3e582d73035c2035", iter.next() + .name()); + assertEquals("c59759f143fb1fe21c197981df75a7ee00290799", iter.next() + .name()); + assertFalse(iter.hasNext()); + } + + /** + * Compare offset from iterator entries with output of findOffset() method. + */ + public void testCompareEntriesOffsetsWithFindOffsets() { + for (MutableEntry me : smallIdx) { + assertEquals(smallIdx.findOffset(me.toObjectId()), me.getOffset()); + } + for (MutableEntry me : denseIdx) { + assertEquals(denseIdx.findOffset(me.toObjectId()), me.getOffset()); + } + } + + /** + * Test partial results of iterator comparing to content of well-known + * (prepared) dense index, that may need multi-level indexing. + */ + public void testIteratorReturnedValues2() { + Iterator<PackIndex.MutableEntry> iter = denseIdx.iterator(); + while (!iter.next().name().equals( + "0a3d7772488b6b106fb62813c4d6d627918d9181")) { + // just iterating + } + assertEquals("1004d0d7ac26fbf63050a234c9b88a46075719d3", iter.next() + .name()); // same level-1 + assertEquals("10da5895682013006950e7da534b705252b03be6", iter.next() + .name()); // same level-1 + assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8", iter.next() + .name()); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java new file mode 100644 index 0000000000..f3082fb294 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV1Test.java @@ -0,0 +1,82 @@ +/* + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * Copyright (C) 2009, Matthias Sohn <matthias.sohn@sap.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; + +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.util.JGitTestUtil; + +public class PackIndexV1Test extends PackIndexTestCase { + @Override + public File getFileForPack34be9032() { + return JGitTestUtil.getTestResourceFile( + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx"); + } + + @Override + public File getFileForPackdf2982f28() { + return JGitTestUtil.getTestResourceFile( + "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idx"); + } + + /** + * Verify CRC32 - V1 should not index anything. + * + * @throws MissingObjectException + */ + @Override + public void testCRC32() throws MissingObjectException { + assertFalse(smallIdx.hasCRC32Support()); + try { + smallIdx.findCRC32(ObjectId + .fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904")); + fail("index V1 shouldn't support CRC"); + } catch (UnsupportedOperationException x) { + // expected + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java new file mode 100644 index 0000000000..c5669f9d24 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackIndexV2Test.java @@ -0,0 +1,93 @@ +/* + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * Copyright (C) 2009, Matthias Sohn <matthias.sohn@sap.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; + +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.util.JGitTestUtil; + +public class PackIndexV2Test extends PackIndexTestCase { + @Override + public File getFileForPack34be9032() { + return JGitTestUtil.getTestResourceFile( + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2"); + } + + @Override + public File getFileForPackdf2982f28() { + return JGitTestUtil.getTestResourceFile( + "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.idxV2"); + } + + /** + * Verify CRC32 indexing. + * + * @throws UnsupportedOperationException + * @throws MissingObjectException + */ + @Override + public void testCRC32() throws MissingObjectException, + UnsupportedOperationException { + assertTrue(smallIdx.hasCRC32Support()); + assertEquals(0x00000000C2B64258l, smallIdx.findCRC32(ObjectId + .fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"))); + assertEquals(0x0000000072AD57C2l, smallIdx.findCRC32(ObjectId + .fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"))); + assertEquals(0x00000000FF10A479l, smallIdx.findCRC32(ObjectId + .fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"))); + assertEquals(0x0000000034B27DDCl, smallIdx.findCRC32(ObjectId + .fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"))); + assertEquals(0x000000004743F1E4l, smallIdx.findCRC32(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"))); + assertEquals(0x00000000640B358Bl, smallIdx.findCRC32(ObjectId + .fromString("902d5476fa249b7abc9d84c611577a81381f0327"))); + assertEquals(0x000000002A17CB5El, smallIdx.findCRC32(ObjectId + .fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"))); + assertEquals(0x000000000B3B5BA6l, smallIdx.findCRC32(ObjectId + .fromString("c59759f143fb1fe21c197981df75a7ee00290799"))); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java new file mode 100644 index 0000000000..19b705813f --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackReverseIndexTest.java @@ -0,0 +1,121 @@ +/* + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.lib.PackIndex.MutableEntry; +import org.eclipse.jgit.util.JGitTestUtil; + +public class PackReverseIndexTest extends RepositoryTestCase { + + private PackIndex idx; + + private PackReverseIndex reverseIdx; + + /** + * Set up tested class instance, test constructor by the way. + */ + public void setUp() throws Exception { + super.setUp(); + // index with both small (< 2^31) and big offsets + idx = PackIndex.open(JGitTestUtil.getTestResourceFile( + "pack-huge.idx")); + reverseIdx = new PackReverseIndex(idx); + } + + /** + * Test findObject() for all index entries. + */ + public void testFindObject() { + for (MutableEntry me : idx) + assertEquals(me.toObjectId(), reverseIdx.findObject(me.getOffset())); + } + + /** + * Test findObject() with illegal argument. + */ + public void testFindObjectWrongOffset() { + assertNull(reverseIdx.findObject(0)); + } + + /** + * Test findNextOffset() for all index entries. + * + * @throws CorruptObjectException + */ + public void testFindNextOffset() throws CorruptObjectException { + long offset = findFirstOffset(); + assertTrue(offset > 0); + for (int i = 0; i < idx.getObjectCount(); i++) { + long newOffset = reverseIdx.findNextOffset(offset, Long.MAX_VALUE); + assertTrue(newOffset > offset); + if (i == idx.getObjectCount() - 1) + assertEquals(newOffset, Long.MAX_VALUE); + else + assertEquals(newOffset, idx.findOffset(reverseIdx + .findObject(newOffset))); + offset = newOffset; + } + } + + /** + * Test findNextOffset() with wrong illegal argument as offset. + */ + public void testFindNextOffsetWrongOffset() { + try { + reverseIdx.findNextOffset(0, Long.MAX_VALUE); + fail("findNextOffset() should throw exception"); + } catch (CorruptObjectException x) { + // expected + } + } + + private long findFirstOffset() { + long min = Long.MAX_VALUE; + for (MutableEntry me : idx) + min = Math.min(min, me.getOffset()); + return min; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java new file mode 100644 index 0000000000..7032907496 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/PackWriterTest.java @@ -0,0 +1,533 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.lib.PackIndex.MutableEntry; +import org.eclipse.jgit.revwalk.RevObject; +import org.eclipse.jgit.revwalk.RevWalk; +import org.eclipse.jgit.transport.IndexPack; +import org.eclipse.jgit.util.JGitTestUtil; + +public class PackWriterTest extends RepositoryTestCase { + + private static final List<ObjectId> EMPTY_LIST_OBJECT = Collections + .<ObjectId> emptyList(); + + private static final List<RevObject> EMPTY_LIST_REVS = Collections + .<RevObject> emptyList(); + + private PackWriter writer; + + private ByteArrayOutputStream os; + + private PackOutputStream cos; + + private File packBase; + + private File packFile; + + private File indexFile; + + private PackFile pack; + + public void setUp() throws Exception { + super.setUp(); + os = new ByteArrayOutputStream(); + cos = new PackOutputStream(os); + packBase = new File(trash, "tmp_pack"); + packFile = new File(trash, "tmp_pack.pack"); + indexFile = new File(trash, "tmp_pack.idx"); + writer = new PackWriter(db, new TextProgressMonitor()); + } + + /** + * Test constructor for exceptions, default settings, initialization. + */ + public void testContructor() { + assertEquals(false, writer.isDeltaBaseAsOffset()); + assertEquals(true, writer.isReuseDeltas()); + assertEquals(true, writer.isReuseObjects()); + assertEquals(0, writer.getObjectsNumber()); + } + + /** + * Change default settings and verify them. + */ + public void testModifySettings() { + writer.setDeltaBaseAsOffset(true); + writer.setReuseDeltas(false); + writer.setReuseObjects(false); + + assertEquals(true, writer.isDeltaBaseAsOffset()); + assertEquals(false, writer.isReuseDeltas()); + assertEquals(false, writer.isReuseObjects()); + } + + /** + * Write empty pack by providing empty sets of interesting/uninteresting + * objects and check for correct format. + * + * @throws IOException + */ + public void testWriteEmptyPack1() throws IOException { + createVerifyOpenPack(EMPTY_LIST_OBJECT, EMPTY_LIST_OBJECT, false, false); + + assertEquals(0, writer.getObjectsNumber()); + assertEquals(0, pack.getObjectCount()); + assertEquals("da39a3ee5e6b4b0d3255bfef95601890afd80709", writer + .computeName().name()); + } + + /** + * Write empty pack by providing empty iterator of objects to write and + * check for correct format. + * + * @throws IOException + */ + public void testWriteEmptyPack2() throws IOException { + createVerifyOpenPack(EMPTY_LIST_REVS.iterator()); + + assertEquals(0, writer.getObjectsNumber()); + assertEquals(0, pack.getObjectCount()); + } + + /** + * Try to pass non-existing object as uninteresting, with non-ignoring + * setting. + * + * @throws IOException + */ + public void testNotIgnoreNonExistingObjects() throws IOException { + final ObjectId nonExisting = ObjectId + .fromString("0000000000000000000000000000000000000001"); + try { + createVerifyOpenPack(EMPTY_LIST_OBJECT, Collections.nCopies(1, + nonExisting), false, false); + fail("Should have thrown MissingObjectException"); + } catch (MissingObjectException x) { + // expected + } + } + + /** + * Try to pass non-existing object as uninteresting, with ignoring setting. + * + * @throws IOException + */ + public void testIgnoreNonExistingObjects() throws IOException { + final ObjectId nonExisting = ObjectId + .fromString("0000000000000000000000000000000000000001"); + createVerifyOpenPack(EMPTY_LIST_OBJECT, Collections.nCopies(1, + nonExisting), false, true); + // shouldn't throw anything + } + + /** + * Create pack basing on only interesting objects, then precisely verify + * content. No delta reuse here. + * + * @throws IOException + */ + public void testWritePack1() throws IOException { + writer.setReuseDeltas(false); + writeVerifyPack1(); + } + + /** + * Test writing pack without object reuse. Pack content/preparation as in + * {@link #testWritePack1()}. + * + * @throws IOException + */ + public void testWritePack1NoObjectReuse() throws IOException { + writer.setReuseDeltas(false); + writer.setReuseObjects(false); + writeVerifyPack1(); + } + + /** + * Create pack basing on both interesting and uninteresting objects, then + * precisely verify content. No delta reuse here. + * + * @throws IOException + */ + public void testWritePack2() throws IOException { + writeVerifyPack2(false); + } + + /** + * Test pack writing with deltas reuse, delta-base first rule. Pack + * content/preparation as in {@link #testWritePack2()}. + * + * @throws IOException + */ + public void testWritePack2DeltasReuseRefs() throws IOException { + writeVerifyPack2(true); + } + + /** + * Test pack writing with delta reuse. Delta bases referred as offsets. Pack + * configuration as in {@link #testWritePack2DeltasReuseRefs()}. + * + * @throws IOException + */ + public void testWritePack2DeltasReuseOffsets() throws IOException { + writer.setDeltaBaseAsOffset(true); + writeVerifyPack2(true); + } + + /** + * Test pack writing with delta reuse. Raw-data copy (reuse) is made on a + * pack with CRC32 index. Pack configuration as in + * {@link #testWritePack2DeltasReuseRefs()}. + * + * @throws IOException + */ + public void testWritePack2DeltasCRC32Copy() throws IOException { + final File packDir = new File(db.getObjectsDirectory(), "pack"); + final File crc32Pack = new File(packDir, + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack"); + final File crc32Idx = new File(packDir, + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idx"); + copyFile(JGitTestUtil.getTestResourceFile( + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.idxV2"), + crc32Idx); + db.openPack(crc32Pack, crc32Idx); + + writeVerifyPack2(true); + } + + /** + * Create pack basing on fixed objects list, then precisely verify content. + * No delta reuse here. + * + * @throws IOException + * @throws MissingObjectException + * + */ + public void testWritePack3() throws MissingObjectException, IOException { + writer.setReuseDeltas(false); + final ObjectId forcedOrder[] = new ObjectId[] { + ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"), + ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"), + ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), + ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"), + ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"), + ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") }; + final RevWalk parser = new RevWalk(db); + final RevObject forcedOrderRevs[] = new RevObject[forcedOrder.length]; + for (int i = 0; i < forcedOrder.length; i++) + forcedOrderRevs[i] = parser.parseAny(forcedOrder[i]); + + createVerifyOpenPack(Arrays.asList(forcedOrderRevs).iterator()); + + assertEquals(forcedOrder.length, writer.getObjectsNumber()); + verifyObjectsOrder(forcedOrder); + assertEquals("ed3f96b8327c7c66b0f8f70056129f0769323d86", writer + .computeName().name()); + } + + /** + * Another pack creation: basing on both interesting and uninteresting + * objects. No delta reuse possible here, as this is a specific case when we + * write only 1 commit, associated with 1 tree, 1 blob. + * + * @throws IOException + */ + public void testWritePack4() throws IOException { + writeVerifyPack4(false); + } + + /** + * Test thin pack writing: 1 blob delta base is on objects edge. Pack + * configuration as in {@link #testWritePack4()}. + * + * @throws IOException + */ + public void testWritePack4ThinPack() throws IOException { + writeVerifyPack4(true); + } + + /** + * Compare sizes of packs created using {@link #testWritePack2()} and + * {@link #testWritePack2DeltasReuseRefs()}. The pack using deltas should + * be smaller. + * + * @throws Exception + */ + public void testWritePack2SizeDeltasVsNoDeltas() throws Exception { + testWritePack2(); + final long sizePack2NoDeltas = cos.length(); + tearDown(); + setUp(); + testWritePack2DeltasReuseRefs(); + final long sizePack2DeltasRefs = cos.length(); + + assertTrue(sizePack2NoDeltas > sizePack2DeltasRefs); + } + + /** + * Compare sizes of packs created using + * {@link #testWritePack2DeltasReuseRefs()} and + * {@link #testWritePack2DeltasReuseOffsets()}. The pack with delta bases + * written as offsets should be smaller. + * + * @throws Exception + */ + public void testWritePack2SizeOffsetsVsRefs() throws Exception { + testWritePack2DeltasReuseRefs(); + final long sizePack2DeltasRefs = cos.length(); + tearDown(); + setUp(); + testWritePack2DeltasReuseOffsets(); + final long sizePack2DeltasOffsets = cos.length(); + + assertTrue(sizePack2DeltasRefs > sizePack2DeltasOffsets); + } + + /** + * Compare sizes of packs created using {@link #testWritePack4()} and + * {@link #testWritePack4ThinPack()}. Obviously, the thin pack should be + * smaller. + * + * @throws Exception + */ + public void testWritePack4SizeThinVsNoThin() throws Exception { + testWritePack4(); + final long sizePack4 = cos.length(); + tearDown(); + setUp(); + testWritePack4ThinPack(); + final long sizePack4Thin = cos.length(); + + assertTrue(sizePack4 > sizePack4Thin); + } + + public void testWriteIndex() throws Exception { + writer.setIndexVersion(2); + writeVerifyPack4(false); + + // Validate that IndexPack came up with the right CRC32 value. + final PackIndex idx1 = PackIndex.open(indexFile); + assertTrue(idx1 instanceof PackIndexV2); + assertEquals(0x4743F1E4L, idx1.findCRC32(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"))); + + // Validate that an index written by PackWriter is the same. + final File idx2File = new File(indexFile.getAbsolutePath() + ".2"); + final FileOutputStream is = new FileOutputStream(idx2File); + try { + writer.writeIndex(is); + } finally { + is.close(); + } + final PackIndex idx2 = PackIndex.open(idx2File); + assertTrue(idx2 instanceof PackIndexV2); + assertEquals(idx1.getObjectCount(), idx2.getObjectCount()); + assertEquals(idx1.getOffset64Count(), idx2.getOffset64Count()); + + for (int i = 0; i < idx1.getObjectCount(); i++) { + final ObjectId id = idx1.getObjectId(i); + assertEquals(id, idx2.getObjectId(i)); + assertEquals(idx1.findOffset(id), idx2.findOffset(id)); + assertEquals(idx1.findCRC32(id), idx2.findCRC32(id)); + } + } + + // TODO: testWritePackDeltasCycle() + // TODO: testWritePackDeltasDepth() + + private void writeVerifyPack1() throws IOException { + final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>(); + interestings.add(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); + createVerifyOpenPack(interestings, EMPTY_LIST_OBJECT, false, false); + + final ObjectId expectedOrder[] = new ObjectId[] { + ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"), + ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"), + ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"), + ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), + ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"), + ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"), + ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"), + ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") }; + + assertEquals(expectedOrder.length, writer.getObjectsNumber()); + verifyObjectsOrder(expectedOrder); + assertEquals("34be9032ac282b11fa9babdc2b2a93ca996c9c2f", writer + .computeName().name()); + } + + private void writeVerifyPack2(boolean deltaReuse) throws IOException { + writer.setReuseDeltas(deltaReuse); + final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>(); + interestings.add(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); + final LinkedList<ObjectId> uninterestings = new LinkedList<ObjectId>(); + uninterestings.add(ObjectId + .fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab")); + createVerifyOpenPack(interestings, uninterestings, false, false); + + final ObjectId expectedOrder[] = new ObjectId[] { + ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"), + ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"), + ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), + ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"), + ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"), + ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3") }; + if (deltaReuse) { + // objects order influenced (swapped) by delta-base first rule + ObjectId temp = expectedOrder[4]; + expectedOrder[4] = expectedOrder[5]; + expectedOrder[5] = temp; + } + assertEquals(expectedOrder.length, writer.getObjectsNumber()); + verifyObjectsOrder(expectedOrder); + assertEquals("ed3f96b8327c7c66b0f8f70056129f0769323d86", writer + .computeName().name()); + } + + private void writeVerifyPack4(final boolean thin) throws IOException { + final LinkedList<ObjectId> interestings = new LinkedList<ObjectId>(); + interestings.add(ObjectId + .fromString("82c6b885ff600be425b4ea96dee75dca255b69e7")); + final LinkedList<ObjectId> uninterestings = new LinkedList<ObjectId>(); + uninterestings.add(ObjectId + .fromString("c59759f143fb1fe21c197981df75a7ee00290799")); + createVerifyOpenPack(interestings, uninterestings, thin, false); + + final ObjectId writtenObjects[] = new ObjectId[] { + ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"), + ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), + ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259") }; + assertEquals(writtenObjects.length, writer.getObjectsNumber()); + ObjectId expectedObjects[]; + if (thin) { + expectedObjects = new ObjectId[4]; + System.arraycopy(writtenObjects, 0, expectedObjects, 0, + writtenObjects.length); + expectedObjects[3] = ObjectId + .fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"); + + } else { + expectedObjects = writtenObjects; + } + verifyObjectsOrder(expectedObjects); + assertEquals("cded4b74176b4456afa456768b2b5aafb41c44fc", writer + .computeName().name()); + } + + private void createVerifyOpenPack(final Collection<ObjectId> interestings, + final Collection<ObjectId> uninterestings, final boolean thin, + final boolean ignoreMissingUninteresting) + throws MissingObjectException, IOException { + writer.setThin(thin); + writer.setIgnoreMissingUninteresting(ignoreMissingUninteresting); + writer.preparePack(interestings, uninterestings); + writer.writePack(cos); + verifyOpenPack(thin); + } + + private void createVerifyOpenPack(final Iterator<RevObject> objectSource) + throws MissingObjectException, IOException { + writer.preparePack(objectSource); + writer.writePack(cos); + verifyOpenPack(false); + } + + private void verifyOpenPack(final boolean thin) throws IOException { + if (thin) { + final InputStream is = new ByteArrayInputStream(os.toByteArray()); + final IndexPack indexer = new IndexPack(db, is, packBase); + try { + indexer.index(new TextProgressMonitor()); + fail("indexer should grumble about missing object"); + } catch (IOException x) { + // expected + } + } + final InputStream is = new ByteArrayInputStream(os.toByteArray()); + final IndexPack indexer = new IndexPack(db, is, packBase); + indexer.setKeepEmpty(true); + indexer.setFixThin(thin); + indexer.setIndexVersion(2); + indexer.index(new TextProgressMonitor()); + pack = new PackFile(indexFile, packFile); + } + + private void verifyObjectsOrder(final ObjectId objectsOrder[]) { + final List<PackIndex.MutableEntry> entries = new ArrayList<PackIndex.MutableEntry>(); + + for (MutableEntry me : pack) { + entries.add(me.cloneEntry()); + } + Collections.sort(entries, new Comparator<PackIndex.MutableEntry>() { + public int compare(MutableEntry o1, MutableEntry o2) { + return Long.signum(o1.getOffset() - o2.getOffset()); + } + }); + + int i = 0; + for (MutableEntry me : entries) { + assertEquals(objectsOrder[i++].toObjectId(), me.toObjectId()); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java new file mode 100644 index 0000000000..5ac75d8043 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReadTreeTest.java @@ -0,0 +1,581 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2008-2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.util.HashMap; + +import org.eclipse.jgit.errors.CheckoutConflictException; + +public class ReadTreeTest extends RepositoryTestCase { + + private Tree theHead; + private Tree theMerge; + private GitIndex theIndex; + private WorkDirCheckout theReadTree; + // Each of these rules are from the read-tree manpage + // go there to see what they mean. + // Rule 0 is left out for obvious reasons :) + public void testRules1thru3_NoIndexEntry() throws IOException { + GitIndex index = new GitIndex(db); + + Tree head = new Tree(db); + FileTreeEntry headFile = head.addFile("foo"); + ObjectId objectId = ObjectId.fromString("ba78e065e2c261d4f7b8f42107588051e87e18e9"); + headFile.setId(objectId); + Tree merge = new Tree(db); + + WorkDirCheckout readTree = new WorkDirCheckout(db, trash, head, index, merge); + readTree.prescanTwoTrees(); + + assertTrue(readTree.removed.contains("foo")); + + readTree = new WorkDirCheckout(db, trash, merge, index, head); + readTree.prescanTwoTrees(); + + assertEquals(objectId, readTree.updated.get("foo")); + + ObjectId anotherId = ObjectId.fromString("ba78e065e2c261d4f7b8f42107588051e87e18ee"); + merge.addFile("foo").setId(anotherId); + + readTree = new WorkDirCheckout(db, trash, head, index, merge); + readTree.prescanTwoTrees(); + + assertEquals(anotherId, readTree.updated.get("foo")); + } + + void setupCase(HashMap<String, String> headEntries, + HashMap<String, String> mergeEntries, + HashMap<String, String> indexEntries) throws IOException { + theHead = buildTree(headEntries); + theMerge = buildTree(mergeEntries); + theIndex = buildIndex(indexEntries); + } + + private GitIndex buildIndex(HashMap<String, String> indexEntries) throws IOException { + GitIndex index = new GitIndex(db); + + if (indexEntries == null) + return index; + for (java.util.Map.Entry<String,String> e : indexEntries.entrySet()) { + index.add(trash, writeTrashFile(e.getKey(), e.getValue())).forceRecheck(); + } + + return index; + } + + private Tree buildTree(HashMap<String, String> headEntries) throws IOException { + Tree tree = new Tree(db); + + if (headEntries == null) + return tree; + for (java.util.Map.Entry<String,String> e : headEntries.entrySet()) { + tree.addFile(e.getKey()).setId(genSha1(e.getValue())); + } + + return tree; + } + + ObjectId genSha1(String data) { + InputStream is = new ByteArrayInputStream(data.getBytes()); + ObjectWriter objectWriter = new ObjectWriter(db); + try { + return objectWriter.writeObject(Constants.OBJ_BLOB, data + .getBytes().length, is, true); + } catch (IOException e) { + fail(e.toString()); + } + return null; + } + + private WorkDirCheckout go() throws IOException { + theReadTree = new WorkDirCheckout(db, trash, theHead, theIndex, theMerge); + theReadTree.prescanTwoTrees(); + return theReadTree; + } + + // for these rules, they all have clean yes/no options + // but it doesn't matter if the entry is clean or not + // so we can just ignore the state in the filesystem entirely + public void testRules4thru13_IndexEntryNotInHead() throws IOException { + // rules 4 and 5 + HashMap<String, String> idxMap; + + idxMap = new HashMap<String, String>(); + idxMap.put("foo", "foo"); + setupCase(null, null, idxMap); + theReadTree = go(); + + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.removed.isEmpty()); + assertTrue(theReadTree.conflicts.isEmpty()); + + // rules 6 and 7 + idxMap = new HashMap<String, String>(); + idxMap.put("foo", "foo"); + setupCase(null, idxMap, idxMap); + theReadTree = go(); + + assertAllEmpty(); + + // rules 8 and 9 + HashMap<String, String> mergeMap; + mergeMap = new HashMap<String, String>(); + + mergeMap.put("foo", "merge"); + setupCase(null, mergeMap, idxMap); + go(); + + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.removed.isEmpty()); + assertTrue(theReadTree.conflicts.contains("foo")); + + // rule 10 + + HashMap<String, String> headMap = new HashMap<String, String>(); + headMap.put("foo", "foo"); + setupCase(headMap, null, idxMap); + go(); + + assertTrue(theReadTree.removed.contains("foo")); + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.conflicts.isEmpty()); + + // rule 11 + setupCase(headMap, null, idxMap); + new File(trash, "foo").delete(); + writeTrashFile("foo", "bar"); + theIndex.getMembers()[0].forceRecheck(); + go(); + + assertTrue(theReadTree.removed.isEmpty()); + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.conflicts.contains("foo")); + + // rule 12 & 13 + headMap.put("foo", "head"); + setupCase(headMap, null, idxMap); + go(); + + assertTrue(theReadTree.removed.isEmpty()); + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.conflicts.contains("foo")); + + // rules 14 & 15 + setupCase(headMap, headMap, idxMap); + go(); + + assertAllEmpty(); + + // rules 16 & 17 + setupCase(headMap, mergeMap, idxMap); go(); + assertTrue(theReadTree.conflicts.contains("foo")); + + // rules 18 & 19 + setupCase(headMap, idxMap, idxMap); go(); + assertAllEmpty(); + + // rule 20 + setupCase(idxMap, mergeMap, idxMap); go(); + assertTrue(theReadTree.updated.containsKey("foo")); + + // rules 21 + setupCase(idxMap, mergeMap, idxMap); + new File(trash, "foo").delete(); + writeTrashFile("foo", "bar"); + theIndex.getMembers()[0].forceRecheck(); + go(); + assertTrue(theReadTree.conflicts.contains("foo")); + } + + private void assertAllEmpty() { + assertTrue(theReadTree.removed.isEmpty()); + assertTrue(theReadTree.updated.isEmpty()); + assertTrue(theReadTree.conflicts.isEmpty()); + } + + public void testDirectoryFileSimple() throws IOException { + theIndex = new GitIndex(db); + theIndex.add(trash, writeTrashFile("DF", "DF")); + Tree treeDF = db.mapTree(theIndex.writeTree()); + + recursiveDelete(new File(trash, "DF")); + theIndex = new GitIndex(db); + theIndex.add(trash, writeTrashFile("DF/DF", "DF/DF")); + Tree treeDFDF = db.mapTree(theIndex.writeTree()); + + theIndex = new GitIndex(db); + recursiveDelete(new File(trash, "DF")); + + theIndex.add(trash, writeTrashFile("DF", "DF")); + theReadTree = new WorkDirCheckout(db, trash, treeDF, theIndex, treeDFDF); + theReadTree.prescanTwoTrees(); + + assertTrue(theReadTree.removed.contains("DF")); + assertTrue(theReadTree.updated.containsKey("DF/DF")); + + recursiveDelete(new File(trash, "DF")); + theIndex = new GitIndex(db); + theIndex.add(trash, writeTrashFile("DF/DF", "DF/DF")); + + theReadTree = new WorkDirCheckout(db, trash, treeDFDF, theIndex, treeDF); + theReadTree.prescanTwoTrees(); + assertTrue(theReadTree.removed.contains("DF/DF")); + assertTrue(theReadTree.updated.containsKey("DF")); + } + + /* + * Directory/File Conflict cases: + * It's entirely possible that in practice a number of these may be equivalent + * to the cases described in git-read-tree.txt. As long as it does the right thing, + * that's all I care about. These are basically reverse-engineered from + * what git currently does. If there are tests for these in git, it's kind of + * hard to track them all down... + * + * H I M Clean H==M H==I I==M Result + * ------------------------------------------------------------------ + *1 D D F Y N Y N Update + *2 D D F N N Y N Conflict + *3 D F D Y N N Update + *4 D F D N N N Update + *5 D F F Y N N Y Keep + *6 D F F N N N Y Keep + *7 F D F Y Y N N Update + *8 F D F N Y N N Conflict + *9 F D F Y N N N Update + *10 F D D N N Y Keep + *11 F D D N N N Conflict + *12 F F D Y N Y N Update + *13 F F D N N Y N Conflict + *14 F F D N N N Conflict + *15 0 F D N N N Conflict + *16 0 D F Y N N N Update + *17 0 D F N N N Conflict + *18 F 0 D Update + *19 D 0 F Update + */ + + public void testDirectoryFileConflicts_1() throws Exception { + // 1 + doit(mk("DF/DF"), mk("DF"), mk("DF/DF")); + assertNoConflicts(); + assertUpdated("DF"); + assertRemoved("DF/DF"); + } + + public void testDirectoryFileConflicts_2() throws Exception { + // 2 + setupCase(mk("DF/DF"), mk("DF"), mk("DF/DF")); + writeTrashFile("DF/DF", "different"); + go(); + assertConflict("DF/DF"); + + } + + public void testDirectoryFileConflicts_3() throws Exception { + // 3 - the first to break! + doit(mk("DF/DF"), mk("DF/DF"), mk("DF")); + assertUpdated("DF/DF"); + assertRemoved("DF"); + } + + public void testDirectoryFileConflicts_4() throws Exception { + // 4 (basically same as 3, just with H and M different) + doit(mk("DF/DF"), mkmap("DF/DF", "foo"), mk("DF")); + assertUpdated("DF/DF"); + assertRemoved("DF"); + + } + + public void testDirectoryFileConflicts_5() throws Exception { + // 5 + doit(mk("DF/DF"), mk("DF"), mk("DF")); + assertRemoved("DF/DF"); + + } + + public void testDirectoryFileConflicts_6() throws Exception { + // 6 + setupCase(mk("DF/DF"), mk("DF"), mk("DF")); + writeTrashFile("DF", "different"); + go(); + assertRemoved("DF/DF"); + } + + public void testDirectoryFileConflicts_7() throws Exception { + // 7 + doit(mk("DF"), mk("DF"), mk("DF/DF")); + assertUpdated("DF"); + assertRemoved("DF/DF"); + + cleanUpDF(); + setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF")); + go(); + assertRemoved("DF/DF/DF/DF/DF"); + assertUpdated("DF/DF"); + + cleanUpDF(); + setupCase(mk("DF/DF"), mk("DF/DF"), mk("DF/DF/DF/DF/DF")); + writeTrashFile("DF/DF/DF/DF/DF", "diff"); + go(); + assertConflict("DF/DF/DF/DF/DF"); + assertUpdated("DF/DF"); + + } + + // 8 ? + + public void testDirectoryFileConflicts_9() throws Exception { + // 9 + doit(mk("DF"), mkmap("DF", "QP"), mk("DF/DF")); + assertRemoved("DF/DF"); + assertUpdated("DF"); + } + + public void testDirectoryFileConflicts_10() throws Exception { + // 10 + cleanUpDF(); + doit(mk("DF"), mk("DF/DF"), mk("DF/DF")); + assertNoConflicts(); + + } + + public void testDirectoryFileConflicts_11() throws Exception { + // 11 + doit(mk("DF"), mk("DF/DF"), mkmap("DF/DF", "asdf")); + assertConflict("DF/DF"); + } + + public void testDirectoryFileConflicts_12() throws Exception { + // 12 + cleanUpDF(); + doit(mk("DF"), mk("DF/DF"), mk("DF")); + assertRemoved("DF"); + assertUpdated("DF/DF"); + } + + public void testDirectoryFileConflicts_13() throws Exception { + // 13 + cleanUpDF(); + setupCase(mk("DF"), mk("DF/DF"), mk("DF")); + writeTrashFile("DF", "asdfsdf"); + go(); + assertConflict("DF"); + assertUpdated("DF/DF"); + } + + public void testDirectoryFileConflicts_14() throws Exception { + // 14 + cleanUpDF(); + doit(mk("DF"), mk("DF/DF"), mkmap("DF", "Foo")); + assertConflict("DF"); + assertUpdated("DF/DF"); + } + + public void testDirectoryFileConflicts_15() throws Exception { + // 15 + doit(mkmap(), mk("DF/DF"), mk("DF")); + assertRemoved("DF"); + assertUpdated("DF/DF"); + } + + public void testDirectoryFileConflicts_15b() throws Exception { + // 15, take 2, just to check multi-leveled + doit(mkmap(), mk("DF/DF/DF/DF"), mk("DF")); + assertRemoved("DF"); + assertUpdated("DF/DF/DF/DF"); + } + + public void testDirectoryFileConflicts_16() throws Exception { + // 16 + cleanUpDF(); + doit(mkmap(), mk("DF"), mk("DF/DF/DF")); + assertRemoved("DF/DF/DF"); + assertUpdated("DF"); + } + + public void testDirectoryFileConflicts_17() throws Exception { + // 17 + cleanUpDF(); + setupCase(mkmap(), mk("DF"), mk("DF/DF/DF")); + writeTrashFile("DF/DF/DF", "asdf"); + go(); + assertConflict("DF/DF/DF"); + assertUpdated("DF"); + } + + public void testDirectoryFileConflicts_18() throws Exception { + // 18 + cleanUpDF(); + doit(mk("DF/DF"), mk("DF/DF/DF/DF"), null); + assertRemoved("DF/DF"); + assertUpdated("DF/DF/DF/DF"); + } + + public void testDirectoryFileConflicts_19() throws Exception { + // 19 + cleanUpDF(); + doit(mk("DF/DF/DF/DF"), mk("DF/DF/DF"), null); + assertRemoved("DF/DF/DF/DF"); + assertUpdated("DF/DF/DF"); + } + + private void cleanUpDF() throws Exception { + tearDown(); + setUp(); + recursiveDelete(new File(trash, "DF")); + } + + private void assertConflict(String s) { + assertTrue(theReadTree.conflicts.contains(s)); + } + + private void assertUpdated(String s) { + assertTrue(theReadTree.updated.containsKey(s)); + } + + private void assertRemoved(String s) { + assertTrue(theReadTree.removed.contains(s)); + } + + private void assertNoConflicts() { + assertTrue(theReadTree.conflicts.isEmpty()); + } + + private void doit(HashMap<String, String> h, HashMap<String, String>m, + HashMap<String, String> i) throws IOException { + setupCase(h, m, i); + go(); + } + + private static HashMap<String, String> mk(String a) { + return mkmap(a, a); + } + + private static HashMap<String, String> mkmap(String... args) { + if ((args.length % 2) > 0) + throw new IllegalArgumentException("needs to be pairs"); + + HashMap<String, String> map = new HashMap<String, String>(); + for (int i = 0; i < args.length; i += 2) { + map.put(args[i], args[i+1]); + } + + return map; + } + + public void testUntrackedConflicts() throws IOException { + setupCase(null, mk("foo"), null); + writeTrashFile("foo", "foo"); + go(); + + assertConflict("foo"); + + recursiveDelete(new File(trash, "foo")); + setupCase(null, mk("foo"), null); + writeTrashFile("foo/bar/baz", ""); + writeTrashFile("foo/blahblah", ""); + go(); + + assertConflict("foo/bar/baz"); + assertConflict("foo/blahblah"); + + recursiveDelete(new File(trash, "foo")); + + setupCase(mkmap("foo/bar", "", "foo/baz", ""), + mk("foo"), mkmap("foo/bar", "", "foo/baz", "")); + assertTrue(new File(trash, "foo/bar").exists()); + go(); + + assertNoConflicts(); + } + + public void testCloseNameConflictsX0() throws IOException { + setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "b.b/b.b","b.b/b.bs"), mkmap("a/a", "a/a-c") ); + checkout(); + go(); + assertNoConflicts(); + } + + public void testCloseNameConflicts1() throws IOException { + setupCase(mkmap("a/a", "a/a-c"), mkmap("a/a","a/a", "a.a/a.a","a.a/a.a"), mkmap("a/a", "a/a-c") ); + checkout(); + go(); + assertNoConflicts(); + } + + private void checkout() throws IOException { + theReadTree = new WorkDirCheckout(db, trash, theHead, theIndex, theMerge); + theReadTree.checkout(); + } + + public void testCheckoutOutChanges() throws IOException { + setupCase(mk("foo"), mk("foo/bar"), mk("foo")); + checkout(); + + assertFalse(new File(trash, "foo").isFile()); + assertTrue(new File(trash, "foo/bar").isFile()); + recursiveDelete(new File(trash, "foo")); + + setupCase(mk("foo/bar"), mk("foo"), mk("foo/bar")); + checkout(); + + assertFalse(new File(trash, "foo/bar").isFile()); + assertTrue(new File(trash, "foo").isFile()); + + setupCase(mk("foo"), mkmap("foo", "qux"), mkmap("foo", "bar")); + + try { + checkout(); + fail("did not throw exception"); + } catch (CheckoutConflictException e) { + // should have thrown + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java new file mode 100644 index 0000000000..d7b6193ce1 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefTest.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2009, Robin Rosenberg + * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.util.Map; + +import org.eclipse.jgit.lib.Ref.Storage; +import org.eclipse.jgit.lib.RefUpdate.Result; + +/** + * Misc tests for refs. A lot of things are tested elsewhere so not having a + * test for a ref related method, does not mean it is untested. + */ +public class RefTest extends RepositoryTestCase { + + public void testReadAllIncludingSymrefs() throws Exception { + ObjectId masterId = db.resolve("refs/heads/master"); + RefUpdate updateRef = db.updateRef("refs/remotes/origin/master"); + updateRef.setNewObjectId(masterId); + updateRef.setForceUpdate(true); + updateRef.update(); + db + .writeSymref("refs/remotes/origin/HEAD", + "refs/remotes/origin/master"); + + ObjectId r = db.resolve("refs/remotes/origin/HEAD"); + assertEquals(masterId, r); + + Map<String, Ref> allRefs = db.getAllRefs(); + Ref refHEAD = allRefs.get("refs/remotes/origin/HEAD"); + assertNotNull(refHEAD); + assertEquals(masterId, refHEAD.getObjectId()); + assertTrue(refHEAD.isPeeled()); + assertNull(refHEAD.getPeeledObjectId()); + + Ref refmaster = allRefs.get("refs/remotes/origin/master"); + assertEquals(masterId, refmaster.getObjectId()); + assertFalse(refmaster.isPeeled()); + assertNull(refmaster.getPeeledObjectId()); + } + + public void testReadSymRefToPacked() throws IOException { + db.writeSymref("HEAD", "refs/heads/b"); + Ref ref = db.getRef("HEAD"); + assertEquals(Ref.Storage.LOOSE_PACKED, ref.getStorage()); + } + + public void testReadSymRefToLoosePacked() throws IOException { + ObjectId pid = db.resolve("refs/heads/master^"); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); // internal + + db.writeSymref("HEAD", "refs/heads/master"); + Ref ref = db.getRef("HEAD"); + assertEquals(Ref.Storage.LOOSE_PACKED, ref.getStorage()); + } + + public void testReadLooseRef() throws IOException { + RefUpdate updateRef = db.updateRef("ref/heads/new"); + updateRef.setNewObjectId(db.resolve("refs/heads/master")); + Result update = updateRef.update(); + assertEquals(Result.NEW, update); + Ref ref = db.getRef("ref/heads/new"); + assertEquals(Storage.LOOSE, ref.getStorage()); + } + + /** + * Let an "outsider" create a loose ref with the same name as a packed one + * + * @throws IOException + * @throws InterruptedException + */ + public void testReadLoosePackedRef() throws IOException, + InterruptedException { + Ref ref = db.getRef("refs/heads/master"); + assertEquals(Storage.PACKED, ref.getStorage()); + FileOutputStream os = new FileOutputStream(new File(db.getDirectory(), + "refs/heads/master")); + os.write(ref.getObjectId().name().getBytes()); + os.write('\n'); + os.close(); + + ref = db.getRef("refs/heads/master"); + assertEquals(Storage.LOOSE_PACKED, ref.getStorage()); + } + + /** + * Modify a packed ref using the API. This creates a loose ref too, ie. + * LOOSE_PACKED + * + * @throws IOException + */ + public void testReadSimplePackedRefSameRepo() throws IOException { + Ref ref = db.getRef("refs/heads/master"); + ObjectId pid = db.resolve("refs/heads/master^"); + assertEquals(Storage.PACKED, ref.getStorage()); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); + + ref = db.getRef("refs/heads/master"); + assertEquals(Storage.LOOSE_PACKED, ref.getStorage()); + } + + public void testOrigResolvedNamesBranch() throws IOException { + Ref ref = db.getRef("a"); + assertEquals("refs/heads/a", ref.getName()); + assertEquals("refs/heads/a", ref.getOrigName()); + } + + public void testOrigResolvedNamesSymRef() throws IOException { + Ref ref = db.getRef("HEAD"); + assertEquals("refs/heads/master", ref.getName()); + assertEquals("HEAD", ref.getOrigName()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java new file mode 100644 index 0000000000..3704c56173 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RefUpdateTest.java @@ -0,0 +1,768 @@ +/* + * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org> + * Copyright (C) 2008-2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.Map.Entry; + +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +public class RefUpdateTest extends RepositoryTestCase { + + private RefUpdate updateRef(final String name) throws IOException { + final RefUpdate ref = db.updateRef(name); + ref.setNewObjectId(db.resolve(Constants.HEAD)); + return ref; + } + + private void delete(final RefUpdate ref, final Result expected) + throws IOException { + delete(ref, expected, true, true); + } + + private void delete(final RefUpdate ref, final Result expected, + final boolean exists, final boolean removed) throws IOException { + assertEquals(exists, db.getAllRefs().containsKey(ref.getName())); + assertEquals(expected, ref.delete()); + assertEquals(!removed, db.getAllRefs().containsKey(ref.getName())); + } + + public void testNoCacheObjectIdSubclass() throws IOException { + final String newRef = "refs/heads/abc"; + final RefUpdate ru = updateRef(newRef); + final RevCommit newid = new RevCommit(ru.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid); + Result update = ru.update(); + assertEquals(Result.NEW, update); + final Ref r = db.getAllRefs().get(newRef); + assertNotNull(r); + assertEquals(newRef, r.getName()); + assertNotNull(r.getObjectId()); + assertNotSame(newid, r.getObjectId()); + assertSame(ObjectId.class, r.getObjectId().getClass()); + assertEquals(newid.copy(), r.getObjectId()); + List<org.eclipse.jgit.lib.ReflogReader.Entry> reverseEntries1 = db.getReflogReader("refs/heads/abc").getReverseEntries(); + org.eclipse.jgit.lib.ReflogReader.Entry entry1 = reverseEntries1.get(0); + assertEquals(1, reverseEntries1.size()); + assertEquals(ObjectId.zeroId(), entry1.getOldId()); + assertEquals(r.getObjectId(), entry1.getNewId()); + assertEquals(new PersonIdent(db).toString(), entry1.getWho().toString()); + assertEquals("", entry1.getComment()); + List<org.eclipse.jgit.lib.ReflogReader.Entry> reverseEntries2 = db.getReflogReader("HEAD").getReverseEntries(); + assertEquals(0, reverseEntries2.size()); + } + + public void testNewNamespaceConflictWithLoosePrefixNameExists() + throws IOException { + final String newRef = "refs/heads/z"; + final RefUpdate ru = updateRef(newRef); + final RevCommit newid = new RevCommit(ru.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid); + Result update = ru.update(); + assertEquals(Result.NEW, update); + // end setup + final String newRef2 = "refs/heads/z/a"; + final RefUpdate ru2 = updateRef(newRef2); + final RevCommit newid2 = new RevCommit(ru2.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid2); + Result update2 = ru2.update(); + assertEquals(Result.LOCK_FAILURE, update2); + assertEquals(1, db.getReflogReader("refs/heads/z").getReverseEntries().size()); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + } + + public void testNewNamespaceConflictWithPackedPrefixNameExists() + throws IOException { + final String newRef = "refs/heads/master/x"; + final RefUpdate ru = updateRef(newRef); + final RevCommit newid = new RevCommit(ru.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid); + Result update = ru.update(); + assertEquals(Result.LOCK_FAILURE, update); + assertNull(db.getReflogReader("refs/heads/master/x")); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + } + + public void testNewNamespaceConflictWithLoosePrefixOfExisting() + throws IOException { + final String newRef = "refs/heads/z/a"; + final RefUpdate ru = updateRef(newRef); + final RevCommit newid = new RevCommit(ru.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid); + Result update = ru.update(); + assertEquals(Result.NEW, update); + // end setup + final String newRef2 = "refs/heads/z"; + final RefUpdate ru2 = updateRef(newRef2); + final RevCommit newid2 = new RevCommit(ru2.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid2); + Result update2 = ru2.update(); + assertEquals(Result.LOCK_FAILURE, update2); + assertEquals(1, db.getReflogReader("refs/heads/z/a").getReverseEntries().size()); + assertNull(db.getReflogReader("refs/heads/z")); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + } + + public void testNewNamespaceConflictWithPackedPrefixOfExisting() + throws IOException { + final String newRef = "refs/heads/prefix"; + final RefUpdate ru = updateRef(newRef); + final RevCommit newid = new RevCommit(ru.getNewObjectId()) { + // empty + }; + ru.setNewObjectId(newid); + Result update = ru.update(); + assertEquals(Result.LOCK_FAILURE, update); + assertNull(db.getReflogReader("refs/heads/prefix")); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + } + + /** + * Delete a ref that is pointed to by HEAD + * + * @throws IOException + */ + public void testDeleteHEADreferencedRef() throws IOException { + ObjectId pid = db.resolve("refs/heads/master^"); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); // internal + + RefUpdate updateRef2 = db.updateRef("refs/heads/master"); + Result delete = updateRef2.delete(); + assertEquals(Result.REJECTED_CURRENT_BRANCH, delete); + assertEquals(pid, db.resolve("refs/heads/master")); + assertEquals(1,db.getReflogReader("refs/heads/master").getReverseEntries().size()); + assertEquals(0,db.getReflogReader("HEAD").getReverseEntries().size()); + } + + public void testLooseDelete() throws IOException { + final String newRef = "refs/heads/abc"; + RefUpdate ref = updateRef(newRef); + ref.update(); // create loose ref + ref = updateRef(newRef); // refresh + delete(ref, Result.NO_CHANGE); + assertNull(db.getReflogReader("refs/heads/abc")); + } + + public void testDeleteHead() throws IOException { + final RefUpdate ref = updateRef(Constants.HEAD); + delete(ref, Result.REJECTED_CURRENT_BRANCH, true, false); + assertEquals(0, db.getReflogReader("refs/heads/master").getReverseEntries().size()); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + } + + /** + * Delete a loose ref and make sure the directory in refs is deleted too, + * and the reflog dir too + * + * @throws IOException + */ + public void testDeleteLooseAndItsDirectory() throws IOException { + ObjectId pid = db.resolve("refs/heads/c^"); + RefUpdate updateRef = db.updateRef("refs/heads/z/c"); + updateRef.setNewObjectId(pid); + updateRef.setForceUpdate(true); + updateRef.setRefLogMessage("new test ref", false); + Result update = updateRef.update(); + assertEquals(Result.NEW, update); // internal + assertTrue(new File(db.getDirectory(), Constants.R_HEADS + "z") + .exists()); + assertTrue(new File(db.getDirectory(), "logs/refs/heads/z").exists()); + + // The real test here + RefUpdate updateRef2 = db.updateRef("refs/heads/z/c"); + updateRef2.setForceUpdate(true); + Result delete = updateRef2.delete(); + assertEquals(Result.FORCED, delete); + assertNull(db.resolve("refs/heads/z/c")); + assertFalse(new File(db.getDirectory(), Constants.R_HEADS + "z") + .exists()); + assertFalse(new File(db.getDirectory(), "logs/refs/heads/z").exists()); + } + + public void testDeleteNotFound() throws IOException { + final RefUpdate ref = updateRef("refs/heads/xyz"); + delete(ref, Result.NEW, false, true); + } + + public void testDeleteFastForward() throws IOException { + final RefUpdate ref = updateRef("refs/heads/a"); + delete(ref, Result.FAST_FORWARD); + } + + public void testDeleteForce() throws IOException { + final RefUpdate ref = db.updateRef("refs/heads/b"); + ref.setNewObjectId(db.resolve("refs/heads/a")); + delete(ref, Result.REJECTED, true, false); + ref.setForceUpdate(true); + delete(ref, Result.FORCED); + } + + public void testRefKeySameAsOrigName() { + Map<String, Ref> allRefs = db.getAllRefs(); + for (Entry<String, Ref> e : allRefs.entrySet()) { + assertEquals(e.getKey(), e.getValue().getOrigName()); + + } + } + + /** + * Try modify a ref forward, fast forward + * + * @throws IOException + */ + public void testUpdateRefForward() throws IOException { + ObjectId ppid = db.resolve("refs/heads/master^"); + ObjectId pid = db.resolve("refs/heads/master"); + + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(ppid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); + assertEquals(ppid, db.resolve("refs/heads/master")); + + // real test + RefUpdate updateRef2 = db.updateRef("refs/heads/master"); + updateRef2.setNewObjectId(pid); + Result update2 = updateRef2.update(); + assertEquals(Result.FAST_FORWARD, update2); + assertEquals(pid, db.resolve("refs/heads/master")); + } + + /** + * Delete a ref that exists both as packed and loose. Make sure the ref + * cannot be resolved after delete. + * + * @throws IOException + */ + public void testDeleteLoosePacked() throws IOException { + ObjectId pid = db.resolve("refs/heads/c^"); + RefUpdate updateRef = db.updateRef("refs/heads/c"); + updateRef.setNewObjectId(pid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); // internal + + // The real test here + RefUpdate updateRef2 = db.updateRef("refs/heads/c"); + updateRef2.setForceUpdate(true); + Result delete = updateRef2.delete(); + assertEquals(Result.FORCED, delete); + assertNull(db.resolve("refs/heads/c")); + } + + /** + * Try modify a ref to same + * + * @throws IOException + */ + public void testUpdateRefNoChange() throws IOException { + ObjectId pid = db.resolve("refs/heads/master"); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + Result update = updateRef.update(); + assertEquals(Result.NO_CHANGE, update); + assertEquals(pid, db.resolve("refs/heads/master")); + } + + /** + * Test case originating from + * <a href="http://bugs.eclipse.org/285991">bug 285991</a> + * + * Make sure the in memory cache is updated properly after + * update of symref. This one did not fail because the + * ref was packed due to implementation issues. + * + * @throws Exception + */ + public void testRefsCacheAfterUpdate() throws Exception { + // Do not use the defalt repo for this case. + Map<String, Ref> allRefs = db.getAllRefs(); + ObjectId oldValue = db.resolve("HEAD"); + ObjectId newValue = db.resolve("HEAD^"); + // first make HEAD refer to loose ref + RefUpdate updateRef = db.updateRef(Constants.HEAD); + updateRef.setForceUpdate(true); + updateRef.setNewObjectId(newValue); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); + + // now update that ref + updateRef = db.updateRef(Constants.HEAD); + updateRef.setForceUpdate(true); + updateRef.setNewObjectId(oldValue); + update = updateRef.update(); + assertEquals(Result.FAST_FORWARD, update); + allRefs = db.getAllRefs(); + assertEquals("refs/heads/master", allRefs.get("refs/heads/master").getName()); + assertEquals("refs/heads/master", allRefs.get("refs/heads/master").getOrigName()); + assertEquals("refs/heads/master", allRefs.get("HEAD").getName()); + assertEquals("HEAD", allRefs.get("HEAD").getOrigName()); + } + + /** + * Test case originating from + * <a href="http://bugs.eclipse.org/285991">bug 285991</a> + * + * Make sure the in memory cache is updated properly after + * update of symref. + * + * @throws Exception + */ + public void testRefsCacheAfterUpdateLoosOnly() throws Exception { + // Do not use the defalt repo for this case. + Map<String, Ref> allRefs = db.getAllRefs(); + ObjectId oldValue = db.resolve("HEAD"); + db.writeSymref(Constants.HEAD, "refs/heads/newref"); + RefUpdate updateRef = db.updateRef(Constants.HEAD); + updateRef.setForceUpdate(true); + updateRef.setNewObjectId(oldValue); + Result update = updateRef.update(); + assertEquals(Result.NEW, update); + allRefs = db.getAllRefs(); + assertEquals("refs/heads/newref", allRefs.get("HEAD").getName()); + assertEquals("HEAD", allRefs.get("HEAD").getOrigName()); + assertEquals("refs/heads/newref", allRefs.get("refs/heads/newref").getName()); + assertEquals("refs/heads/newref", allRefs.get("refs/heads/newref").getOrigName()); + } + + /** + * Try modify a ref, but get wrong expected old value + * + * @throws IOException + */ + public void testUpdateRefLockFailureWrongOldValue() throws IOException { + ObjectId pid = db.resolve("refs/heads/master"); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + updateRef.setExpectedOldObjectId(db.resolve("refs/heads/master^")); + Result update = updateRef.update(); + assertEquals(Result.LOCK_FAILURE, update); + assertEquals(pid, db.resolve("refs/heads/master")); + } + + /** + * Try modify a ref forward, fast forward, checking old value first + * + * @throws IOException + */ + public void testUpdateRefForwardWithCheck1() throws IOException { + ObjectId ppid = db.resolve("refs/heads/master^"); + ObjectId pid = db.resolve("refs/heads/master"); + + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(ppid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); + assertEquals(ppid, db.resolve("refs/heads/master")); + + // real test + RefUpdate updateRef2 = db.updateRef("refs/heads/master"); + updateRef2.setExpectedOldObjectId(ppid); + updateRef2.setNewObjectId(pid); + Result update2 = updateRef2.update(); + assertEquals(Result.FAST_FORWARD, update2); + assertEquals(pid, db.resolve("refs/heads/master")); + } + + /** + * Try modify a ref forward, fast forward, checking old commit first + * + * @throws IOException + */ + public void testUpdateRefForwardWithCheck2() throws IOException { + ObjectId ppid = db.resolve("refs/heads/master^"); + ObjectId pid = db.resolve("refs/heads/master"); + + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(ppid); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals(Result.FORCED, update); + assertEquals(ppid, db.resolve("refs/heads/master")); + + // real test + RevCommit old = new RevWalk(db).parseCommit(ppid); + RefUpdate updateRef2 = db.updateRef("refs/heads/master"); + updateRef2.setExpectedOldObjectId(old); + updateRef2.setNewObjectId(pid); + Result update2 = updateRef2.update(); + assertEquals(Result.FAST_FORWARD, update2); + assertEquals(pid, db.resolve("refs/heads/master")); + } + + /** + * Try modify a ref that is locked + * + * @throws IOException + */ + public void testUpdateRefLockFailureLocked() throws IOException { + ObjectId opid = db.resolve("refs/heads/master"); + ObjectId pid = db.resolve("refs/heads/master^"); + RefUpdate updateRef = db.updateRef("refs/heads/master"); + updateRef.setNewObjectId(pid); + LockFile lockFile1 = new LockFile(new File(db.getDirectory(),"refs/heads/master")); + try { + assertTrue(lockFile1.lock()); // precondition to test + Result update = updateRef.update(); + assertEquals(Result.LOCK_FAILURE, update); + assertEquals(opid, db.resolve("refs/heads/master")); + LockFile lockFile2 = new LockFile(new File(db.getDirectory(),"refs/heads/master")); + assertFalse(lockFile2.lock()); // was locked, still is + } finally { + lockFile1.unlock(); + } + } + + /** + * Try to delete a ref. Delete requires force. + * + * @throws IOException + */ + public void testDeleteLoosePackedRejected() throws IOException { + ObjectId pid = db.resolve("refs/heads/c^"); + ObjectId oldpid = db.resolve("refs/heads/c"); + RefUpdate updateRef = db.updateRef("refs/heads/c"); + updateRef.setNewObjectId(pid); + Result update = updateRef.update(); + assertEquals(Result.REJECTED, update); + assertEquals(oldpid, db.resolve("refs/heads/c")); + } + + public void testRenameBranchNoPreviousLog() throws IOException { + assertFalse("precondition, no log on old branchg", new File(db + .getDirectory(), "logs/refs/heads/b").exists()); + ObjectId rb = db.resolve("refs/heads/b"); + ObjectId oldHead = db.resolve(Constants.HEAD); + assertFalse(rb.equals(oldHead)); // assumption for this test + RefRename renameRef = db.renameRef("refs/heads/b", + "refs/heads/new/name"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + assertEquals(rb, db.resolve("refs/heads/new/name")); + assertNull(db.resolve("refs/heads/b")); + assertEquals(1, db.getReflogReader("new/name").getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name") + .getLastEntry().getComment()); + assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); + assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged + } + + public void testRenameBranchHasPreviousLog() throws IOException { + ObjectId rb = db.resolve("refs/heads/b"); + ObjectId oldHead = db.resolve(Constants.HEAD); + assertFalse("precondition for this test, branch b != HEAD", rb + .equals(oldHead)); + RefLogWriter.writeReflog(db, rb, rb, "Just a message", "refs/heads/b"); + assertTrue("no log on old branch", new File(db.getDirectory(), + "logs/refs/heads/b").exists()); + RefRename renameRef = db.renameRef("refs/heads/b", + "refs/heads/new/name"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + assertEquals(rb, db.resolve("refs/heads/new/name")); + assertNull(db.resolve("refs/heads/b")); + assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name") + .getLastEntry().getComment()); + assertEquals("Just a message", db.getReflogReader("new/name") + .getReverseEntries().get(1).getComment()); + assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); + assertEquals(oldHead, db.resolve(Constants.HEAD)); // unchanged + } + + public void testRenameCurrentBranch() throws IOException { + ObjectId rb = db.resolve("refs/heads/b"); + db.writeSymref(Constants.HEAD, "refs/heads/b"); + ObjectId oldHead = db.resolve(Constants.HEAD); + assertTrue("internal test condition, b == HEAD", rb.equals(oldHead)); + RefLogWriter.writeReflog(db, rb, rb, "Just a message", "refs/heads/b"); + assertTrue("no log on old branch", new File(db.getDirectory(), + "logs/refs/heads/b").exists()); + RefRename renameRef = db.renameRef("refs/heads/b", + "refs/heads/new/name"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + assertEquals(rb, db.resolve("refs/heads/new/name")); + assertNull(db.resolve("refs/heads/b")); + assertEquals("Branch: renamed b to new/name", db.getReflogReader( + "new/name").getLastEntry().getComment()); + assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); + assertEquals(rb, db.resolve(Constants.HEAD)); + assertEquals(2, db.getReflogReader("new/name").getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", db.getReflogReader("new/name").getReverseEntries().get(0).getComment()); + assertEquals("Just a message", db.getReflogReader("new/name").getReverseEntries().get(1).getComment()); + } + + public void testRenameBranchAlsoInPack() throws IOException { + ObjectId rb = db.resolve("refs/heads/b"); + ObjectId rb2 = db.resolve("refs/heads/b~1"); + assertEquals(Ref.Storage.PACKED, db.getRef("refs/heads/b").getStorage()); + RefUpdate updateRef = db.updateRef("refs/heads/b"); + updateRef.setNewObjectId(rb2); + updateRef.setForceUpdate(true); + Result update = updateRef.update(); + assertEquals("internal check new ref is loose", Result.FORCED, update); + assertEquals(Ref.Storage.LOOSE_PACKED, db.getRef("refs/heads/b") + .getStorage()); + RefLogWriter.writeReflog(db, rb, rb, "Just a message", "refs/heads/b"); + assertTrue("no log on old branch", new File(db.getDirectory(), + "logs/refs/heads/b").exists()); + RefRename renameRef = db.renameRef("refs/heads/b", + "refs/heads/new/name"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + assertEquals(rb2, db.resolve("refs/heads/new/name")); + assertNull(db.resolve("refs/heads/b")); + assertEquals("Branch: renamed b to new/name", db.getReflogReader( + "new/name").getLastEntry().getComment()); + assertEquals(3, db.getReflogReader("refs/heads/new/name").getReverseEntries().size()); + assertEquals("Branch: renamed b to new/name", db.getReflogReader("refs/heads/new/name").getReverseEntries().get(0).getComment()); + assertEquals(0, db.getReflogReader("HEAD").getReverseEntries().size()); + // make sure b's log file is gone too. + assertFalse(new File(db.getDirectory(), "logs/refs/heads/b").exists()); + + // Create new Repository instance, to reread caches and make sure our + // assumptions are persistent. + Repository ndb = new Repository(db.getDirectory()); + assertEquals(rb2, ndb.resolve("refs/heads/new/name")); + assertNull(ndb.resolve("refs/heads/b")); + } + + public void tryRenameWhenLocked(String toLock, String fromName, + String toName, String headPointsTo) throws IOException { + // setup + db.writeSymref(Constants.HEAD, headPointsTo); + ObjectId oldfromId = db.resolve(fromName); + ObjectId oldHeadId = db.resolve(Constants.HEAD); + RefLogWriter.writeReflog(db, oldfromId, oldfromId, "Just a message", + fromName); + List<org.eclipse.jgit.lib.ReflogReader.Entry> oldFromLog = db + .getReflogReader(fromName).getReverseEntries(); + List<org.eclipse.jgit.lib.ReflogReader.Entry> oldHeadLog = oldHeadId != null ? db + .getReflogReader(Constants.HEAD).getReverseEntries() : null; + + assertTrue("internal check, we have a log", new File(db.getDirectory(), + "logs/" + fromName).exists()); + + // "someone" has branch X locked + LockFile lockFile = new LockFile(new File(db.getDirectory(), toLock)); + try { + assertTrue(lockFile.lock()); + + // Now this is our test + RefRename renameRef = db.renameRef(fromName, toName); + Result result = renameRef.rename(); + assertEquals(Result.LOCK_FAILURE, result); + + // Check that the involved refs are the same despite the failure + assertExists(false, toName); + if (!toLock.equals(toName)) + assertExists(false, toName + ".lock"); + assertExists(true, toLock + ".lock"); + if (!toLock.equals(fromName)) + assertExists(false, "logs/" + fromName + ".lock"); + assertExists(false, "logs/" + toName + ".lock"); + assertEquals(oldHeadId, db.resolve(Constants.HEAD)); + assertEquals(oldfromId, db.resolve(fromName)); + assertNull(db.resolve(toName)); + assertEquals(oldFromLog.toString(), db.getReflogReader(fromName) + .getReverseEntries().toString()); + if (oldHeadId != null) + assertEquals(oldHeadLog, db.getReflogReader(Constants.HEAD) + .getReverseEntries()); + } finally { + lockFile.unlock(); + } + } + + private void assertExists(boolean positive, String toName) { + assertEquals(toName + (positive ? " " : " does not ") + "exist", + positive, new File(db.getDirectory(), toName).exists()); + } + + public void testRenameBranchCannotLockAFileHEADisFromLockHEAD() + throws IOException { + tryRenameWhenLocked("HEAD", "refs/heads/b", "refs/heads/new/name", + "refs/heads/b"); + } + + public void testRenameBranchCannotLockAFileHEADisFromLockFrom() + throws IOException { + tryRenameWhenLocked("refs/heads/b", "refs/heads/b", + "refs/heads/new/name", "refs/heads/b"); + } + + public void testRenameBranchCannotLockAFileHEADisFromLockTo() + throws IOException { + tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b", + "refs/heads/new/name", "refs/heads/b"); + } + + public void testRenameBranchCannotLockAFileHEADisToLockFrom() + throws IOException { + tryRenameWhenLocked("refs/heads/b", "refs/heads/b", + "refs/heads/new/name", "refs/heads/new/name"); + } + + public void testRenameBranchCannotLockAFileHEADisToLockTo() + throws IOException { + tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b", + "refs/heads/new/name", "refs/heads/new/name"); + } + + public void testRenameBranchCannotLockAFileHEADisToLockTmp() + throws IOException { + tryRenameWhenLocked("RENAMED-REF.." + Thread.currentThread().getId(), + "refs/heads/b", "refs/heads/new/name", "refs/heads/new/name"); + } + + public void testRenameBranchCannotLockAFileHEADisOtherLockFrom() + throws IOException { + tryRenameWhenLocked("refs/heads/b", "refs/heads/b", + "refs/heads/new/name", "refs/heads/a"); + } + + public void testRenameBranchCannotLockAFileHEADisOtherLockTo() + throws IOException { + tryRenameWhenLocked("refs/heads/new/name", "refs/heads/b", + "refs/heads/new/name", "refs/heads/a"); + } + + public void testRenameBranchCannotLockAFileHEADisOtherLockTmp() + throws IOException { + tryRenameWhenLocked("RENAMED-REF.." + Thread.currentThread().getId(), + "refs/heads/b", "refs/heads/new/name", "refs/heads/a"); + } + + public void testRenameRefNameColission1avoided() throws IOException { + // setup + ObjectId rb = db.resolve("refs/heads/b"); + db.writeSymref(Constants.HEAD, "refs/heads/a"); + RefUpdate updateRef = db.updateRef("refs/heads/a"); + updateRef.setNewObjectId(rb); + updateRef.setRefLogMessage("Setup", false); + assertEquals(Result.FAST_FORWARD, updateRef.update()); + ObjectId oldHead = db.resolve(Constants.HEAD); + assertTrue(rb.equals(oldHead)); // assumption for this test + RefLogWriter.writeReflog(db, rb, rb, "Just a message", "refs/heads/a"); + assertTrue("internal check, we have a log", new File(db.getDirectory(), + "logs/refs/heads/a").exists()); + + // Now this is our test + RefRename renameRef = db.renameRef("refs/heads/a", "refs/heads/a/b"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + assertNull(db.resolve("refs/heads/a")); + assertEquals(rb, db.resolve("refs/heads/a/b")); + assertEquals(3, db.getReflogReader("a/b").getReverseEntries().size()); + assertEquals("Branch: renamed a to a/b", db.getReflogReader("a/b") + .getReverseEntries().get(0).getComment()); + assertEquals("Just a message", db.getReflogReader("a/b") + .getReverseEntries().get(1).getComment()); + assertEquals("Setup", db.getReflogReader("a/b").getReverseEntries() + .get(2).getComment()); + // same thing was logged to HEAD + assertEquals("Branch: renamed a to a/b", db.getReflogReader("HEAD") + .getReverseEntries().get(0).getComment()); + } + + public void testRenameRefNameColission2avoided() throws IOException { + // setup + ObjectId rb = db.resolve("refs/heads/b"); + db.writeSymref(Constants.HEAD, "refs/heads/prefix/a"); + RefUpdate updateRef = db.updateRef("refs/heads/prefix/a"); + updateRef.setNewObjectId(rb); + updateRef.setRefLogMessage("Setup", false); + updateRef.setForceUpdate(true); + assertEquals(Result.FORCED, updateRef.update()); + ObjectId oldHead = db.resolve(Constants.HEAD); + assertTrue(rb.equals(oldHead)); // assumption for this test + RefLogWriter.writeReflog(db, rb, rb, "Just a message", + "refs/heads/prefix/a"); + assertTrue("internal check, we have a log", new File(db.getDirectory(), + "logs/refs/heads/prefix/a").exists()); + + // Now this is our test + RefRename renameRef = db.renameRef("refs/heads/prefix/a", + "refs/heads/prefix"); + Result result = renameRef.rename(); + assertEquals(Result.RENAMED, result); + + assertNull(db.resolve("refs/heads/prefix/a")); + assertEquals(rb, db.resolve("refs/heads/prefix")); + assertEquals(3, db.getReflogReader("prefix").getReverseEntries().size()); + assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader( + "prefix").getReverseEntries().get(0).getComment()); + assertEquals("Just a message", db.getReflogReader("prefix") + .getReverseEntries().get(1).getComment()); + assertEquals("Setup", db.getReflogReader("prefix").getReverseEntries() + .get(2).getComment()); + assertEquals("Branch: renamed prefix/a to prefix", db.getReflogReader( + "HEAD").getReverseEntries().get(0).getComment()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java new file mode 100644 index 0000000000..dae7cb8955 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ReflogReaderTest.java @@ -0,0 +1,176 @@ +/* + * Copyright (C) 2009, Robin Rosenberg + * Copyright (C) 2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.text.SimpleDateFormat; +import java.util.List; + +import org.eclipse.jgit.lib.ReflogReader.Entry; + +public class ReflogReaderTest extends RepositoryTestCase { + + static byte[] oneLine = "da85355dfc525c9f6f3927b876f379f46ccf826e 3e7549db262d1e836d9bf0af7e22355468f1717c A O Thor Too <authortoo@wri.tr> 1243028200 +0200\tcommit: Add a toString for debugging to RemoteRefUpdate\n" + .getBytes(); + + static byte[] twoLine = ("0000000000000000000000000000000000000000 c6734895958052a9dbc396cff4459dc1a25029ab A U Thor <thor@committer.au> 1243028201 -0100\tbranch: Created from rr/renamebranchv4\n" + + "c6734895958052a9dbc396cff4459dc1a25029ab 54794942a18a237c57a80719afed44bb78172b10 Same A U Thor <same.author@example.com> 1243028202 +0100\trebase finished: refs/heads/rr/renamebranch5 onto c6e3b9fe2da0293f11eae202ec35fb343191a82d\n") + .getBytes(); + + static byte[] twoLineWithAppendInProgress = ("0000000000000000000000000000000000000000 c6734895958052a9dbc396cff4459dc1a25029ab A U Thor <thor@committer.au> 1243028201 -0100\tbranch: Created from rr/renamebranchv4\n" + + "c6734895958052a9dbc396cff4459dc1a25029ab 54794942a18a237c57a80719afed44bb78172b10 Same A U Thor <same.author@example.com> 1243028202 +0100\trebase finished: refs/heads/rr/renamebranch5 onto c6e3b9fe2da0293f11eae202ec35fb343191a82d\n" + + "54794942a18a237c57a80719afed44bb78172b10 ") + .getBytes(); + + static byte[] aLine = "1111111111111111111111111111111111111111 3e7549db262d1e836d9bf0af7e22355468f1717c A U Thor <thor@committer.au> 1243028201 -0100\tbranch: change to a\n" + .getBytes(); + + static byte[] masterLine = "2222222222222222222222222222222222222222 3e7549db262d1e836d9bf0af7e22355468f1717c A U Thor <thor@committer.au> 1243028201 -0100\tbranch: change to master\n" + .getBytes(); + + static byte[] headLine = "3333333333333333333333333333333333333333 3e7549db262d1e836d9bf0af7e22355468f1717c A U Thor <thor@committer.au> 1243028201 -0100\tbranch: change to HEAD\n" + .getBytes(); + + public void testReadOneLine() throws Exception { + setupReflog("logs/refs/heads/master", oneLine); + + ReflogReader reader = new ReflogReader(db, "refs/heads/master"); + Entry e = reader.getLastEntry(); + assertEquals(ObjectId + .fromString("da85355dfc525c9f6f3927b876f379f46ccf826e"), e + .getOldId()); + assertEquals(ObjectId + .fromString("3e7549db262d1e836d9bf0af7e22355468f1717c"), e + .getNewId()); + assertEquals("A O Thor Too", e.getWho().getName()); + assertEquals("authortoo@wri.tr", e.getWho().getEmailAddress()); + assertEquals(120, e.getWho().getTimeZoneOffset()); + assertEquals("2009-05-22T23:36:40", iso(e.getWho())); + assertEquals("commit: Add a toString for debugging to RemoteRefUpdate", + e.getComment()); + } + + private String iso(PersonIdent id) { + final SimpleDateFormat fmt; + fmt = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); + fmt.setTimeZone(id.getTimeZone()); + return fmt.format(id.getWhen()); + } + + public void testReadTwoLine() throws Exception { + setupReflog("logs/refs/heads/master", twoLine); + + ReflogReader reader = new ReflogReader(db, "refs/heads/master"); + List<Entry> reverseEntries = reader.getReverseEntries(); + assertEquals(2, reverseEntries.size()); + Entry e = reverseEntries.get(0); + assertEquals(ObjectId + .fromString("c6734895958052a9dbc396cff4459dc1a25029ab"), e + .getOldId()); + assertEquals(ObjectId + .fromString("54794942a18a237c57a80719afed44bb78172b10"), e + .getNewId()); + assertEquals("Same A U Thor", e.getWho().getName()); + assertEquals("same.author@example.com", e.getWho().getEmailAddress()); + assertEquals(60, e.getWho().getTimeZoneOffset()); + assertEquals("2009-05-22T22:36:42", iso(e.getWho())); + assertEquals( + "rebase finished: refs/heads/rr/renamebranch5 onto c6e3b9fe2da0293f11eae202ec35fb343191a82d", + e.getComment()); + + e = reverseEntries.get(1); + assertEquals(ObjectId + .fromString("0000000000000000000000000000000000000000"), e + .getOldId()); + assertEquals(ObjectId + .fromString("c6734895958052a9dbc396cff4459dc1a25029ab"), e + .getNewId()); + assertEquals("A U Thor", e.getWho().getName()); + assertEquals("thor@committer.au", e.getWho().getEmailAddress()); + assertEquals(-60, e.getWho().getTimeZoneOffset()); + assertEquals("2009-05-22T20:36:41", iso(e.getWho())); + assertEquals("branch: Created from rr/renamebranchv4", e.getComment()); + } + + public void testReadWhileAppendIsInProgress() throws Exception { + setupReflog("logs/refs/heads/master", twoLineWithAppendInProgress); + ReflogReader reader = new ReflogReader(db, "refs/heads/master"); + List<Entry> reverseEntries = reader.getReverseEntries(); + assertEquals(2, reverseEntries.size()); + Entry e = reverseEntries.get(0); + assertEquals(ObjectId + .fromString("c6734895958052a9dbc396cff4459dc1a25029ab"), e + .getOldId()); + assertEquals(ObjectId + .fromString("54794942a18a237c57a80719afed44bb78172b10"), e + .getNewId()); + assertEquals("Same A U Thor", e.getWho().getName()); + assertEquals("same.author@example.com", e.getWho().getEmailAddress()); + assertEquals(60, e.getWho().getTimeZoneOffset()); + assertEquals("2009-05-22T22:36:42", iso(e.getWho())); + assertEquals( + "rebase finished: refs/heads/rr/renamebranch5 onto c6e3b9fe2da0293f11eae202ec35fb343191a82d", + e.getComment()); + // while similar to testReadTwoLine, we can assume that if we get the last entry + // right, everything else is too + } + + + public void testReadRightLog() throws Exception { + setupReflog("logs/refs/heads/a", aLine); + setupReflog("logs/refs/heads/master", masterLine); + setupReflog("logs/HEAD", headLine); + assertEquals("branch: change to master", db.getReflogReader("master") + .getLastEntry().getComment()); + assertEquals("branch: change to a", db.getReflogReader("a") + .getLastEntry().getComment()); + assertEquals("branch: change to HEAD", db.getReflogReader("HEAD") + .getLastEntry().getComment()); + } + + public void testNoLog() throws Exception { + assertEquals(0, db.getReflogReader("master").getReverseEntries().size()); + assertNull(db.getReflogReader("master").getLastEntry()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java new file mode 100644 index 0000000000..c0591755f4 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryCacheTest.java @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.jgit.errors.RepositoryNotFoundException; +import org.eclipse.jgit.lib.RepositoryCache.FileKey; + +public class RepositoryCacheTest extends RepositoryTestCase { + public void testNonBareFileKey() { + File gitdir = db.getDirectory(); + File parent = gitdir.getParentFile(); + File other = new File(parent, "notagit"); + assertEquals(gitdir, FileKey.exact(gitdir).getFile()); + assertEquals(parent, FileKey.exact(parent).getFile()); + assertEquals(other, FileKey.exact(other).getFile()); + + assertEquals(gitdir, FileKey.lenient(gitdir).getFile()); + assertEquals(gitdir, FileKey.lenient(parent).getFile()); + assertEquals(other, FileKey.lenient(other).getFile()); + } + + public void testBareFileKey() throws IOException { + Repository bare = createNewEmptyRepo(true); + File gitdir = bare.getDirectory(); + File parent = gitdir.getParentFile(); + String name = gitdir.getName(); + assertTrue(name.endsWith(".git")); + name = name.substring(0, name.length() - 4); + + assertEquals(gitdir, FileKey.exact(gitdir).getFile()); + + assertEquals(gitdir, FileKey.lenient(gitdir).getFile()); + assertEquals(gitdir, FileKey.lenient(new File(parent, name)).getFile()); + } + + public void testFileKeyOpenExisting() throws IOException { + Repository r; + + r = new FileKey(db.getDirectory()).open(true); + assertNotNull(r); + assertEquals(db.getDirectory(), r.getDirectory()); + r.close(); + + r = new FileKey(db.getDirectory()).open(false); + assertNotNull(r); + assertEquals(db.getDirectory(), r.getDirectory()); + r.close(); + } + + public void testFileKeyOpenNew() throws IOException { + final Repository n = createNewEmptyRepo(true); + final File gitdir = n.getDirectory(); + n.close(); + recursiveDelete(gitdir); + assertFalse(gitdir.exists()); + + try { + new FileKey(gitdir).open(true); + fail("incorrectly opened a non existant repository"); + } catch (RepositoryNotFoundException e) { + assertEquals("repository not found: " + gitdir, e.getMessage()); + } + + final Repository o = new FileKey(gitdir).open(false); + assertNotNull(o); + assertEquals(gitdir, o.getDirectory()); + assertFalse(gitdir.exists()); + } + + public void testCacheRegisterOpen() throws Exception { + final File dir = db.getDirectory(); + RepositoryCache.register(db); + assertSame(db, RepositoryCache.open(FileKey.exact(dir))); + + assertEquals(".git", dir.getName()); + final File parent = dir.getParentFile(); + assertSame(db, RepositoryCache.open(FileKey.lenient(parent))); + } + + public void testCacheOpen() throws Exception { + final FileKey loc = FileKey.exact(db.getDirectory()); + final Repository d2 = RepositoryCache.open(loc); + assertNotSame(db, d2); + assertSame(d2, RepositoryCache.open(FileKey.exact(loc.getFile()))); + d2.close(); + d2.close(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java new file mode 100644 index 0000000000..08e701ab50 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryConfigTest.java @@ -0,0 +1,259 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.util.Arrays; +import java.util.LinkedList; + +import junit.framework.TestCase; + +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.util.SystemReader; + +/** + * Test reading of git config + */ +public class RepositoryConfigTest extends TestCase { + public void test001_ReadBareKey() throws ConfigInvalidException { + final Config c = parse("[foo]\nbar\n"); + assertEquals(true, c.getBoolean("foo", null, "bar", false)); + assertEquals("", c.getString("foo", null, "bar")); + } + + public void test002_ReadWithSubsection() throws ConfigInvalidException { + final Config c = parse("[foo \"zip\"]\nbar\n[foo \"zap\"]\nbar=false\nn=3\n"); + assertEquals(true, c.getBoolean("foo", "zip", "bar", false)); + assertEquals("", c.getString("foo","zip", "bar")); + assertEquals(false, c.getBoolean("foo", "zap", "bar", true)); + assertEquals("false", c.getString("foo", "zap", "bar")); + assertEquals(3, c.getInt("foo", "zap", "n", 4)); + assertEquals(4, c.getInt("foo", "zap","m", 4)); + } + + public void test003_PutRemote() { + final Config c = new Config(); + c.setString("sec", "ext", "name", "value"); + c.setString("sec", "ext", "name2", "value2"); + final String expText = "[sec \"ext\"]\n\tname = value\n\tname2 = value2\n"; + assertEquals(expText, c.toText()); + } + + public void test004_PutGetSimple() { + Config c = new Config(); + c.setString("my", null, "somename", "false"); + assertEquals("false", c.getString("my", null, "somename")); + assertEquals("[my]\n\tsomename = false\n", c.toText()); + } + + public void test005_PutGetStringList() { + Config c = new Config(); + final LinkedList<String> values = new LinkedList<String>(); + values.add("value1"); + values.add("value2"); + c.setStringList("my", null, "somename", values); + + final Object[] expArr = values.toArray(); + final String[] actArr = c.getStringList("my", null, "somename"); + assertTrue(Arrays.equals(expArr, actArr)); + + final String expText = "[my]\n\tsomename = value1\n\tsomename = value2\n"; + assertEquals(expText, c.toText()); + } + + public void test006_readCaseInsensitive() throws ConfigInvalidException { + final Config c = parse("[Foo]\nBar\n"); + assertEquals(true, c.getBoolean("foo", null, "bar", false)); + assertEquals("", c.getString("foo", null, "bar")); + } + + public void test007_readUserConfig() { + final MockSystemReader mockSystemReader = new MockSystemReader(); + SystemReader.setInstance(mockSystemReader); + final String hostname = mockSystemReader.getHostname(); + final Config userGitConfig = mockSystemReader.userGitConfig; + final Config localConfig = new Config(userGitConfig); + mockSystemReader.values.clear(); + + String authorName; + String authorEmail; + + // no values defined nowhere + authorName = localConfig.get(UserConfig.KEY).getAuthorName(); + authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail(); + assertEquals(Constants.UNKNOWN_USER_DEFAULT, authorName); + assertEquals(Constants.UNKNOWN_USER_DEFAULT + "@" + hostname, authorEmail); + + // the system user name is defined + mockSystemReader.values.put(Constants.OS_USER_NAME_KEY, "os user name"); + localConfig.uncache(UserConfig.KEY); + authorName = localConfig.get(UserConfig.KEY).getAuthorName(); + assertEquals("os user name", authorName); + + if (hostname != null && hostname.length() != 0) { + authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail(); + assertEquals("os user name@" + hostname, authorEmail); + } + + // the git environment variables are defined + mockSystemReader.values.put(Constants.GIT_AUTHOR_NAME_KEY, "git author name"); + mockSystemReader.values.put(Constants.GIT_AUTHOR_EMAIL_KEY, "author@email"); + localConfig.uncache(UserConfig.KEY); + authorName = localConfig.get(UserConfig.KEY).getAuthorName(); + authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail(); + assertEquals("git author name", authorName); + assertEquals("author@email", authorEmail); + + // the values are defined in the global configuration + userGitConfig.setString("user", null, "name", "global username"); + userGitConfig.setString("user", null, "email", "author@globalemail"); + authorName = localConfig.get(UserConfig.KEY).getAuthorName(); + authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail(); + assertEquals("global username", authorName); + assertEquals("author@globalemail", authorEmail); + + // the values are defined in the local configuration + localConfig.setString("user", null, "name", "local username"); + localConfig.setString("user", null, "email", "author@localemail"); + authorName = localConfig.get(UserConfig.KEY).getAuthorName(); + authorEmail = localConfig.get(UserConfig.KEY).getAuthorEmail(); + assertEquals("local username", authorName); + assertEquals("author@localemail", authorEmail); + + authorName = localConfig.get(UserConfig.KEY).getCommitterName(); + authorEmail = localConfig.get(UserConfig.KEY).getCommitterEmail(); + assertEquals("local username", authorName); + assertEquals("author@localemail", authorEmail); + } + + public void testReadBoolean_TrueFalse1() throws ConfigInvalidException { + final Config c = parse("[s]\na = true\nb = false\n"); + assertEquals("true", c.getString("s", null, "a")); + assertEquals("false", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadBoolean_TrueFalse2() throws ConfigInvalidException { + final Config c = parse("[s]\na = TrUe\nb = fAlSe\n"); + assertEquals("TrUe", c.getString("s", null, "a")); + assertEquals("fAlSe", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadBoolean_YesNo1() throws ConfigInvalidException { + final Config c = parse("[s]\na = yes\nb = no\n"); + assertEquals("yes", c.getString("s", null, "a")); + assertEquals("no", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadBoolean_YesNo2() throws ConfigInvalidException { + final Config c = parse("[s]\na = yEs\nb = NO\n"); + assertEquals("yEs", c.getString("s", null, "a")); + assertEquals("NO", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadBoolean_OnOff1() throws ConfigInvalidException { + final Config c = parse("[s]\na = on\nb = off\n"); + assertEquals("on", c.getString("s", null, "a")); + assertEquals("off", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadBoolean_OnOff2() throws ConfigInvalidException { + final Config c = parse("[s]\na = ON\nb = OFF\n"); + assertEquals("ON", c.getString("s", null, "a")); + assertEquals("OFF", c.getString("s", null, "b")); + + assertTrue(c.getBoolean("s", "a", false)); + assertFalse(c.getBoolean("s", "b", true)); + } + + public void testReadLong() throws ConfigInvalidException { + assertReadLong(1L); + assertReadLong(-1L); + assertReadLong(Long.MIN_VALUE); + assertReadLong(Long.MAX_VALUE); + assertReadLong(4L * 1024 * 1024 * 1024, "4g"); + assertReadLong(3L * 1024 * 1024, "3 m"); + assertReadLong(8L * 1024, "8 k"); + + try { + assertReadLong(-1, "1.5g"); + fail("incorrectly accepted 1.5g"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid integer value: s.a=1.5g", e.getMessage()); + } + } + + private void assertReadLong(long exp) throws ConfigInvalidException { + assertReadLong(exp, String.valueOf(exp)); + } + + private void assertReadLong(long exp, String act) + throws ConfigInvalidException { + final Config c = parse("[s]\na = " + act + "\n"); + assertEquals(exp, c.getLong("s", null, "a", 0L)); + } + + private Config parse(final String content) throws ConfigInvalidException { + final Config c = new Config(null); + c.fromText(content); + return c; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java new file mode 100644 index 0000000000..2870e4126a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/RepositoryTestCase.java @@ -0,0 +1,347 @@ +/* + * Copyright (C) 2007-2009, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2007, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.Reader; +import java.util.ArrayList; +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.jgit.util.JGitTestUtil; +import org.eclipse.jgit.util.SystemReader; + +/** + * Base class for most JGit unit tests. + * + * Sets up a predefined test repository and has support for creating additional + * repositories and destroying them when the tests are finished. + * + * A system property <em>jgit.junit.usemmap</em> defines whether memory mapping + * is used. Memory mapping has an effect on the file system, in that memory + * mapped files in java cannot be deleted as long as they mapped arrays have not + * been reclaimed by the garbage collector. The programmer cannot control this + * with precision, though hinting using <em>{@link java.lang.System#gc}</em> + * often helps. + */ +public abstract class RepositoryTestCase extends TestCase { + + protected final File trashParent = new File("trash"); + + protected File trash; + + protected File trash_git; + + protected static final PersonIdent jauthor; + + protected static final PersonIdent jcommitter; + + static { + jauthor = new PersonIdent("J. Author", "jauthor@example.com"); + jcommitter = new PersonIdent("J. Committer", "jcommitter@example.com"); + } + + protected boolean packedGitMMAP; + + /** + * Configure JGit before setting up test repositories. + */ + protected void configure() { + final WindowCacheConfig c = new WindowCacheConfig(); + c.setPackedGitLimit(128 * WindowCacheConfig.KB); + c.setPackedGitWindowSize(8 * WindowCacheConfig.KB); + c.setPackedGitMMAP("true".equals(System.getProperty("jgit.junit.usemmap"))); + c.setDeltaBaseCacheLimit(8 * WindowCacheConfig.KB); + WindowCache.reconfigure(c); + } + + /** + * Utility method to delete a directory recursively. It is + * also used internally. If a file or directory cannot be removed + * it throws an AssertionFailure. + * + * @param dir + */ + protected void recursiveDelete(final File dir) { + recursiveDelete(dir, false, getClass().getName() + "." + getName(), true); + } + + protected static boolean recursiveDelete(final File dir, boolean silent, + final String name, boolean failOnError) { + assert !(silent && failOnError); + if (!dir.exists()) + return silent; + final File[] ls = dir.listFiles(); + if (ls != null) { + for (int k = 0; k < ls.length; k++) { + final File e = ls[k]; + if (e.isDirectory()) { + silent = recursiveDelete(e, silent, name, failOnError); + } else { + if (!e.delete()) { + if (!silent) { + reportDeleteFailure(name, failOnError, e); + } + silent = !failOnError; + } + } + } + } + if (!dir.delete()) { + if (!silent) { + reportDeleteFailure(name, failOnError, dir); + } + silent = !failOnError; + } + return silent; + } + + private static void reportDeleteFailure(final String name, + boolean failOnError, final File e) { + String severity; + if (failOnError) + severity = "Error"; + else + severity = "Warning"; + String msg = severity + ": Failed to delete " + e; + if (name != null) + msg += " in " + name; + if (failOnError) + fail(msg); + else + System.out.println(msg); + } + + protected static void copyFile(final File src, final File dst) + throws IOException { + final FileInputStream fis = new FileInputStream(src); + try { + final FileOutputStream fos = new FileOutputStream(dst); + try { + final byte[] buf = new byte[4096]; + int r; + while ((r = fis.read(buf)) > 0) { + fos.write(buf, 0, r); + } + } finally { + fos.close(); + } + } finally { + fis.close(); + } + } + + protected File writeTrashFile(final String name, final String data) + throws IOException { + File tf = new File(trash, name); + File tfp = tf.getParentFile(); + if (!tfp.exists() && !tf.getParentFile().mkdirs()) + throw new Error("Could not create directory " + tf.getParentFile()); + final OutputStreamWriter fw = new OutputStreamWriter( + new FileOutputStream(tf), "UTF-8"); + try { + fw.write(data); + } finally { + fw.close(); + } + return tf; + } + + protected static void checkFile(File f, final String checkData) + throws IOException { + Reader r = new InputStreamReader(new FileInputStream(f), "ISO-8859-1"); + try { + char[] data = new char[(int) f.length()]; + if (f.length() != r.read(data)) + throw new IOException("Internal error reading file data from "+f); + assertEquals(checkData, new String(data)); + } finally { + r.close(); + } + } + + protected Repository db; + + private static Thread shutdownhook; + private static List<Runnable> shutDownCleanups = new ArrayList<Runnable>(); + private static int testcount; + + private ArrayList<Repository> repositoriesToClose = new ArrayList<Repository>(); + + public void setUp() throws Exception { + super.setUp(); + configure(); + final String name = getClass().getName() + "." + getName(); + recursiveDelete(trashParent, true, name, false); // Cleanup old failed stuff + trash = new File(trashParent,"trash"+System.currentTimeMillis()+"."+(testcount++)); + trash_git = new File(trash, ".git").getCanonicalFile(); + if (shutdownhook == null) { + shutdownhook = new Thread() { + @Override + public void run() { + // This may look superfluous, but is an extra attempt + // to clean up. First GC to release as many resources + // as possible and then try to clean up one test repo + // at a time (to record problems) and finally to drop + // the directory containing all test repositories. + System.gc(); + for (Runnable r : shutDownCleanups) + r.run(); + recursiveDelete(trashParent, false, null, false); + } + }; + Runtime.getRuntime().addShutdownHook(shutdownhook); + } + + final MockSystemReader mockSystemReader = new MockSystemReader(); + mockSystemReader.userGitConfig = new FileBasedConfig(new File( + trash_git, "usergitconfig")); + SystemReader.setInstance(mockSystemReader); + + db = new Repository(trash_git); + db.create(); + + final String[] packs = { + "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f", + "pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371", + "pack-9fb5b411fe6dfa89cc2e6b89d2bd8e5de02b5745", + "pack-546ff360fe3488adb20860ce3436a2d6373d2796", + "pack-cbdeda40019ae0e6e789088ea0f51f164f489d14", + "pack-e6d07037cbcf13376308a0a995d1fa48f8f76aaa", + "pack-3280af9c07ee18a87705ef50b0cc4cd20266cf12" + }; + final File packDir = new File(db.getObjectsDirectory(), "pack"); + for (int k = 0; k < packs.length; k++) { + copyFile(JGitTestUtil.getTestResourceFile(packs[k] + ".pack"), new File(packDir, + packs[k] + ".pack")); + copyFile(JGitTestUtil.getTestResourceFile(packs[k] + ".idx"), new File(packDir, + packs[k] + ".idx")); + } + + copyFile(JGitTestUtil.getTestResourceFile("packed-refs"), new File(trash_git,"packed-refs")); + } + + protected void tearDown() throws Exception { + RepositoryCache.clear(); + db.close(); + for (Repository r : repositoriesToClose) + r.close(); + + // Since memory mapping is controlled by the GC we need to + // tell it this is a good time to clean up and unlock + // memory mapped files. + if (packedGitMMAP) + System.gc(); + + final String name = getClass().getName() + "." + getName(); + recursiveDelete(trash, false, name, true); + for (Repository r : repositoriesToClose) + recursiveDelete(r.getWorkDir(), false, name, true); + repositoriesToClose.clear(); + + super.tearDown(); + } + + /** + * Helper for creating extra empty repos + * + * @return a new empty git repository for testing purposes + * + * @throws IOException + */ + protected Repository createNewEmptyRepo() throws IOException { + return createNewEmptyRepo(false); + } + + /** + * Helper for creating extra empty repos + * + * @param bare if true, create a bare repository. + * @return a new empty git repository for testing purposes + * + * @throws IOException + */ + protected Repository createNewEmptyRepo(boolean bare) throws IOException { + final File newTestRepo = new File(trashParent, "new" + + System.currentTimeMillis() + "." + (testcount++) + + (bare ? "" : "/") + ".git").getCanonicalFile(); + assertFalse(newTestRepo.exists()); + final Repository newRepo = new Repository(newTestRepo); + newRepo.create(); + final String name = getClass().getName() + "." + getName(); + shutDownCleanups.add(new Runnable() { + public void run() { + recursiveDelete(newTestRepo, false, name, false); + } + }); + repositoriesToClose.add(newRepo); + return newRepo; + } + + protected void setupReflog(String logName, byte[] data) + throws FileNotFoundException, IOException { + File logfile = new File(db.getDirectory(), logName); + if (!logfile.getParentFile().mkdirs() + && !logfile.getParentFile().isDirectory()) { + throw new IOException( + "oops, cannot create the directory for the test reflog file" + + logfile); + } + FileOutputStream fileOutputStream = new FileOutputStream(logfile); + try { + fileOutputStream.write(data); + } finally { + fileOutputStream.close(); + } + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_ObjectId.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_ObjectId.java new file mode 100644 index 0000000000..03176cb8fd --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_ObjectId.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk> + * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import junit.framework.TestCase; + +public class T0001_ObjectId extends TestCase { + public void test001_toString() { + final String x = "def4c620bc3713bb1bb26b808ec9312548e73946"; + final ObjectId oid = ObjectId.fromString(x); + assertEquals(x, oid.name()); + } + + public void test002_toString() { + final String x = "ff00eedd003713bb1bb26b808ec9312548e73946"; + final ObjectId oid = ObjectId.fromString(x); + assertEquals(x, oid.name()); + } + + public void test003_equals() { + final String x = "def4c620bc3713bb1bb26b808ec9312548e73946"; + final ObjectId a = ObjectId.fromString(x); + final ObjectId b = ObjectId.fromString(x); + assertEquals(a.hashCode(), b.hashCode()); + assertTrue("a and b are same", a.equals(b)); + } + + public void test004_isId() { + assertTrue("valid id", ObjectId + .isId("def4c620bc3713bb1bb26b808ec9312548e73946")); + } + + public void test005_notIsId() { + assertFalse("bob is not an id", ObjectId.isId("bob")); + } + + public void test006_notIsId() { + assertFalse("39 digits is not an id", ObjectId + .isId("def4c620bc3713bb1bb26b808ec9312548e7394")); + } + + public void test007_isId() { + assertTrue("uppercase is accepted", ObjectId + .isId("Def4c620bc3713bb1bb26b808ec9312548e73946")); + } + + public void test008_notIsId() { + assertFalse("g is not a valid hex digit", ObjectId + .isId("gef4c620bc3713bb1bb26b808ec9312548e73946")); + } + + public void test009_toString() { + final String x = "ff00eedd003713bb1bb26b808ec9312548e73946"; + final ObjectId oid = ObjectId.fromString(x); + assertEquals(x, ObjectId.toString(oid)); + } + + public void test010_toString() { + final String x = "0000000000000000000000000000000000000000"; + assertEquals(x, ObjectId.toString(null)); + } + + public void test011_toString() { + final String x = "0123456789ABCDEFabcdef1234567890abcdefAB"; + final ObjectId oid = ObjectId.fromString(x); + assertEquals(x.toLowerCase(), oid.name()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdent.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdent.java new file mode 100644 index 0000000000..aaa88c0281 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0001_PersonIdent.java @@ -0,0 +1,111 @@ +/* + * Copyright (C) 2006-2007, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.util.Date; +import java.util.TimeZone; + +import junit.framework.TestCase; + +public class T0001_PersonIdent extends TestCase { + public void test001_NewIdent() { + final PersonIdent p = new PersonIdent("A U Thor", "author@example.com", + new Date(1142878501000L), TimeZone.getTimeZone("EST")); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + assertEquals("A U Thor <author@example.com> 1142878501 -0500", p + .toExternalString()); + } + + public void test002_ParseIdent() { + final String i = "A U Thor <author@example.com> 1142878501 -0500"; + final PersonIdent p = new PersonIdent(i); + assertEquals(i, p.toExternalString()); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } + + public void test003_ParseIdent() { + final String i = "A U Thor <author@example.com> 1142878501 +0230"; + final PersonIdent p = new PersonIdent(i); + assertEquals(i, p.toExternalString()); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } + + public void test004_ParseIdent() { + final String i = "A U Thor<author@example.com> 1142878501 +0230"; + final PersonIdent p = new PersonIdent(i); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } + + public void test005_ParseIdent() { + final String i = "A U Thor<author@example.com>1142878501 +0230"; + final PersonIdent p = new PersonIdent(i); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } + + public void test006_ParseIdent() { + final String i = "A U Thor <author@example.com>1142878501 +0230"; + final PersonIdent p = new PersonIdent(i); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } + + public void test007_ParseIdent() { + final String i = "A U Thor<author@example.com>1142878501 +0230 "; + final PersonIdent p = new PersonIdent(i); + assertEquals("A U Thor", p.getName()); + assertEquals("author@example.com", p.getEmailAddress()); + assertEquals(1142878501000L, p.getWhen().getTime()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0002_Tree.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0002_Tree.java new file mode 100644 index 0000000000..66c3c75f18 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0002_Tree.java @@ -0,0 +1,287 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.IOException; +import java.io.UnsupportedEncodingException; +import java.util.ArrayList; +import java.util.List; + +public class T0002_Tree extends RepositoryTestCase { + private static final ObjectId SOME_FAKE_ID = ObjectId.fromString( + "0123456789abcdef0123456789abcdef01234567"); + + private int compareNamesUsingSpecialCompare(String a,String b) throws UnsupportedEncodingException { + char lasta = '\0'; + byte[] abytes; + if (a.length() > 0 && a.charAt(a.length()-1) == '/') { + lasta = '/'; + a = a.substring(0, a.length() - 1); + } + abytes = a.getBytes("ISO-8859-1"); + char lastb = '\0'; + byte[] bbytes; + if (b.length() > 0 && b.charAt(b.length()-1) == '/') { + lastb = '/'; + b = b.substring(0, b.length() - 1); + } + bbytes = b.getBytes("ISO-8859-1"); + return Tree.compareNames(abytes, bbytes, lasta, lastb); + } + + public void test000_sort_01() throws UnsupportedEncodingException { + assertEquals(0, compareNamesUsingSpecialCompare("a","a")); + } + public void test000_sort_02() throws UnsupportedEncodingException { + assertEquals(-1, compareNamesUsingSpecialCompare("a","b")); + assertEquals(1, compareNamesUsingSpecialCompare("b","a")); + } + public void test000_sort_03() throws UnsupportedEncodingException { + assertEquals(1, compareNamesUsingSpecialCompare("a:","a")); + assertEquals(1, compareNamesUsingSpecialCompare("a/","a")); + assertEquals(-1, compareNamesUsingSpecialCompare("a","a/")); + assertEquals(-1, compareNamesUsingSpecialCompare("a","a:")); + assertEquals(1, compareNamesUsingSpecialCompare("a:","a/")); + assertEquals(-1, compareNamesUsingSpecialCompare("a/","a:")); + } + public void test000_sort_04() throws UnsupportedEncodingException { + assertEquals(-1, compareNamesUsingSpecialCompare("a.a","a/a")); + assertEquals(1, compareNamesUsingSpecialCompare("a/a","a.a")); + } + public void test000_sort_05() throws UnsupportedEncodingException { + assertEquals(-1, compareNamesUsingSpecialCompare("a.","a/")); + assertEquals(1, compareNamesUsingSpecialCompare("a/","a.")); + + } + + public void test001_createEmpty() throws IOException { + final Tree t = new Tree(db); + assertTrue("isLoaded", t.isLoaded()); + assertTrue("isModified", t.isModified()); + assertTrue("no parent", t.getParent() == null); + assertTrue("isRoot", t.isRoot()); + assertTrue("no name", t.getName() == null); + assertTrue("no nameUTF8", t.getNameUTF8() == null); + assertTrue("has entries array", t.members() != null); + assertTrue("entries is empty", t.members().length == 0); + assertEquals("full name is empty", "", t.getFullName()); + assertTrue("no id", t.getId() == null); + assertTrue("tree is self", t.getTree() == t); + assertTrue("database is r", t.getRepository() == db); + assertTrue("no foo child", t.findTreeMember("foo") == null); + assertTrue("no foo child", t.findBlobMember("foo") == null); + } + + public void test002_addFile() throws IOException { + final Tree t = new Tree(db); + t.setId(SOME_FAKE_ID); + assertTrue("has id", t.getId() != null); + assertFalse("not modified", t.isModified()); + + final String n = "bob"; + final FileTreeEntry f = t.addFile(n); + assertNotNull("have file", f); + assertEquals("name matches", n, f.getName()); + assertEquals("name matches", f.getName(), new String(f.getNameUTF8(), + "UTF-8")); + assertEquals("full name matches", n, f.getFullName()); + assertTrue("no id", f.getId() == null); + assertTrue("is modified", t.isModified()); + assertTrue("has no id", t.getId() == null); + assertTrue("found bob", t.findBlobMember(f.getName()) == f); + + final TreeEntry[] i = t.members(); + assertNotNull("members array not null", i); + assertTrue("iterator is not empty", i != null && i.length > 0); + assertTrue("iterator returns file", i != null && i[0] == f); + assertTrue("iterator is empty", i != null && i.length == 1); + } + + public void test004_addTree() throws IOException { + final Tree t = new Tree(db); + t.setId(SOME_FAKE_ID); + assertTrue("has id", t.getId() != null); + assertFalse("not modified", t.isModified()); + + final String n = "bob"; + final Tree f = t.addTree(n); + assertNotNull("have tree", f); + assertEquals("name matches", n, f.getName()); + assertEquals("name matches", f.getName(), new String(f.getNameUTF8(), + "UTF-8")); + assertEquals("full name matches", n, f.getFullName()); + assertTrue("no id", f.getId() == null); + assertTrue("parent matches", f.getParent() == t); + assertTrue("repository matches", f.getRepository() == db); + assertTrue("isLoaded", f.isLoaded()); + assertFalse("has items", f.members().length > 0); + assertFalse("is root", f.isRoot()); + assertTrue("tree is self", f.getTree() == f); + assertTrue("parent is modified", t.isModified()); + assertTrue("parent has no id", t.getId() == null); + assertTrue("found bob child", t.findTreeMember(f.getName()) == f); + + final TreeEntry[] i = t.members(); + assertTrue("iterator is not empty", i.length > 0); + assertTrue("iterator returns file", i[0] == f); + assertTrue("iterator is empty", i.length == 1); + } + + public void test005_addRecursiveFile() throws IOException { + final Tree t = new Tree(db); + final FileTreeEntry f = t.addFile("a/b/c"); + assertNotNull("created f", f); + assertEquals("c", f.getName()); + assertEquals("b", f.getParent().getName()); + assertEquals("a", f.getParent().getParent().getName()); + assertTrue("t is great-grandparent", t == f.getParent().getParent() + .getParent()); + } + + public void test005_addRecursiveTree() throws IOException { + final Tree t = new Tree(db); + final Tree f = t.addTree("a/b/c"); + assertNotNull("created f", f); + assertEquals("c", f.getName()); + assertEquals("b", f.getParent().getName()); + assertEquals("a", f.getParent().getParent().getName()); + assertTrue("t is great-grandparent", t == f.getParent().getParent() + .getParent()); + } + + public void test006_addDeepTree() throws IOException { + final Tree t = new Tree(db); + + final Tree e = t.addTree("e"); + assertNotNull("have e", e); + assertTrue("e.parent == t", e.getParent() == t); + final Tree f = t.addTree("f"); + assertNotNull("have f", f); + assertTrue("f.parent == t", f.getParent() == t); + final Tree g = f.addTree("g"); + assertNotNull("have g", g); + assertTrue("g.parent == f", g.getParent() == f); + final Tree h = g.addTree("h"); + assertNotNull("have h", h); + assertTrue("h.parent = g", h.getParent() == g); + + h.setId(SOME_FAKE_ID); + assertTrue("h not modified", !h.isModified()); + g.setId(SOME_FAKE_ID); + assertTrue("g not modified", !g.isModified()); + f.setId(SOME_FAKE_ID); + assertTrue("f not modified", !f.isModified()); + e.setId(SOME_FAKE_ID); + assertTrue("e not modified", !e.isModified()); + t.setId(SOME_FAKE_ID); + assertTrue("t not modified.", !t.isModified()); + + assertEquals("full path of h ok", "f/g/h", h.getFullName()); + assertTrue("Can find h", t.findTreeMember(h.getFullName()) == h); + assertTrue("Can't find f/z", t.findBlobMember("f/z") == null); + assertTrue("Can't find y/z", t.findBlobMember("y/z") == null); + + final FileTreeEntry i = h.addFile("i"); + assertNotNull(i); + assertEquals("full path of i ok", "f/g/h/i", i.getFullName()); + assertTrue("Can find i", t.findBlobMember(i.getFullName()) == i); + assertTrue("h modified", h.isModified()); + assertTrue("g modified", g.isModified()); + assertTrue("f modified", f.isModified()); + assertTrue("e not modified", !e.isModified()); + assertTrue("t modified", t.isModified()); + + assertTrue("h no id", h.getId() == null); + assertTrue("g no id", g.getId() == null); + assertTrue("f no id", f.getId() == null); + assertTrue("e has id", e.getId() != null); + assertTrue("t no id", t.getId() == null); + } + + public void test007_manyFileLookup() throws IOException { + final Tree t = new Tree(db); + final List<FileTreeEntry> files = new ArrayList<FileTreeEntry>(26 * 26); + for (char level1 = 'a'; level1 <= 'z'; level1++) { + for (char level2 = 'a'; level2 <= 'z'; level2++) { + final String n = "." + level1 + level2 + "9"; + final FileTreeEntry f = t.addFile(n); + assertNotNull("File " + n + " added.", f); + assertEquals(n, f.getName()); + files.add(f); + } + } + assertEquals(files.size(), t.memberCount()); + final TreeEntry[] ents = t.members(); + assertNotNull(ents); + assertEquals(files.size(), ents.length); + for (int k = 0; k < ents.length; k++) { + assertTrue("File " + files.get(k).getName() + + " is at " + k + ".", files.get(k) == ents[k]); + } + } + + public void test008_SubtreeInternalSorting() throws IOException { + final Tree t = new Tree(db); + final FileTreeEntry e0 = t.addFile("a-b"); + final FileTreeEntry e1 = t.addFile("a-"); + final FileTreeEntry e2 = t.addFile("a=b"); + final Tree e3 = t.addTree("a"); + final FileTreeEntry e4 = t.addFile("a="); + + final TreeEntry[] ents = t.members(); + assertSame(e1, ents[0]); + assertSame(e0, ents[1]); + assertSame(e3, ents[2]); + assertSame(e4, ents[3]); + assertSame(e2, ents[4]); + } + + public void test009_SymlinkAndGitlink() throws IOException { + final Tree symlinkTree = db.mapTree("symlink"); + assertTrue("Symlink entry exists", symlinkTree.existsBlob("symlink.txt")); + final Tree gitlinkTree = db.mapTree("gitlink"); + assertTrue("Gitlink entry exists", gitlinkTree.existsBlob("submodule")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java new file mode 100644 index 0000000000..d17cea6aec --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0003_Basic.java @@ -0,0 +1,581 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileReader; +import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; + +import org.eclipse.jgit.errors.ConfigInvalidException; + +public class T0003_Basic extends RepositoryTestCase { + public void test001_Initalize() { + final File gitdir = new File(trash, ".git"); + final File objects = new File(gitdir, "objects"); + final File objects_pack = new File(objects, "pack"); + final File objects_info = new File(objects, "info"); + final File refs = new File(gitdir, "refs"); + final File refs_heads = new File(refs, "heads"); + final File refs_tags = new File(refs, "tags"); + final File HEAD = new File(gitdir, "HEAD"); + + assertTrue("Exists " + trash, trash.isDirectory()); + assertTrue("Exists " + objects, objects.isDirectory()); + assertTrue("Exists " + objects_pack, objects_pack.isDirectory()); + assertTrue("Exists " + objects_info, objects_info.isDirectory()); + assertEquals(2, objects.listFiles().length); + assertTrue("Exists " + refs, refs.isDirectory()); + assertTrue("Exists " + refs_heads, refs_heads.isDirectory()); + assertTrue("Exists " + refs_tags, refs_tags.isDirectory()); + assertTrue("Exists " + HEAD, HEAD.isFile()); + assertEquals(23, HEAD.length()); + } + + public void test002_WriteEmptyTree() throws IOException { + // One of our test packs contains the empty tree object. If the pack is + // open when we create it we won't write the object file out as a loose + // object (as it already exists in the pack). + // + final Repository newdb = createNewEmptyRepo(); + final Tree t = new Tree(newdb); + t.accept(new WriteTree(trash, newdb), TreeEntry.MODIFIED_ONLY); + assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", t.getId() + .name()); + final File o = new File(new File(new File(newdb.getDirectory(), + "objects"), "4b"), "825dc642cb6eb9a060e54bf8d69288fbee4904"); + assertTrue("Exists " + o, o.isFile()); + assertTrue("Read-only " + o, !o.canWrite()); + } + + public void test002_WriteEmptyTree2() throws IOException { + // File shouldn't exist as it is in a test pack. + // + final Tree t = new Tree(db); + t.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY); + assertEquals("4b825dc642cb6eb9a060e54bf8d69288fbee4904", t.getId() + .name()); + final File o = new File(new File(new File(trash_git, "objects"), "4b"), + "825dc642cb6eb9a060e54bf8d69288fbee4904"); + assertFalse("Exists " + o, o.isFile()); + } + + public void test003_WriteShouldBeEmptyTree() throws IOException { + final Tree t = new Tree(db); + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + t.addFile("should-be-empty").setId(emptyId); + t.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY); + assertEquals("7bb943559a305bdd6bdee2cef6e5df2413c3d30a", t.getId() + .name()); + + File o; + o = new File(new File(new File(trash_git, "objects"), "7b"), + "b943559a305bdd6bdee2cef6e5df2413c3d30a"); + assertTrue("Exists " + o, o.isFile()); + assertTrue("Read-only " + o, !o.canWrite()); + + o = new File(new File(new File(trash_git, "objects"), "e6"), + "9de29bb2d1d6434b8b29ae775ad8c2e48c5391"); + assertTrue("Exists " + o, o.isFile()); + assertTrue("Read-only " + o, !o.canWrite()); + } + + public void test004_CheckNewConfig() { + final RepositoryConfig c = db.getConfig(); + assertNotNull(c); + assertEquals("0", c.getString("core", null, "repositoryformatversion")); + assertEquals("0", c.getString("CoRe", null, "REPOSITORYFoRmAtVeRsIoN")); + assertEquals("true", c.getString("core", null, "filemode")); + assertEquals("true", c.getString("cOrE", null, "fIlEModE")); + assertNull(c.getString("notavalue", null, "reallyNotAValue")); + } + + public void test005_ReadSimpleConfig() { + final RepositoryConfig c = db.getConfig(); + assertNotNull(c); + assertEquals("0", c.getString("core", null, "repositoryformatversion")); + assertEquals("0", c.getString("CoRe", null, "REPOSITORYFoRmAtVeRsIoN")); + assertEquals("true", c.getString("core", null, "filemode")); + assertEquals("true", c.getString("cOrE", null, "fIlEModE")); + assertNull(c.getString("notavalue", null, "reallyNotAValue")); + } + + public void test006_ReadUglyConfig() throws IOException, + ConfigInvalidException { + final RepositoryConfig c = db.getConfig(); + final File cfg = new File(db.getDirectory(), "config"); + final FileWriter pw = new FileWriter(cfg); + final String configStr = " [core];comment\n\tfilemode = yes\n" + + "[user]\n" + + " email = A U Thor <thor@example.com> # Just an example...\n" + + " name = \"A Thor \\\\ \\\"\\t \"\n" + + " defaultCheckInComment = a many line\\n\\\ncomment\\n\\\n" + + " to test\n"; + pw.write(configStr); + pw.close(); + c.load(); + assertEquals("yes", c.getString("core", null, "filemode")); + assertEquals("A U Thor <thor@example.com>", c + .getString("user", null, "email")); + assertEquals("A Thor \\ \"\t ", c.getString("user", null, "name")); + assertEquals("a many line\ncomment\n to test", c.getString("user", + null, "defaultCheckInComment")); + c.save(); + final FileReader fr = new FileReader(cfg); + final char[] cbuf = new char[configStr.length()]; + fr.read(cbuf); + fr.close(); + assertEquals(configStr, new String(cbuf)); + } + + public void test007_Open() throws IOException { + final Repository db2 = new Repository(db.getDirectory()); + assertEquals(db.getDirectory(), db2.getDirectory()); + assertEquals(db.getObjectsDirectory(), db2.getObjectsDirectory()); + assertNotSame(db.getConfig(), db2.getConfig()); + } + + public void test008_FailOnWrongVersion() throws IOException { + final File cfg = new File(db.getDirectory(), "config"); + final FileWriter pw = new FileWriter(cfg); + final String badvers = "ihopethisisneveraversion"; + final String configStr = "[core]\n" + "\trepositoryFormatVersion=" + + badvers + "\n"; + pw.write(configStr); + pw.close(); + + try { + new Repository(db.getDirectory()); + fail("incorrectly opened a bad repository"); + } catch (IOException ioe) { + assertTrue(ioe.getMessage().indexOf("format") > 0); + assertTrue(ioe.getMessage().indexOf(badvers) > 0); + } + } + + public void test009_CreateCommitOldFormat() throws IOException, + ConfigInvalidException { + writeTrashFile(".git/config", "[core]\n" + "legacyHeaders=1\n"); + db.getConfig().load(); + + final Tree t = new Tree(db); + final FileTreeEntry f = t.addFile("i-am-a-file"); + writeTrashFile(f.getName(), "and this is the data in me\n"); + t.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY); + assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"), + t.getTreeId()); + + final Commit c = new Commit(db); + c.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + c.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60)); + c.setMessage("A Commit\n"); + c.setTree(t); + assertEquals(t.getTreeId(), c.getTreeId()); + c.commit(); + final ObjectId cmtid = ObjectId.fromString( + "803aec4aba175e8ab1d666873c984c0308179099"); + assertEquals(cmtid, c.getCommitId()); + + // Verify the commit we just wrote is in the correct format. + final XInputStream xis = new XInputStream(new FileInputStream(db + .toFile(cmtid))); + try { + assertEquals(0x78, xis.readUInt8()); + assertEquals(0x9c, xis.readUInt8()); + assertTrue(0x789c % 31 == 0); + } finally { + xis.close(); + } + + // Verify we can read it. + final Commit c2 = db.mapCommit(cmtid); + assertNotNull(c2); + assertEquals(c.getMessage(), c2.getMessage()); + assertEquals(c.getTreeId(), c2.getTreeId()); + assertEquals(c.getAuthor(), c2.getAuthor()); + assertEquals(c.getCommitter(), c2.getCommitter()); + } + + public void test012_SubtreeExternalSorting() throws IOException { + final ObjectId emptyBlob = new ObjectWriter(db).writeBlob(new byte[0]); + final Tree t = new Tree(db); + final FileTreeEntry e0 = t.addFile("a-"); + final FileTreeEntry e1 = t.addFile("a-b"); + final FileTreeEntry e2 = t.addFile("a/b"); + final FileTreeEntry e3 = t.addFile("a="); + final FileTreeEntry e4 = t.addFile("a=b"); + + e0.setId(emptyBlob); + e1.setId(emptyBlob); + e2.setId(emptyBlob); + e3.setId(emptyBlob); + e4.setId(emptyBlob); + + t.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY); + assertEquals(ObjectId.fromString("b47a8f0a4190f7572e11212769090523e23eb1ea"), + t.getId()); + } + + public void test020_createBlobTag() throws IOException { + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + final Tag t = new Tag(db); + t.setObjId(emptyId); + t.setType("blob"); + t.setTag("test020"); + t.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + t.setMessage("test020 tagged\n"); + t.tag(); + assertEquals("6759556b09fbb4fd8ae5e315134481cc25d46954", t.getTagId().name()); + + Tag mapTag = db.mapTag("test020"); + assertEquals("blob", mapTag.getType()); + assertEquals("test020 tagged\n", mapTag.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag.getAuthor()); + assertEquals("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", mapTag.getObjId().name()); + } + + public void test020b_createBlobPlainTag() throws IOException { + test020_createBlobTag(); + Tag t = new Tag(db); + t.setTag("test020b"); + t.setObjId(ObjectId.fromString("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391")); + t.tag(); + + Tag mapTag = db.mapTag("test020b"); + assertEquals("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", mapTag.getObjId().name()); + + // We do not repeat the plain tag test for other object types + } + + public void test021_createTreeTag() throws IOException { + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + final Tree almostEmptyTree = new Tree(db); + almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); + final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); + final Tag t = new Tag(db); + t.setObjId(almostEmptyTreeId); + t.setType("tree"); + t.setTag("test021"); + t.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + t.setMessage("test021 tagged\n"); + t.tag(); + assertEquals("b0517bc8dbe2096b419d42424cd7030733f4abe5", t.getTagId().name()); + + Tag mapTag = db.mapTag("test021"); + assertEquals("tree", mapTag.getType()); + assertEquals("test021 tagged\n", mapTag.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag.getAuthor()); + assertEquals("417c01c8795a35b8e835113a85a5c0c1c77f67fb", mapTag.getObjId().name()); + } + + public void test022_createCommitTag() throws IOException { + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + final Tree almostEmptyTree = new Tree(db); + almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); + final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); + final Commit almostEmptyCommit = new Commit(db); + almostEmptyCommit.setAuthor(new PersonIdent(jauthor, 1154236443000L, -2 * 60)); // not exactly the same + almostEmptyCommit.setCommitter(new PersonIdent(jauthor, 1154236443000L, -2 * 60)); + almostEmptyCommit.setMessage("test022\n"); + almostEmptyCommit.setTreeId(almostEmptyTreeId); + ObjectId almostEmptyCommitId = new ObjectWriter(db).writeCommit(almostEmptyCommit); + final Tag t = new Tag(db); + t.setObjId(almostEmptyCommitId); + t.setType("commit"); + t.setTag("test022"); + t.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + t.setMessage("test022 tagged\n"); + t.tag(); + assertEquals("0ce2ebdb36076ef0b38adbe077a07d43b43e3807", t.getTagId().name()); + + Tag mapTag = db.mapTag("test022"); + assertEquals("commit", mapTag.getType()); + assertEquals("test022 tagged\n", mapTag.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag.getAuthor()); + assertEquals("b5d3b45a96b340441f5abb9080411705c51cc86c", mapTag.getObjId().name()); + } + + public void test023_createCommitNonAnullii() throws IOException { + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + final Tree almostEmptyTree = new Tree(db); + almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); + final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); + Commit commit = new Commit(db); + commit.setTreeId(almostEmptyTreeId); + commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60)); + commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60)); + commit.setEncoding("UTF-8"); + commit.setMessage("\u00dcbergeeks"); + ObjectId cid = new ObjectWriter(db).writeCommit(commit); + assertEquals("4680908112778718f37e686cbebcc912730b3154", cid.name()); + } + + public void test024_createCommitNonAscii() throws IOException { + final ObjectId emptyId = new ObjectWriter(db).writeBlob(new byte[0]); + final Tree almostEmptyTree = new Tree(db); + almostEmptyTree.addEntry(new FileTreeEntry(almostEmptyTree, emptyId, "empty".getBytes(), false)); + final ObjectId almostEmptyTreeId = new ObjectWriter(db).writeTree(almostEmptyTree); + Commit commit = new Commit(db); + commit.setTreeId(almostEmptyTreeId); + commit.setAuthor(new PersonIdent("Joe H\u00e4cker","joe@example.com",4294967295000L,60)); + commit.setCommitter(new PersonIdent("Joe Hacker","joe2@example.com",4294967295000L,60)); + commit.setEncoding("ISO-8859-1"); + commit.setMessage("\u00dcbergeeks"); + ObjectId cid = new ObjectWriter(db).writeCommit(commit); + assertEquals("2979b39d385014b33287054b87f77bcb3ecb5ebf", cid.name()); + } + + public void test025_packedRefs() throws IOException { + test020_createBlobTag(); + test021_createTreeTag(); + test022_createCommitTag(); + + if (!new File(db.getDirectory(),"refs/tags/test020").delete()) throw new Error("Cannot delete unpacked tag"); + if (!new File(db.getDirectory(),"refs/tags/test021").delete()) throw new Error("Cannot delete unpacked tag"); + if (!new File(db.getDirectory(),"refs/tags/test022").delete()) throw new Error("Cannot delete unpacked tag"); + + // We cannot resolve it now, since we have no ref + Tag mapTag20missing = db.mapTag("test020"); + assertNull(mapTag20missing); + + // Construct packed refs file + PrintWriter w = new PrintWriter(new FileWriter(new File(db.getDirectory(), "packed-refs"))); + w.println("# packed-refs with: peeled"); + w.println("6759556b09fbb4fd8ae5e315134481cc25d46954 refs/tags/test020"); + w.println("^e69de29bb2d1d6434b8b29ae775ad8c2e48c5391"); + w.println("b0517bc8dbe2096b419d42424cd7030733f4abe5 refs/tags/test021"); + w.println("^417c01c8795a35b8e835113a85a5c0c1c77f67fb"); + w.println("0ce2ebdb36076ef0b38adbe077a07d43b43e3807 refs/tags/test022"); + w.println("^b5d3b45a96b340441f5abb9080411705c51cc86c"); + w.close(); + + Tag mapTag20 = db.mapTag("test020"); + assertNotNull("have tag test020", mapTag20); + assertEquals("blob", mapTag20.getType()); + assertEquals("test020 tagged\n", mapTag20.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag20.getAuthor()); + assertEquals("e69de29bb2d1d6434b8b29ae775ad8c2e48c5391", mapTag20.getObjId().name()); + + Tag mapTag21 = db.mapTag("test021"); + assertEquals("tree", mapTag21.getType()); + assertEquals("test021 tagged\n", mapTag21.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag21.getAuthor()); + assertEquals("417c01c8795a35b8e835113a85a5c0c1c77f67fb", mapTag21.getObjId().name()); + + Tag mapTag22 = db.mapTag("test022"); + assertEquals("commit", mapTag22.getType()); + assertEquals("test022 tagged\n", mapTag22.getMessage()); + assertEquals(new PersonIdent(jauthor, 1154236443000L, -4 * 60), mapTag22.getAuthor()); + assertEquals("b5d3b45a96b340441f5abb9080411705c51cc86c", mapTag22.getObjId().name()); + } + + public void test025_computeSha1NoStore() throws IOException { + byte[] data = "test025 some data, more than 16 bytes to get good coverage" + .getBytes("ISO-8859-1"); + // TODO: but we do not test legacy header writing + final ObjectId id = new ObjectWriter(db).computeBlobSha1(data.length, + new ByteArrayInputStream(data)); + assertEquals("4f561df5ecf0dfbd53a0dc0f37262fef075d9dde", id.name()); + } + + public void test026_CreateCommitMultipleparents() throws IOException { + final Tree t = new Tree(db); + final FileTreeEntry f = t.addFile("i-am-a-file"); + writeTrashFile(f.getName(), "and this is the data in me\n"); + t.accept(new WriteTree(trash, db), TreeEntry.MODIFIED_ONLY); + assertEquals(ObjectId.fromString("00b1f73724f493096d1ffa0b0f1f1482dbb8c936"), + t.getTreeId()); + + final Commit c1 = new Commit(db); + c1.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + c1.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60)); + c1.setMessage("A Commit\n"); + c1.setTree(t); + assertEquals(t.getTreeId(), c1.getTreeId()); + c1.commit(); + final ObjectId cmtid1 = ObjectId.fromString( + "803aec4aba175e8ab1d666873c984c0308179099"); + assertEquals(cmtid1, c1.getCommitId()); + + final Commit c2 = new Commit(db); + c2.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + c2.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60)); + c2.setMessage("A Commit 2\n"); + c2.setTree(t); + assertEquals(t.getTreeId(), c2.getTreeId()); + c2.setParentIds(new ObjectId[] { c1.getCommitId() } ); + c2.commit(); + final ObjectId cmtid2 = ObjectId.fromString( + "95d068687c91c5c044fb8c77c5154d5247901553"); + assertEquals(cmtid2, c2.getCommitId()); + + Commit rm2 = db.mapCommit(cmtid2); + assertNotSame(c2, rm2); // assert the parsed objects is not from the cache + assertEquals(c2.getAuthor(), rm2.getAuthor()); + assertEquals(c2.getCommitId(), rm2.getCommitId()); + assertEquals(c2.getMessage(), rm2.getMessage()); + assertEquals(c2.getTree().getTreeId(), rm2.getTree().getTreeId()); + assertEquals(1, rm2.getParentIds().length); + assertEquals(c1.getCommitId(), rm2.getParentIds()[0]); + + final Commit c3 = new Commit(db); + c3.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + c3.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60)); + c3.setMessage("A Commit 3\n"); + c3.setTree(t); + assertEquals(t.getTreeId(), c3.getTreeId()); + c3.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId() }); + c3.commit(); + final ObjectId cmtid3 = ObjectId.fromString( + "ce6e1ce48fbeeb15a83f628dc8dc2debefa066f4"); + assertEquals(cmtid3, c3.getCommitId()); + + Commit rm3 = db.mapCommit(cmtid3); + assertNotSame(c3, rm3); // assert the parsed objects is not from the cache + assertEquals(c3.getAuthor(), rm3.getAuthor()); + assertEquals(c3.getCommitId(), rm3.getCommitId()); + assertEquals(c3.getMessage(), rm3.getMessage()); + assertEquals(c3.getTree().getTreeId(), rm3.getTree().getTreeId()); + assertEquals(2, rm3.getParentIds().length); + assertEquals(c1.getCommitId(), rm3.getParentIds()[0]); + assertEquals(c2.getCommitId(), rm3.getParentIds()[1]); + + final Commit c4 = new Commit(db); + c4.setAuthor(new PersonIdent(jauthor, 1154236443000L, -4 * 60)); + c4.setCommitter(new PersonIdent(jcommitter, 1154236443000L, -4 * 60)); + c4.setMessage("A Commit 4\n"); + c4.setTree(t); + assertEquals(t.getTreeId(), c3.getTreeId()); + c4.setParentIds(new ObjectId[] { c1.getCommitId(), c2.getCommitId(), c3.getCommitId() }); + c4.commit(); + final ObjectId cmtid4 = ObjectId.fromString( + "d1fca9fe3fef54e5212eb67902c8ed3e79736e27"); + assertEquals(cmtid4, c4.getCommitId()); + + Commit rm4 = db.mapCommit(cmtid4); + assertNotSame(c4, rm3); // assert the parsed objects is not from the cache + assertEquals(c4.getAuthor(), rm4.getAuthor()); + assertEquals(c4.getCommitId(), rm4.getCommitId()); + assertEquals(c4.getMessage(), rm4.getMessage()); + assertEquals(c4.getTree().getTreeId(), rm4.getTree().getTreeId()); + assertEquals(3, rm4.getParentIds().length); + assertEquals(c1.getCommitId(), rm4.getParentIds()[0]); + assertEquals(c2.getCommitId(), rm4.getParentIds()[1]); + assertEquals(c3.getCommitId(), rm4.getParentIds()[2]); + } + + public void test027_UnpackedRefHigherPriorityThanPacked() throws IOException { + PrintWriter writer = new PrintWriter(new FileWriter(new File(db.getDirectory(), "refs/heads/a"))); + String unpackedId = "7f822839a2fe9760f386cbbbcb3f92c5fe81def7"; + writer.print(unpackedId); + writer.print('\n'); + writer.close(); + + ObjectId resolved = db.resolve("refs/heads/a"); + assertEquals(unpackedId, resolved.name()); + } + + public void test028_LockPackedRef() throws IOException { + writeTrashFile(".git/packed-refs", "7f822839a2fe9760f386cbbbcb3f92c5fe81def7 refs/heads/foobar"); + writeTrashFile(".git/HEAD", "ref: refs/heads/foobar\n"); + + ObjectId resolve = db.resolve("HEAD"); + assertEquals("7f822839a2fe9760f386cbbbcb3f92c5fe81def7", resolve.name()); + + RefUpdate lockRef = db.updateRef("HEAD"); + ObjectId newId = ObjectId.fromString("07f822839a2fe9760f386cbbbcb3f92c5fe81def"); + lockRef.setNewObjectId(newId); + assertEquals(RefUpdate.Result.FORCED, lockRef.forceUpdate()); + + assertTrue(new File(db.getDirectory(), "refs/heads/foobar").exists()); + assertEquals(newId, db.resolve("refs/heads/foobar")); + + // Again. The ref already exists + RefUpdate lockRef2 = db.updateRef("HEAD"); + ObjectId newId2 = ObjectId.fromString("7f822839a2fe9760f386cbbbcb3f92c5fe81def7"); + lockRef2.setNewObjectId(newId2); + assertEquals(RefUpdate.Result.FORCED, lockRef2.forceUpdate()); + + assertTrue(new File(db.getDirectory(), "refs/heads/foobar").exists()); + assertEquals(newId2, db.resolve("refs/heads/foobar")); + } + + public void test029_mapObject() throws IOException { + assertEquals(new byte[0].getClass(), db.mapObject(ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"), null).getClass()); + assertEquals(Commit.class, db.mapObject(ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"), null).getClass()); + assertEquals(Tree.class, db.mapObject(ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"), null).getClass()); + assertEquals(Tag.class, db.mapObject(ObjectId.fromString("17768080a2318cd89bba4c8b87834401e2095703"), null).getClass()); + } + + public void test30_stripWorkDir() { + File relCwd = new File("."); + File absCwd = relCwd.getAbsoluteFile(); + File absBase = new File(new File(absCwd, "repo"), "workdir"); + File relBase = new File(new File(relCwd, "repo"), "workdir"); + assertEquals(absBase.getAbsolutePath(), relBase.getAbsolutePath()); + + File relBaseFile = new File(new File(relBase, "other"), "module.c"); + File absBaseFile = new File(new File(absBase, "other"), "module.c"); + assertEquals("other/module.c", Repository.stripWorkDir(relBase, relBaseFile)); + assertEquals("other/module.c", Repository.stripWorkDir(relBase, absBaseFile)); + assertEquals("other/module.c", Repository.stripWorkDir(absBase, relBaseFile)); + assertEquals("other/module.c", Repository.stripWorkDir(absBase, absBaseFile)); + + File relNonFile = new File(new File(relCwd, "not-repo"), ".gitignore"); + File absNonFile = new File(new File(absCwd, "not-repo"), ".gitignore"); + assertEquals("", Repository.stripWorkDir(relBase, relNonFile)); + assertEquals("", Repository.stripWorkDir(absBase, absNonFile)); + + assertEquals("", Repository.stripWorkDir(db.getWorkDir(), db.getWorkDir())); + + File file = new File(new File(db.getWorkDir(), "subdir"), "File.java"); + assertEquals("subdir/File.java", Repository.stripWorkDir(db.getWorkDir(), file)); + + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java new file mode 100644 index 0000000000..adddbfe099 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0004_PackReader.java @@ -0,0 +1,114 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2007, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; + +import org.eclipse.jgit.util.JGitTestUtil; + +public class T0004_PackReader extends RepositoryTestCase { + private static final String PACK_NAME = "pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f"; + private static final File TEST_PACK = JGitTestUtil.getTestResourceFile(PACK_NAME + ".pack"); + private static final File TEST_IDX = JGitTestUtil.getTestResourceFile(PACK_NAME + ".idx"); + + public void test003_lookupCompressedObject() throws IOException { + final PackFile pr; + final ObjectId id; + final PackedObjectLoader or; + + id = ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"); + pr = new PackFile(TEST_IDX, TEST_PACK); + or = pr.get(new WindowCursor(), id); + assertNotNull(or); + assertEquals(Constants.OBJ_TREE, or.getType()); + assertEquals(35, or.getSize()); + assertEquals(7738, or.getDataOffset()); + pr.close(); + } + + public void test004_lookupDeltifiedObject() throws IOException { + final ObjectId id; + final ObjectLoader or; + + id = ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"); + or = db.openObject(id); + assertNotNull(or); + assertTrue(or instanceof PackedObjectLoader); + assertEquals(Constants.OBJ_BLOB, or.getType()); + assertEquals(18009, or.getSize()); + assertEquals(537, ((PackedObjectLoader) or).getDataOffset()); + } + + public void test005_todopack() throws IOException { + final File todopack = JGitTestUtil.getTestResourceFile("todopack"); + if (!todopack.isDirectory()) { + System.err.println("Skipping " + getName() + ": no " + todopack); + return; + } + + final File packDir = new File(db.getObjectsDirectory(), "pack"); + final String packname = "pack-2e71952edc41f3ce7921c5e5dd1b64f48204cf35"; + copyFile(new File(todopack, packname + ".pack"), new File(packDir, + packname + ".pack")); + copyFile(new File(todopack, packname + ".idx"), new File(packDir, + packname + ".idx")); + Tree t; + + t = db + .mapTree(ObjectId.fromString( + "aac9df07f653dd18b935298deb813e02c32d2e6f")); + assertNotNull(t); + t.memberCount(); + + t = db + .mapTree(ObjectId.fromString( + "6b9ffbebe7b83ac6a61c9477ab941d999f5d0c96")); + assertNotNull(t); + t.memberCount(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0007_Index.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0007_Index.java new file mode 100644 index 0000000000..74e4bfbdea --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0007_Index.java @@ -0,0 +1,455 @@ +/* + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import org.eclipse.jgit.lib.GitIndex.Entry; +import org.eclipse.jgit.util.FS; + +public class T0007_Index extends RepositoryTestCase { + + static boolean canrungitstatus; + static { + try { + canrungitstatus = system(new File("."),"git --version") == 0; + } catch (IOException e) { + System.out.println("Warning: cannot invoke native git to validate index"); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + private static int system(File dir, String cmd) throws IOException, + InterruptedException { + final Process process = Runtime.getRuntime().exec(cmd, null, dir); + new Thread() { + public void run() { + try { + InputStream s = process.getErrorStream(); + for (int c = s.read(); c != -1; c = s.read()) { + System.err.print((char) c); + } + s.close(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + }.start(); + final Thread t2 = new Thread() { + public void run() { + synchronized (this) { + try { + InputStream e = process.getInputStream(); + for (int c = e.read(); c != -1; c = e.read()) { + System.out.print((char) c); + } + e.close(); + } catch (IOException e1) { + // TODO Auto-generated catch block + e1.printStackTrace(); + } + } + } + }; + t2.start(); + process.getOutputStream().close(); + int ret = process.waitFor(); + synchronized (t2) { + return ret; + } + } + + public void testCreateEmptyIndex() throws Exception { + GitIndex index = new GitIndex(db); + index.write(); +// native git doesn't like an empty index +// assertEquals(0,system(trash,"git status")); + + GitIndex indexr = new GitIndex(db); + indexr.read(); + assertEquals(0, indexr.getMembers().length); + } + + public void testReadWithNoIndex() throws Exception { + GitIndex index = new GitIndex(db); + index.read(); + assertEquals(0, index.getMembers().length); + } + + public void testCreateSimpleSortTestIndex() throws Exception { + GitIndex index = new GitIndex(db); + writeTrashFile("a/b", "data:a/b"); + writeTrashFile("a:b", "data:a:b"); + writeTrashFile("a.b", "data:a.b"); + index.add(trash, new File(trash, "a/b")); + index.add(trash, new File(trash, "a:b")); + index.add(trash, new File(trash, "a.b")); + index.write(); + + assertEquals("a/b", index.getEntry("a/b").getName()); + assertEquals("a:b", index.getEntry("a:b").getName()); + assertEquals("a.b", index.getEntry("a.b").getName()); + assertNull(index.getEntry("a*b")); + + // Repeat test for re-read index + GitIndex indexr = new GitIndex(db); + indexr.read(); + assertEquals("a/b", indexr.getEntry("a/b").getName()); + assertEquals("a:b", indexr.getEntry("a:b").getName()); + assertEquals("a.b", indexr.getEntry("a.b").getName()); + assertNull(indexr.getEntry("a*b")); + + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void testUpdateSimpleSortTestIndex() throws Exception { + GitIndex index = new GitIndex(db); + writeTrashFile("a/b", "data:a/b"); + writeTrashFile("a:b", "data:a:b"); + writeTrashFile("a.b", "data:a.b"); + index.add(trash, new File(trash, "a/b")); + index.add(trash, new File(trash, "a:b")); + index.add(trash, new File(trash, "a.b")); + writeTrashFile("a/b", "data:a/b modified"); + index.add(trash, new File(trash, "a/b")); + index.write(); + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void testWriteTree() throws Exception { + GitIndex index = new GitIndex(db); + writeTrashFile("a/b", "data:a/b"); + writeTrashFile("a:b", "data:a:b"); + writeTrashFile("a.b", "data:a.b"); + index.add(trash, new File(trash, "a/b")); + index.add(trash, new File(trash, "a:b")); + index.add(trash, new File(trash, "a.b")); + index.write(); + + ObjectId id = index.writeTree(); + assertEquals("c696abc3ab8e091c665f49d00eb8919690b3aec3", id.name()); + + writeTrashFile("a/b", "data:a/b"); + index.add(trash, new File(trash, "a/b")); + + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void testReadTree() throws Exception { + // Prepare tree + GitIndex index = new GitIndex(db); + writeTrashFile("a/b", "data:a/b"); + writeTrashFile("a:b", "data:a:b"); + writeTrashFile("a.b", "data:a.b"); + index.add(trash, new File(trash, "a/b")); + index.add(trash, new File(trash, "a:b")); + index.add(trash, new File(trash, "a.b")); + index.write(); + + ObjectId id = index.writeTree(); + System.out.println("wrote id " + id); + assertEquals("c696abc3ab8e091c665f49d00eb8919690b3aec3", id.name()); + GitIndex index2 = new GitIndex(db); + + index2.readTree(db.mapTree(ObjectId.fromString( + "c696abc3ab8e091c665f49d00eb8919690b3aec3"))); + Entry[] members = index2.getMembers(); + assertEquals(3, members.length); + assertEquals("a.b", members[0].getName()); + assertEquals("a/b", members[1].getName()); + assertEquals("a:b", members[2].getName()); + assertEquals(3, members.length); + + GitIndex indexr = new GitIndex(db); + indexr.read(); + Entry[] membersr = indexr.getMembers(); + assertEquals(3, membersr.length); + assertEquals("a.b", membersr[0].getName()); + assertEquals("a/b", membersr[1].getName()); + assertEquals("a:b", membersr[2].getName()); + assertEquals(3, membersr.length); + + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void testReadTree2() throws Exception { + // Prepare a larger tree to test some odd cases in tree writing + GitIndex index = new GitIndex(db); + File f1 = writeTrashFile("a/a/a/a", "data:a/a/a/a"); + File f2 = writeTrashFile("a/c/c", "data:a/c/c"); + File f3 = writeTrashFile("a/b", "data:a/b"); + File f4 = writeTrashFile("a:b", "data:a:b"); + File f5 = writeTrashFile("a/d", "data:a/d"); + File f6 = writeTrashFile("a.b", "data:a.b"); + index.add(trash, f1); + index.add(trash, f2); + index.add(trash, f3); + index.add(trash, f4); + index.add(trash, f5); + index.add(trash, f6); + index.write(); + ObjectId id = index.writeTree(); + System.out.println("wrote id " + id); + assertEquals("ba78e065e2c261d4f7b8f42107588051e87e18e9", id.name()); + GitIndex index2 = new GitIndex(db); + + index2.readTree(db.mapTree(ObjectId.fromString( + "ba78e065e2c261d4f7b8f42107588051e87e18e9"))); + Entry[] members = index2.getMembers(); + assertEquals(6, members.length); + assertEquals("a.b", members[0].getName()); + assertEquals("a/a/a/a", members[1].getName()); + assertEquals("a/b", members[2].getName()); + assertEquals("a/c/c", members[3].getName()); + assertEquals("a/d", members[4].getName()); + assertEquals("a:b", members[5].getName()); + + // reread and test + GitIndex indexr = new GitIndex(db); + indexr.read(); + Entry[] membersr = indexr.getMembers(); + assertEquals(6, membersr.length); + assertEquals("a.b", membersr[0].getName()); + assertEquals("a/a/a/a", membersr[1].getName()); + assertEquals("a/b", membersr[2].getName()); + assertEquals("a/c/c", membersr[3].getName()); + assertEquals("a/d", membersr[4].getName()); + assertEquals("a:b", membersr[5].getName()); + } + + public void testDelete() throws Exception { + GitIndex index = new GitIndex(db); + writeTrashFile("a/b", "data:a/b"); + writeTrashFile("a:b", "data:a:b"); + writeTrashFile("a.b", "data:a.b"); + index.add(trash, new File(trash, "a/b")); + index.add(trash, new File(trash, "a:b")); + index.add(trash, new File(trash, "a.b")); + index.write(); + index.writeTree(); + index.remove(trash, new File(trash, "a:b")); + index.write(); + assertEquals("a.b", index.getMembers()[0].getName()); + assertEquals("a/b", index.getMembers()[1].getName()); + + GitIndex indexr = new GitIndex(db); + indexr.read(); + assertEquals("a.b", indexr.getMembers()[0].getName()); + assertEquals("a/b", indexr.getMembers()[1].getName()); + + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void testCheckout() throws Exception { + // Prepare tree, remote it and checkout + GitIndex index = new GitIndex(db); + File aslashb = writeTrashFile("a/b", "data:a/b"); + File acolonb = writeTrashFile("a:b", "data:a:b"); + File adotb = writeTrashFile("a.b", "data:a.b"); + index.add(trash, aslashb); + index.add(trash, acolonb); + index.add(trash, adotb); + index.write(); + index.writeTree(); + delete(aslashb); + delete(acolonb); + delete(adotb); + delete(aslashb.getParentFile()); + + GitIndex index2 = new GitIndex(db); + assertEquals(0, index2.getMembers().length); + + index2.readTree(db.mapTree(ObjectId.fromString( + "c696abc3ab8e091c665f49d00eb8919690b3aec3"))); + + index2.checkout(trash); + assertEquals("data:a/b", content(aslashb)); + assertEquals("data:a:b", content(acolonb)); + assertEquals("data:a.b", content(adotb)); + + if (canrungitstatus) + assertEquals(0, system(trash, "git status")); + } + + public void test030_executeBit_coreModeTrue() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception { + if (!FS.INSTANCE.supportsExecute()) { + System.err.println("Test ignored since platform FS does not support the execute permission"); + return; + } + try { + // coremode true is the default, typically set to false + // by git init (but not jgit!) + Method canExecute = File.class.getMethod("canExecute", (Class[])null); + Method setExecute = File.class.getMethod("setExecutable", new Class[] { Boolean.TYPE }); + File execFile = writeTrashFile("exec","exec"); + if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.TRUE })).booleanValue()) + throw new Error("could not set execute bit on "+execFile.getAbsolutePath()+"for test"); + File nonexecFile = writeTrashFile("nonexec","nonexec"); + if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.FALSE })).booleanValue()) + throw new Error("could not clear execute bit on "+nonexecFile.getAbsolutePath()+"for test"); + + GitIndex index = new GitIndex(db); + index.filemode = Boolean.TRUE; // TODO: we need a way to set this using config + index.add(trash, execFile); + index.add(trash, nonexecFile); + Tree tree = db.mapTree(index.writeTree()); + assertEquals(FileMode.EXECUTABLE_FILE, tree.findBlobMember(execFile.getName()).getMode()); + assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(nonexecFile.getName()).getMode()); + + index.write(); + + if (!execFile.delete()) + throw new Error("Problem in test, cannot delete test file "+execFile.getAbsolutePath()); + if (!nonexecFile.delete()) + throw new Error("Problem in test, cannot delete test file "+nonexecFile.getAbsolutePath()); + GitIndex index2 = new GitIndex(db); + index2.filemode = Boolean.TRUE; // TODO: we need a way to set this using config + index2.read(); + index2.checkout(trash); + assertTrue(((Boolean)canExecute.invoke(execFile,(Object[])null)).booleanValue()); + assertFalse(((Boolean)canExecute.invoke(nonexecFile,(Object[])null)).booleanValue()); + + assertFalse(index2.getEntry(execFile.getName()).isModified(trash)); + assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash)); + + if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.FALSE })).booleanValue()) + throw new Error("could not clear set execute bit on "+execFile.getAbsolutePath()+"for test"); + if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.TRUE })).booleanValue()) + throw new Error("could set execute bit on "+nonexecFile.getAbsolutePath()+"for test"); + + assertTrue(index2.getEntry(execFile.getName()).isModified(trash)); + assertTrue(index2.getEntry(nonexecFile.getName()).isModified(trash)); + + } catch (NoSuchMethodException e) { + System.err.println("Test ignored when running under JDK < 1.6"); + return; + } + } + + public void test031_executeBit_coreModeFalse() throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, Error, Exception { + if (!FS.INSTANCE.supportsExecute()) { + System.err.println("Test ignored since platform FS does not support the execute permission"); + return; + } + try { + // coremode true is the default, typically set to false + // by git init (but not jgit!) + Method canExecute = File.class.getMethod("canExecute", (Class[])null); + Method setExecute = File.class.getMethod("setExecutable", new Class[] { Boolean.TYPE }); + File execFile = writeTrashFile("exec","exec"); + if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.TRUE })).booleanValue()) + throw new Error("could not set execute bit on "+execFile.getAbsolutePath()+"for test"); + File nonexecFile = writeTrashFile("nonexec","nonexec"); + if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.FALSE })).booleanValue()) + throw new Error("could not clear execute bit on "+nonexecFile.getAbsolutePath()+"for test"); + + GitIndex index = new GitIndex(db); + index.filemode = Boolean.FALSE; // TODO: we need a way to set this using config + index.add(trash, execFile); + index.add(trash, nonexecFile); + Tree tree = db.mapTree(index.writeTree()); + assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(execFile.getName()).getMode()); + assertEquals(FileMode.REGULAR_FILE, tree.findBlobMember(nonexecFile.getName()).getMode()); + + index.write(); + + if (!execFile.delete()) + throw new Error("Problem in test, cannot delete test file "+execFile.getAbsolutePath()); + if (!nonexecFile.delete()) + throw new Error("Problem in test, cannot delete test file "+nonexecFile.getAbsolutePath()); + GitIndex index2 = new GitIndex(db); + index2.filemode = Boolean.FALSE; // TODO: we need a way to set this using config + index2.read(); + index2.checkout(trash); + assertFalse(((Boolean)canExecute.invoke(execFile,(Object[])null)).booleanValue()); + assertFalse(((Boolean)canExecute.invoke(nonexecFile,(Object[])null)).booleanValue()); + + assertFalse(index2.getEntry(execFile.getName()).isModified(trash)); + assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash)); + + if (!((Boolean)setExecute.invoke(execFile, new Object[] { Boolean.FALSE })).booleanValue()) + throw new Error("could not clear set execute bit on "+execFile.getAbsolutePath()+"for test"); + if (!((Boolean)setExecute.invoke(nonexecFile, new Object[] { Boolean.TRUE })).booleanValue()) + throw new Error("could set execute bit on "+nonexecFile.getAbsolutePath()+"for test"); + + // no change since we ignore the execute bit + assertFalse(index2.getEntry(execFile.getName()).isModified(trash)); + assertFalse(index2.getEntry(nonexecFile.getName()).isModified(trash)); + + } catch (NoSuchMethodException e) { + System.err.println("Test ignored when running under JDK < 1.6"); + return; + } + } + + private String content(File f) throws IOException { + byte[] buf = new byte[(int) f.length()]; + FileInputStream is = new FileInputStream(f); + try { + int read = is.read(buf); + assertEquals(f.length(), read); + return new String(buf, 0); + } finally { + is.close(); + } + } + + private void delete(File f) throws IOException { + if (!f.delete()) + throw new IOException("Failed to delete f"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0008_testparserev.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0008_testparserev.java new file mode 100644 index 0000000000..ac730ff6a2 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/T0008_testparserev.java @@ -0,0 +1,142 @@ +/* + * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk> + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.IOException; + +public class T0008_testparserev extends RepositoryTestCase { + + public void testObjectId_existing() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0").name()); + } + + public void testObjectId_nonexisting() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c1",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c1").name()); + } + + public void testObjectId_objectid_implicit_firstparent() throws IOException { + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^").name()); + assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^^").name()); + assertEquals("bab66b48f836ed950c99134ef666436fb07a09a0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^^^").name()); + } + + public void testObjectId_objectid_self() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^0").name()); + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^0^0").name()); + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^0^0^0").name()); + } + + public void testObjectId_objectid_explicit_firstparent() throws IOException { + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^1").name()); + assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^1^1").name()); + assertEquals("bab66b48f836ed950c99134ef666436fb07a09a0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^1^1^1").name()); + } + + public void testObjectId_objectid_explicit_otherparents() throws IOException { + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^1").name()); + assertEquals("f73b95671f326616d66b2afb3bdfcdbbce110b44",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^2").name()); + assertEquals("d0114ab8ac326bab30e3a657a0397578c5a1af88",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^3").name()); + assertEquals("d0114ab8ac326bab30e3a657a0397578c5a1af88",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^03").name()); + } + + public void testRef_refname() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("master^0").name()); + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("master^").name()); + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("refs/heads/master^1").name()); + } + + public void testDistance() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0~0").name()); + assertEquals("6e1475206e57110fcef4b92320436c1e9872a322",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0~1").name()); + assertEquals("1203b03dc816ccbb67773f28b3c19318654b0bc8",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0~2").name()); + assertEquals("bab66b48f836ed950c99134ef666436fb07a09a0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0~3").name()); + assertEquals("bab66b48f836ed950c99134ef666436fb07a09a0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0~03").name()); + } + + public void testTree() throws IOException { + assertEquals("6020a3b8d5d636e549ccbd0c53e2764684bb3125",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^{tree}").name()); + assertEquals("02ba32d3649e510002c21651936b7077aa75ffa9",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^^{tree}").name()); + } + + public void testHEAD() throws IOException { + assertEquals("6020a3b8d5d636e549ccbd0c53e2764684bb3125",db.resolve("HEAD^{tree}").name()); + } + + public void testDerefCommit() throws IOException { + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^{}").name()); + assertEquals("49322bb17d3acc9146f98c97d078513228bbf3c0",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^{commit}").name()); + // double deref + assertEquals("6020a3b8d5d636e549ccbd0c53e2764684bb3125",db.resolve("49322bb17d3acc9146f98c97d078513228bbf3c0^{commit}^{tree}").name()); + } + + public void testDerefTag() throws IOException { + assertEquals("17768080a2318cd89bba4c8b87834401e2095703",db.resolve("refs/tags/B").name()); + assertEquals("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",db.resolve("refs/tags/B^{commit}").name()); + assertEquals("032c063ce34486359e3ee3d4f9e5c225b9e1a4c2",db.resolve("refs/tags/B10th").name()); + assertEquals("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",db.resolve("refs/tags/B10th^{commit}").name()); + assertEquals("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",db.resolve("refs/tags/B10th^{}").name()); + assertEquals("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",db.resolve("refs/tags/B10th^0").name()); + assertEquals("d86a2aada2f5e7ccf6f11880bfb9ab404e8a8864",db.resolve("refs/tags/B10th~0").name()); + assertEquals("0966a434eb1a025db6b71485ab63a3bfbea520b6",db.resolve("refs/tags/B10th^").name()); + assertEquals("0966a434eb1a025db6b71485ab63a3bfbea520b6",db.resolve("refs/tags/B10th^1").name()); + assertEquals("0966a434eb1a025db6b71485ab63a3bfbea520b6",db.resolve("refs/tags/B10th~1").name()); + assertEquals("2c349335b7f797072cf729c4f3bb0914ecb6dec9",db.resolve("refs/tags/B10th~2").name()); + } + + public void testDerefBlob() throws IOException { + assertEquals("fd608fbe625a2b456d9f15c2b1dc41f252057dd7",db.resolve("spearce-gpg-pub^{}").name()); + assertEquals("fd608fbe625a2b456d9f15c2b1dc41f252057dd7",db.resolve("spearce-gpg-pub^{blob}").name()); + assertEquals("fd608fbe625a2b456d9f15c2b1dc41f252057dd7",db.resolve("fd608fbe625a2b456d9f15c2b1dc41f252057dd7^{}").name()); + assertEquals("fd608fbe625a2b456d9f15c2b1dc41f252057dd7",db.resolve("fd608fbe625a2b456d9f15c2b1dc41f252057dd7^{blob}").name()); + } + + public void testDerefTree() throws IOException { + assertEquals("032c063ce34486359e3ee3d4f9e5c225b9e1a4c2",db.resolve("refs/tags/B10th").name()); + assertEquals("856ec208ae6cadac25a6d74f19b12bb27a24fe24",db.resolve("032c063ce34486359e3ee3d4f9e5c225b9e1a4c2^{tree}").name()); + assertEquals("856ec208ae6cadac25a6d74f19b12bb27a24fe24",db.resolve("refs/tags/B10th^{tree}").name()); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorLeafOnlyTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorLeafOnlyTest.java new file mode 100644 index 0000000000..6b19cc1e89 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorLeafOnlyTest.java @@ -0,0 +1,129 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.IOException; + +public class TreeIteratorLeafOnlyTest extends RepositoryTestCase { + + /** Empty tree */ + public void testEmpty() { + Tree tree = new Tree(db); + TreeIterator i = makeIterator(tree); + assertFalse(i.hasNext()); + } + + /** + * one file + * + * @throws IOException + */ + public void testSimpleF1() throws IOException { + Tree tree = new Tree(db); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("x", i.next().getName()); + } + + /** + * two files + * + * @throws IOException + */ + public void testSimpleF2() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a"); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getName()); + assertEquals("x", i.next().getName()); + } + + /** + * Empty tree + * + * @throws IOException + */ + public void testSimpleT() throws IOException { + Tree tree = new Tree(db); + tree.addTree("a"); + TreeIterator i = makeIterator(tree); + assertFalse(i.hasNext()); + } + + public void testTricky() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a.b"); + tree.addFile("a.c"); + tree.addFile("a/b.b/b"); + tree.addFile("a/b"); + tree.addFile("a/c"); + tree.addFile("a=c"); + tree.addFile("a=d"); + + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("a.b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a.c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b.b/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=d", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + private TreeIterator makeIterator(Tree tree) { + return new TreeIterator(tree); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPostOrderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPostOrderTest.java new file mode 100644 index 0000000000..caf8bff2a7 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPostOrderTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.IOException; + +public class TreeIteratorPostOrderTest extends RepositoryTestCase { + + /** Empty tree */ + public void testEmpty() { + Tree tree = new Tree(db); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + /** + * one file + * + * @throws IOException + */ + public void testSimpleF1() throws IOException { + Tree tree = new Tree(db); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("x", i.next().getName()); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + /** + * two files + * + * @throws IOException + */ + public void testSimpleF2() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a"); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getName()); + assertEquals("x", i.next().getName()); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + /** + * Empty tree + * + * @throws IOException + */ + public void testSimpleT() throws IOException { + Tree tree = new Tree(db); + tree.addTree("a"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + public void testTricky() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a.b"); + tree.addFile("a.c"); + tree.addFile("a/b.b/b"); + tree.addFile("a/b"); + tree.addFile("a/c"); + tree.addFile("a=c"); + tree.addFile("a=d"); + + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("a.b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a.c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b.b/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b.b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=d", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + private TreeIterator makeIterator(Tree tree) { + return new TreeIterator(tree, TreeIterator.Order.POSTORDER); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPreOrderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPreOrderTest.java new file mode 100644 index 0000000000..c6f41446d2 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/TreeIteratorPreOrderTest.java @@ -0,0 +1,147 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.IOException; + +public class TreeIteratorPreOrderTest extends RepositoryTestCase { + + /** Empty tree */ + public void testEmpty() { + Tree tree = new Tree(db); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + /** + * one file + * + * @throws IOException + */ + public void testSimpleF1() throws IOException { + Tree tree = new Tree(db); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("x", i.next().getName()); + assertFalse(i.hasNext()); + } + + /** + * two files + * + * @throws IOException + */ + public void testSimpleF2() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a"); + tree.addFile("x"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getName()); + assertEquals("x", i.next().getName()); + assertFalse(i.hasNext()); + } + + /** + * Empty tree + * + * @throws IOException + */ + public void testSimpleT() throws IOException { + Tree tree = new Tree(db); + tree.addTree("a"); + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + public void testTricky() throws IOException { + Tree tree = new Tree(db); + tree.addFile("a.b"); + tree.addFile("a.c"); + tree.addFile("a/b.b/b"); + tree.addFile("a/b"); + tree.addFile("a/c"); + tree.addFile("a=c"); + tree.addFile("a=d"); + + TreeIterator i = makeIterator(tree); + assertTrue(i.hasNext()); + assertEquals("", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a.b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a.c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b.b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/b.b/b", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a/c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=c", i.next().getFullName()); + assertTrue(i.hasNext()); + assertEquals("a=d", i.next().getFullName()); + assertFalse(i.hasNext()); + } + + private TreeIterator makeIterator(Tree tree) { + return new TreeIterator(tree, TreeIterator.Order.PREORDER); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java new file mode 100644 index 0000000000..79e2eba701 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/ValidRefNameTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import junit.framework.TestCase; + +public class ValidRefNameTest extends TestCase { + private static void assertValid(final boolean exp, final String name) { + assertEquals("\"" + name + "\"", exp, Repository.isValidRefName(name)); + } + + public void testEmptyString() { + assertValid(false, ""); + assertValid(false, "/"); + } + + public void testMustHaveTwoComponents() { + assertValid(false, "master"); + assertValid(true, "heads/master"); + } + + public void testValidHead() { + assertValid(true, "refs/heads/master"); + assertValid(true, "refs/heads/pu"); + assertValid(true, "refs/heads/z"); + assertValid(true, "refs/heads/FoO"); + } + + public void testValidTag() { + assertValid(true, "refs/tags/v1.0"); + } + + public void testNoLockSuffix() { + assertValid(false, "refs/heads/master.lock"); + } + + public void testNoDirectorySuffix() { + assertValid(false, "refs/heads/master/"); + } + + public void testNoSpace() { + assertValid(false, "refs/heads/i haz space"); + } + + public void testNoAsciiControlCharacters() { + for (char c = '\0'; c < ' '; c++) + assertValid(false, "refs/heads/mast" + c + "er"); + } + + public void testNoBareDot() { + assertValid(false, "refs/heads/."); + assertValid(false, "refs/heads/.."); + assertValid(false, "refs/heads/./master"); + assertValid(false, "refs/heads/../master"); + } + + public void testNoLeadingOrTrailingDot() { + assertValid(false, "."); + assertValid(false, "refs/heads/.bar"); + assertValid(false, "refs/heads/..bar"); + assertValid(false, "refs/heads/bar."); + } + + public void testContainsDot() { + assertValid(true, "refs/heads/m.a.s.t.e.r"); + assertValid(false, "refs/heads/master..pu"); + } + + public void testNoMagicRefCharacters() { + assertValid(false, "refs/heads/master^"); + assertValid(false, "refs/heads/^master"); + assertValid(false, "^refs/heads/master"); + + assertValid(false, "refs/heads/master~"); + assertValid(false, "refs/heads/~master"); + assertValid(false, "~refs/heads/master"); + + assertValid(false, "refs/heads/master:"); + assertValid(false, "refs/heads/:master"); + assertValid(false, ":refs/heads/master"); + } + + public void testShellGlob() { + assertValid(false, "refs/heads/master?"); + assertValid(false, "refs/heads/?master"); + assertValid(false, "?refs/heads/master"); + + assertValid(false, "refs/heads/master["); + assertValid(false, "refs/heads/[master"); + assertValid(false, "[refs/heads/master"); + + assertValid(false, "refs/heads/master*"); + assertValid(false, "refs/heads/*master"); + assertValid(false, "*refs/heads/master"); + } + + public void testValidSpecialCharacters() { + assertValid(true, "refs/heads/!"); + assertValid(true, "refs/heads/\""); + assertValid(true, "refs/heads/#"); + assertValid(true, "refs/heads/$"); + assertValid(true, "refs/heads/%"); + assertValid(true, "refs/heads/&"); + assertValid(true, "refs/heads/'"); + assertValid(true, "refs/heads/("); + assertValid(true, "refs/heads/)"); + assertValid(true, "refs/heads/+"); + assertValid(true, "refs/heads/,"); + assertValid(true, "refs/heads/-"); + assertValid(true, "refs/heads/;"); + assertValid(true, "refs/heads/<"); + assertValid(true, "refs/heads/="); + assertValid(true, "refs/heads/>"); + assertValid(true, "refs/heads/@"); + assertValid(true, "refs/heads/]"); + assertValid(true, "refs/heads/_"); + assertValid(true, "refs/heads/`"); + assertValid(true, "refs/heads/{"); + assertValid(true, "refs/heads/|"); + assertValid(true, "refs/heads/}"); + + // This is valid on UNIX, but not on Windows + // hence we make in invalid due to non-portability + // + assertValid(false, "refs/heads/\\"); + } + + public void testUnicodeNames() { + assertValid(true, "refs/heads/\u00e5ngstr\u00f6m"); + } + + public void testRefLogQueryIsValidRef() { + assertValid(false, "refs/heads/master@{1}"); + assertValid(false, "refs/heads/master@{1.hour.ago}"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java new file mode 100644 index 0000000000..55b568d8fd --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheGetTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.BufferedReader; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.ArrayList; +import java.util.List; + +import org.eclipse.jgit.errors.CorruptObjectException; +import org.eclipse.jgit.util.JGitTestUtil; +import org.eclipse.jgit.util.MutableInteger; + +public class WindowCacheGetTest extends RepositoryTestCase { + private List<TestObject> toLoad; + + @Override + public void setUp() throws Exception { + super.setUp(); + + toLoad = new ArrayList<TestObject>(); + final BufferedReader br = new BufferedReader(new InputStreamReader( + new FileInputStream(JGitTestUtil + .getTestResourceFile("all_packed_objects.txt")), + Constants.CHARSET)); + try { + String line; + while ((line = br.readLine()) != null) { + final String[] parts = line.split(" {1,}"); + final TestObject o = new TestObject(); + o.id = ObjectId.fromString(parts[0]); + o.setType(parts[1]); + o.rawSize = Integer.parseInt(parts[2]); + // parts[3] is the size-in-pack + o.offset = Long.parseLong(parts[4]); + toLoad.add(o); + } + } finally { + br.close(); + } + assertEquals(96, toLoad.size()); + } + + public void testCache_Defaults() throws IOException { + final WindowCacheConfig cfg = new WindowCacheConfig(); + WindowCache.reconfigure(cfg); + doCacheTests(); + checkLimits(cfg); + + final WindowCache cache = WindowCache.getInstance(); + assertEquals(6, cache.getOpenFiles()); + assertEquals(17346, cache.getOpenBytes()); + } + + public void testCache_TooFewFiles() throws IOException { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitOpenFiles(2); + WindowCache.reconfigure(cfg); + doCacheTests(); + checkLimits(cfg); + } + + public void testCache_TooSmallLimit() throws IOException { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitWindowSize(4096); + cfg.setPackedGitLimit(4096); + WindowCache.reconfigure(cfg); + doCacheTests(); + checkLimits(cfg); + } + + private void checkLimits(final WindowCacheConfig cfg) { + final WindowCache cache = WindowCache.getInstance(); + assertTrue(cache.getOpenFiles() <= cfg.getPackedGitOpenFiles()); + assertTrue(cache.getOpenBytes() <= cfg.getPackedGitLimit()); + assertTrue(0 < cache.getOpenFiles()); + assertTrue(0 < cache.getOpenBytes()); + } + + private void doCacheTests() throws IOException { + for (final TestObject o : toLoad) { + final ObjectLoader or = db.openObject(o.id); + assertNotNull(or); + assertTrue(or instanceof PackedObjectLoader); + assertEquals(o.type, or.getType()); + assertEquals(o.rawSize, or.getRawSize()); + assertEquals(o.offset, ((PackedObjectLoader) or).getObjectOffset()); + } + } + + private class TestObject { + ObjectId id; + + int type; + + int rawSize; + + long offset; + + void setType(final String typeStr) throws CorruptObjectException { + final byte[] typeRaw = Constants.encode(typeStr + " "); + final MutableInteger ptr = new MutableInteger(); + type = Constants.decodeTypeString(id, typeRaw, (byte) ' ', ptr); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java new file mode 100644 index 0000000000..9e093c85bd --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WindowCacheReconfigureTest.java @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +public class WindowCacheReconfigureTest extends RepositoryTestCase { + public void testConfigureCache_PackedGitLimit_0() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitLimit(0); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitLimit = 0"); + } catch (IllegalArgumentException e) { + // + } + } + + public void testConfigureCache_PackedGitWindowSize_0() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitWindowSize(0); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitWindowSize = 0"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid window size", e.getMessage()); + } + } + + public void testConfigureCache_PackedGitWindowSize_512() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitWindowSize(512); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitWindowSize = 512"); + } catch (IllegalArgumentException e) { + assertEquals("Invalid window size", e.getMessage()); + } + } + + public void testConfigureCache_PackedGitWindowSize_4097() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitWindowSize(4097); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitWindowSize = 4097"); + } catch (IllegalArgumentException e) { + assertEquals("Window size must be power of 2", e.getMessage()); + } + } + + public void testConfigureCache_PackedGitOpenFiles_0() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitOpenFiles(0); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitOpenFiles = 0"); + } catch (IllegalArgumentException e) { + assertEquals("Open files must be >= 1", e.getMessage()); + } + } + + public void testConfigureCache_PackedGitWindowSizeAbovePackedGitLimit() { + try { + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitLimit(1024); + cfg.setPackedGitWindowSize(8192); + WindowCache.reconfigure(cfg); + fail("incorrectly permitted PackedGitWindowSize > PackedGitLimit"); + } catch (IllegalArgumentException e) { + assertEquals("Window size must be < limit", e.getMessage()); + } + } + + public void testConfigureCache_Limits1() { + // This test is just to force coverage over some lower bounds for + // the table. We don't want the table to wind up with too small + // of a size. This is highly dependent upon the table allocation + // algorithm actually implemented in WindowCache. + // + final WindowCacheConfig cfg = new WindowCacheConfig(); + cfg.setPackedGitLimit(6 * 4096 / 5); + cfg.setPackedGitWindowSize(4096); + WindowCache.reconfigure(cfg); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckoutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckoutTest.java new file mode 100644 index 0000000000..2599468faa --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/WorkDirCheckoutTest.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2007, Dave Watson <dwatson@mimvista.com> + * Copyright (C) 2006, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; + +import org.eclipse.jgit.errors.CheckoutConflictException; + +public class WorkDirCheckoutTest extends RepositoryTestCase { + public void testFindingConflicts() throws IOException { + GitIndex index = new GitIndex(db); + index.add(trash, writeTrashFile("bar", "bar")); + index.add(trash, writeTrashFile("foo/bar/baz/qux", "foo/bar")); + recursiveDelete(new File(trash, "bar")); + recursiveDelete(new File(trash, "foo")); + writeTrashFile("bar/baz/qux/foo", "another nasty one"); + writeTrashFile("foo", "troublesome little bugger"); + + WorkDirCheckout workDirCheckout = new WorkDirCheckout(db, trash, index, + index); + workDirCheckout.prescanOneTree(); + ArrayList<String> conflictingEntries = workDirCheckout + .getConflicts(); + ArrayList<String> removedEntries = workDirCheckout.getRemoved(); + assertEquals("bar/baz/qux/foo", conflictingEntries.get(0)); + assertEquals("foo", conflictingEntries.get(1)); + + GitIndex index2 = new GitIndex(db); + recursiveDelete(new File(trash, "bar")); + recursiveDelete(new File(trash, "foo")); + + index2.add(trash, writeTrashFile("bar/baz/qux/foo", "bar")); + index2.add(trash, writeTrashFile("foo", "lalala")); + + workDirCheckout = new WorkDirCheckout(db, trash, index2, index); + workDirCheckout.prescanOneTree(); + + conflictingEntries = workDirCheckout.getConflicts(); + removedEntries = workDirCheckout.getRemoved(); + assertTrue(conflictingEntries.isEmpty()); + assertTrue(removedEntries.contains("bar/baz/qux/foo")); + assertTrue(removedEntries.contains("foo")); + } + + public void testCheckingOutWithConflicts() throws IOException { + GitIndex index = new GitIndex(db); + index.add(trash, writeTrashFile("bar", "bar")); + index.add(trash, writeTrashFile("foo/bar/baz/qux", "foo/bar")); + recursiveDelete(new File(trash, "bar")); + recursiveDelete(new File(trash, "foo")); + writeTrashFile("bar/baz/qux/foo", "another nasty one"); + writeTrashFile("foo", "troublesome little bugger"); + + try { + WorkDirCheckout workDirCheckout = new WorkDirCheckout(db, trash, + index, index); + workDirCheckout.checkout(); + fail("Should have thrown exception"); + } catch (CheckoutConflictException e) { + // all is well + } + + WorkDirCheckout workDirCheckout = new WorkDirCheckout(db, trash, index, + index); + workDirCheckout.setFailOnConflict(false); + workDirCheckout.checkout(); + + assertTrue(new File(trash, "bar").isFile()); + assertTrue(new File(trash, "foo/bar/baz/qux").isFile()); + + GitIndex index2 = new GitIndex(db); + recursiveDelete(new File(trash, "bar")); + recursiveDelete(new File(trash, "foo")); + index2.add(trash, writeTrashFile("bar/baz/qux/foo", "bar")); + writeTrashFile("bar/baz/qux/bar", "evil? I thought it said WEEVIL!"); + index2.add(trash, writeTrashFile("foo", "lalala")); + + workDirCheckout = new WorkDirCheckout(db, trash, index2, index); + workDirCheckout.setFailOnConflict(false); + workDirCheckout.checkout(); + + assertTrue(new File(trash, "bar").isFile()); + assertTrue(new File(trash, "foo/bar/baz/qux").isFile()); + assertNotNull(index2.getEntry("bar")); + assertNotNull(index2.getEntry("foo/bar/baz/qux")); + assertNull(index2.getEntry("bar/baz/qux/foo")); + assertNull(index2.getEntry("foo")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java new file mode 100644 index 0000000000..eef32b9276 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/XInputStream.java @@ -0,0 +1,88 @@ +/* + * Copyright (C) 2006-2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.lib; + +import java.io.BufferedInputStream; +import java.io.EOFException; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jgit.util.NB; + +class XInputStream extends BufferedInputStream { + private final byte[] intbuf = new byte[8]; + + XInputStream(final InputStream s) { + super(s); + } + + synchronized byte[] readFully(final int len) throws IOException { + final byte[] b = new byte[len]; + readFully(b, 0, len); + return b; + } + + synchronized void readFully(final byte[] b, int o, int len) + throws IOException { + int r; + while (len > 0 && (r = read(b, o, len)) > 0) { + o += r; + len -= r; + } + if (len > 0) + throw new EOFException(); + } + + int readUInt8() throws IOException { + final int r = read(); + if (r < 0) + throw new EOFException(); + return r; + } + + long readUInt32() throws IOException { + readFully(intbuf, 0, 4); + return NB.decodeUInt32(intbuf, 0); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/empty.gitindex.dat b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/empty.gitindex.dat Binary files differnew file mode 100644 index 0000000000..3330d716f1 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/empty.gitindex.dat diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/sorttest.gitindex.dat b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/sorttest.gitindex.dat Binary files differnew file mode 100644 index 0000000000..217f2e3811 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/lib/sorttest.gitindex.dat diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java new file mode 100644 index 0000000000..42e653be37 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/CherryPickTest.java @@ -0,0 +1,156 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Robin Rosenberg + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.merge; + +import java.io.ByteArrayInputStream; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.Commit; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; + +public class CherryPickTest extends RepositoryTestCase { + public void testPick() throws Exception { + // B---O + // \----P---T + // + // Cherry-pick "T" onto "O". This shouldn't introduce "p-fail", which + // was created by "P", nor should it modify "a", which was done by "P". + // + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeP = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder p = treeP.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("a", FileMode.REGULAR_FILE)); + + o.add(makeEntry("a", FileMode.REGULAR_FILE)); + o.add(makeEntry("o", FileMode.REGULAR_FILE)); + + p.add(makeEntry("a", FileMode.REGULAR_FILE, "q")); + p.add(makeEntry("p-fail", FileMode.REGULAR_FILE)); + + t.add(makeEntry("a", FileMode.REGULAR_FILE)); + t.add(makeEntry("t", FileMode.REGULAR_FILE)); + + b.finish(); + o.finish(); + p.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId B = commit(ow, treeB, new ObjectId[] {}); + final ObjectId O = commit(ow, treeO, new ObjectId[] { B }); + final ObjectId P = commit(ow, treeP, new ObjectId[] { B }); + final ObjectId T = commit(ow, treeT, new ObjectId[] { P }); + + ThreeWayMerger twm = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + twm.setBase(P); + boolean merge = twm.merge(new ObjectId[] { O, T }); + assertTrue(merge); + + final TreeWalk tw = new TreeWalk(db); + tw.setRecursive(true); + tw.reset(twm.getResultTreeId()); + + assertTrue(tw.next()); + assertEquals("a", tw.getPathString()); + assertCorrectId(treeO, tw); + + assertTrue(tw.next()); + assertEquals("o", tw.getPathString()); + assertCorrectId(treeO, tw); + + assertTrue(tw.next()); + assertEquals("t", tw.getPathString()); + assertCorrectId(treeT, tw); + + assertFalse(tw.next()); + } + + private void assertCorrectId(final DirCache treeT, final TreeWalk tw) { + assertEquals(treeT.getEntry(tw.getPathString()).getObjectId(), tw + .getObjectId(0)); + } + + private ObjectId commit(final ObjectWriter ow, final DirCache treeB, + final ObjectId[] parentIds) throws Exception { + final Commit c = new Commit(db); + c.setTreeId(treeB.writeTree(ow)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setCommitter(c.getAuthor()); + c.setParentIds(parentIds); + c.setMessage("Tree " + c.getTreeId().name()); + return ow.writeCommit(c); + } + + private DirCacheEntry makeEntry(final String path, final FileMode mode) + throws Exception { + return makeEntry(path, mode, path); + } + + private DirCacheEntry makeEntry(final String path, final FileMode mode, + final String content) throws Exception { + final DirCacheEntry ent = new DirCacheEntry(path); + ent.setFileMode(mode); + final byte[] contentBytes = Constants.encode(content); + ent.setObjectId(new ObjectWriter(db).computeBlobSha1( + contentBytes.length, new ByteArrayInputStream(contentBytes))); + return ent; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java new file mode 100644 index 0000000000..0e50220067 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/merge/SimpleMergeTest.java @@ -0,0 +1,391 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Robin Rosenberg + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.merge; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.Commit; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; + +public class SimpleMergeTest extends RepositoryTestCase { + + public void testOurs() throws IOException { + Merger ourMerger = MergeStrategy.OURS.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); + assertTrue(merge); + assertEquals(db.mapTree("a").getId(), ourMerger.getResultTreeId()); + } + + public void testTheirs() throws IOException { + Merger ourMerger = MergeStrategy.THEIRS.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); + assertTrue(merge); + assertEquals(db.mapTree("c").getId(), ourMerger.getResultTreeId()); + } + + public void testTrivialTwoWay() throws IOException { + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c") }); + assertTrue(merge); + assertEquals("02ba32d3649e510002c21651936b7077aa75ffa9",ourMerger.getResultTreeId().name()); + } + + public void testTrivialTwoWay_disjointhistories() throws IOException { + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a"), db.resolve("c~4") }); + assertTrue(merge); + assertEquals("86265c33b19b2be71bdd7b8cb95823f2743d03a8",ourMerger.getResultTreeId().name()); + } + + public void testTrivialTwoWay_ok() throws IOException { + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("a^0^0^0"), db.resolve("a^0^0^1") }); + assertTrue(merge); + assertEquals(db.mapTree("a^0^0").getId(), ourMerger.getResultTreeId()); + } + + public void testTrivialTwoWay_conflict() throws IOException { + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { db.resolve("f"), db.resolve("g") }); + assertFalse(merge); + } + + public void testTrivialTwoWay_validSubtreeSort() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("libelf-po/a", FileMode.REGULAR_FILE)); + b.add(makeEntry("libelf/c", FileMode.REGULAR_FILE)); + + o.add(makeEntry("Makefile", FileMode.REGULAR_FILE)); + o.add(makeEntry("libelf-po/a", FileMode.REGULAR_FILE)); + o.add(makeEntry("libelf/c", FileMode.REGULAR_FILE)); + + t.add(makeEntry("libelf-po/a", FileMode.REGULAR_FILE)); + t.add(makeEntry("libelf/c", FileMode.REGULAR_FILE, "blah")); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertTrue(merge); + + final TreeWalk tw = new TreeWalk(db); + tw.setRecursive(true); + tw.reset(ourMerger.getResultTreeId()); + + assertTrue(tw.next()); + assertEquals("Makefile", tw.getPathString()); + assertCorrectId(treeO, tw); + + assertTrue(tw.next()); + assertEquals("libelf-po/a", tw.getPathString()); + assertCorrectId(treeO, tw); + + assertTrue(tw.next()); + assertEquals("libelf/c", tw.getPathString()); + assertCorrectId(treeT, tw); + + assertFalse(tw.next()); + } + + public void testTrivialTwoWay_concurrentSubtreeChange() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + b.add(makeEntry("d/t", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d/o", FileMode.REGULAR_FILE, "o !")); + o.add(makeEntry("d/t", FileMode.REGULAR_FILE)); + + t.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + t.add(makeEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertTrue(merge); + + final TreeWalk tw = new TreeWalk(db); + tw.setRecursive(true); + tw.reset(ourMerger.getResultTreeId()); + + assertTrue(tw.next()); + assertEquals("d/o", tw.getPathString()); + assertCorrectId(treeO, tw); + + assertTrue(tw.next()); + assertEquals("d/t", tw.getPathString()); + assertCorrectId(treeT, tw); + + assertFalse(tw.next()); + } + + public void testTrivialTwoWay_conflictSubtreeChange() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + b.add(makeEntry("d/t", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + o.add(makeEntry("d/t", FileMode.REGULAR_FILE, "o !")); + + t.add(makeEntry("d/o", FileMode.REGULAR_FILE, "t !")); + t.add(makeEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + public void testTrivialTwoWay_leftDFconflict1() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + b.add(makeEntry("d/t", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d", FileMode.REGULAR_FILE)); + + t.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + t.add(makeEntry("d/t", FileMode.REGULAR_FILE, "t !")); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + public void testTrivialTwoWay_rightDFconflict1() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + b.add(makeEntry("d/t", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + o.add(makeEntry("d/t", FileMode.REGULAR_FILE, "o !")); + + t.add(makeEntry("d", FileMode.REGULAR_FILE)); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + public void testTrivialTwoWay_leftDFconflict2() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d", FileMode.REGULAR_FILE, "o !")); + + t.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + public void testTrivialTwoWay_rightDFconflict2() throws Exception { + final DirCache treeB = DirCache.read(db); + final DirCache treeO = DirCache.read(db); + final DirCache treeT = DirCache.read(db); + { + final DirCacheBuilder b = treeB.builder(); + final DirCacheBuilder o = treeO.builder(); + final DirCacheBuilder t = treeT.builder(); + + b.add(makeEntry("d", FileMode.REGULAR_FILE)); + + o.add(makeEntry("d/o", FileMode.REGULAR_FILE)); + + t.add(makeEntry("d", FileMode.REGULAR_FILE, "t !")); + + b.finish(); + o.finish(); + t.finish(); + } + + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId b = commit(ow, treeB, new ObjectId[] {}); + final ObjectId o = commit(ow, treeO, new ObjectId[] { b }); + final ObjectId t = commit(ow, treeT, new ObjectId[] { b }); + + Merger ourMerger = MergeStrategy.SIMPLE_TWO_WAY_IN_CORE.newMerger(db); + boolean merge = ourMerger.merge(new ObjectId[] { o, t }); + assertFalse(merge); + } + + private void assertCorrectId(final DirCache treeT, final TreeWalk tw) { + assertEquals(treeT.getEntry(tw.getPathString()).getObjectId(), tw + .getObjectId(0)); + } + + private ObjectId commit(final ObjectWriter ow, final DirCache treeB, + final ObjectId[] parentIds) throws Exception { + final Commit c = new Commit(db); + c.setTreeId(treeB.writeTree(ow)); + c.setAuthor(new PersonIdent("A U Thor", "a.u.thor", 1L, 0)); + c.setCommitter(c.getAuthor()); + c.setParentIds(parentIds); + c.setMessage("Tree " + c.getTreeId().name()); + return ow.writeCommit(c); + } + + private DirCacheEntry makeEntry(final String path, final FileMode mode) + throws Exception { + return makeEntry(path, mode, path); + } + + private DirCacheEntry makeEntry(final String path, final FileMode mode, + final String content) throws Exception { + final DirCacheEntry ent = new DirCacheEntry(path); + ent.setFileMode(mode); + final byte[] contentBytes = Constants.encode(content); + ent.setObjectId(new ObjectWriter(db).computeBlobSha1( + contentBytes.length, new ByteArrayInputStream(contentBytes))); + return ent; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/EditListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/EditListTest.java new file mode 100644 index 0000000000..c265bc097b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/EditListTest.java @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.diff.Edit; +import org.eclipse.jgit.diff.EditList; + +public class EditListTest extends TestCase { + public void testHunkHeader() throws IOException { + final Patch p = parseTestPatchFile("testGetText_BothISO88591.patch"); + final FileHeader fh = p.getFiles().get(0); + + final EditList list0 = fh.getHunks().get(0).toEditList(); + assertEquals(1, list0.size()); + assertEquals(new Edit(4 - 1, 5 - 1, 4 - 1, 5 - 1), list0.get(0)); + + final EditList list1 = fh.getHunks().get(1).toEditList(); + assertEquals(1, list1.size()); + assertEquals(new Edit(16 - 1, 17 - 1, 16 - 1, 17 - 1), list1.get(0)); + } + + public void testFileHeader() throws IOException { + final Patch p = parseTestPatchFile("testGetText_BothISO88591.patch"); + final FileHeader fh = p.getFiles().get(0); + final EditList e = fh.toEditList(); + assertEquals(2, e.size()); + assertEquals(new Edit(4 - 1, 5 - 1, 4 - 1, 5 - 1), e.get(0)); + assertEquals(new Edit(16 - 1, 17 - 1, 16 - 1, 17 - 1), e.get(1)); + } + + public void testTypes() throws IOException { + final Patch p = parseTestPatchFile("testEditList_Types.patch"); + final FileHeader fh = p.getFiles().get(0); + final EditList e = fh.toEditList(); + assertEquals(3, e.size()); + assertEquals(new Edit(3 - 1, 3 - 1, 3 - 1, 4 - 1), e.get(0)); + assertEquals(new Edit(17 - 1, 19 - 1, 18 - 1, 18 - 1), e.get(1)); + assertEquals(new Edit(23 - 1, 25 - 1, 22 - 1, 28 - 1), e.get(2)); + } + + private Patch parseTestPatchFile(final String patchFile) throws IOException { + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/FileHeaderTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/FileHeaderTest.java new file mode 100644 index 0000000000..8d9e302a82 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/FileHeaderTest.java @@ -0,0 +1,434 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; + +public class FileHeaderTest extends TestCase { + public void testParseGitFileName_Empty() { + final FileHeader fh = data(""); + assertEquals(-1, fh.parseGitFileName(0, fh.buf.length)); + assertNotNull(fh.getHunks()); + assertTrue(fh.getHunks().isEmpty()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_NoLF() { + final FileHeader fh = data("a/ b/"); + assertEquals(-1, fh.parseGitFileName(0, fh.buf.length)); + } + + public void testParseGitFileName_NoSecondLine() { + final FileHeader fh = data("\n"); + assertEquals(-1, fh.parseGitFileName(0, fh.buf.length)); + } + + public void testParseGitFileName_EmptyHeader() { + final FileHeader fh = data("\n\n"); + assertEquals(1, fh.parseGitFileName(0, fh.buf.length)); + } + + public void testParseGitFileName_Foo() { + final String name = "foo"; + final FileHeader fh = header(name); + assertEquals(gitLine(name).length(), fh.parseGitFileName(0, + fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_FailFooBar() { + final FileHeader fh = data("a/foo b/bar\n-"); + assertTrue(fh.parseGitFileName(0, fh.buf.length) > 0); + assertNull(fh.getOldName()); + assertNull(fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_FooSpBar() { + final String name = "foo bar"; + final FileHeader fh = header(name); + assertEquals(gitLine(name).length(), fh.parseGitFileName(0, + fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_DqFooTabBar() { + final String name = "foo\tbar"; + final String dqName = "foo\\tbar"; + final FileHeader fh = dqHeader(dqName); + assertEquals(dqGitLine(dqName).length(), fh.parseGitFileName(0, + fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_DqFooSpLfNulBar() { + final String name = "foo \n\0bar"; + final String dqName = "foo \\n\\0bar"; + final FileHeader fh = dqHeader(dqName); + assertEquals(dqGitLine(dqName).length(), fh.parseGitFileName(0, + fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_SrcFooC() { + final String name = "src/foo/bar/argh/code.c"; + final FileHeader fh = header(name); + assertEquals(gitLine(name).length(), fh.parseGitFileName(0, + fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseGitFileName_SrcFooCNonStandardPrefix() { + final String name = "src/foo/bar/argh/code.c"; + final String header = "project-v-1.0/" + name + " mydev/" + name + "\n"; + final FileHeader fh = data(header + "-"); + assertEquals(header.length(), fh.parseGitFileName(0, fh.buf.length)); + assertEquals(name, fh.getOldName()); + assertSame(fh.getOldName(), fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + } + + public void testParseUnicodeName_NewFile() { + final FileHeader fh = data("diff --git \"a/\\303\\205ngstr\\303\\266m\" \"b/\\303\\205ngstr\\303\\266m\"\n" + + "new file mode 100644\n" + + "index 0000000..7898192\n" + + "--- /dev/null\n" + + "+++ \"b/\\303\\205ngstr\\303\\266m\"\n" + + "@@ -0,0 +1 @@\n" + "+a\n"); + assertParse(fh); + + assertEquals("/dev/null", fh.getOldName()); + assertSame(FileHeader.DEV_NULL, fh.getOldName()); + assertEquals("\u00c5ngstr\u00f6m", fh.getNewName()); + + assertSame(FileHeader.ChangeType.ADD, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertSame(FileMode.MISSING, fh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + + assertEquals("0000000", fh.getOldId().name()); + assertEquals("7898192", fh.getNewId().name()); + assertEquals(0, fh.getScore()); + } + + public void testParseUnicodeName_DeleteFile() { + final FileHeader fh = data("diff --git \"a/\\303\\205ngstr\\303\\266m\" \"b/\\303\\205ngstr\\303\\266m\"\n" + + "deleted file mode 100644\n" + + "index 7898192..0000000\n" + + "--- \"a/\\303\\205ngstr\\303\\266m\"\n" + + "+++ /dev/null\n" + + "@@ -1 +0,0 @@\n" + "-a\n"); + assertParse(fh); + + assertEquals("\u00c5ngstr\u00f6m", fh.getOldName()); + assertEquals("/dev/null", fh.getNewName()); + assertSame(FileHeader.DEV_NULL, fh.getNewName()); + + assertSame(FileHeader.ChangeType.DELETE, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertSame(FileMode.REGULAR_FILE, fh.getOldMode()); + assertSame(FileMode.MISSING, fh.getNewMode()); + + assertEquals("7898192", fh.getOldId().name()); + assertEquals("0000000", fh.getNewId().name()); + assertEquals(0, fh.getScore()); + } + + public void testParseModeChange() { + final FileHeader fh = data("diff --git a/a b b/a b\n" + + "old mode 100644\n" + "new mode 100755\n"); + assertParse(fh); + assertEquals("a b", fh.getOldName()); + assertEquals("a b", fh.getNewName()); + + assertSame(FileHeader.ChangeType.MODIFY, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertNull(fh.getOldId()); + assertNull(fh.getNewId()); + + assertSame(FileMode.REGULAR_FILE, fh.getOldMode()); + assertSame(FileMode.EXECUTABLE_FILE, fh.getNewMode()); + assertEquals(0, fh.getScore()); + } + + public void testParseRename100_NewStyle() { + final FileHeader fh = data("diff --git a/a b/ c/\\303\\205ngstr\\303\\266m\n" + + "similarity index 100%\n" + + "rename from a\n" + + "rename to \" c/\\303\\205ngstr\\303\\266m\"\n"); + int ptr = fh.parseGitFileName(0, fh.buf.length); + assertTrue(ptr > 0); + assertNull(fh.getOldName()); // can't parse names on a rename + assertNull(fh.getNewName()); + + ptr = fh.parseGitHeaders(ptr, fh.buf.length); + assertTrue(ptr > 0); + + assertEquals("a", fh.getOldName()); + assertEquals(" c/\u00c5ngstr\u00f6m", fh.getNewName()); + + assertSame(FileHeader.ChangeType.RENAME, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertNull(fh.getOldId()); + assertNull(fh.getNewId()); + + assertNull(fh.getOldMode()); + assertNull(fh.getNewMode()); + + assertEquals(100, fh.getScore()); + } + + public void testParseRename100_OldStyle() { + final FileHeader fh = data("diff --git a/a b/ c/\\303\\205ngstr\\303\\266m\n" + + "similarity index 100%\n" + + "rename old a\n" + + "rename new \" c/\\303\\205ngstr\\303\\266m\"\n"); + int ptr = fh.parseGitFileName(0, fh.buf.length); + assertTrue(ptr > 0); + assertNull(fh.getOldName()); // can't parse names on a rename + assertNull(fh.getNewName()); + + ptr = fh.parseGitHeaders(ptr, fh.buf.length); + assertTrue(ptr > 0); + + assertEquals("a", fh.getOldName()); + assertEquals(" c/\u00c5ngstr\u00f6m", fh.getNewName()); + + assertSame(FileHeader.ChangeType.RENAME, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertNull(fh.getOldId()); + assertNull(fh.getNewId()); + + assertNull(fh.getOldMode()); + assertNull(fh.getNewMode()); + + assertEquals(100, fh.getScore()); + } + + public void testParseCopy100() { + final FileHeader fh = data("diff --git a/a b/ c/\\303\\205ngstr\\303\\266m\n" + + "similarity index 100%\n" + + "copy from a\n" + + "copy to \" c/\\303\\205ngstr\\303\\266m\"\n"); + int ptr = fh.parseGitFileName(0, fh.buf.length); + assertTrue(ptr > 0); + assertNull(fh.getOldName()); // can't parse names on a copy + assertNull(fh.getNewName()); + + ptr = fh.parseGitHeaders(ptr, fh.buf.length); + assertTrue(ptr > 0); + + assertEquals("a", fh.getOldName()); + assertEquals(" c/\u00c5ngstr\u00f6m", fh.getNewName()); + + assertSame(FileHeader.ChangeType.COPY, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.hasMetaDataChanges()); + + assertNull(fh.getOldId()); + assertNull(fh.getNewId()); + + assertNull(fh.getOldMode()); + assertNull(fh.getNewMode()); + + assertEquals(100, fh.getScore()); + } + + public void testParseFullIndexLine_WithMode() { + final String oid = "78981922613b2afb6025042ff6bd878ac1994e85"; + final String nid = "61780798228d17af2d34fce4cfbdf35556832472"; + final FileHeader fh = data("diff --git a/a b/a\n" + "index " + oid + + ".." + nid + " 100644\n" + "--- a/a\n" + "+++ b/a\n"); + assertParse(fh); + + assertEquals("a", fh.getOldName()); + assertEquals("a", fh.getNewName()); + + assertSame(FileMode.REGULAR_FILE, fh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + assertFalse(fh.hasMetaDataChanges()); + + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + + assertTrue(fh.getOldId().isComplete()); + assertTrue(fh.getNewId().isComplete()); + + assertEquals(ObjectId.fromString(oid), fh.getOldId().toObjectId()); + assertEquals(ObjectId.fromString(nid), fh.getNewId().toObjectId()); + } + + public void testParseFullIndexLine_NoMode() { + final String oid = "78981922613b2afb6025042ff6bd878ac1994e85"; + final String nid = "61780798228d17af2d34fce4cfbdf35556832472"; + final FileHeader fh = data("diff --git a/a b/a\n" + "index " + oid + + ".." + nid + "\n" + "--- a/a\n" + "+++ b/a\n"); + assertParse(fh); + + assertEquals("a", fh.getOldName()); + assertEquals("a", fh.getNewName()); + assertFalse(fh.hasMetaDataChanges()); + + assertNull(fh.getOldMode()); + assertNull(fh.getNewMode()); + + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + + assertTrue(fh.getOldId().isComplete()); + assertTrue(fh.getNewId().isComplete()); + + assertEquals(ObjectId.fromString(oid), fh.getOldId().toObjectId()); + assertEquals(ObjectId.fromString(nid), fh.getNewId().toObjectId()); + } + + public void testParseAbbrIndexLine_WithMode() { + final int a = 7; + final String oid = "78981922613b2afb6025042ff6bd878ac1994e85"; + final String nid = "61780798228d17af2d34fce4cfbdf35556832472"; + final FileHeader fh = data("diff --git a/a b/a\n" + "index " + + oid.substring(0, a - 1) + ".." + nid.substring(0, a - 1) + + " 100644\n" + "--- a/a\n" + "+++ b/a\n"); + assertParse(fh); + + assertEquals("a", fh.getOldName()); + assertEquals("a", fh.getNewName()); + + assertSame(FileMode.REGULAR_FILE, fh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + assertFalse(fh.hasMetaDataChanges()); + + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + + assertFalse(fh.getOldId().isComplete()); + assertFalse(fh.getNewId().isComplete()); + + assertEquals(oid.substring(0, a - 1), fh.getOldId().name()); + assertEquals(nid.substring(0, a - 1), fh.getNewId().name()); + + assertTrue(ObjectId.fromString(oid).startsWith(fh.getOldId())); + assertTrue(ObjectId.fromString(nid).startsWith(fh.getNewId())); + } + + public void testParseAbbrIndexLine_NoMode() { + final int a = 7; + final String oid = "78981922613b2afb6025042ff6bd878ac1994e85"; + final String nid = "61780798228d17af2d34fce4cfbdf35556832472"; + final FileHeader fh = data("diff --git a/a b/a\n" + "index " + + oid.substring(0, a - 1) + ".." + nid.substring(0, a - 1) + + "\n" + "--- a/a\n" + "+++ b/a\n"); + assertParse(fh); + + assertEquals("a", fh.getOldName()); + assertEquals("a", fh.getNewName()); + + assertNull(fh.getOldMode()); + assertNull(fh.getNewMode()); + assertFalse(fh.hasMetaDataChanges()); + + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + + assertFalse(fh.getOldId().isComplete()); + assertFalse(fh.getNewId().isComplete()); + + assertEquals(oid.substring(0, a - 1), fh.getOldId().name()); + assertEquals(nid.substring(0, a - 1), fh.getNewId().name()); + + assertTrue(ObjectId.fromString(oid).startsWith(fh.getOldId())); + assertTrue(ObjectId.fromString(nid).startsWith(fh.getNewId())); + } + + private static void assertParse(final FileHeader fh) { + int ptr = fh.parseGitFileName(0, fh.buf.length); + assertTrue(ptr > 0); + ptr = fh.parseGitHeaders(ptr, fh.buf.length); + assertTrue(ptr > 0); + } + + private static FileHeader data(final String in) { + return new FileHeader(Constants.encodeASCII(in), 0); + } + + private static FileHeader header(final String path) { + return data(gitLine(path) + "--- " + path + "\n"); + } + + private static String gitLine(final String path) { + return "a/" + path + " b/" + path + "\n"; + } + + private static FileHeader dqHeader(final String path) { + return data(dqGitLine(path) + "--- " + path + "\n"); + } + + private static String dqGitLine(final String path) { + return "\"a/" + path + "\" \"b/" + path + "\"\n"; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/GetTextTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/GetTextTest.java new file mode 100644 index 0000000000..8d06987fde --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/GetTextTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; + +import junit.framework.TestCase; + +public class GetTextTest extends TestCase { + public void testGetText_BothISO88591() throws IOException { + final Charset cs = Charset.forName("ISO-8859-1"); + final Patch p = parseTestPatchFile(); + assertTrue(p.getErrors().isEmpty()); + assertEquals(1, p.getFiles().size()); + final FileHeader fh = p.getFiles().get(0); + assertEquals(2, fh.getHunks().size()); + assertEquals(readTestPatchFile(cs), fh.getScriptText(cs, cs)); + } + + public void testGetText_NoBinary() throws IOException { + final Charset cs = Charset.forName("ISO-8859-1"); + final Patch p = parseTestPatchFile(); + assertTrue(p.getErrors().isEmpty()); + assertEquals(1, p.getFiles().size()); + final FileHeader fh = p.getFiles().get(0); + assertEquals(0, fh.getHunks().size()); + assertEquals(readTestPatchFile(cs), fh.getScriptText(cs, cs)); + } + + public void testGetText_Convert() throws IOException { + final Charset csOld = Charset.forName("ISO-8859-1"); + final Charset csNew = Charset.forName("UTF-8"); + final Patch p = parseTestPatchFile(); + assertTrue(p.getErrors().isEmpty()); + assertEquals(1, p.getFiles().size()); + final FileHeader fh = p.getFiles().get(0); + assertEquals(2, fh.getHunks().size()); + + // Read the original file as ISO-8859-1 and fix up the one place + // where we changed the character encoding. That makes the exp + // string match what we really expect to get back. + // + String exp = readTestPatchFile(csOld); + exp = exp.replace("\303\205ngstr\303\266m", "\u00c5ngstr\u00f6m"); + + assertEquals(exp, fh.getScriptText(csOld, csNew)); + } + + public void testGetText_DiffCc() throws IOException { + final Charset csOld = Charset.forName("ISO-8859-1"); + final Charset csNew = Charset.forName("UTF-8"); + final Patch p = parseTestPatchFile(); + assertTrue(p.getErrors().isEmpty()); + assertEquals(1, p.getFiles().size()); + final CombinedFileHeader fh = (CombinedFileHeader) p.getFiles().get(0); + assertEquals(1, fh.getHunks().size()); + + // Read the original file as ISO-8859-1 and fix up the one place + // where we changed the character encoding. That makes the exp + // string match what we really expect to get back. + // + String exp = readTestPatchFile(csOld); + exp = exp.replace("\303\205ngstr\303\266m", "\u00c5ngstr\u00f6m"); + + assertEquals(exp, fh + .getScriptText(new Charset[] { csNew, csOld, csNew })); + } + + private Patch parseTestPatchFile() throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } + + private String readTestPatchFile(final Charset cs) throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final InputStreamReader r = new InputStreamReader(in, cs); + char[] tmp = new char[2048]; + final StringBuilder s = new StringBuilder(); + int n; + while ((n = r.read(tmp)) > 0) + s.append(tmp, 0, n); + return s.toString(); + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java new file mode 100644 index 0000000000..f2bae6eb19 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcErrorTest.java @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +public class PatchCcErrorTest extends TestCase { + public void testError_CcTruncatedOld() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertEquals(3, p.getErrors().size()); + { + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals( + "Truncated hunk, at least 1 lines is missing for ancestor 1", + e.getMessage()); + assertEquals(346, e.getOffset()); + assertTrue(e.getLineText().startsWith( + "@@@ -55,12 -163,13 +163,15 @@@ public ")); + } + { + final FormatError e = p.getErrors().get(1); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals( + "Truncated hunk, at least 2 lines is missing for ancestor 2", + e.getMessage()); + assertEquals(346, e.getOffset()); + assertTrue(e.getLineText().startsWith( + "@@@ -55,12 -163,13 +163,15 @@@ public ")); + } + { + final FormatError e = p.getErrors().get(2); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals("Truncated hunk, at least 3 new lines is missing", e + .getMessage()); + assertEquals(346, e.getOffset()); + assertTrue(e.getLineText().startsWith( + "@@@ -55,12 -163,13 +163,15 @@@ public ")); + } + } + + private Patch parseTestPatchFile() throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcTest.java new file mode 100644 index 0000000000..e97d373d9a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchCcTest.java @@ -0,0 +1,206 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jgit.lib.FileMode; + +import junit.framework.TestCase; + +public class PatchCcTest extends TestCase { + public void testParse_OneFileCc() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final CombinedFileHeader cfh = (CombinedFileHeader) p.getFiles().get(0); + + assertEquals("org.spearce.egit.ui/src/org/spearce/egit/ui/UIText.java", + cfh.getNewName()); + assertEquals(cfh.getNewName(), cfh.getOldName()); + + assertEquals(98, cfh.startOffset); + + assertEquals(2, cfh.getParentCount()); + assertSame(cfh.getOldId(0), cfh.getOldId()); + assertEquals("169356b", cfh.getOldId(0).name()); + assertEquals("dd8c317", cfh.getOldId(1).name()); + assertEquals("fd85931", cfh.getNewId().name()); + + assertSame(cfh.getOldMode(0), cfh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, cfh.getOldMode(0)); + assertSame(FileMode.REGULAR_FILE, cfh.getOldMode(1)); + assertSame(FileMode.EXECUTABLE_FILE, cfh.getNewMode()); + assertSame(FileHeader.ChangeType.MODIFY, cfh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, cfh.getPatchType()); + + assertEquals(1, cfh.getHunks().size()); + { + final CombinedHunkHeader h = cfh.getHunks().get(0); + + assertSame(cfh, h.getFileHeader()); + assertEquals(346, h.startOffset); + assertEquals(764, h.endOffset); + + assertSame(h.getOldImage(0), h.getOldImage()); + assertSame(cfh.getOldId(0), h.getOldImage(0).getId()); + assertSame(cfh.getOldId(1), h.getOldImage(1).getId()); + + assertEquals(55, h.getOldImage(0).getStartLine()); + assertEquals(12, h.getOldImage(0).getLineCount()); + assertEquals(3, h.getOldImage(0).getLinesAdded()); + assertEquals(0, h.getOldImage(0).getLinesDeleted()); + + assertEquals(163, h.getOldImage(1).getStartLine()); + assertEquals(13, h.getOldImage(1).getLineCount()); + assertEquals(2, h.getOldImage(1).getLinesAdded()); + assertEquals(0, h.getOldImage(1).getLinesDeleted()); + + assertEquals(163, h.getNewStartLine()); + assertEquals(15, h.getNewLineCount()); + + assertEquals(10, h.getLinesContext()); + } + } + + public void testParse_CcNewFile() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final CombinedFileHeader cfh = (CombinedFileHeader) p.getFiles().get(0); + + assertSame(FileHeader.DEV_NULL, cfh.getOldName()); + assertEquals("d", cfh.getNewName()); + + assertEquals(187, cfh.startOffset); + + assertEquals(2, cfh.getParentCount()); + assertSame(cfh.getOldId(0), cfh.getOldId()); + assertEquals("0000000", cfh.getOldId(0).name()); + assertEquals("0000000", cfh.getOldId(1).name()); + assertEquals("4bcfe98", cfh.getNewId().name()); + + assertSame(cfh.getOldMode(0), cfh.getOldMode()); + assertSame(FileMode.MISSING, cfh.getOldMode(0)); + assertSame(FileMode.MISSING, cfh.getOldMode(1)); + assertSame(FileMode.REGULAR_FILE, cfh.getNewMode()); + assertSame(FileHeader.ChangeType.ADD, cfh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, cfh.getPatchType()); + + assertEquals(1, cfh.getHunks().size()); + { + final CombinedHunkHeader h = cfh.getHunks().get(0); + + assertSame(cfh, h.getFileHeader()); + assertEquals(273, h.startOffset); + assertEquals(300, h.endOffset); + + assertSame(h.getOldImage(0), h.getOldImage()); + assertSame(cfh.getOldId(0), h.getOldImage(0).getId()); + assertSame(cfh.getOldId(1), h.getOldImage(1).getId()); + + assertEquals(1, h.getOldImage(0).getStartLine()); + assertEquals(0, h.getOldImage(0).getLineCount()); + assertEquals(1, h.getOldImage(0).getLinesAdded()); + assertEquals(0, h.getOldImage(0).getLinesDeleted()); + + assertEquals(1, h.getOldImage(1).getStartLine()); + assertEquals(0, h.getOldImage(1).getLineCount()); + assertEquals(1, h.getOldImage(1).getLinesAdded()); + assertEquals(0, h.getOldImage(1).getLinesDeleted()); + + assertEquals(1, h.getNewStartLine()); + assertEquals(1, h.getNewLineCount()); + + assertEquals(0, h.getLinesContext()); + } + } + + public void testParse_CcDeleteFile() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final CombinedFileHeader cfh = (CombinedFileHeader) p.getFiles().get(0); + + assertEquals("a", cfh.getOldName()); + assertSame(FileHeader.DEV_NULL, cfh.getNewName()); + + assertEquals(187, cfh.startOffset); + + assertEquals(2, cfh.getParentCount()); + assertSame(cfh.getOldId(0), cfh.getOldId()); + assertEquals("7898192", cfh.getOldId(0).name()); + assertEquals("2e65efe", cfh.getOldId(1).name()); + assertEquals("0000000", cfh.getNewId().name()); + + assertSame(cfh.getOldMode(0), cfh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, cfh.getOldMode(0)); + assertSame(FileMode.REGULAR_FILE, cfh.getOldMode(1)); + assertSame(FileMode.MISSING, cfh.getNewMode()); + assertSame(FileHeader.ChangeType.DELETE, cfh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, cfh.getPatchType()); + + assertTrue(cfh.getHunks().isEmpty()); + } + + private Patch parseTestPatchFile() throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchErrorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchErrorTest.java new file mode 100644 index 0000000000..62a107130e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchErrorTest.java @@ -0,0 +1,180 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +public class PatchErrorTest extends TestCase { + public void testError_DisconnectedHunk() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + { + final FileHeader fh = p.getFiles().get(0); + assertEquals( + "org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java", + fh.getNewName()); + assertEquals(1, fh.getHunks().size()); + } + + assertEquals(1, p.getErrors().size()); + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals("Hunk disconnected from file", e.getMessage()); + assertEquals(18, e.getOffset()); + assertTrue(e.getLineText().startsWith("@@ -109,4 +109,11 @@ assert")); + } + + public void testError_TruncatedOld() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertEquals(1, p.getErrors().size()); + + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals("Truncated hunk, at least 1 old lines is missing", e + .getMessage()); + assertEquals(313, e.getOffset()); + assertTrue(e.getLineText().startsWith("@@ -236,9 +236,9 @@ protected ")); + } + + public void testError_TruncatedNew() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertEquals(1, p.getErrors().size()); + + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals("Truncated hunk, at least 1 new lines is missing", e + .getMessage()); + assertEquals(313, e.getOffset()); + assertTrue(e.getLineText().startsWith("@@ -236,9 +236,9 @@ protected ")); + } + + public void testError_BodyTooLong() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertEquals(1, p.getErrors().size()); + + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.WARNING, e.getSeverity()); + assertEquals("Hunk header 4:11 does not match body line count of 4:12", + e.getMessage()); + assertEquals(349, e.getOffset()); + assertTrue(e.getLineText().startsWith("@@ -109,4 +109,11 @@ assert")); + } + + public void testError_GarbageBetweenFiles() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(2, p.getFiles().size()); + { + final FileHeader fh = p.getFiles().get(0); + assertEquals( + "org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java", + fh.getNewName()); + assertEquals(1, fh.getHunks().size()); + } + { + final FileHeader fh = p.getFiles().get(1); + assertEquals( + "org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java", + fh.getNewName()); + assertEquals(1, fh.getHunks().size()); + } + + assertEquals(1, p.getErrors().size()); + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.WARNING, e.getSeverity()); + assertEquals("Unexpected hunk trailer", e.getMessage()); + assertEquals(926, e.getOffset()); + assertEquals("I AM NOT HERE\n", e.getLineText()); + } + + public void testError_GitBinaryNoForwardHunk() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(2, p.getFiles().size()); + { + final FileHeader fh = p.getFiles().get(0); + assertEquals("org.spearce.egit.ui/icons/toolbar/fetchd.png", fh + .getNewName()); + assertSame(FileHeader.PatchType.GIT_BINARY, fh.getPatchType()); + assertTrue(fh.getHunks().isEmpty()); + assertNull(fh.getForwardBinaryHunk()); + } + { + final FileHeader fh = p.getFiles().get(1); + assertEquals("org.spearce.egit.ui/icons/toolbar/fetche.png", fh + .getNewName()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertTrue(fh.getHunks().isEmpty()); + assertNull(fh.getForwardBinaryHunk()); + } + + assertEquals(1, p.getErrors().size()); + final FormatError e = p.getErrors().get(0); + assertSame(FormatError.Severity.ERROR, e.getSeverity()); + assertEquals("Missing forward-image in GIT binary patch", e + .getMessage()); + assertEquals(297, e.getOffset()); + assertEquals("\n", e.getLineText()); + } + + private Patch parseTestPatchFile() throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchTest.java new file mode 100644 index 0000000000..52d6e27ca8 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/patch/PatchTest.java @@ -0,0 +1,358 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.patch; + +import java.io.IOException; +import java.io.InputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; + +public class PatchTest extends TestCase { + public void testEmpty() { + final Patch p = new Patch(); + assertTrue(p.getFiles().isEmpty()); + assertTrue(p.getErrors().isEmpty()); + } + + public void testParse_ConfigCaseInsensitive() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(2, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final FileHeader fRepositoryConfigTest = p.getFiles().get(0); + final FileHeader fRepositoryConfig = p.getFiles().get(1); + + assertEquals( + "org.eclipse.jgit.test/tst/org/spearce/jgit/lib/RepositoryConfigTest.java", + fRepositoryConfigTest.getNewName()); + + assertEquals( + "org.eclipse.jgit/src/org/spearce/jgit/lib/RepositoryConfig.java", + fRepositoryConfig.getNewName()); + + assertEquals(572, fRepositoryConfigTest.startOffset); + assertEquals(1490, fRepositoryConfig.startOffset); + + assertEquals("da7e704", fRepositoryConfigTest.getOldId().name()); + assertEquals("34ce04a", fRepositoryConfigTest.getNewId().name()); + assertSame(FileHeader.PatchType.UNIFIED, fRepositoryConfigTest + .getPatchType()); + assertSame(FileMode.REGULAR_FILE, fRepositoryConfigTest.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fRepositoryConfigTest.getNewMode()); + assertEquals(1, fRepositoryConfigTest.getHunks().size()); + { + final HunkHeader h = fRepositoryConfigTest.getHunks().get(0); + assertSame(fRepositoryConfigTest, h.getFileHeader()); + assertEquals(921, h.startOffset); + assertEquals(109, h.getOldImage().getStartLine()); + assertEquals(4, h.getOldImage().getLineCount()); + assertEquals(109, h.getNewStartLine()); + assertEquals(11, h.getNewLineCount()); + + assertEquals(4, h.getLinesContext()); + assertEquals(7, h.getOldImage().getLinesAdded()); + assertEquals(0, h.getOldImage().getLinesDeleted()); + assertSame(fRepositoryConfigTest.getOldId(), h.getOldImage() + .getId()); + + assertEquals(1490, h.endOffset); + } + + assertEquals("45c2f8a", fRepositoryConfig.getOldId().name()); + assertEquals("3291bba", fRepositoryConfig.getNewId().name()); + assertSame(FileHeader.PatchType.UNIFIED, fRepositoryConfig + .getPatchType()); + assertSame(FileMode.REGULAR_FILE, fRepositoryConfig.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fRepositoryConfig.getNewMode()); + assertEquals(3, fRepositoryConfig.getHunks().size()); + { + final HunkHeader h = fRepositoryConfig.getHunks().get(0); + assertSame(fRepositoryConfig, h.getFileHeader()); + assertEquals(1803, h.startOffset); + assertEquals(236, h.getOldImage().getStartLine()); + assertEquals(9, h.getOldImage().getLineCount()); + assertEquals(236, h.getNewStartLine()); + assertEquals(9, h.getNewLineCount()); + + assertEquals(7, h.getLinesContext()); + assertEquals(2, h.getOldImage().getLinesAdded()); + assertEquals(2, h.getOldImage().getLinesDeleted()); + assertSame(fRepositoryConfig.getOldId(), h.getOldImage().getId()); + + assertEquals(2434, h.endOffset); + } + { + final HunkHeader h = fRepositoryConfig.getHunks().get(1); + assertEquals(2434, h.startOffset); + assertEquals(300, h.getOldImage().getStartLine()); + assertEquals(7, h.getOldImage().getLineCount()); + assertEquals(300, h.getNewStartLine()); + assertEquals(7, h.getNewLineCount()); + + assertEquals(6, h.getLinesContext()); + assertEquals(1, h.getOldImage().getLinesAdded()); + assertEquals(1, h.getOldImage().getLinesDeleted()); + + assertEquals(2816, h.endOffset); + } + { + final HunkHeader h = fRepositoryConfig.getHunks().get(2); + assertEquals(2816, h.startOffset); + assertEquals(954, h.getOldImage().getStartLine()); + assertEquals(7, h.getOldImage().getLineCount()); + assertEquals(954, h.getNewStartLine()); + assertEquals(7, h.getNewLineCount()); + + assertEquals(6, h.getLinesContext()); + assertEquals(1, h.getOldImage().getLinesAdded()); + assertEquals(1, h.getOldImage().getLinesDeleted()); + + assertEquals(3035, h.endOffset); + } + } + + public void testParse_NoBinary() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(5, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + for (int i = 0; i < 4; i++) { + final FileHeader fh = p.getFiles().get(i); + assertSame(FileHeader.ChangeType.ADD, fh.getChangeType()); + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + assertEquals("0000000", fh.getOldId().name()); + assertSame(FileMode.MISSING, fh.getOldMode()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + assertTrue(fh.getNewName().startsWith( + "org.spearce.egit.ui/icons/toolbar/")); + assertSame(FileHeader.PatchType.BINARY, fh.getPatchType()); + assertTrue(fh.getHunks().isEmpty()); + assertTrue(fh.hasMetaDataChanges()); + + assertNull(fh.getForwardBinaryHunk()); + assertNull(fh.getReverseBinaryHunk()); + } + + final FileHeader fh = p.getFiles().get(4); + assertEquals("org.spearce.egit.ui/plugin.xml", fh.getNewName()); + assertSame(FileHeader.ChangeType.MODIFY, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertFalse(fh.hasMetaDataChanges()); + assertEquals("ee8a5a0", fh.getNewId().name()); + assertNull(fh.getForwardBinaryHunk()); + assertNull(fh.getReverseBinaryHunk()); + assertEquals(1, fh.getHunks().size()); + assertEquals(272, fh.getHunks().get(0).getOldImage().getStartLine()); + } + + public void testParse_GitBinaryLiteral() throws IOException { + final Patch p = parseTestPatchFile(); + final int[] binsizes = { 359, 393, 372, 404 }; + assertEquals(5, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + for (int i = 0; i < 4; i++) { + final FileHeader fh = p.getFiles().get(i); + assertSame(FileHeader.ChangeType.ADD, fh.getChangeType()); + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + assertEquals(ObjectId.zeroId().name(), fh.getOldId().name()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + assertTrue(fh.getNewName().startsWith( + "org.spearce.egit.ui/icons/toolbar/")); + assertSame(FileHeader.PatchType.GIT_BINARY, fh.getPatchType()); + assertTrue(fh.getHunks().isEmpty()); + assertTrue(fh.hasMetaDataChanges()); + + final BinaryHunk fwd = fh.getForwardBinaryHunk(); + final BinaryHunk rev = fh.getReverseBinaryHunk(); + assertNotNull(fwd); + assertNotNull(rev); + assertEquals(binsizes[i], fwd.getSize()); + assertEquals(0, rev.getSize()); + + assertSame(fh, fwd.getFileHeader()); + assertSame(fh, rev.getFileHeader()); + + assertSame(BinaryHunk.Type.LITERAL_DEFLATED, fwd.getType()); + assertSame(BinaryHunk.Type.LITERAL_DEFLATED, rev.getType()); + } + + final FileHeader fh = p.getFiles().get(4); + assertEquals("org.spearce.egit.ui/plugin.xml", fh.getNewName()); + assertSame(FileHeader.ChangeType.MODIFY, fh.getChangeType()); + assertSame(FileHeader.PatchType.UNIFIED, fh.getPatchType()); + assertFalse(fh.hasMetaDataChanges()); + assertEquals("ee8a5a0", fh.getNewId().name()); + assertNull(fh.getForwardBinaryHunk()); + assertNull(fh.getReverseBinaryHunk()); + assertEquals(1, fh.getHunks().size()); + assertEquals(272, fh.getHunks().get(0).getOldImage().getStartLine()); + } + + public void testParse_GitBinaryDelta() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final FileHeader fh = p.getFiles().get(0); + assertTrue(fh.getNewName().startsWith("zero.bin")); + assertSame(FileHeader.ChangeType.MODIFY, fh.getChangeType()); + assertSame(FileHeader.PatchType.GIT_BINARY, fh.getPatchType()); + assertSame(FileMode.REGULAR_FILE, fh.getNewMode()); + + assertNotNull(fh.getOldId()); + assertNotNull(fh.getNewId()); + assertEquals("08e7df176454f3ee5eeda13efa0adaa54828dfd8", fh.getOldId() + .name()); + assertEquals("d70d8710b6d32ff844af0ee7c247e4b4b051867f", fh.getNewId() + .name()); + + assertTrue(fh.getHunks().isEmpty()); + assertFalse(fh.hasMetaDataChanges()); + + final BinaryHunk fwd = fh.getForwardBinaryHunk(); + final BinaryHunk rev = fh.getReverseBinaryHunk(); + assertNotNull(fwd); + assertNotNull(rev); + assertEquals(12, fwd.getSize()); + assertEquals(11, rev.getSize()); + + assertSame(fh, fwd.getFileHeader()); + assertSame(fh, rev.getFileHeader()); + + assertSame(BinaryHunk.Type.DELTA_DEFLATED, fwd.getType()); + assertSame(BinaryHunk.Type.DELTA_DEFLATED, rev.getType()); + + assertEquals(496, fh.endOffset); + } + + public void testParse_FixNoNewline() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final FileHeader f = p.getFiles().get(0); + + assertEquals("a", f.getNewName()); + assertEquals(252, f.startOffset); + + assertEquals("2e65efe", f.getOldId().name()); + assertEquals("f2ad6c7", f.getNewId().name()); + assertSame(FileHeader.PatchType.UNIFIED, f.getPatchType()); + assertSame(FileMode.REGULAR_FILE, f.getOldMode()); + assertSame(FileMode.REGULAR_FILE, f.getNewMode()); + assertEquals(1, f.getHunks().size()); + { + final HunkHeader h = f.getHunks().get(0); + assertSame(f, h.getFileHeader()); + assertEquals(317, h.startOffset); + assertEquals(1, h.getOldImage().getStartLine()); + assertEquals(1, h.getOldImage().getLineCount()); + assertEquals(1, h.getNewStartLine()); + assertEquals(1, h.getNewLineCount()); + + assertEquals(0, h.getLinesContext()); + assertEquals(1, h.getOldImage().getLinesAdded()); + assertEquals(1, h.getOldImage().getLinesDeleted()); + assertSame(f.getOldId(), h.getOldImage().getId()); + + assertEquals(363, h.endOffset); + } + } + + public void testParse_AddNoNewline() throws IOException { + final Patch p = parseTestPatchFile(); + assertEquals(1, p.getFiles().size()); + assertTrue(p.getErrors().isEmpty()); + + final FileHeader f = p.getFiles().get(0); + + assertEquals("a", f.getNewName()); + assertEquals(256, f.startOffset); + + assertEquals("f2ad6c7", f.getOldId().name()); + assertEquals("c59d9b6", f.getNewId().name()); + assertSame(FileHeader.PatchType.UNIFIED, f.getPatchType()); + assertSame(FileMode.REGULAR_FILE, f.getOldMode()); + assertSame(FileMode.REGULAR_FILE, f.getNewMode()); + assertEquals(1, f.getHunks().size()); + { + final HunkHeader h = f.getHunks().get(0); + assertSame(f, h.getFileHeader()); + assertEquals(321, h.startOffset); + assertEquals(1, h.getOldImage().getStartLine()); + assertEquals(1, h.getOldImage().getLineCount()); + assertEquals(1, h.getNewStartLine()); + assertEquals(1, h.getNewLineCount()); + + assertEquals(0, h.getLinesContext()); + assertEquals(1, h.getOldImage().getLinesAdded()); + assertEquals(1, h.getOldImage().getLinesDeleted()); + assertSame(f.getOldId(), h.getOldImage().getId()); + + assertEquals(367, h.endOffset); + } + } + + private Patch parseTestPatchFile() throws IOException { + final String patchFile = getName() + ".patch"; + final InputStream in = getClass().getResourceAsStream(patchFile); + if (in == null) { + fail("No " + patchFile + " test vector"); + return null; // Never happens + } + try { + final Patch p = new Patch(); + p.parse(in); + return p; + } finally { + in.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/AlwaysEmptyRevQueueTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/AlwaysEmptyRevQueueTest.java new file mode 100644 index 0000000000..d752501c12 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/AlwaysEmptyRevQueueTest.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public class AlwaysEmptyRevQueueTest extends RevWalkTestCase { + private final AbstractRevQueue q = AbstractRevQueue.EMPTY_QUEUE; + + public void testEmpty() throws Exception { + assertNull(q.next()); + assertTrue(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertFalse(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + assertEquals(0, q.outputType()); + } + + public void testClear() throws Exception { + q.clear(); + testEmpty(); + } + + public void testAddFails() throws Exception { + try { + q.add(commit()); + fail("Did not throw UnsupportedOperationException"); + } catch (UnsupportedOperationException e) { + // expected result + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/DateRevQueueTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/DateRevQueueTest.java new file mode 100644 index 0000000000..b3a92951b6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/DateRevQueueTest.java @@ -0,0 +1,124 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public class DateRevQueueTest extends RevQueueTestCase<DateRevQueue> { + protected DateRevQueue create() { + return new DateRevQueue(); + } + + public void testEmpty() throws Exception { + super.testEmpty(); + assertNull(q.peek()); + assertEquals(Generator.SORT_COMMIT_TIME_DESC, q.outputType()); + } + + public void testCloneEmpty() throws Exception { + q = new DateRevQueue(AbstractRevQueue.EMPTY_QUEUE); + assertNull(q.next()); + } + + public void testInsertOutOfOrder() throws Exception { + final RevCommit a = parse(commit()); + final RevCommit b = parse(commit(10, a)); + final RevCommit c1 = parse(commit(5, b)); + final RevCommit c2 = parse(commit(-50, b)); + + q.add(c2); + q.add(a); + q.add(b); + q.add(c1); + + assertCommit(c1, q.next()); + assertCommit(b, q.next()); + assertCommit(a, q.next()); + assertCommit(c2, q.next()); + assertNull(q.next()); + } + + public void testInsertTie() throws Exception { + final RevCommit a = parse(commit()); + final RevCommit b = parse(commit(0, a)); + { + q = create(); + q.add(a); + q.add(b); + + assertCommit(a, q.next()); + assertCommit(b, q.next()); + assertNull(q.next()); + } + { + q = create(); + q.add(b); + q.add(a); + + assertCommit(b, q.next()); + assertCommit(a, q.next()); + assertNull(q.next()); + } + } + + public void testCloneFIFO() throws Exception { + final RevCommit a = parse(commit()); + final RevCommit b = parse(commit(200, a)); + final RevCommit c = parse(commit(200, b)); + + final FIFORevQueue src = new FIFORevQueue(); + src.add(a); + src.add(b); + src.add(c); + + q = new DateRevQueue(src); + assertFalse(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertFalse(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + assertCommit(c, q.peek()); + assertCommit(c, q.peek()); + + assertCommit(c, q.next()); + assertCommit(b, q.next()); + assertCommit(a, q.next()); + assertNull(q.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FIFORevQueueTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FIFORevQueueTest.java new file mode 100644 index 0000000000..3f4daab9f6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FIFORevQueueTest.java @@ -0,0 +1,87 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.ArrayList; + +public class FIFORevQueueTest extends RevQueueTestCase<FIFORevQueue> { + protected FIFORevQueue create() { + return new FIFORevQueue(); + } + + public void testEmpty() throws Exception { + super.testEmpty(); + assertEquals(0, q.outputType()); + } + + public void testCloneEmpty() throws Exception { + q = new FIFORevQueue(AbstractRevQueue.EMPTY_QUEUE); + assertNull(q.next()); + } + + public void testAddLargeBlocks() throws Exception { + final ArrayList<RevCommit> lst = new ArrayList<RevCommit>(); + for (int i = 0; i < 3 * BlockRevQueue.Block.BLOCK_SIZE; i++) { + final RevCommit c = commit(); + lst.add(c); + q.add(c); + } + for (int i = 0; i < lst.size(); i++) + assertSame(lst.get(i), q.next()); + } + + public void testUnpopAtFront() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(); + final RevCommit c = commit(); + + q.add(a); + q.unpop(b); + q.unpop(c); + + assertSame(c, q.next()); + assertSame(b, q.next()); + assertSame(a, q.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java new file mode 100644 index 0000000000..d199f04ccb --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/FooterLineTest.java @@ -0,0 +1,323 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.List; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class FooterLineTest extends RepositoryTestCase { + public void testNoFooters_EmptyBody() { + final RevCommit commit = parse(""); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_NewlineOnlyBody1() { + final RevCommit commit = parse("\n"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_NewlineOnlyBody5() { + final RevCommit commit = parse("\n\n\n\n\n"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_OneLineBodyNoLF() { + final RevCommit commit = parse("this is a commit"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_OneLineBodyWithLF() { + final RevCommit commit = parse("this is a commit\n"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_ShortBodyNoLF() { + final RevCommit commit = parse("subject\n\nbody of commit"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testNoFooters_ShortBodyWithLF() { + final RevCommit commit = parse("subject\n\nbody of commit\n"); + final List<FooterLine> footers = commit.getFooterLines(); + assertNotNull(footers); + assertEquals(0, footers.size()); + } + + public void testSignedOffBy_OneUserNoLF() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Signed-off-by: A. U. Thor <a@example.com>"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("A. U. Thor <a@example.com>", f.getValue()); + assertEquals("a@example.com", f.getEmailAddress()); + } + + public void testSignedOffBy_OneUserWithLF() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Signed-off-by: A. U. Thor <a@example.com>\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("A. U. Thor <a@example.com>", f.getValue()); + assertEquals("a@example.com", f.getEmailAddress()); + } + + public void testSignedOffBy_IgnoreWhitespace() { + // We only ignore leading whitespace on the value, trailing + // is assumed part of the value. + // + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Signed-off-by: A. U. Thor <a@example.com> \n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("A. U. Thor <a@example.com> ", f.getValue()); + assertEquals("a@example.com", f.getEmailAddress()); + } + + public void testEmptyValueNoLF() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Signed-off-by:"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("", f.getValue()); + assertNull(f.getEmailAddress()); + } + + public void testEmptyValueWithLF() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Signed-off-by:\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("", f.getValue()); + assertNull(f.getEmailAddress()); + } + + public void testShortKey() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "K:V\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("K", f.getKey()); + assertEquals("V", f.getValue()); + assertNull(f.getEmailAddress()); + } + + public void testNonDelimtedEmail() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Acked-by: re@example.com\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Acked-by", f.getKey()); + assertEquals("re@example.com", f.getValue()); + assertEquals("re@example.com", f.getEmailAddress()); + } + + public void testNotEmail() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + "\n" + + "Acked-by: Main Tain Er\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(1, footers.size()); + + f = footers.get(0); + assertEquals("Acked-by", f.getKey()); + assertEquals("Main Tain Er", f.getValue()); + assertNull(f.getEmailAddress()); + } + + public void testSignedOffBy_ManyUsers() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + + "Not-A-Footer-Line: this line must not be read as a footer\n" + + "\n" // paragraph break, now footers appear in final block + + "Signed-off-by: A. U. Thor <a@example.com>\n" + + "CC: <some.mailing.list@example.com>\n" + + "Acked-by: Some Reviewer <sr@example.com>\n" + + "Signed-off-by: Main Tain Er <mte@example.com>\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(4, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("A. U. Thor <a@example.com>", f.getValue()); + assertEquals("a@example.com", f.getEmailAddress()); + + f = footers.get(1); + assertEquals("CC", f.getKey()); + assertEquals("<some.mailing.list@example.com>", f.getValue()); + assertEquals("some.mailing.list@example.com", f.getEmailAddress()); + + f = footers.get(2); + assertEquals("Acked-by", f.getKey()); + assertEquals("Some Reviewer <sr@example.com>", f.getValue()); + assertEquals("sr@example.com", f.getEmailAddress()); + + f = footers.get(3); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("Main Tain Er <mte@example.com>", f.getValue()); + assertEquals("mte@example.com", f.getEmailAddress()); + } + + public void testSignedOffBy_SkipNonFooter() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + + "Not-A-Footer-Line: this line must not be read as a footer\n" + + "\n" // paragraph break, now footers appear in final block + + "Signed-off-by: A. U. Thor <a@example.com>\n" + + "CC: <some.mailing.list@example.com>\n" + + "not really a footer line but we'll skip it anyway\n" + + "Acked-by: Some Reviewer <sr@example.com>\n" + + "Signed-off-by: Main Tain Er <mte@example.com>\n"); + final List<FooterLine> footers = commit.getFooterLines(); + FooterLine f; + + assertNotNull(footers); + assertEquals(4, footers.size()); + + f = footers.get(0); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("A. U. Thor <a@example.com>", f.getValue()); + + f = footers.get(1); + assertEquals("CC", f.getKey()); + assertEquals("<some.mailing.list@example.com>", f.getValue()); + + f = footers.get(2); + assertEquals("Acked-by", f.getKey()); + assertEquals("Some Reviewer <sr@example.com>", f.getValue()); + + f = footers.get(3); + assertEquals("Signed-off-by", f.getKey()); + assertEquals("Main Tain Er <mte@example.com>", f.getValue()); + } + + public void testFilterFootersIgnoreCase() { + final RevCommit commit = parse("subject\n\nbody of commit\n" + + "Not-A-Footer-Line: this line must not be read as a footer\n" + + "\n" // paragraph break, now footers appear in final block + + "Signed-Off-By: A. U. Thor <a@example.com>\n" + + "CC: <some.mailing.list@example.com>\n" + + "Acked-by: Some Reviewer <sr@example.com>\n" + + "signed-off-by: Main Tain Er <mte@example.com>\n"); + final List<String> footers = commit.getFooterLines("signed-off-by"); + + assertNotNull(footers); + assertEquals(2, footers.size()); + + assertEquals("A. U. Thor <a@example.com>", footers.get(0)); + assertEquals("Main Tain Er <mte@example.com>", footers.get(1)); + } + + private RevCommit parse(final String msg) { + final StringBuilder buf = new StringBuilder(); + buf.append("tree " + ObjectId.zeroId().name() + "\n"); + buf.append("author A. U. Thor <a@example.com> 1 +0000\n"); + buf.append("committer A. U. Thor <a@example.com> 1 +0000\n"); + buf.append("\n"); + buf.append(msg); + + final RevWalk walk = new RevWalk(db); + walk.setRetainBody(true); + final RevCommit c = new RevCommit(ObjectId.zeroId()); + c.parseCanonical(walk, Constants.encode(buf.toString())); + return c; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/LIFORevQueueTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/LIFORevQueueTest.java new file mode 100644 index 0000000000..7676a71503 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/LIFORevQueueTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.ArrayList; +import java.util.Collections; + +public class LIFORevQueueTest extends RevQueueTestCase<LIFORevQueue> { + protected LIFORevQueue create() { + return new LIFORevQueue(); + } + + public void testEmpty() throws Exception { + super.testEmpty(); + assertEquals(0, q.outputType()); + } + + public void testCloneEmpty() throws Exception { + q = new LIFORevQueue(AbstractRevQueue.EMPTY_QUEUE); + assertNull(q.next()); + } + + public void testAddLargeBlocks() throws Exception { + final ArrayList<RevCommit> lst = new ArrayList<RevCommit>(); + for (int i = 0; i < 3 * BlockRevQueue.Block.BLOCK_SIZE; i++) { + final RevCommit c = commit(); + lst.add(c); + q.add(c); + } + Collections.reverse(lst); + for (int i = 0; i < lst.size(); i++) + assertSame(lst.get(i), q.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkTest.java new file mode 100644 index 0000000000..7dddeee205 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/ObjectWalkTest.java @@ -0,0 +1,196 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public class ObjectWalkTest extends RevWalkTestCase { + protected ObjectWalk objw; + + protected RevWalk createRevWalk() { + return objw = new ObjectWalk(db); + } + + public void testNoCommits() throws Exception { + assertNull(objw.next()); + assertNull(objw.nextObject()); + } + + public void testTwoCommitsEmptyTree() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + markStart(b); + + assertCommit(b, objw.next()); + assertCommit(a, objw.next()); + assertNull(objw.next()); + + assertSame(emptyTree, objw.nextObject()); + assertNull(objw.nextObject()); + } + + public void testOneCommitOneTreeTwoBlob() throws Exception { + final RevBlob f0 = blob("0"); + final RevBlob f1 = blob("1"); + final RevTree t = tree(file("0", f0), file("1", f1), file("2", f1)); + final RevCommit a = commit(t); + markStart(a); + + assertCommit(a, objw.next()); + assertNull(objw.next()); + + assertSame(t, objw.nextObject()); + assertSame(f0, objw.nextObject()); + assertSame(f1, objw.nextObject()); + assertNull(objw.nextObject()); + } + + public void testTwoCommitTwoTreeTwoBlob() throws Exception { + final RevBlob f0 = blob("0"); + final RevBlob f1 = blob("1"); + final RevBlob f2 = blob("0v2"); + final RevTree ta = tree(file("0", f0), file("1", f1), file("2", f1)); + final RevTree tb = tree(file("0", f2), file("1", f1), file("2", f1)); + final RevCommit a = commit(ta); + final RevCommit b = commit(tb, a); + markStart(b); + + assertCommit(b, objw.next()); + assertCommit(a, objw.next()); + assertNull(objw.next()); + + assertSame(tb, objw.nextObject()); + assertSame(f2, objw.nextObject()); + assertSame(f1, objw.nextObject()); + + assertSame(ta, objw.nextObject()); + assertSame(f0, objw.nextObject()); + + assertNull(objw.nextObject()); + } + + public void testTwoCommitDeepTree1() throws Exception { + final RevBlob f0 = blob("0"); + final RevBlob f1 = blob("0v2"); + final RevTree ta = tree(file("a/b/0", f0)); + final RevTree tb = tree(file("a/b/1", f1)); + final RevCommit a = commit(ta); + final RevCommit b = commit(tb, a); + markStart(b); + + assertCommit(b, objw.next()); + assertCommit(a, objw.next()); + assertNull(objw.next()); + + assertSame(tb, objw.nextObject()); + assertSame(get(tb, "a"), objw.nextObject()); + assertSame(get(tb, "a/b"), objw.nextObject()); + assertSame(f1, objw.nextObject()); + + assertSame(ta, objw.nextObject()); + assertSame(get(ta, "a"), objw.nextObject()); + assertSame(get(ta, "a/b"), objw.nextObject()); + assertSame(f0, objw.nextObject()); + + assertNull(objw.nextObject()); + } + + public void testTwoCommitDeepTree2() throws Exception { + final RevBlob f1 = blob("1"); + final RevTree ta = tree(file("a/b/0", f1), file("a/c/q", f1)); + final RevTree tb = tree(file("a/b/1", f1), file("a/c/q", f1)); + final RevCommit a = commit(ta); + final RevCommit b = commit(tb, a); + markStart(b); + + assertCommit(b, objw.next()); + assertCommit(a, objw.next()); + assertNull(objw.next()); + + assertSame(tb, objw.nextObject()); + assertSame(get(tb, "a"), objw.nextObject()); + assertSame(get(tb, "a/b"), objw.nextObject()); + assertSame(f1, objw.nextObject()); + assertSame(get(tb, "a/c"), objw.nextObject()); + + assertSame(ta, objw.nextObject()); + assertSame(get(ta, "a"), objw.nextObject()); + assertSame(get(ta, "a/b"), objw.nextObject()); + + assertNull(objw.nextObject()); + } + + public void testCull() throws Exception { + final RevBlob f1 = blob("1"); + final RevBlob f2 = blob("2"); + final RevBlob f3 = blob("3"); + final RevBlob f4 = blob("4"); + + final RevTree ta = tree(file("a/1", f1), file("c/3", f3)); + final RevCommit a = commit(ta); + + final RevTree tb = tree(file("a/1", f2), file("c/3", f3)); + final RevCommit b1 = commit(tb, a); + final RevCommit b2 = commit(tb, b1); + + final RevTree tc = tree(file("a/1", f4)); + final RevCommit c1 = commit(tc, a); + final RevCommit c2 = commit(tc, c1); + + markStart(b2); + markUninteresting(c2); + + assertCommit(b2, objw.next()); + assertCommit(b1, objw.next()); + assertNull(objw.next()); + + assertTrue(a.has(RevFlag.UNINTERESTING)); + assertTrue(ta.has(RevFlag.UNINTERESTING)); + assertTrue(f1.has(RevFlag.UNINTERESTING)); + assertTrue(f3.has(RevFlag.UNINTERESTING)); + + assertSame(tb, objw.nextObject()); + assertSame(get(tb, "a"), objw.nextObject()); + assertSame(f2, objw.nextObject()); + assertNull(objw.nextObject()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java new file mode 100644 index 0000000000..b7e84419c9 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevCommitParseTest.java @@ -0,0 +1,321 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.io.ByteArrayOutputStream; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class RevCommitParseTest extends RepositoryTestCase { + public void testParse_NoParents() throws Exception { + final ObjectId treeId = id("9788669ad918b6fcce64af8882fc9a81cb6aba67"); + final String authorName = "A U. Thor"; + final String authorEmail = "a_u_thor@example.com"; + final int authorTime = 1218123387; + + final String committerName = "C O. Miter"; + final String committerEmail = "comiter@example.com"; + final int committerTime = 1218123390; + final StringBuilder body = new StringBuilder(); + + body.append("tree "); + body.append(treeId.name()); + body.append("\n"); + + body.append("author "); + body.append(authorName); + body.append(" <"); + body.append(authorEmail); + body.append("> "); + body.append(authorTime); + body.append(" +0700\n"); + + body.append("committer "); + body.append(committerName); + body.append(" <"); + body.append(committerEmail); + body.append("> "); + body.append(committerTime); + body.append(" -0500\n"); + + body.append("\n"); + + final RevWalk rw = new RevWalk(db); + final RevCommit c; + + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + assertNull(c.getTree()); + assertNull(c.parents); + + c.parseCanonical(rw, body.toString().getBytes("UTF-8")); + assertNotNull(c.getTree()); + assertEquals(treeId, c.getTree().getId()); + assertSame(rw.lookupTree(treeId), c.getTree()); + + assertNotNull(c.parents); + assertEquals(0, c.parents.length); + assertEquals("", c.getFullMessage()); + + final PersonIdent cAuthor = c.getAuthorIdent(); + assertNotNull(cAuthor); + assertEquals(authorName, cAuthor.getName()); + assertEquals(authorEmail, cAuthor.getEmailAddress()); + + final PersonIdent cCommitter = c.getCommitterIdent(); + assertNotNull(cCommitter); + assertEquals(committerName, cCommitter.getName()); + assertEquals(committerEmail, cCommitter.getEmailAddress()); + } + + private RevCommit create(final String msg) throws Exception { + final StringBuilder b = new StringBuilder(); + b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n"); + b.append("author A U. Thor <a_u_thor@example.com> 1218123387 +0700\n"); + b.append("committer C O. Miter <c@example.com> 1218123390 -0500\n"); + b.append("\n"); + b.append(msg); + + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toString().getBytes("UTF-8")); + return c; + } + + public void testParse_WeirdHeaderOnlyCommit() throws Exception { + final StringBuilder b = new StringBuilder(); + b.append("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n"); + b.append("author A U. Thor <a_u_thor@example.com> 1218123387 +0700\n"); + b.append("committer C O. Miter <c@example.com> 1218123390 -0500\n"); + + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toString().getBytes("UTF-8")); + + assertEquals("", c.getFullMessage()); + assertEquals("", c.getShortMessage()); + } + + public void testParse_implicit_UTF8_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("UTF-8")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("UTF-8")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Sm\u00f6rg\u00e5sbord\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertSame(Constants.CHARSET, c.getEncoding()); + assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); + assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage()); + } + + public void testParse_implicit_mixed_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("UTF-8")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("ISO-8859-1")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Sm\u00f6rg\u00e5sbord\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertSame(Constants.CHARSET, c.getEncoding()); + assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); + assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c.getFullMessage()); + } + + /** + * Test parsing of a commit whose encoding is given and works. + * + * @throws Exception + */ + public void testParse_explicit_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("EUC-JP")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("EUC-JP")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("EUC-JP")); + b.write("encoding euc_JP\n".getBytes("EUC-JP")); + b.write("\n".getBytes("EUC-JP")); + b.write("\u304d\u308c\u3044\n".getBytes("EUC-JP")); + b.write("\n".getBytes("EUC-JP")); + b.write("Hi\n".getBytes("EUC-JP")); + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("EUC-JP", c.getEncoding().name()); + assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + /** + * This is a twisted case, but show what we expect here. We can revise the + * expectations provided this case is updated. + * + * What happens here is that an encoding us given, but data is not encoded + * that way (and we can detect it), so we try other encodings. + * + * @throws Exception + */ + public void testParse_explicit_bad_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("UTF-8")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("ISO-8859-1")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("UTF-8")); + b.write("encoding EUC-JP\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Hi\n".getBytes("UTF-8")); + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("EUC-JP", c.getEncoding().name()); + assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + /** + * This is a twisted case too, but show what we expect here. We can revise the + * expectations provided this case is updated. + * + * What happens here is that an encoding us given, but data is not encoded + * that way (and we can detect it), so we try other encodings. Here data could + * actually be decoded in the stated encoding, but we override using UTF-8. + * + * @throws Exception + */ + public void testParse_explicit_bad_encoded2() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("tree 9788669ad918b6fcce64af8882fc9a81cb6aba67\n".getBytes("UTF-8")); + b.write("author F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n".getBytes("UTF-8")); + b.write("committer C O. Miter <c@example.com> 1218123390 -0500\n".getBytes("UTF-8")); + b.write("encoding ISO-8859-1\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Hi\n".getBytes("UTF-8")); + final RevCommit c; + c = new RevCommit(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); // bogus id + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("ISO-8859-1", c.getEncoding().name()); + assertEquals("F\u00f6r fattare", c.getAuthorIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + public void testParse_NoMessage() throws Exception { + final String msg = ""; + final RevCommit c = create(msg); + assertEquals(msg, c.getFullMessage()); + assertEquals(msg, c.getShortMessage()); + } + + public void testParse_OnlyLFMessage() throws Exception { + final RevCommit c = create("\n"); + assertEquals("\n", c.getFullMessage()); + assertEquals("", c.getShortMessage()); + } + + public void testParse_ShortLineOnlyNoLF() throws Exception { + final String shortMsg = "This is a short message."; + final RevCommit c = create(shortMsg); + assertEquals(shortMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEndLF() throws Exception { + final String shortMsg = "This is a short message."; + final String fullMsg = shortMsg + "\n"; + final RevCommit c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEmbeddedLF() throws Exception { + final String fullMsg = "This is a\nshort message."; + final String shortMsg = fullMsg.replace('\n', ' '); + final RevCommit c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEmbeddedAndEndingLF() throws Exception { + final String fullMsg = "This is a\nshort message.\n"; + final String shortMsg = "This is a short message."; + final RevCommit c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_GitStyleMessage() throws Exception { + final String shortMsg = "This fixes a bug."; + final String body = "We do it with magic and pixie dust and stuff.\n" + + "\n" + "Signed-off-by: A U. Thor <author@example.com>\n"; + final String fullMsg = shortMsg + "\n" + "\n" + body; + final RevCommit c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + private static ObjectId id(final String str) { + return ObjectId.fromString(str); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevFlagSetTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevFlagSetTest.java new file mode 100644 index 0000000000..13f1cfc4cc --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevFlagSetTest.java @@ -0,0 +1,137 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.Arrays; +import java.util.Iterator; + +public class RevFlagSetTest extends RevWalkTestCase { + public void testEmpty() { + final RevFlagSet set = new RevFlagSet(); + assertEquals(0, set.mask); + assertEquals(0, set.size()); + assertNotNull(set.iterator()); + assertFalse(set.iterator().hasNext()); + } + + public void testAddOne() { + final String flagName = "flag"; + final RevFlag flag = rw.newFlag(flagName); + assertTrue(0 != flag.mask); + assertSame(flagName, flag.name); + + final RevFlagSet set = new RevFlagSet(); + assertTrue(set.add(flag)); + assertFalse(set.add(flag)); + assertEquals(flag.mask, set.mask); + assertEquals(1, set.size()); + final Iterator<RevFlag> i = set.iterator(); + assertTrue(i.hasNext()); + assertSame(flag, i.next()); + assertFalse(i.hasNext()); + } + + public void testAddTwo() { + final RevFlag flag1 = rw.newFlag("flag_1"); + final RevFlag flag2 = rw.newFlag("flag_2"); + assertTrue((flag1.mask & flag2.mask) == 0); + + final RevFlagSet set = new RevFlagSet(); + assertTrue(set.add(flag1)); + assertTrue(set.add(flag2)); + assertEquals(flag1.mask | flag2.mask, set.mask); + assertEquals(2, set.size()); + } + + public void testContainsAll() { + final RevFlag flag1 = rw.newFlag("flag_1"); + final RevFlag flag2 = rw.newFlag("flag_2"); + final RevFlagSet set1 = new RevFlagSet(); + assertTrue(set1.add(flag1)); + assertTrue(set1.add(flag2)); + + assertTrue(set1.containsAll(set1)); + assertTrue(set1.containsAll(Arrays + .asList(new RevFlag[] { flag1, flag2 }))); + + final RevFlagSet set2 = new RevFlagSet(); + set2.add(rw.newFlag("flag_3")); + assertFalse(set1.containsAll(set2)); + } + + public void testEquals() { + final RevFlag flag1 = rw.newFlag("flag_1"); + final RevFlag flag2 = rw.newFlag("flag_2"); + final RevFlagSet set = new RevFlagSet(); + assertTrue(set.add(flag1)); + assertTrue(set.add(flag2)); + + assertTrue(new RevFlagSet(set).equals(set)); + assertTrue(new RevFlagSet(Arrays.asList(new RevFlag[] { flag1, flag2 })) + .equals(set)); + } + + public void testRemove() { + final RevFlag flag1 = rw.newFlag("flag_1"); + final RevFlag flag2 = rw.newFlag("flag_2"); + final RevFlagSet set = new RevFlagSet(); + assertTrue(set.add(flag1)); + assertTrue(set.add(flag2)); + + assertTrue(set.remove(flag1)); + assertFalse(set.remove(flag1)); + assertEquals(flag2.mask, set.mask); + assertFalse(set.contains(flag1)); + } + + public void testContains() { + final RevFlag flag1 = rw.newFlag("flag_1"); + final RevFlag flag2 = rw.newFlag("flag_2"); + final RevFlagSet set = new RevFlagSet(); + set.add(flag1); + assertTrue(set.contains(flag1)); + assertFalse(set.contains(flag2)); + assertFalse(set.contains("bob")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java new file mode 100644 index 0000000000..87ecaa8c53 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevObjectTest.java @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import org.eclipse.jgit.lib.AnyObjectId; +import org.eclipse.jgit.lib.Constants; + +public class RevObjectTest extends RevWalkTestCase { + public void testId() throws Exception { + final RevCommit a = commit(); + assertSame(a, a.getId()); + } + + public void testEqualsIsIdentity() throws Exception { + final RevCommit a1 = commit(); + final RevCommit b1 = commit(); + + assertTrue(a1.equals(a1)); + assertTrue(a1.equals((Object) a1)); + assertFalse(a1.equals(b1)); + + assertFalse(a1.equals(a1.copy())); + assertFalse(a1.equals((Object) a1.copy())); + assertFalse(a1.equals("")); + + final RevWalk rw2 = new RevWalk(db); + final RevCommit a2 = rw2.parseCommit(a1); + final RevCommit b2 = rw2.parseCommit(b1); + assertNotSame(a1, a2); + assertNotSame(b1, b2); + + assertFalse(a1.equals(a2)); + assertFalse(b1.equals(b2)); + + assertEquals(a1.hashCode(), a2.hashCode()); + assertEquals(b1.hashCode(), b2.hashCode()); + + assertTrue(AnyObjectId.equals(a1, a2)); + assertTrue(AnyObjectId.equals(b1, b2)); + } + + public void testRevObjectTypes() throws Exception { + assertEquals(Constants.OBJ_TREE, emptyTree.getType()); + assertEquals(Constants.OBJ_COMMIT, commit().getType()); + assertEquals(Constants.OBJ_BLOB, blob("").getType()); + assertEquals(Constants.OBJ_TAG, tag("emptyTree", emptyTree).getType()); + } + + public void testHasRevFlag() throws Exception { + final RevCommit a = commit(); + assertFalse(a.has(RevFlag.UNINTERESTING)); + a.flags |= RevWalk.UNINTERESTING; + assertTrue(a.has(RevFlag.UNINTERESTING)); + } + + public void testHasAnyFlag() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + final RevFlagSet s = new RevFlagSet(); + s.add(flag1); + s.add(flag2); + + assertFalse(a.hasAny(s)); + a.flags |= flag1.mask; + assertTrue(a.hasAny(s)); + } + + public void testHasAllFlag() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + final RevFlagSet s = new RevFlagSet(); + s.add(flag1); + s.add(flag2); + + assertFalse(a.hasAll(s)); + a.flags |= flag1.mask; + assertFalse(a.hasAll(s)); + a.flags |= flag2.mask; + assertTrue(a.hasAll(s)); + } + + public void testAddRevFlag() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + assertEquals(0, a.flags); + + a.add(flag1); + assertEquals(flag1.mask, a.flags); + + a.add(flag2); + assertEquals(flag1.mask | flag2.mask, a.flags); + } + + public void testAddRevFlagSet() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + final RevFlagSet s = new RevFlagSet(); + s.add(flag1); + s.add(flag2); + + assertEquals(0, a.flags); + + a.add(s); + assertEquals(flag1.mask | flag2.mask, a.flags); + } + + public void testRemoveRevFlag() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + a.add(flag1); + a.add(flag2); + assertEquals(flag1.mask | flag2.mask, a.flags); + a.remove(flag2); + assertEquals(flag1.mask, a.flags); + } + + public void testRemoveRevFlagSet() throws Exception { + final RevCommit a = commit(); + final RevFlag flag1 = rw.newFlag("flag1"); + final RevFlag flag2 = rw.newFlag("flag2"); + final RevFlag flag3 = rw.newFlag("flag3"); + final RevFlagSet s = new RevFlagSet(); + s.add(flag1); + s.add(flag2); + a.add(flag3); + a.add(s); + assertEquals(flag1.mask | flag2.mask | flag3.mask, a.flags); + a.remove(s); + assertEquals(flag3.mask, a.flags); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevQueueTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevQueueTestCase.java new file mode 100644 index 0000000000..24e84b041d --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevQueueTestCase.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public abstract class RevQueueTestCase<T extends AbstractRevQueue> extends + RevWalkTestCase { + protected T q; + + public void setUp() throws Exception { + super.setUp(); + q = create(); + } + + protected abstract T create(); + + public void testEmpty() throws Exception { + assertNull(q.next()); + assertTrue(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertFalse(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + } + + public void testClear() throws Exception { + final RevCommit a = parse(commit()); + final RevCommit b = parse(commit(a)); + + q.add(a); + q.add(b); + q.clear(); + assertNull(q.next()); + } + + public void testHasFlags() throws Exception { + final RevCommit a = parse(commit()); + final RevCommit b = parse(commit(a)); + + q.add(a); + q.add(b); + + assertFalse(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertFalse(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + + a.flags |= RevWalk.UNINTERESTING; + assertFalse(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertTrue(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + + b.flags |= RevWalk.UNINTERESTING; + assertTrue(q.everbodyHasFlag(RevWalk.UNINTERESTING)); + assertTrue(q.anybodyHasFlag(RevWalk.UNINTERESTING)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java new file mode 100644 index 0000000000..8800536d27 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevTagParseTest.java @@ -0,0 +1,356 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.io.ByteArrayOutputStream; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class RevTagParseTest extends RepositoryTestCase { + public void testTagBlob() throws Exception { + testOneType(Constants.OBJ_BLOB); + } + + public void testTagTree() throws Exception { + testOneType(Constants.OBJ_TREE); + } + + public void testTagCommit() throws Exception { + testOneType(Constants.OBJ_COMMIT); + } + + public void testTagTag() throws Exception { + testOneType(Constants.OBJ_TAG); + } + + private void testOneType(final int typeCode) throws Exception { + final ObjectId id = id("9788669ad918b6fcce64af8882fc9a81cb6aba67"); + final StringBuilder b = new StringBuilder(); + b.append("object " + id.name() + "\n"); + b.append("type " + Constants.typeString(typeCode) + "\n"); + b.append("tag v1.2.3.4.5\n"); + b.append("tagger A U. Thor <a_u_thor@example.com> 1218123387 +0700\n"); + b.append("\n"); + + final RevWalk rw = new RevWalk(db); + final RevTag c; + + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + assertNull(c.getObject()); + assertNull(c.getTagName()); + + c.parseCanonical(rw, b.toString().getBytes("UTF-8")); + assertNotNull(c.getObject()); + assertEquals(id, c.getObject().getId()); + assertSame(rw.lookupAny(id, typeCode), c.getObject()); + } + + public void testParseAllFields() throws Exception { + final ObjectId treeId = id("9788669ad918b6fcce64af8882fc9a81cb6aba67"); + final String name = "v1.2.3.4.5"; + final String taggerName = "A U. Thor"; + final String taggerEmail = "a_u_thor@example.com"; + final int taggerTime = 1218123387; + + final StringBuilder body = new StringBuilder(); + + body.append("object "); + body.append(treeId.name()); + body.append("\n"); + + body.append("type tree\n"); + + body.append("tag "); + body.append(name); + body.append("\n"); + + body.append("tagger "); + body.append(taggerName); + body.append(" <"); + body.append(taggerEmail); + body.append("> "); + body.append(taggerTime); + body.append(" +0700\n"); + + body.append("\n"); + + final RevWalk rw = new RevWalk(db); + final RevTag c; + + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + assertNull(c.getObject()); + assertNull(c.getTagName()); + + c.parseCanonical(rw, body.toString().getBytes("UTF-8")); + assertNotNull(c.getObject()); + assertEquals(treeId, c.getObject().getId()); + assertSame(rw.lookupTree(treeId), c.getObject()); + + assertNotNull(c.getTagName()); + assertEquals(name, c.getTagName()); + assertEquals("", c.getFullMessage()); + + final PersonIdent cTagger = c.getTaggerIdent(); + assertNotNull(cTagger); + assertEquals(taggerName, cTagger.getName()); + assertEquals(taggerEmail, cTagger.getEmailAddress()); + } + + private RevTag create(final String msg) throws Exception { + final StringBuilder b = new StringBuilder(); + b.append("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n"); + b.append("type tree\n"); + b.append("tag v1.2.3.4.5\n"); + b.append("tagger A U. Thor <a_u_thor@example.com> 1218123387 +0700\n"); + b.append("\n"); + b.append(msg); + + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toString().getBytes("UTF-8")); + return c; + } + + public void testParse_implicit_UTF8_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("UTF-8")); + b.write("type tree\n".getBytes("UTF-8")); + b.write("tag v1.2.3.4.5\n".getBytes("UTF-8")); + + b + .write("tagger F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Sm\u00f6rg\u00e5sbord\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("F\u00f6r fattare", c.getTaggerIdent().getName()); + assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c + .getFullMessage()); + } + + public void testParse_implicit_mixed_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("UTF-8")); + b.write("type tree\n".getBytes("UTF-8")); + b.write("tag v1.2.3.4.5\n".getBytes("UTF-8")); + b + .write("tagger F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("ISO-8859-1")); + b.write("\n".getBytes("UTF-8")); + b.write("Sm\u00f6rg\u00e5sbord\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("F\u00f6r fattare", c.getTaggerIdent().getName()); + assertEquals("Sm\u00f6rg\u00e5sbord", c.getShortMessage()); + assertEquals("Sm\u00f6rg\u00e5sbord\n\n\u304d\u308c\u3044\n", c + .getFullMessage()); + } + + /** + * Test parsing of a commit whose encoding is given and works. + * + * @throws Exception + */ + public void testParse_explicit_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("EUC-JP")); + b.write("type tree\n".getBytes("EUC-JP")); + b.write("tag v1.2.3.4.5\n".getBytes("EUC-JP")); + b + .write("tagger F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("EUC-JP")); + b.write("encoding euc_JP\n".getBytes("EUC-JP")); + b.write("\n".getBytes("EUC-JP")); + b.write("\u304d\u308c\u3044\n".getBytes("EUC-JP")); + b.write("\n".getBytes("EUC-JP")); + b.write("Hi\n".getBytes("EUC-JP")); + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("F\u00f6r fattare", c.getTaggerIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + /** + * This is a twisted case, but show what we expect here. We can revise the + * expectations provided this case is updated. + * + * What happens here is that an encoding us given, but data is not encoded + * that way (and we can detect it), so we try other encodings. + * + * @throws Exception + */ + public void testParse_explicit_bad_encoded() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("UTF-8")); + b.write("type tree\n".getBytes("UTF-8")); + b.write("tag v1.2.3.4.5\n".getBytes("UTF-8")); + b + .write("tagger F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("ISO-8859-1")); + b.write("encoding EUC-JP\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Hi\n".getBytes("UTF-8")); + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("F\u00f6r fattare", c.getTaggerIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + /** + * This is a twisted case too, but show what we expect here. We can revise + * the expectations provided this case is updated. + * + * What happens here is that an encoding us given, but data is not encoded + * that way (and we can detect it), so we try other encodings. Here data + * could actually be decoded in the stated encoding, but we override using + * UTF-8. + * + * @throws Exception + */ + public void testParse_explicit_bad_encoded2() throws Exception { + final ByteArrayOutputStream b = new ByteArrayOutputStream(); + b.write("object 9788669ad918b6fcce64af8882fc9a81cb6aba67\n" + .getBytes("UTF-8")); + b.write("type tree\n".getBytes("UTF-8")); + b.write("tag v1.2.3.4.5\n".getBytes("UTF-8")); + b + .write("tagger F\u00f6r fattare <a_u_thor@example.com> 1218123387 +0700\n" + .getBytes("UTF-8")); + b.write("encoding ISO-8859-1\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("\u304d\u308c\u3044\n".getBytes("UTF-8")); + b.write("\n".getBytes("UTF-8")); + b.write("Hi\n".getBytes("UTF-8")); + final RevTag c; + c = new RevTag(id("9473095c4cb2f12aefe1db8a355fe3fafba42f67")); + c.parseCanonical(new RevWalk(db), b.toByteArray()); + + assertEquals("F\u00f6r fattare", c.getTaggerIdent().getName()); + assertEquals("\u304d\u308c\u3044", c.getShortMessage()); + assertEquals("\u304d\u308c\u3044\n\nHi\n", c.getFullMessage()); + } + + public void testParse_NoMessage() throws Exception { + final String msg = ""; + final RevTag c = create(msg); + assertEquals(msg, c.getFullMessage()); + assertEquals(msg, c.getShortMessage()); + } + + public void testParse_OnlyLFMessage() throws Exception { + final RevTag c = create("\n"); + assertEquals("\n", c.getFullMessage()); + assertEquals("", c.getShortMessage()); + } + + public void testParse_ShortLineOnlyNoLF() throws Exception { + final String shortMsg = "This is a short message."; + final RevTag c = create(shortMsg); + assertEquals(shortMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEndLF() throws Exception { + final String shortMsg = "This is a short message."; + final String fullMsg = shortMsg + "\n"; + final RevTag c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEmbeddedLF() throws Exception { + final String fullMsg = "This is a\nshort message."; + final String shortMsg = fullMsg.replace('\n', ' '); + final RevTag c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_ShortLineOnlyEmbeddedAndEndingLF() throws Exception { + final String fullMsg = "This is a\nshort message.\n"; + final String shortMsg = "This is a short message."; + final RevTag c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + public void testParse_GitStyleMessage() throws Exception { + final String shortMsg = "This fixes a bug."; + final String body = "We do it with magic and pixie dust and stuff.\n" + + "\n" + "Signed-off-by: A U. Thor <author@example.com>\n"; + final String fullMsg = shortMsg + "\n" + "\n" + body; + final RevTag c = create(fullMsg); + assertEquals(fullMsg, c.getFullMessage()); + assertEquals(shortMsg, c.getShortMessage()); + } + + private static ObjectId id(final String str) { + return ObjectId.fromString(str); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java new file mode 100644 index 0000000000..9e879c5f0d --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkCullTest.java @@ -0,0 +1,100 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public class RevWalkCullTest extends RevWalkTestCase { + public void testProperlyCullAllAncestors1() throws Exception { + // Credit goes to Junio C Hamano <gitster@pobox.com> for this + // test case in git-core (t/t6009-rev-list-parent.sh) + // + // We induce a clock skew so two is dated before one. + // + final RevCommit a = commit(); + final RevCommit b = commit(-2400, a); + final RevCommit c = commit(b); + final RevCommit d = commit(c); + + markStart(a); + markUninteresting(d); + assertNull(rw.next()); + } + + public void testProperlyCullAllAncestors2() throws Exception { + // Despite clock skew on c1 being very old it should not + // produce, neither should a or b, or any part of that chain. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(-5, b); + final RevCommit c2 = commit(10, b); + final RevCommit d = commit(c1, c2); + + markStart(d); + markUninteresting(c1); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertNull(rw.next()); + } + + public void testProperlyCullAllAncestors_LongHistory() throws Exception { + final RevCommit a = commit(); + RevCommit b = commit(a); + for (int i = 0; i < 24; i++) { + b = commit(b); + if ((i & 2) == 0) + markUninteresting(b); + } + final RevCommit c = commit(b); + + markStart(c); + markUninteresting(b); + assertCommit(c, rw.next()); + assertNull(rw.next()); + + // We should have aborted before we got back so far that "a" + // would be parsed. Thus, its parents shouldn't be allocated. + // + assertNull(a.parents); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java new file mode 100644 index 0000000000..db4c38e72b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkFilterTest.java @@ -0,0 +1,297 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.io.IOException; +import java.util.Date; + +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.errors.MissingObjectException; +import org.eclipse.jgit.errors.StopWalkException; +import org.eclipse.jgit.revwalk.filter.AndRevFilter; +import org.eclipse.jgit.revwalk.filter.CommitTimeRevFilter; +import org.eclipse.jgit.revwalk.filter.NotRevFilter; +import org.eclipse.jgit.revwalk.filter.OrRevFilter; +import org.eclipse.jgit.revwalk.filter.RevFilter; + +public class RevWalkFilterTest extends RevWalkTestCase { + private static final MyAll MY_ALL = new MyAll(); + + public void testFilter_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(RevFilter.ALL); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_Negate_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(RevFilter.ALL.negate()); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_NOT_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(NotRevFilter.create(RevFilter.ALL)); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(RevFilter.NONE); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_NOT_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(NotRevFilter.create(RevFilter.NONE)); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_ALL_And_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(AndRevFilter.create(RevFilter.ALL, RevFilter.NONE)); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_NONE_And_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(AndRevFilter.create(RevFilter.NONE, RevFilter.ALL)); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_ALL_Or_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(OrRevFilter.create(RevFilter.ALL, RevFilter.NONE)); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_NONE_Or_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(OrRevFilter.create(RevFilter.NONE, RevFilter.ALL)); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_MY_ALL_And_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(AndRevFilter.create(MY_ALL, RevFilter.NONE)); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_NONE_And_MY_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(AndRevFilter.create(RevFilter.NONE, MY_ALL)); + markStart(c); + assertNull(rw.next()); + } + + public void testFilter_MY_ALL_Or_NONE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(OrRevFilter.create(MY_ALL, RevFilter.NONE)); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_NONE_Or_MY_ALL() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + + rw.setRevFilter(OrRevFilter.create(RevFilter.NONE, MY_ALL)); + markStart(c); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testFilter_NO_MERGES() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(b); + final RevCommit c2 = commit(b); + final RevCommit d = commit(c1, c2); + final RevCommit e = commit(d); + + rw.setRevFilter(RevFilter.NO_MERGES); + markStart(e); + assertCommit(e, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testCommitTimeRevFilter() throws Exception { + final RevCommit a = commit(); + tick(100); + + final RevCommit b = commit(a); + tick(100); + + Date since = new Date(nowTick); + final RevCommit c1 = commit(b); + tick(100); + + final RevCommit c2 = commit(b); + tick(100); + + Date until = new Date(nowTick); + final RevCommit d = commit(c1, c2); + tick(100); + + final RevCommit e = commit(d); + + { + RevFilter after = CommitTimeRevFilter.after(since); + assertNotNull(after); + rw.setRevFilter(after); + markStart(e); + assertCommit(e, rw.next()); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter before = CommitTimeRevFilter.before(until); + assertNotNull(before); + rw.reset(); + rw.setRevFilter(before); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + { + RevFilter between = CommitTimeRevFilter.between(since, until); + assertNotNull(between); + rw.reset(); + rw.setRevFilter(between); + markStart(e); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + } + + private static class MyAll extends RevFilter { + @Override + public RevFilter clone() { + return this; + } + + @Override + public boolean include(RevWalk walker, RevCommit cmit) + throws StopWalkException, MissingObjectException, + IncorrectObjectTypeException, IOException { + return true; + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java new file mode 100644 index 0000000000..10c9f9b12e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkMergeBaseTest.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import org.eclipse.jgit.revwalk.filter.RevFilter; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +public class RevWalkMergeBaseTest extends RevWalkTestCase { + public void testNone() throws Exception { + final RevCommit c1 = commit(commit(commit())); + final RevCommit c2 = commit(commit(commit())); + + rw.setRevFilter(RevFilter.MERGE_BASE); + markStart(c1); + markStart(c2); + assertNull(rw.next()); + } + + public void testDisallowTreeFilter() throws Exception { + final RevCommit c1 = commit(); + final RevCommit c2 = commit(); + + rw.setRevFilter(RevFilter.MERGE_BASE); + rw.setTreeFilter(TreeFilter.ANY_DIFF); + markStart(c1); + markStart(c2); + try { + assertNull(rw.next()); + fail("did not throw IllegalStateException"); + } catch (IllegalStateException ise) { + // expected result + } + } + + public void testSimple() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(commit(commit(commit(commit(b))))); + final RevCommit c2 = commit(commit(commit(commit(commit(b))))); + + rw.setRevFilter(RevFilter.MERGE_BASE); + markStart(c1); + markStart(c2); + assertCommit(b, rw.next()); + assertNull(rw.next()); + } + + public void testMultipleHeads_SameBase1() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(commit(commit(commit(commit(b))))); + final RevCommit c2 = commit(commit(commit(commit(commit(b))))); + final RevCommit c3 = commit(commit(commit(b))); + + rw.setRevFilter(RevFilter.MERGE_BASE); + markStart(c1); + markStart(c2); + markStart(c3); + assertCommit(b, rw.next()); + assertNull(rw.next()); + } + + public void testMultipleHeads_SameBase2() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + final RevCommit d1 = commit(commit(commit(commit(commit(b))))); + final RevCommit d2 = commit(commit(commit(commit(commit(c))))); + final RevCommit d3 = commit(commit(commit(c))); + + rw.setRevFilter(RevFilter.MERGE_BASE); + markStart(d1); + markStart(d2); + markStart(d3); + assertCommit(b, rw.next()); + assertNull(rw.next()); + } + + public void testCrissCross() throws Exception { + // See http://marc.info/?l=git&m=111463358500362&w=2 for a nice + // description of what this test is creating. We don't have a + // clean merge base for d,e as they each merged the parents b,c + // in different orders. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(a); + final RevCommit d = commit(b, c); + final RevCommit e = commit(c, b); + + rw.setRevFilter(RevFilter.MERGE_BASE); + markStart(d); + markStart(e); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertNull(rw.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter1Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter1Test.java new file mode 100644 index 0000000000..986a886566 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter1Test.java @@ -0,0 +1,182 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.Collections; + +import org.eclipse.jgit.treewalk.filter.AndTreeFilter; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +public class RevWalkPathFilter1Test extends RevWalkTestCase { + protected void filter(final String path) { + rw.setTreeFilter(AndTreeFilter.create(PathFilterGroup + .createFromStrings(Collections.singleton(path)), + TreeFilter.ANY_DIFF)); + } + + public void testEmpty_EmptyTree() throws Exception { + final RevCommit a = commit(); + filter("a"); + markStart(a); + assertNull(rw.next()); + } + + public void testEmpty_NoMatch() throws Exception { + final RevCommit a = commit(tree(file("0", blob("0")))); + filter("a"); + markStart(a); + assertNull(rw.next()); + } + + public void testSimple1() throws Exception { + final RevCommit a = commit(tree(file("0", blob("0")))); + filter("0"); + markStart(a); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testEdits_MatchNone() throws Exception { + final RevCommit a = commit(tree(file("0", blob("a")))); + final RevCommit b = commit(tree(file("0", blob("b"))), a); + final RevCommit c = commit(tree(file("0", blob("c"))), b); + final RevCommit d = commit(tree(file("0", blob("d"))), c); + filter("a"); + markStart(d); + assertNull(rw.next()); + } + + public void testEdits_MatchAll() throws Exception { + final RevCommit a = commit(tree(file("0", blob("a")))); + final RevCommit b = commit(tree(file("0", blob("b"))), a); + final RevCommit c = commit(tree(file("0", blob("c"))), b); + final RevCommit d = commit(tree(file("0", blob("d"))), c); + filter("0"); + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testStringOfPearls_FilePath1() throws Exception { + final RevCommit a = commit(tree(file("d/f", blob("a")))); + final RevCommit b = commit(tree(file("d/f", blob("a"))), a); + final RevCommit c = commit(tree(file("d/f", blob("b"))), b); + filter("d/f"); + markStart(c); + + assertCommit(c, rw.next()); + assertEquals(1, c.getParentCount()); + assertCommit(a, c.getParent(0)); // b was skipped + + assertCommit(a, rw.next()); + assertEquals(0, a.getParentCount()); + assertNull(rw.next()); + } + + public void testStringOfPearls_FilePath2() throws Exception { + final RevCommit a = commit(tree(file("d/f", blob("a")))); + final RevCommit b = commit(tree(file("d/f", blob("a"))), a); + final RevCommit c = commit(tree(file("d/f", blob("b"))), b); + final RevCommit d = commit(tree(file("d/f", blob("b"))), c); + filter("d/f"); + markStart(d); + + // d was skipped + assertCommit(c, rw.next()); + assertEquals(1, c.getParentCount()); + assertCommit(a, c.getParent(0)); // b was skipped + + assertCommit(a, rw.next()); + assertEquals(0, a.getParentCount()); + assertNull(rw.next()); + } + + public void testStringOfPearls_DirPath2() throws Exception { + final RevCommit a = commit(tree(file("d/f", blob("a")))); + final RevCommit b = commit(tree(file("d/f", blob("a"))), a); + final RevCommit c = commit(tree(file("d/f", blob("b"))), b); + final RevCommit d = commit(tree(file("d/f", blob("b"))), c); + filter("d"); + markStart(d); + + // d was skipped + assertCommit(c, rw.next()); + assertEquals(1, c.getParentCount()); + assertCommit(a, c.getParent(0)); // b was skipped + + assertCommit(a, rw.next()); + assertEquals(0, a.getParentCount()); + assertNull(rw.next()); + } + + public void testStringOfPearls_FilePath3() throws Exception { + final RevCommit a = commit(tree(file("d/f", blob("a")))); + final RevCommit b = commit(tree(file("d/f", blob("a"))), a); + final RevCommit c = commit(tree(file("d/f", blob("b"))), b); + final RevCommit d = commit(tree(file("d/f", blob("b"))), c); + final RevCommit e = commit(tree(file("d/f", blob("b"))), d); + final RevCommit f = commit(tree(file("d/f", blob("b"))), e); + final RevCommit g = commit(tree(file("d/f", blob("b"))), f); + final RevCommit h = commit(tree(file("d/f", blob("b"))), g); + final RevCommit i = commit(tree(file("d/f", blob("c"))), h); + filter("d/f"); + markStart(i); + + assertCommit(i, rw.next()); + assertEquals(1, i.getParentCount()); + assertCommit(c, i.getParent(0)); // h..d was skipped + + assertCommit(c, rw.next()); + assertEquals(1, c.getParentCount()); + assertCommit(a, c.getParent(0)); // b was skipped + + assertCommit(a, rw.next()); + assertEquals(0, a.getParentCount()); + assertNull(rw.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter6012Test.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter6012Test.java new file mode 100644 index 0000000000..73d41eae64 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkPathFilter6012Test.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.lang.reflect.Field; +import java.util.Collections; +import java.util.HashMap; + +import org.eclipse.jgit.treewalk.filter.AndTreeFilter; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +// Note: Much of this test case is broken as it depends upon +// the graph applying topological sorting *before* doing merge +// simplification. It also depends upon a difference between +// full history and non-full history for a path, something we +// don't quite yet have a distiction for in JGit. +// +public class RevWalkPathFilter6012Test extends RevWalkTestCase { + private static final String pA = "pA", pF = "pF", pE = "pE"; + + private RevCommit a, b, c, d, e, f, g, h, i; + + private HashMap<RevCommit, String> byName; + + public void setUp() throws Exception { + super.setUp(); + + // Test graph was stolen from git-core t6012-rev-list-simplify + // (by Junio C Hamano in 65347030590bcc251a9ff2ed96487a0f1b9e9fa8) + // + final RevBlob zF = blob("zF"); + final RevBlob zH = blob("zH"); + final RevBlob zI = blob("zI"); + final RevBlob zS = blob("zS"); + final RevBlob zY = blob("zY"); + + a = commit(tree(file(pF, zH))); + b = commit(tree(file(pF, zI)), a); + c = commit(tree(file(pF, zI)), a); + d = commit(tree(file(pA, zS), file(pF, zI)), c); + parse(d); + e = commit(d.getTree(), d, b); + f = commit(tree(file(pA, zS), file(pE, zY), file(pF, zI)), e); + parse(f); + g = commit(tree(file(pE, zY), file(pF, zI)), b); + h = commit(f.getTree(), g, f); + i = commit(tree(file(pA, zS), file(pE, zY), file(pF, zF)), h); + + byName = new HashMap<RevCommit, String>(); + for (Field z : RevWalkPathFilter6012Test.class.getDeclaredFields()) { + if (z.getType() == RevCommit.class) + byName.put((RevCommit) z.get(this), z.getName()); + } + } + + protected void check(final RevCommit... order) throws Exception { + markStart(i); + final StringBuilder act = new StringBuilder(); + for (final RevCommit z : rw) { + final String name = byName.get(z); + assertNotNull(name); + act.append(name); + act.append(' '); + } + final StringBuilder exp = new StringBuilder(); + for (final RevCommit z : order) { + final String name = byName.get(z); + assertNotNull(name); + exp.append(name); + exp.append(' '); + } + assertEquals(exp.toString(), act.toString()); + } + + protected void filter(final String path) { + rw.setTreeFilter(AndTreeFilter.create(PathFilterGroup + .createFromStrings(Collections.singleton(path)), + TreeFilter.ANY_DIFF)); + } + + public void test1() throws Exception { + // TODO --full-history + check(i, h, g, f, e, d, c, b, a); + } + + public void test2() throws Exception { + // TODO --full-history + filter(pF); + // TODO fix broken test + // check(i, h, e, c, b, a); + } + + public void test3() throws Exception { + // TODO --full-history + rw.sort(RevSort.TOPO); + filter(pF); + // TODO fix broken test + // check(i, h, e, c, b, a); + } + + public void test4() throws Exception { + // TODO --full-history + rw.sort(RevSort.COMMIT_TIME_DESC); + filter(pF); + // TODO fix broken test + // check(i, h, e, c, b, a); + } + + public void test5() throws Exception { + // TODO --simplify-merges + filter(pF); + // TODO fix broken test + // check(i, e, c, b, a); + } + + public void test6() throws Exception { + filter(pF); + check(i, b, a); + } + + public void test7() throws Exception { + rw.sort(RevSort.TOPO); + filter(pF); + check(i, b, a); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkSortTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkSortTest.java new file mode 100644 index 0000000000..0d3e0cf5aa --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkSortTest.java @@ -0,0 +1,168 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +public class RevWalkSortTest extends RevWalkTestCase { + public void testSort_Default() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(1, a); + final RevCommit c = commit(1, b); + final RevCommit d = commit(1, c); + + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testSort_COMMIT_TIME_DESC() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + final RevCommit d = commit(c); + + rw.sort(RevSort.COMMIT_TIME_DESC); + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testSort_REVERSE() throws Exception { + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(b); + final RevCommit d = commit(c); + + rw.sort(RevSort.REVERSE); + markStart(d); + assertCommit(a, rw.next()); + assertCommit(b, rw.next()); + assertCommit(c, rw.next()); + assertCommit(d, rw.next()); + assertNull(rw.next()); + } + + public void testSort_COMMIT_TIME_DESC_OutOfOrder1() throws Exception { + // Despite being out of order time-wise, a strand-of-pearls must + // still maintain topological order. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c = commit(-5, b); + final RevCommit d = commit(10, c); + assertTrue(parse(a).getCommitTime() < parse(d).getCommitTime()); + assertTrue(parse(c).getCommitTime() < parse(b).getCommitTime()); + + rw.sort(RevSort.COMMIT_TIME_DESC); + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testSort_COMMIT_TIME_DESC_OutOfOrder2() throws Exception { + // c1 is back dated before its parent. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(-5, b); + final RevCommit c2 = commit(10, b); + final RevCommit d = commit(c1, c2); + + rw.sort(RevSort.COMMIT_TIME_DESC); + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertCommit(c1, rw.next()); + assertNull(rw.next()); + } + + public void testSort_TOPO() throws Exception { + // c1 is back dated before its parent. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(-5, b); + final RevCommit c2 = commit(10, b); + final RevCommit d = commit(c1, c2); + + rw.sort(RevSort.TOPO); + markStart(d); + assertCommit(d, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(b, rw.next()); + assertCommit(a, rw.next()); + assertNull(rw.next()); + } + + public void testSort_TOPO_REVERSE() throws Exception { + // c1 is back dated before its parent. + // + final RevCommit a = commit(); + final RevCommit b = commit(a); + final RevCommit c1 = commit(-5, b); + final RevCommit c2 = commit(10, b); + final RevCommit d = commit(c1, c2); + + rw.sort(RevSort.TOPO); + rw.sort(RevSort.REVERSE, true); + markStart(d); + assertCommit(a, rw.next()); + assertCommit(b, rw.next()); + assertCommit(c1, rw.next()); + assertCommit(c2, rw.next()); + assertCommit(d, rw.next()); + assertNull(rw.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java new file mode 100644 index 0000000000..50fbce41aa --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/revwalk/RevWalkTestCase.java @@ -0,0 +1,183 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.revwalk; + +import java.util.Collections; +import java.util.Date; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.Commit; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.PersonIdent; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.Tag; +import org.eclipse.jgit.lib.Tree; +import org.eclipse.jgit.treewalk.TreeWalk; +import org.eclipse.jgit.treewalk.filter.PathFilterGroup; + +/** Support for tests of the {@link RevWalk} class. */ +public abstract class RevWalkTestCase extends RepositoryTestCase { + protected ObjectWriter ow; + + protected RevTree emptyTree; + + protected long nowTick; + + protected RevWalk rw; + + public void setUp() throws Exception { + super.setUp(); + ow = new ObjectWriter(db); + rw = createRevWalk(); + emptyTree = rw.parseTree(ow.writeTree(new Tree(db))); + nowTick = 1236977987000L; + } + + protected RevWalk createRevWalk() { + return new RevWalk(db); + } + + protected void tick(final int secDelta) { + nowTick += secDelta * 1000L; + } + + protected RevBlob blob(final String content) throws Exception { + return rw.lookupBlob(ow.writeBlob(Constants.encode(content))); + } + + protected DirCacheEntry file(final String path, final RevBlob blob) + throws Exception { + final DirCacheEntry e = new DirCacheEntry(path); + e.setFileMode(FileMode.REGULAR_FILE); + e.setObjectId(blob); + return e; + } + + protected RevTree tree(final DirCacheEntry... entries) throws Exception { + final DirCache dc = DirCache.newInCore(); + final DirCacheBuilder b = dc.builder(); + for (final DirCacheEntry e : entries) + b.add(e); + b.finish(); + return rw.lookupTree(dc.writeTree(ow)); + } + + protected RevObject get(final RevTree tree, final String path) + throws Exception { + final TreeWalk tw = new TreeWalk(db); + tw.setFilter(PathFilterGroup.createFromStrings(Collections + .singleton(path))); + tw.reset(tree); + while (tw.next()) { + if (tw.isSubtree() && !path.equals(tw.getPathString())) { + tw.enterSubtree(); + continue; + } + final ObjectId entid = tw.getObjectId(0); + final FileMode entmode = tw.getFileMode(0); + return rw.lookupAny(entid, entmode.getObjectType()); + } + fail("Can't find " + path + " in tree " + tree.name()); + return null; // never reached. + } + + protected RevCommit commit(final RevCommit... parents) throws Exception { + return commit(1, emptyTree, parents); + } + + protected RevCommit commit(final RevTree tree, final RevCommit... parents) + throws Exception { + return commit(1, tree, parents); + } + + protected RevCommit commit(final int secDelta, final RevCommit... parents) + throws Exception { + return commit(secDelta, emptyTree, parents); + } + + protected RevCommit commit(final int secDelta, final RevTree tree, + final RevCommit... parents) throws Exception { + tick(secDelta); + final Commit c = new Commit(db); + c.setTreeId(tree); + c.setParentIds(parents); + c.setAuthor(new PersonIdent(jauthor, new Date(nowTick))); + c.setCommitter(new PersonIdent(jcommitter, new Date(nowTick))); + c.setMessage(""); + return rw.lookupCommit(ow.writeCommit(c)); + } + + protected RevTag tag(final String name, final RevObject dst) + throws Exception { + final Tag t = new Tag(db); + t.setType(Constants.typeString(dst.getType())); + t.setObjId(dst.toObjectId()); + t.setTag(name); + t.setTagger(new PersonIdent(jcommitter, new Date(nowTick))); + t.setMessage(""); + return (RevTag) rw.lookupAny(ow.writeTag(t), Constants.OBJ_TAG); + } + + protected <T extends RevObject> T parse(final T t) throws Exception { + rw.parseBody(t); + return t; + } + + protected void markStart(final RevCommit commit) throws Exception { + rw.markStart(commit); + } + + protected void markUninteresting(final RevCommit commit) throws Exception { + rw.markUninteresting(commit); + } + + protected void assertCommit(final RevCommit exp, final RevCommit act) { + assertSame(exp, act); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java new file mode 100644 index 0000000000..fb9b358b2a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/BundleWriterTest.java @@ -0,0 +1,160 @@ +/* + * Copyright (C) 2008, Google Inc. + * Copyright (C) 2008, Mike Ralphson <mike@abacus.co.uk> + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.IOException; +import java.net.URISyntaxException; +import java.util.Collections; +import java.util.Set; + +import org.eclipse.jgit.errors.MissingBundlePrerequisiteException; +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.lib.NullProgressMonitor; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.revwalk.RevCommit; +import org.eclipse.jgit.revwalk.RevWalk; + +public class BundleWriterTest extends RepositoryTestCase { + + public void testWrite0() throws Exception { + // Create a tiny bundle, (well one of) the first commits only + final byte[] bundle = makeBundle("refs/heads/firstcommit", + "42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", null); + + // Then we clone a new repo from that bundle and do a simple test. This + // makes sure + // we could read the bundle we created. + Repository newRepo = createNewEmptyRepo(); + FetchResult fetchResult = fetchFromBundle(newRepo, bundle); + Ref advertisedRef = fetchResult + .getAdvertisedRef("refs/heads/firstcommit"); + + // We expect firstcommit to appear by id + assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", advertisedRef + .getObjectId().name()); + // ..and by name as the bundle created a new ref + assertEquals("42e4e7c5e507e113ebbb7801b16b52cf867b7ce1", newRepo + .resolve("refs/heads/firstcommit").name()); + } + + /** + * Incremental bundle test + * + * @throws Exception + */ + public void testWrite1() throws Exception { + byte[] bundle; + + // Create a small bundle, an early commit + bundle = makeBundle("refs/heads/aa", db.resolve("a").name(), null); + + // Then we clone a new repo from that bundle and do a simple test. This + // makes sure + // we could read the bundle we created. + Repository newRepo = createNewEmptyRepo(); + FetchResult fetchResult = fetchFromBundle(newRepo, bundle); + Ref advertisedRef = fetchResult.getAdvertisedRef("refs/heads/aa"); + + assertEquals(db.resolve("a").name(), advertisedRef.getObjectId().name()); + assertEquals(db.resolve("a").name(), newRepo.resolve("refs/heads/aa") + .name()); + assertNull(newRepo.resolve("refs/heads/a")); + + // Next an incremental bundle + bundle = makeBundle("refs/heads/cc", db.resolve("c").name(), + new RevWalk(db).parseCommit(db.resolve("a").toObjectId())); + fetchResult = fetchFromBundle(newRepo, bundle); + advertisedRef = fetchResult.getAdvertisedRef("refs/heads/cc"); + assertEquals(db.resolve("c").name(), advertisedRef.getObjectId().name()); + assertEquals(db.resolve("c").name(), newRepo.resolve("refs/heads/cc") + .name()); + assertNull(newRepo.resolve("refs/heads/c")); + assertNull(newRepo.resolve("refs/heads/a")); // still unknown + + try { + // Check that we actually needed the first bundle + Repository newRepo2 = createNewEmptyRepo(); + fetchResult = fetchFromBundle(newRepo2, bundle); + fail("We should not be able to fetch from bundle with prerequisites that are not fulfilled"); + } catch (MissingBundlePrerequisiteException e) { + assertTrue(e.getMessage() + .indexOf(db.resolve("refs/heads/a").name()) >= 0); + } + } + + private FetchResult fetchFromBundle(final Repository newRepo, + final byte[] bundle) throws URISyntaxException, + NotSupportedException, TransportException { + final URIish uri = new URIish("in-memory://"); + final ByteArrayInputStream in = new ByteArrayInputStream(bundle); + final RefSpec rs = new RefSpec("refs/heads/*:refs/heads/*"); + final Set<RefSpec> refs = Collections.singleton(rs); + return new TransportBundleStream(newRepo, uri, in).fetch( + NullProgressMonitor.INSTANCE, refs); + } + + private byte[] makeBundle(final String name, + final String anObjectToInclude, final RevCommit assume) + throws FileNotFoundException, IOException { + final BundleWriter bw; + + bw = new BundleWriter(db, NullProgressMonitor.INSTANCE); + bw.include(name, ObjectId.fromString(anObjectToInclude)); + if (assume != null) + bw.assume(assume); + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + bw.writeBundle(out); + return out.toByteArray(); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java new file mode 100644 index 0000000000..78f4393c3a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/IndexPackTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2007-2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.PackFile; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.TextProgressMonitor; +import org.eclipse.jgit.util.JGitTestUtil; + +/** + * Test indexing of git packs. A pack is read from a stream, copied + * to a new pack and an index is created. Then the packs are tested + * to make sure they contain the expected objects (well we don't test + * for all of them unless the packs are very small). + */ +public class IndexPackTest extends RepositoryTestCase { + + /** + * Test indexing one of the test packs in the egit repo. It has deltas. + * + * @throws IOException + */ + public void test1() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile("pack-34be9032ac282b11fa9babdc2b2a93ca996c9c2f.pack"); + final InputStream is = new FileInputStream(packFile); + try { + IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack1")); + pack.index(new TextProgressMonitor()); + PackFile file = new PackFile(new File(trash, "tmp_pack1.idx"), new File(trash, "tmp_pack1.pack")); + assertTrue(file.hasObject(ObjectId.fromString("4b825dc642cb6eb9a060e54bf8d69288fbee4904"))); + assertTrue(file.hasObject(ObjectId.fromString("540a36d136cf413e4b064c2b0e0a4db60f77feab"))); + assertTrue(file.hasObject(ObjectId.fromString("5b6e7c66c276e7610d4a73c70ec1a1f7c1003259"))); + assertTrue(file.hasObject(ObjectId.fromString("6ff87c4664981e4397625791c8ea3bbb5f2279a3"))); + assertTrue(file.hasObject(ObjectId.fromString("82c6b885ff600be425b4ea96dee75dca255b69e7"))); + assertTrue(file.hasObject(ObjectId.fromString("902d5476fa249b7abc9d84c611577a81381f0327"))); + assertTrue(file.hasObject(ObjectId.fromString("aabf2ffaec9b497f0950352b3e582d73035c2035"))); + assertTrue(file.hasObject(ObjectId.fromString("c59759f143fb1fe21c197981df75a7ee00290799"))); + } finally { + is.close(); + } + } + + /** + * This is just another pack. It so happens that we have two convenient pack to + * test with in the repository. + * + * @throws IOException + */ + public void test2() throws IOException { + File packFile = JGitTestUtil.getTestResourceFile("pack-df2982f284bbabb6bdb59ee3fcc6eb0983e20371.pack"); + final InputStream is = new FileInputStream(packFile); + try { + IndexPack pack = new IndexPack(db, is, new File(trash, "tmp_pack2")); + pack.index(new TextProgressMonitor()); + PackFile file = new PackFile(new File(trash, "tmp_pack2.idx"), new File(trash, "tmp_pack2.pack")); + assertTrue(file.hasObject(ObjectId.fromString("02ba32d3649e510002c21651936b7077aa75ffa9"))); + assertTrue(file.hasObject(ObjectId.fromString("0966a434eb1a025db6b71485ab63a3bfbea520b6"))); + assertTrue(file.hasObject(ObjectId.fromString("09efc7e59a839528ac7bda9fa020dc9101278680"))); + assertTrue(file.hasObject(ObjectId.fromString("0a3d7772488b6b106fb62813c4d6d627918d9181"))); + assertTrue(file.hasObject(ObjectId.fromString("1004d0d7ac26fbf63050a234c9b88a46075719d3"))); + assertTrue(file.hasObject(ObjectId.fromString("10da5895682013006950e7da534b705252b03be6"))); + assertTrue(file.hasObject(ObjectId.fromString("1203b03dc816ccbb67773f28b3c19318654b0bc8"))); + assertTrue(file.hasObject(ObjectId.fromString("15fae9e651043de0fd1deef588aa3fbf5a7a41c6"))); + assertTrue(file.hasObject(ObjectId.fromString("16f9ec009e5568c435f473ba3a1df732d49ce8c3"))); + assertTrue(file.hasObject(ObjectId.fromString("1fd7d579fb6ae3fe942dc09c2c783443d04cf21e"))); + assertTrue(file.hasObject(ObjectId.fromString("20a8ade77639491ea0bd667bf95de8abf3a434c8"))); + assertTrue(file.hasObject(ObjectId.fromString("2675188fd86978d5bc4d7211698b2118ae3bf658"))); + // and lots more... + } finally { + is.close(); + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java new file mode 100644 index 0000000000..abb6fe0db0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/LongMapTest.java @@ -0,0 +1,138 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import junit.framework.TestCase; + +public class LongMapTest extends TestCase { + private LongMap<Long> map; + + protected void setUp() throws Exception { + super.setUp(); + map = new LongMap<Long>(); + } + + public void testEmptyMap() { + assertFalse(map.containsKey(0)); + assertFalse(map.containsKey(1)); + + assertNull(map.get(0)); + assertNull(map.get(1)); + + assertNull(map.remove(0)); + assertNull(map.remove(1)); + } + + public void testInsertMinValue() { + final Long min = Long.valueOf(Long.MIN_VALUE); + assertNull(map.put(Long.MIN_VALUE, min)); + assertTrue(map.containsKey(Long.MIN_VALUE)); + assertSame(min, map.get(Long.MIN_VALUE)); + assertFalse(map.containsKey(Integer.MIN_VALUE)); + } + + public void testReplaceMaxValue() { + final Long min = Long.valueOf(Long.MAX_VALUE); + final Long one = Long.valueOf(1); + assertNull(map.put(Long.MAX_VALUE, min)); + assertSame(min, map.get(Long.MAX_VALUE)); + assertSame(min, map.put(Long.MAX_VALUE, one)); + assertSame(one, map.get(Long.MAX_VALUE)); + } + + public void testRemoveOne() { + final long start = 1; + assertNull(map.put(start, Long.valueOf(start))); + assertEquals(Long.valueOf(start), map.remove(start)); + assertFalse(map.containsKey(start)); + } + + public void testRemoveCollision1() { + // This test relies upon the fact that we always >>> 1 the value + // to derive an unsigned hash code. Thus, 0 and 1 fall into the + // same hash bucket. Further it relies on the fact that we add + // the 2nd put at the top of the chain, so removing the 1st will + // cause a different code path. + // + assertNull(map.put(0, Long.valueOf(0))); + assertNull(map.put(1, Long.valueOf(1))); + assertEquals(Long.valueOf(0), map.remove(0)); + + assertFalse(map.containsKey(0)); + assertTrue(map.containsKey(1)); + } + + public void testRemoveCollision2() { + // This test relies upon the fact that we always >>> 1 the value + // to derive an unsigned hash code. Thus, 0 and 1 fall into the + // same hash bucket. Further it relies on the fact that we add + // the 2nd put at the top of the chain, so removing the 2nd will + // cause a different code path. + // + assertNull(map.put(0, Long.valueOf(0))); + assertNull(map.put(1, Long.valueOf(1))); + assertEquals(Long.valueOf(1), map.remove(1)); + + assertTrue(map.containsKey(0)); + assertFalse(map.containsKey(1)); + } + + public void testSmallMap() { + final long start = 12; + final long n = 8; + for (long i = start; i < start + n; i++) + assertNull(map.put(i, Long.valueOf(i))); + for (long i = start; i < start + n; i++) + assertEquals(Long.valueOf(i), map.get(i)); + } + + public void testLargeMap() { + final long start = Integer.MAX_VALUE; + final long n = 100000; + for (long i = start; i < start + n; i++) + assertNull(map.put(i, Long.valueOf(i))); + for (long i = start; i < start + n; i++) + assertEquals(Long.valueOf(i), map.get(i)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java new file mode 100644 index 0000000000..f66e2fd33e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/OpenSshConfigTest.java @@ -0,0 +1,228 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.File; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; + +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.transport.OpenSshConfig.Host; + +public class OpenSshConfigTest extends RepositoryTestCase { + private File home; + + private File configFile; + + private OpenSshConfig osc; + + public void setUp() throws Exception { + super.setUp(); + + home = new File(trash, "home"); + home.mkdir(); + + configFile = new File(new File(home, ".ssh"), "config"); + configFile.getParentFile().mkdir(); + + System.setProperty("user.name", "jex_junit"); + osc = new OpenSshConfig(home, configFile); + } + + private void config(final String data) throws IOException { + final OutputStreamWriter fw = new OutputStreamWriter( + new FileOutputStream(configFile), "UTF-8"); + fw.write(data); + fw.close(); + } + + public void testNoConfig() { + final Host h = osc.lookup("repo.or.cz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex_junit", h.getUser()); + assertEquals(22, h.getPort()); + assertNull(h.getIdentityFile()); + } + + public void testSeparatorParsing() throws Exception { + config("Host\tfirst\n" + + "\tHostName\tfirst.tld\n" + + "\n" + + "Host second\n" + + " HostName\tsecond.tld\n" + + "Host=third\n" + + "HostName=third.tld\n\n\n" + + "\t Host = fourth\n\n\n" + + " \t HostName\t=fourth.tld\n" + + "Host\t = last\n" + + "HostName \t last.tld"); + assertNotNull(osc.lookup("first")); + assertEquals("first.tld", osc.lookup("first").getHostName()); + assertNotNull(osc.lookup("second")); + assertEquals("second.tld", osc.lookup("second").getHostName()); + assertNotNull(osc.lookup("third")); + assertEquals("third.tld", osc.lookup("third").getHostName()); + assertNotNull(osc.lookup("fourth")); + assertEquals("fourth.tld", osc.lookup("fourth").getHostName()); + assertNotNull(osc.lookup("last")); + assertEquals("last.tld", osc.lookup("last").getHostName()); + } + + public void testQuoteParsing() throws Exception { + config("Host \"good\"\n" + + " HostName=\"good.tld\"\n" + + " Port=\"6007\"\n" + + " User=\"gooduser\"\n" + + "Host multiple unquoted and \"quoted\" \"hosts\"\n" + + " Port=\"2222\"\n" + + "Host \"spaced\"\n" + + "# Bad host name, but testing preservation of spaces\n" + + " HostName=\" spaced\ttld \"\n" + + "# Misbalanced quotes\n" + + "Host \"bad\"\n" + + "# OpenSSH doesn't allow this but ...\n" + + " HostName=bad.tld\"\n"); + assertEquals("good.tld", osc.lookup("good").getHostName()); + assertEquals("gooduser", osc.lookup("good").getUser()); + assertEquals(6007, osc.lookup("good").getPort()); + assertEquals(2222, osc.lookup("multiple").getPort()); + assertEquals(2222, osc.lookup("quoted").getPort()); + assertEquals(2222, osc.lookup("and").getPort()); + assertEquals(2222, osc.lookup("unquoted").getPort()); + assertEquals(2222, osc.lookup("hosts").getPort()); + assertEquals(" spaced\ttld ", osc.lookup("spaced").getHostName()); + assertEquals("bad.tld\"", osc.lookup("bad").getHostName()); + } + + public void testAlias_DoesNotMatch() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n"); + final Host h = osc.lookup("repo.or.cz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex_junit", h.getUser()); + assertEquals(22, h.getPort()); + assertNull(h.getIdentityFile()); + } + + public void testAlias_OptionsSet() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\tPort 2222\n" + + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_OptionsKeywordCaseInsensitive() throws Exception { + config("hOsT orcz\n" + "\thOsTnAmE repo.or.cz\n" + "\tPORT 2222\n" + + "\tuser jex\n" + "\tidentityfile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_OptionsInherit() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tHostName not.a.host.example.com\n" + "\tPort 2222\n" + + "\tUser jex\n" + "\tIdentityFile .ssh/id_jex\n" + + "\tForwardX11 no\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("repo.or.cz", h.getHostName()); + assertEquals("jex", h.getUser()); + assertEquals(2222, h.getPort()); + assertEquals(new File(home, ".ssh/id_jex"), h.getIdentityFile()); + } + + public void testAlias_PreferredAuthenticationsDefault() throws Exception { + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertNull(h.getPreferredAuthentications()); + } + + public void testAlias_PreferredAuthentications() throws Exception { + config("Host orcz\n" + "\tPreferredAuthentications publickey\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("publickey", h.getPreferredAuthentications()); + } + + public void testAlias_InheritPreferredAuthentications() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tPreferredAuthentications publickey, hostbased\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals("publickey,hostbased", h.getPreferredAuthentications()); + } + + public void testAlias_BatchModeDefault() throws Exception { + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(false, h.isBatchMode()); + } + + public void testAlias_BatchModeYes() throws Exception { + config("Host orcz\n" + "\tBatchMode yes\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(true, h.isBatchMode()); + } + + public void testAlias_InheritBatchMode() throws Exception { + config("Host orcz\n" + "\tHostName repo.or.cz\n" + "\n" + "Host *\n" + + "\tBatchMode yes\n"); + final Host h = osc.lookup("orcz"); + assertNotNull(h); + assertEquals(true, h.isBatchMode()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java new file mode 100644 index 0000000000..1bcac9e37b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineInTest.java @@ -0,0 +1,268 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.MutableObjectId; +import org.eclipse.jgit.lib.ObjectId; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class PacketLineInTest extends TestCase { + private ByteArrayInputStream rawIn; + + private PacketLineIn in; + + // readString + + public void testReadString1() throws IOException { + init("0006a\n0007bc\n"); + assertEquals("a", in.readString()); + assertEquals("bc", in.readString()); + assertEOF(); + } + + public void testReadString2() throws IOException { + init("0032want fcfcfb1fd94829c1a1704f894fc111d14770d34e\n"); + final String act = in.readString(); + assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act); + assertEOF(); + } + + public void testReadString4() throws IOException { + init("0005a0006bc"); + assertEquals("a", in.readString()); + assertEquals("bc", in.readString()); + assertEOF(); + } + + public void testReadString5() throws IOException { + // accept both upper and lower case + init("000Fhi i am a s"); + assertEquals("hi i am a s", in.readString()); + assertEOF(); + + init("000fhi i am a s"); + assertEquals("hi i am a s", in.readString()); + assertEOF(); + } + + public void testReadString_LenHELO() { + init("HELO"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + public void testReadString_Len0001() { + init("0001"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0001", e.getMessage()); + } + } + + public void testReadString_Len0002() { + init("0002"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0002", e.getMessage()); + } + } + + public void testReadString_Len0003() { + init("0003"); + try { + in.readString(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: 0003", e.getMessage()); + } + } + + public void testReadString_Len0004() throws IOException { + init("0004"); + final String act = in.readString(); + assertEquals("", act); + assertNotSame(PacketLineIn.END, act); + assertEOF(); + } + + public void testReadString_End() throws IOException { + init("0000"); + assertSame(PacketLineIn.END, in.readString()); + assertEOF(); + } + + // readStringNoLF + + public void testReadStringRaw1() throws IOException { + init("0005a0006bc"); + assertEquals("a", in.readStringRaw()); + assertEquals("bc", in.readStringRaw()); + assertEOF(); + } + + public void testReadStringRaw2() throws IOException { + init("0031want fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final String act = in.readStringRaw(); + assertEquals("want fcfcfb1fd94829c1a1704f894fc111d14770d34e", act); + assertEOF(); + } + + public void testReadStringRaw3() throws IOException { + init("0004"); + final String act = in.readStringRaw(); + assertEquals("", act); + assertNotSame(PacketLineIn.END, act); + assertEOF(); + } + + public void testReadStringRaw_End() throws IOException { + init("0000"); + assertSame(PacketLineIn.END, in.readStringRaw()); + assertEOF(); + } + + public void testReadStringRaw4() { + init("HELO"); + try { + in.readStringRaw(); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + // readACK + + public void testReadACK_NAK() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + actid.fromString(expid.name()); + + init("0008NAK\n"); + assertSame(PacketLineIn.AckNackResult.NAK, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_ACK1() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + + init("0031ACK fcfcfb1fd94829c1a1704f894fc111d14770d34e\n"); + assertSame(PacketLineIn.AckNackResult.ACK, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_ACKcontinue1() throws IOException { + final ObjectId expid = ObjectId + .fromString("fcfcfb1fd94829c1a1704f894fc111d14770d34e"); + final MutableObjectId actid = new MutableObjectId(); + + init("003aACK fcfcfb1fd94829c1a1704f894fc111d14770d34e continue\n"); + assertSame(PacketLineIn.AckNackResult.ACK_CONTINUE, in.readACK(actid)); + assertTrue(actid.equals(expid)); + assertEOF(); + } + + public void testReadACK_Invalid1() { + init("HELO"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted invalid packet header"); + } catch (IOException e) { + assertEquals("Invalid packet line header: HELO", e.getMessage()); + } + } + + public void testReadACK_Invalid2() { + init("0009HELO\n"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted invalid ACK/NAK"); + } catch (IOException e) { + assertEquals("Expected ACK/NAK, got: HELO", e.getMessage()); + } + } + + public void testReadACK_Invalid3() { + init("0000"); + try { + in.readACK(new MutableObjectId()); + fail("incorrectly accepted no ACK/NAK"); + } catch (IOException e) { + assertEquals("Expected ACK/NAK, found EOF", e.getMessage()); + } + } + + // test support + + private void init(final String msg) { + rawIn = new ByteArrayInputStream(Constants.encodeASCII(msg)); + in = new PacketLineIn(rawIn); + } + + private void assertEOF() { + assertEquals(-1, rawIn.read()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java new file mode 100644 index 0000000000..6eb98ac126 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PacketLineOutTest.java @@ -0,0 +1,181 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class PacketLineOutTest extends TestCase { + private ByteArrayOutputStream rawOut; + + private PacketLineOut out; + + protected void setUp() throws Exception { + super.setUp(); + rawOut = new ByteArrayOutputStream(); + out = new PacketLineOut(rawOut); + } + + // writeString + + public void testWriteString1() throws IOException { + out.writeString("a"); + out.writeString("bc"); + assertBuffer("0005a0006bc"); + } + + public void testWriteString2() throws IOException { + out.writeString("a\n"); + out.writeString("bc\n"); + assertBuffer("0006a\n0007bc\n"); + } + + public void testWriteString3() throws IOException { + out.writeString(""); + assertBuffer("0004"); + } + + // end + + public void testWriteEnd() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + rawOut.write(arg0); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new PacketLineOut(mockout).end(); + assertBuffer("0000"); + assertEquals(1, flushCnt[0]); + } + + // writePacket + + public void testWritePacket1() throws IOException { + out.writePacket(new byte[] { 'a' }); + assertBuffer("0005a"); + } + + public void testWritePacket2() throws IOException { + out.writePacket(new byte[] { 'a', 'b', 'c', 'd' }); + assertBuffer("0008abcd"); + } + + public void testWritePacket3() throws IOException { + final int buflen = SideBandOutputStream.MAX_BUF + - SideBandOutputStream.HDR_SIZE; + final byte[] buf = new byte[buflen]; + for (int i = 0; i < buf.length; i++) { + buf[i] = (byte) i; + } + out.writePacket(buf); + out.flush(); + + final byte[] act = rawOut.toByteArray(); + final String explen = Integer.toString(buf.length + 4, 16); + assertEquals(4 + buf.length, act.length); + assertEquals(new String(act, 0, 4, "UTF-8"), explen); + for (int i = 0, j = 4; i < buf.length; i++, j++) { + assertEquals(buf[i], act[j]); + } + } + + // writeChannelPacket + + public void testWriteChannelPacket1() throws IOException { + out.writeChannelPacket(1, new byte[] { 'a' }, 0, 1); + assertBuffer("0006\001a"); + } + + public void testWriteChannelPacket2() throws IOException { + out.writeChannelPacket(2, new byte[] { 'b' }, 0, 1); + assertBuffer("0006\002b"); + } + + public void testWriteChannelPacket3() throws IOException { + out.writeChannelPacket(3, new byte[] { 'c' }, 0, 1); + assertBuffer("0006\003c"); + } + + // flush + + public void testFlush() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + fail("should not write"); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new PacketLineOut(mockout).flush(); + assertEquals(1, flushCnt[0]); + } + + private void assertBuffer(final String exp) throws IOException { + assertEquals(exp, new String(rawOut.toByteArray(), + Constants.CHARACTER_ENCODING)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java new file mode 100644 index 0000000000..4a47456f69 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/PushProcessTest.java @@ -0,0 +1,418 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.IOException; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; + +import org.eclipse.jgit.errors.NotSupportedException; +import org.eclipse.jgit.errors.TransportException; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ProgressMonitor; +import org.eclipse.jgit.lib.Ref; +import org.eclipse.jgit.lib.Repository; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.TextProgressMonitor; +import org.eclipse.jgit.lib.RefUpdate.Result; +import org.eclipse.jgit.transport.RemoteRefUpdate.Status; + +public class PushProcessTest extends RepositoryTestCase { + private PushProcess process; + + private MockTransport transport; + + private HashSet<RemoteRefUpdate> refUpdates; + + private HashSet<Ref> advertisedRefs; + + private Status connectionUpdateStatus; + + @Override + public void setUp() throws Exception { + super.setUp(); + transport = new MockTransport(db, new URIish()); + refUpdates = new HashSet<RemoteRefUpdate>(); + advertisedRefs = new HashSet<Ref>(); + connectionUpdateStatus = Status.OK; + } + + /** + * Test for fast-forward remote update. + * + * @throws IOException + */ + public void testUpdateFastForward() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for non fast-forward remote update, when remote object is not known + * to local repository. + * + * @throws IOException + */ + public void testUpdateNonFastForwardUnknownObject() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("0000000000000000000000000000000000000001")); + testOneUpdateStatus(rru, ref, Status.REJECTED_NONFASTFORWARD, null); + } + + /** + * Test for non fast-forward remote update, when remote object is known to + * local repository, but it is not an ancestor of new object. + * + * @throws IOException + */ + public void testUpdateNonFastForward() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.REJECTED_NONFASTFORWARD, null); + } + + /** + * Test for non fast-forward remote update, when force update flag is set. + * + * @throws IOException + */ + public void testUpdateNonFastForwardForced() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", true, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.OK, false); + } + + /** + * Test for remote ref creation. + * + * @throws IOException + */ + public void testUpdateCreateRef() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + testOneUpdateStatus(rru, null, Status.OK, true); + } + + /** + * Test for remote ref deletion. + * + * @throws IOException + */ + public void testUpdateDelete() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for remote ref deletion (try), when that ref doesn't exist on remote + * repo. + * + * @throws IOException + */ + public void testUpdateDeleteNonExisting() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + testOneUpdateStatus(rru, null, Status.NON_EXISTING, null); + } + + /** + * Test for remote ref update, when it is already up to date. + * + * @throws IOException + */ + public void testUpdateUpToDate() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + testOneUpdateStatus(rru, ref, Status.UP_TO_DATE, null); + } + + /** + * Test for remote ref update with expected remote object. + * + * @throws IOException + */ + public void testUpdateExpectedRemote() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, ObjectId + .fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.OK, true); + } + + /** + * Test for remote ref update with expected old object set, when old object + * is not that expected one. + * + * @throws IOException + */ + public void testUpdateUnexpectedRemote() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, ObjectId + .fromString("0000000000000000000000000000000000000001")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_REMOTE_CHANGED, null); + } + + /** + * Test for remote ref update with expected old object set, when old object + * is not that expected one and force update flag is set (which should have + * lower priority) - shouldn't change behavior. + * + * @throws IOException + */ + public void testUpdateUnexpectedRemoteVsForce() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", true, null, ObjectId + .fromString("0000000000000000000000000000000000000001")); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_REMOTE_CHANGED, null); + } + + /** + * Test for remote ref update, when connection rejects update. + * + * @throws IOException + */ + public void testUpdateRejectedByConnection() throws IOException { + connectionUpdateStatus = Status.REJECTED_OTHER_REASON; + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + testOneUpdateStatus(rru, ref, Status.REJECTED_OTHER_REASON, null); + } + + /** + * Test for remote refs updates with mixed cases that shouldn't depend on + * each other. + * + * @throws IOException + */ + public void testUpdateMixedCases() throws IOException { + final RemoteRefUpdate rruOk = new RemoteRefUpdate(db, null, + "refs/heads/master", false, null, null); + final Ref refToChange = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + final RemoteRefUpdate rruReject = new RemoteRefUpdate(db, null, + "refs/heads/nonexisting", false, null, null); + refUpdates.add(rruOk); + refUpdates.add(rruReject); + advertisedRefs.add(refToChange); + executePush(); + assertEquals(Status.OK, rruOk.getStatus()); + assertEquals(true, rruOk.isFastForward()); + assertEquals(Status.NON_EXISTING, rruReject.getStatus()); + } + + /** + * Test for local tracking ref update. + * + * @throws IOException + */ + public void testTrackingRefUpdateEnabled() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, "refs/remotes/test/master", null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + final TrackingRefUpdate tru = result + .getTrackingRefUpdate("refs/remotes/test/master"); + assertNotNull(tru); + assertEquals("refs/remotes/test/master", tru.getLocalName()); + assertEquals(Result.NEW, tru.getResult()); + } + + /** + * Test for local tracking ref update disabled. + * + * @throws IOException + */ + public void testTrackingRefUpdateDisabled() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + assertTrue(result.getTrackingRefUpdates().isEmpty()); + } + + /** + * Test for local tracking ref update when remote update has failed. + * + * @throws IOException + */ + public void testTrackingRefUpdateOnReject() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "ac7e7e44c1885efb472ad54a78327d66bfc4ecef", + "refs/heads/master", false, null, null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("2c349335b7f797072cf729c4f3bb0914ecb6dec9")); + final PushResult result = testOneUpdateStatus(rru, ref, + Status.REJECTED_NONFASTFORWARD, null); + assertTrue(result.getTrackingRefUpdates().isEmpty()); + } + + /** + * Test for push operation result - that contains expected elements. + * + * @throws IOException + */ + public void testPushResult() throws IOException { + final RemoteRefUpdate rru = new RemoteRefUpdate(db, + "2c349335b7f797072cf729c4f3bb0914ecb6dec9", + "refs/heads/master", false, "refs/remotes/test/master", null); + final Ref ref = new Ref(Ref.Storage.LOOSE, "refs/heads/master", + ObjectId.fromString("ac7e7e44c1885efb472ad54a78327d66bfc4ecef")); + refUpdates.add(rru); + advertisedRefs.add(ref); + final PushResult result = executePush(); + assertEquals(1, result.getTrackingRefUpdates().size()); + assertEquals(1, result.getAdvertisedRefs().size()); + assertEquals(1, result.getRemoteUpdates().size()); + assertNotNull(result.getTrackingRefUpdate("refs/remotes/test/master")); + assertNotNull(result.getAdvertisedRef("refs/heads/master")); + assertNotNull(result.getRemoteUpdate("refs/heads/master")); + } + + private PushResult testOneUpdateStatus(final RemoteRefUpdate rru, + final Ref advertisedRef, final Status expectedStatus, + Boolean fastForward) throws NotSupportedException, + TransportException { + refUpdates.add(rru); + if (advertisedRef != null) + advertisedRefs.add(advertisedRef); + final PushResult result = executePush(); + assertEquals(expectedStatus, rru.getStatus()); + if (fastForward != null) + assertEquals(fastForward.booleanValue(), rru.isFastForward()); + return result; + } + + private PushResult executePush() throws NotSupportedException, + TransportException { + process = new PushProcess(transport, refUpdates); + return process.execute(new TextProgressMonitor()); + } + + private class MockTransport extends Transport { + MockTransport(Repository local, URIish uri) { + super(local, uri); + } + + @Override + public FetchConnection openFetch() throws NotSupportedException, + TransportException { + throw new NotSupportedException("mock"); + } + + @Override + public PushConnection openPush() throws NotSupportedException, + TransportException { + return new MockPushConnection(); + } + + @Override + public void close() { + // nothing here + } + } + + private class MockPushConnection extends BaseConnection implements + PushConnection { + MockPushConnection() { + final Map<String, Ref> refsMap = new HashMap<String, Ref>(); + for (final Ref r : advertisedRefs) + refsMap.put(r.getName(), r); + available(refsMap); + } + + @Override + public void close() { + // nothing here + } + + public void push(ProgressMonitor monitor, + Map<String, RemoteRefUpdate> refsToUpdate) + throws TransportException { + for (final RemoteRefUpdate rru : refsToUpdate.values()) { + assertEquals(Status.NOT_ATTEMPTED, rru.getStatus()); + rru.setStatus(connectionUpdateStatus); + } + } + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java new file mode 100644 index 0000000000..38dbe0962e --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RefSpecTest.java @@ -0,0 +1,275 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Ref; + +public class RefSpecTest extends TestCase { + public void testMasterMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(sn + ":" + sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals(sn + ":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testSplitLastColon() { + final String lhs = ":m:a:i:n:t"; + final String rhs = "refs/heads/maint"; + final RefSpec rs = new RefSpec(lhs + ":" + rhs); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(lhs, rs.getSource()); + assertEquals(rhs, rs.getDestination()); + assertEquals(lhs + ":" + rhs, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + } + + public void testForceMasterMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec("+" + sn + ":" + sn); + assertTrue(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals("+" + sn + ":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertNull(rs.getDestination()); + assertEquals(sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testForceMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec("+" + sn); + assertTrue(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals(sn, rs.getSource()); + assertNull(rs.getDestination()); + assertEquals("+" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testDeleteMaster() { + final String sn = "refs/heads/master"; + final RefSpec rs = new RefSpec(":" + sn); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertNull(rs.getSource()); + assertEquals(sn, rs.getDestination()); + assertEquals(":" + sn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r = new Ref(Ref.Storage.LOOSE, sn, null); + assertFalse(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + assertSame(rs, rs.expandFromSource(r)); + + r = new Ref(Ref.Storage.LOOSE, sn + "-and-more", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testForceRemotesOrigin() { + final String srcn = "refs/heads/*"; + final String dstn = "refs/remotes/origin/*"; + final RefSpec rs = new RefSpec("+" + srcn + ":" + dstn); + assertTrue(rs.isForceUpdate()); + assertTrue(rs.isWildcard()); + assertEquals(srcn, rs.getSource()); + assertEquals(dstn, rs.getDestination()); + assertEquals("+" + srcn + ":" + dstn, rs.toString()); + assertEquals(rs, new RefSpec(rs.toString())); + + Ref r; + RefSpec expanded; + + r = new Ref(Ref.Storage.LOOSE, "refs/heads/master", null); + assertTrue(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + expanded = rs.expandFromSource(r); + assertNotSame(rs, expanded); + assertTrue(expanded.isForceUpdate()); + assertFalse(expanded.isWildcard()); + assertEquals(r.getName(), expanded.getSource()); + assertEquals("refs/remotes/origin/master", expanded.getDestination()); + + r = new Ref(Ref.Storage.LOOSE, "refs/remotes/origin/next", null); + assertFalse(rs.matchSource(r)); + assertTrue(rs.matchDestination(r)); + + r = new Ref(Ref.Storage.LOOSE, "refs/tags/v1.0", null); + assertFalse(rs.matchSource(r)); + assertFalse(rs.matchDestination(r)); + } + + public void testCreateEmpty() { + final RefSpec rs = new RefSpec(); + assertFalse(rs.isForceUpdate()); + assertFalse(rs.isWildcard()); + assertEquals("HEAD", rs.getSource()); + assertNull(rs.getDestination()); + assertEquals("HEAD", rs.toString()); + } + + public void testSetForceUpdate() { + final String s = "refs/heads/*:refs/remotes/origin/*"; + final RefSpec a = new RefSpec(s); + assertFalse(a.isForceUpdate()); + RefSpec b = a.setForceUpdate(true); + assertNotSame(a, b); + assertFalse(a.isForceUpdate()); + assertTrue(b.isForceUpdate()); + assertEquals(s, a.toString()); + assertEquals("+" + s, b.toString()); + } + + public void testSetSource() { + final RefSpec a = new RefSpec(); + final RefSpec b = a.setSource("refs/heads/master"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("refs/heads/master", b.toString()); + } + + public void testSetDestination() { + final RefSpec a = new RefSpec(); + final RefSpec b = a.setDestination("refs/heads/master"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("HEAD:refs/heads/master", b.toString()); + } + + public void testSetDestination_SourceNull() { + final RefSpec a = new RefSpec(); + RefSpec b; + + b = a.setDestination("refs/heads/master"); + b = b.setSource(null); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals(":refs/heads/master", b.toString()); + } + + public void testSetSourceDestination() { + final RefSpec a = new RefSpec(); + final RefSpec b; + b = a.setSourceDestination("refs/heads/*", "refs/remotes/origin/*"); + assertNotSame(a, b); + assertEquals("HEAD", a.toString()); + assertEquals("refs/heads/*:refs/remotes/origin/*", b.toString()); + } + + public void testExpandFromDestination_NonWildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec(src + ":" + dst); + final RefSpec r = a.expandFromDestination(dst); + assertSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } + + public void testExpandFromDestination_Wildcard() { + final String src = "refs/heads/master"; + final String dst = "refs/remotes/origin/master"; + final RefSpec a = new RefSpec("refs/heads/*:refs/remotes/origin/*"); + final RefSpec r = a.expandFromDestination(dst); + assertNotSame(a, r); + assertFalse(r.isWildcard()); + assertEquals(src, r.getSource()); + assertEquals(dst, r.getDestination()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java new file mode 100644 index 0000000000..3d9b51f9b6 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/RemoteConfigTest.java @@ -0,0 +1,432 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.util.List; + +import junit.framework.TestCase; + +import org.eclipse.jgit.errors.ConfigInvalidException; +import org.eclipse.jgit.lib.Config; + +public class RemoteConfigTest extends TestCase { + private Config config; + + protected void setUp() throws Exception { + super.setUp(); + config = new Config(); + } + + private void readConfig(final String dat) throws ConfigInvalidException { + config = new Config(); + config.fromText(dat); + } + + private void checkConfig(final String exp) { + assertEquals(exp, config.toText()); + } + + private static void assertEquals(final String exp, final URIish act) { + assertEquals(exp, act != null ? act.toString() : null); + } + + public void testSimple() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("spearce", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + assertNotNull(rc.getTagOpt()); + assertEquals(0, rc.getTimeout()); + assertSame(TagOpt.AUTO_FOLLOW, rc.getTagOpt()); + + assertEquals(1, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + + assertEquals(1, rc.getFetchRefSpecs().size()); + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/remotes/spearce/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + } + + public void testSimpleNoTags() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --no-tags\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertSame(TagOpt.NO_TAGS, rc.getTagOpt()); + } + + public void testSimpleAlwaysTags() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "tagopt = --tags\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertSame(TagOpt.FETCH_TAGS, rc.getTagOpt()); + } + + public void testMirror() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/heads/*\n" + + "fetch = refs/tags/*:refs/tags/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("spearce", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(1, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + + assertEquals(2, rc.getFetchRefSpecs().size()); + + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/heads/*", spec.getDestination()); + + spec = rc.getFetchRefSpecs().get(1); + assertFalse(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/tags/*", spec.getSource()); + assertEquals("refs/tags/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + } + + public void testBackup() throws Exception { + readConfig("[remote \"backup\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = user@repo.or.cz:/srv/git/egit.git\n" + + "push = +refs/heads/*:refs/heads/*\n" + + "push = refs/tags/*:refs/tags/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "backup"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("backup", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(2, allURIs.size()); + assertEquals("http://www.spearce.org/egit.git", allURIs.get(0)); + assertEquals("user@repo.or.cz:/srv/git/egit.git", allURIs.get(1)); + + assertEquals(0, rc.getFetchRefSpecs().size()); + + assertEquals(2, rc.getPushRefSpecs().size()); + spec = rc.getPushRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/heads/*", spec.getDestination()); + + spec = rc.getPushRefSpecs().get(1); + assertFalse(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/tags/*", spec.getSource()); + assertEquals("refs/tags/*", spec.getDestination()); + } + + public void testUploadPack() throws Exception { + readConfig("[remote \"example\"]\n" + + "url = user@example.com:egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/example/*\n" + + "uploadpack = /path/to/git/git-upload-pack\n" + + "receivepack = /path/to/git/git-receive-pack\n"); + + final RemoteConfig rc = new RemoteConfig(config, "example"); + final List<URIish> allURIs = rc.getURIs(); + RefSpec spec; + + assertEquals("example", rc.getName()); + assertNotNull(allURIs); + assertNotNull(rc.getFetchRefSpecs()); + assertNotNull(rc.getPushRefSpecs()); + + assertEquals(1, allURIs.size()); + assertEquals("user@example.com:egit.git", allURIs.get(0)); + + assertEquals(1, rc.getFetchRefSpecs().size()); + spec = rc.getFetchRefSpecs().get(0); + assertTrue(spec.isForceUpdate()); + assertTrue(spec.isWildcard()); + assertEquals("refs/heads/*", spec.getSource()); + assertEquals("refs/remotes/example/*", spec.getDestination()); + + assertEquals(0, rc.getPushRefSpecs().size()); + + assertEquals("/path/to/git/git-upload-pack", rc.getUploadPack()); + assertEquals("/path/to/git/git-receive-pack", rc.getReceivePack()); + } + + public void testUnknown() throws Exception { + readConfig(""); + + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertEquals(0, rc.getURIs().size()); + assertEquals(0, rc.getFetchRefSpecs().size()); + assertEquals(0, rc.getPushRefSpecs().size()); + assertEquals("git-upload-pack", rc.getUploadPack()); + assertEquals("git-receive-pack", rc.getReceivePack()); + } + + public void testAddURI() throws Exception { + readConfig(""); + + final URIish uri = new URIish("/some/dir"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertEquals(0, rc.getURIs().size()); + + assertTrue(rc.addURI(uri)); + assertEquals(1, rc.getURIs().size()); + assertSame(uri, rc.getURIs().get(0)); + + assertFalse(rc.addURI(new URIish(uri.toString()))); + assertEquals(1, rc.getURIs().size()); + } + + public void testRemoveFirstURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(a)); + assertEquals(2, rc.getURIs().size()); + assertSame(b, rc.getURIs().get(0)); + assertSame(c, rc.getURIs().get(1)); + } + + public void testRemoveMiddleURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(b)); + assertEquals(2, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(c, rc.getURIs().get(1)); + } + + public void testRemoveLastURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final URIish b = new URIish("/another/dir"); + final URIish c = new URIish("/more/dirs"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + assertTrue(rc.addURI(b)); + assertTrue(rc.addURI(c)); + + assertEquals(3, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + assertSame(c, rc.getURIs().get(2)); + + assertTrue(rc.removeURI(c)); + assertEquals(2, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + assertSame(b, rc.getURIs().get(1)); + } + + public void testRemoveOnlyURI() throws Exception { + readConfig(""); + + final URIish a = new URIish("/some/dir"); + final RemoteConfig rc = new RemoteConfig(config, "backup"); + assertTrue(rc.addURI(a)); + + assertEquals(1, rc.getURIs().size()); + assertSame(a, rc.getURIs().get(0)); + + assertTrue(rc.removeURI(a)); + assertEquals(0, rc.getURIs().size()); + } + + public void testCreateOrigin() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n"); + } + + public void testSaveAddURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + rc.addURI(new URIish("/some/dir")); + assertEquals(2, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + + "\turl = http://www.spearce.org/egit.git\n" + + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveRemoveLastURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = /some/dir\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(2, rc.getURIs().size()); + rc.removeURI(new URIish("/some/dir")); + assertEquals(1, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + + "\turl = http://www.spearce.org/egit.git\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveRemoveFirstURI() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "url = /some/dir\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n"); + + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(2, rc.getURIs().size()); + rc.removeURI(new URIish("http://www.spearce.org/egit.git")); + assertEquals(1, rc.getURIs().size()); + rc.update(config); + checkConfig("[remote \"spearce\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/spearce/*\n"); + } + + public void testSaveNoTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.NO_TAGS); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --no-tags\n"); + } + + public void testSaveAllTags() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTagOpt(TagOpt.FETCH_TAGS); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttagopt = --tags\n"); + } + + public void testSimpleTimeout() throws Exception { + readConfig("[remote \"spearce\"]\n" + + "url = http://www.spearce.org/egit.git\n" + + "fetch = +refs/heads/*:refs/remotes/spearce/*\n" + + "timeout = 12\n"); + final RemoteConfig rc = new RemoteConfig(config, "spearce"); + assertEquals(12, rc.getTimeout()); + } + + public void testSaveTimeout() throws Exception { + final RemoteConfig rc = new RemoteConfig(config, "origin"); + rc.addURI(new URIish("/some/dir")); + rc.addFetchRefSpec(new RefSpec("+refs/heads/*:refs/remotes/" + + rc.getName() + "/*")); + rc.setTimeout(60); + rc.update(config); + checkConfig("[remote \"origin\"]\n" + "\turl = /some/dir\n" + + "\tfetch = +refs/heads/*:refs/remotes/origin/*\n" + + "\ttimeout = 60\n"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java new file mode 100644 index 0000000000..3c79f138c8 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/SideBandOutputStreamTest.java @@ -0,0 +1,152 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +// Note, test vectors created with: +// +// perl -e 'printf "%4.4x%s\n", 4+length($ARGV[0]),$ARGV[0]' + +public class SideBandOutputStreamTest extends TestCase { + private ByteArrayOutputStream rawOut; + + private PacketLineOut pckOut; + + protected void setUp() throws Exception { + super.setUp(); + rawOut = new ByteArrayOutputStream(); + pckOut = new PacketLineOut(rawOut); + } + + public void testWrite_CH_DATA() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\001abc"); + } + + public void testWrite_CH_PROGRESS() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\002abc"); + } + + public void testWrite_CH_ERROR() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_ERROR, pckOut); + out.write(new byte[] { 'a', 'b', 'c' }); + assertBuffer("0008\003abc"); + } + + public void testWrite_Small() throws IOException { + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write('a'); + out.write('b'); + out.write('c'); + assertBuffer("0006\001a0006\001b0006\001c"); + } + + public void testWrite_Large() throws IOException { + final int buflen = SideBandOutputStream.MAX_BUF + - SideBandOutputStream.HDR_SIZE; + final byte[] buf = new byte[buflen]; + for (int i = 0; i < buf.length; i++) { + buf[i] = (byte) i; + } + + final SideBandOutputStream out; + out = new SideBandOutputStream(SideBandOutputStream.CH_DATA, pckOut); + out.write(buf); + + final byte[] act = rawOut.toByteArray(); + final String explen = Integer.toString(buf.length + 5, 16); + assertEquals(5 + buf.length, act.length); + assertEquals(new String(act, 0, 4, "UTF-8"), explen); + assertEquals(1, act[4]); + for (int i = 0, j = 5; i < buf.length; i++, j++) { + assertEquals(buf[i], act[j]); + } + } + + public void testFlush() throws IOException { + final int[] flushCnt = new int[1]; + final OutputStream mockout = new OutputStream() { + @Override + public void write(int arg0) throws IOException { + fail("should not write"); + } + + @Override + public void flush() throws IOException { + flushCnt[0]++; + } + }; + + new SideBandOutputStream(SideBandOutputStream.CH_DATA, + new PacketLineOut(mockout)).flush(); + assertEquals(0, flushCnt[0]); + + new SideBandOutputStream(SideBandOutputStream.CH_ERROR, + new PacketLineOut(mockout)).flush(); + assertEquals(1, flushCnt[0]); + + new SideBandOutputStream(SideBandOutputStream.CH_PROGRESS, + new PacketLineOut(mockout)).flush(); + assertEquals(2, flushCnt[0]); + } + + private void assertBuffer(final String exp) throws IOException { + assertEquals(exp, new String(rawOut.toByteArray(), + Constants.CHARACTER_ENCODING)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java new file mode 100644 index 0000000000..75e661bcf9 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/TransportTest.java @@ -0,0 +1,197 @@ +/* + * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import java.io.IOException; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; + +import org.eclipse.jgit.lib.RepositoryConfig; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class TransportTest extends RepositoryTestCase { + private Transport transport; + + private RemoteConfig remoteConfig; + + @Override + public void setUp() throws Exception { + super.setUp(); + final RepositoryConfig config = db.getConfig(); + remoteConfig = new RemoteConfig(config, "test"); + remoteConfig.addURI(new URIish("http://everyones.loves.git/u/2")); + transport = null; + } + + @Override + protected void tearDown() throws Exception { + if (transport != null) { + transport.close(); + transport = null; + } + super.tearDown(); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with simple RefSpec - no + * wildcard, no tracking ref in repo configuration. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesNoWildcardNoTracking() + throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "refs/heads/master:refs/heads/x"))); + + assertEquals(1, result.size()); + final RemoteRefUpdate rru = result.iterator().next(); + assertNull(rru.getExpectedOldObjectId()); + assertFalse(rru.isForceUpdate()); + assertEquals("refs/heads/master", rru.getSrcRef()); + assertEquals(db.resolve("refs/heads/master"), rru.getNewObjectId()); + assertEquals("refs/heads/x", rru.getRemoteName()); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with no-destination RefSpec + * (destination should be set up for the same name as source). + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesNoWildcardNoDestination() + throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/master"))); + + assertEquals(1, result.size()); + final RemoteRefUpdate rru = result.iterator().next(); + assertNull(rru.getExpectedOldObjectId()); + assertTrue(rru.isForceUpdate()); + assertEquals("refs/heads/master", rru.getSrcRef()); + assertEquals(db.resolve("refs/heads/master"), rru.getNewObjectId()); + assertEquals("refs/heads/master", rru.getRemoteName()); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion with wildcard RefSpec. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesWildcardNoTracking() throws IOException { + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/*:refs/heads/test/*"))); + + assertEquals(12, result.size()); + boolean foundA = false; + boolean foundB = false; + for (final RemoteRefUpdate rru : result) { + if ("refs/heads/a".equals(rru.getSrcRef()) + && "refs/heads/test/a".equals(rru.getRemoteName())) + foundA = true; + if ("refs/heads/b".equals(rru.getSrcRef()) + && "refs/heads/test/b".equals(rru.getRemoteName())) + foundB = true; + } + assertTrue(foundA); + assertTrue(foundB); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion for more than one RefSpecs + * handling. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesTwoRefSpecs() throws IOException { + transport = Transport.open(db, remoteConfig); + final RefSpec specA = new RefSpec("+refs/heads/a:refs/heads/b"); + final RefSpec specC = new RefSpec("+refs/heads/c:refs/heads/d"); + final Collection<RefSpec> specs = Arrays.asList(specA, specC); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(specs); + + assertEquals(2, result.size()); + boolean foundA = false; + boolean foundC = false; + for (final RemoteRefUpdate rru : result) { + if ("refs/heads/a".equals(rru.getSrcRef()) + && "refs/heads/b".equals(rru.getRemoteName())) + foundA = true; + if ("refs/heads/c".equals(rru.getSrcRef()) + && "refs/heads/d".equals(rru.getRemoteName())) + foundC = true; + } + assertTrue(foundA); + assertTrue(foundC); + } + + /** + * Test RefSpec to RemoteRefUpdate conversion for tracking ref search. + * + * @throws IOException + */ + public void testFindRemoteRefUpdatesTrackingRef() throws IOException { + remoteConfig.addFetchRefSpec(new RefSpec( + "refs/heads/*:refs/remotes/test/*")); + transport = Transport.open(db, remoteConfig); + final Collection<RemoteRefUpdate> result = transport + .findRemoteRefUpdatesFor(Collections.nCopies(1, new RefSpec( + "+refs/heads/a:refs/heads/a"))); + + assertEquals(1, result.size()); + final TrackingRefUpdate tru = result.iterator().next() + .getTrackingRefUpdate(); + assertEquals("refs/remotes/test/a", tru.getLocalName()); + assertEquals("refs/heads/a", tru.getRemoteName()); + assertEquals(db.resolve("refs/heads/a"), tru.getNewObjectId()); + assertNull(tru.getOldObjectId()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java new file mode 100644 index 0000000000..2598fdc1f5 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/transport/URIishTest.java @@ -0,0 +1,247 @@ +/* + * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg@dewire.com> + * Copyright (C) 2008, Shawn O. Pearce <spearce@spearce.org> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.transport; + +import junit.framework.TestCase; + +public class URIishTest extends TestCase { + + public void testUnixFile() throws Exception { + final String str = "/home/m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testWindowsFile() throws Exception { + final String str = "D:/m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals(str, u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testWindowsFile2() throws Exception { + final String str = "D:\\m y"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals("D:/m y", u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testUNC() throws Exception { + final String str = "\\\\some\\place"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("//some/place", u.getPath()); + assertEquals("//some/place", u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testFileProtoUnix() throws Exception { + final String str = "file:///home/m y"; + URIish u = new URIish(str); + assertEquals("file", u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("/home/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testFileProtoWindows() throws Exception { + final String str = "file:///D:/m y"; + URIish u = new URIish(str); + assertEquals("file", u.getScheme()); + assertFalse(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoUnix() throws Exception { + final String str = "git://example.com/home/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("example.com", u.getHost()); + assertEquals("/home/m y", u.getPath()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoUnixPort() throws Exception { + final String str = "git://example.com:333/home/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("example.com", u.getHost()); + assertEquals("/home/m y", u.getPath()); + assertEquals(333, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoWindowsPort() throws Exception { + final String str = "git://example.com:338/D:/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals(338, u.getPort()); + assertEquals("example.com", u.getHost()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitProtoWindows() throws Exception { + final String str = "git://example.com/D:/m y"; + URIish u = new URIish(str); + assertEquals("git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("D:/m y", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testScpStyleWithoutUser() throws Exception { + final String str = "example.com:some/p ath"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testScpStyleWithUser() throws Exception { + final String str = "user@example.com:some/p ath"; + URIish u = new URIish(str); + assertNull(u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("some/p ath", u.getPath()); + assertEquals("user", u.getUser()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testGitSshProto() throws Exception { + final String str = "git+ssh://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("git+ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshGitProto() throws Exception { + final String str = "ssh+git://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh+git", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProto() throws Exception { + final String str = "ssh://example.com/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals(-1, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProtoWithUserAndPort() throws Exception { + final String str = "ssh://user@example.com:33/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals("user", u.getUser()); + assertNull(u.getPass()); + assertEquals(33, u.getPort()); + assertEquals(str, u.toString()); + assertEquals(u, new URIish(str)); + } + + public void testSshProtoWithUserPassAndPort() throws Exception { + final String str = "ssh://user:pass@example.com:33/some/p ath"; + URIish u = new URIish(str); + assertEquals("ssh", u.getScheme()); + assertTrue(u.isRemote()); + assertEquals("/some/p ath", u.getPath()); + assertEquals("example.com", u.getHost()); + assertEquals("user", u.getUser()); + assertEquals("pass", u.getPass()); + assertEquals(33, u.getPort()); + assertEquals(str, u.toPrivateString()); + assertEquals(u.setPass(null).toPrivateString(), u.toString()); + assertEquals(u, new URIish(str)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java new file mode 100644 index 0000000000..e96445a30a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/AbstractTreeIteratorTest.java @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2009, Google Inc. + * Copyright (C) 2009, Tor Arne Vestbø <torarnv@gmail.com> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import java.io.IOException; + +import junit.framework.TestCase; + +import org.eclipse.jgit.errors.IncorrectObjectTypeException; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.Repository; + + +public class AbstractTreeIteratorTest extends TestCase { + private static String prefix(String path) { + final int s = path.lastIndexOf('/'); + return s > 0 ? path.substring(0, s) : ""; + } + + public class FakeTreeIterator extends WorkingTreeIterator { + public FakeTreeIterator(String pathName, FileMode fileMode) { + super(prefix(pathName)); + mode = fileMode.getBits(); + + final int s = pathName.lastIndexOf('/'); + final byte[] name = Constants.encode(pathName.substring(s + 1)); + ensurePathCapacity(pathOffset + name.length, pathOffset); + System.arraycopy(name, 0, path, pathOffset, name.length); + pathLen = pathOffset + name.length; + } + + @Override + public AbstractTreeIterator createSubtreeIterator(Repository repo) + throws IncorrectObjectTypeException, IOException { + return null; + } + } + + public void testPathCompare() throws Exception { + assertTrue(new FakeTreeIterator("a", FileMode.REGULAR_FILE).pathCompare( + new FakeTreeIterator("a", FileMode.TREE)) < 0); + + assertTrue(new FakeTreeIterator("a", FileMode.TREE).pathCompare( + new FakeTreeIterator("a", FileMode.REGULAR_FILE)) > 0); + + assertTrue(new FakeTreeIterator("a", FileMode.REGULAR_FILE).pathCompare( + new FakeTreeIterator("a", FileMode.REGULAR_FILE)) == 0); + + assertTrue(new FakeTreeIterator("a", FileMode.TREE).pathCompare( + new FakeTreeIterator("a", FileMode.TREE)) == 0); + } + + public void testGrowPath() throws Exception { + final FakeTreeIterator i = new FakeTreeIterator("ab", FileMode.TREE); + final byte[] origpath = i.path; + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + + i.growPath(2); + + assertNotSame(origpath, i.path); + assertEquals(origpath.length * 2, i.path.length); + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + } + + public void testEnsurePathCapacityFastCase() throws Exception { + final FakeTreeIterator i = new FakeTreeIterator("ab", FileMode.TREE); + final int want = 50; + final byte[] origpath = i.path; + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + assertTrue(want < i.path.length); + + i.ensurePathCapacity(want, 2); + + assertSame(origpath, i.path); + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + } + + public void testEnsurePathCapacityGrows() throws Exception { + final FakeTreeIterator i = new FakeTreeIterator("ab", FileMode.TREE); + final int want = 384; + final byte[] origpath = i.path; + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + assertTrue(i.path.length < want); + + i.ensurePathCapacity(want, 2); + + assertNotSame(origpath, i.path); + assertEquals(512, i.path.length); + assertEquals(i.path[0], 'a'); + assertEquals(i.path[1], 'b'); + } + + public void testEntryFileMode() { + for (FileMode m : new FileMode[] { FileMode.TREE, + FileMode.REGULAR_FILE, FileMode.EXECUTABLE_FILE, + FileMode.GITLINK, FileMode.SYMLINK }) { + final FakeTreeIterator i = new FakeTreeIterator("a", m); + assertEquals(m.getBits(), i.getEntryRawMode()); + assertSame(m, i.getEntryFileMode()); + } + } + + public void testEntryPath() { + FakeTreeIterator i = new FakeTreeIterator("a/b/cd", FileMode.TREE); + assertEquals("a/b/cd", i.getEntryPathString()); + assertEquals(2, i.getNameLength()); + byte[] b = new byte[3]; + b[0] = 0x0a; + i.getName(b, 1); + assertEquals(0x0a, b[0]); + assertEquals('c', b[1]); + assertEquals('d', b[2]); + } + + public void testCreateEmptyTreeIterator() { + FakeTreeIterator i = new FakeTreeIterator("a/b/cd", FileMode.TREE); + EmptyTreeIterator e = i.createEmptyTreeIterator(); + assertNotNull(e); + assertEquals(i.getEntryPathString() + "/", e.getEntryPathString()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/CanonicalTreeParserTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/CanonicalTreeParserTest.java new file mode 100644 index 0000000000..da25f8d632 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/CanonicalTreeParserTest.java @@ -0,0 +1,353 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import java.io.ByteArrayOutputStream; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.util.RawParseUtils; + +public class CanonicalTreeParserTest extends TestCase { + private final CanonicalTreeParser ctp = new CanonicalTreeParser(); + + private final FileMode m644 = FileMode.REGULAR_FILE; + + private final FileMode mt = FileMode.TREE; + + private final ObjectId hash_a = ObjectId + .fromString("6b9c715d21d5486e59083fb6071566aa6ecd4d42"); + + private final ObjectId hash_foo = ObjectId + .fromString("a213e8e25bb2442326e86cbfb9ef56319f482869"); + + private final ObjectId hash_sometree = ObjectId + .fromString("daf4bdb0d7bb24319810fe0e73aa317663448c93"); + + private byte[] tree1; + + private byte[] tree2; + + private byte[] tree3; + + public void setUp() throws Exception { + super.setUp(); + + tree1 = mktree(entry(m644, "a", hash_a)); + tree2 = mktree(entry(m644, "a", hash_a), entry(m644, "foo", hash_foo)); + tree3 = mktree(entry(m644, "a", hash_a), entry(mt, "b_sometree", + hash_sometree), entry(m644, "foo", hash_foo)); + } + + private static byte[] mktree(final byte[]... data) throws Exception { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + for (final byte[] e : data) + out.write(e); + return out.toByteArray(); + } + + private static byte[] entry(final FileMode mode, final String name, + final ObjectId id) throws Exception { + final ByteArrayOutputStream out = new ByteArrayOutputStream(); + mode.copyTo(out); + out.write(' '); + out.write(Constants.encode(name)); + out.write(0); + id.copyRawTo(out); + return out.toByteArray(); + } + + private String path() { + return RawParseUtils.decode(Constants.CHARSET, ctp.path, + ctp.pathOffset, ctp.pathLen); + } + + public void testEmptyTree_AtEOF() throws Exception { + ctp.reset(new byte[0]); + assertTrue(ctp.eof()); + } + + public void testOneEntry_Forward() throws Exception { + ctp.reset(tree1); + + assertTrue(ctp.first()); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + + ctp.next(1); + assertFalse(ctp.first()); + assertTrue(ctp.eof()); + } + + public void testTwoEntries_ForwardOneAtATime() throws Exception { + ctp.reset(tree2); + + assertTrue(ctp.first()); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + + ctp.next(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("foo", path()); + assertEquals(hash_foo, ctp.getEntryObjectId()); + + ctp.next(1); + assertFalse(ctp.first()); + assertTrue(ctp.eof()); + } + + public void testOneEntry_Seek1IsEOF() throws Exception { + ctp.reset(tree1); + ctp.next(1); + assertTrue(ctp.eof()); + } + + public void testTwoEntries_Seek2IsEOF() throws Exception { + ctp.reset(tree2); + ctp.next(2); + assertTrue(ctp.eof()); + } + + public void testThreeEntries_Seek3IsEOF() throws Exception { + ctp.reset(tree3); + ctp.next(3); + assertTrue(ctp.eof()); + } + + public void testThreeEntries_Seek2() throws Exception { + ctp.reset(tree3); + + ctp.next(2); + assertFalse(ctp.eof()); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("foo", path()); + assertEquals(hash_foo, ctp.getEntryObjectId()); + + ctp.next(1); + assertTrue(ctp.eof()); + } + + public void testOneEntry_Backwards() throws Exception { + ctp.reset(tree1); + ctp.next(1); + assertFalse(ctp.first()); + assertTrue(ctp.eof()); + + ctp.back(1); + assertTrue(ctp.first()); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + } + + public void testTwoEntries_BackwardsOneAtATime() throws Exception { + ctp.reset(tree2); + ctp.next(2); + assertTrue(ctp.eof()); + + ctp.back(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("foo", path()); + assertEquals(hash_foo, ctp.getEntryObjectId()); + + ctp.back(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + } + + public void testTwoEntries_BackwardsTwo() throws Exception { + ctp.reset(tree2); + ctp.next(2); + assertTrue(ctp.eof()); + + ctp.back(2); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + + ctp.next(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("foo", path()); + assertEquals(hash_foo, ctp.getEntryObjectId()); + + ctp.next(1); + assertTrue(ctp.eof()); + } + + public void testThreeEntries_BackwardsTwo() throws Exception { + ctp.reset(tree3); + ctp.next(3); + assertTrue(ctp.eof()); + + ctp.back(2); + assertFalse(ctp.eof()); + assertEquals(mt.getBits(), ctp.mode); + assertEquals("b_sometree", path()); + assertEquals(hash_sometree, ctp.getEntryObjectId()); + + ctp.next(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("foo", path()); + assertEquals(hash_foo, ctp.getEntryObjectId()); + + ctp.next(1); + assertTrue(ctp.eof()); + } + + public void testBackwards_ConfusingPathName() throws Exception { + final String aVeryConfusingName = "confusing 644 entry 755 and others"; + ctp.reset(mktree(entry(m644, "a", hash_a), entry(mt, aVeryConfusingName, + hash_sometree), entry(m644, "foo", hash_foo))); + ctp.next(3); + assertTrue(ctp.eof()); + + ctp.back(2); + assertFalse(ctp.eof()); + assertEquals(mt.getBits(), ctp.mode); + assertEquals(aVeryConfusingName, path()); + assertEquals(hash_sometree, ctp.getEntryObjectId()); + + ctp.back(1); + assertFalse(ctp.eof()); + assertEquals(m644.getBits(), ctp.mode); + assertEquals("a", path()); + assertEquals(hash_a, ctp.getEntryObjectId()); + } + + public void testBackwords_Prebuilts1() throws Exception { + // What is interesting about this test is the ObjectId for the + // "darwin-x86" path entry ends in an octal digit (37 == '7'). + // Thus when scanning backwards we could over scan and consume + // part of the SHA-1, and miss the path terminator. + // + final ObjectId common = ObjectId + .fromString("af7bf97cb9bce3f60f1d651a0ef862e9447dd8bc"); + final ObjectId darwinx86 = ObjectId + .fromString("e927f7398240f78face99e1a738dac54ef738e37"); + final ObjectId linuxx86 = ObjectId + .fromString("ac08dd97120c7cb7d06e98cd5b152011183baf21"); + final ObjectId windows = ObjectId + .fromString("6c4c64c221a022bb973165192cca4812033479df"); + + ctp.reset(mktree(entry(mt, "common", common), entry(mt, "darwin-x86", + darwinx86), entry(mt, "linux-x86", linuxx86), entry(mt, + "windows", windows))); + ctp.next(3); + assertEquals("windows", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(windows, ctp.getEntryObjectId()); + + ctp.back(1); + assertEquals("linux-x86", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(linuxx86, ctp.getEntryObjectId()); + + ctp.next(1); + assertEquals("windows", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(windows, ctp.getEntryObjectId()); + } + + public void testBackwords_Prebuilts2() throws Exception { + // What is interesting about this test is the ObjectId for the + // "darwin-x86" path entry ends in an octal digit (37 == '7'). + // Thus when scanning backwards we could over scan and consume + // part of the SHA-1, and miss the path terminator. + // + final ObjectId common = ObjectId + .fromString("af7bf97cb9bce3f60f1d651a0ef862e9447dd8bc"); + final ObjectId darwinx86 = ObjectId + .fromString("0000000000000000000000000000000000000037"); + final ObjectId linuxx86 = ObjectId + .fromString("ac08dd97120c7cb7d06e98cd5b152011183baf21"); + final ObjectId windows = ObjectId + .fromString("6c4c64c221a022bb973165192cca4812033479df"); + + ctp.reset(mktree(entry(mt, "common", common), entry(mt, "darwin-x86", + darwinx86), entry(mt, "linux-x86", linuxx86), entry(mt, + "windows", windows))); + ctp.next(3); + assertEquals("windows", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(windows, ctp.getEntryObjectId()); + + ctp.back(1); + assertEquals("linux-x86", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(linuxx86, ctp.getEntryObjectId()); + + ctp.next(1); + assertEquals("windows", ctp.getEntryPathString()); + assertSame(mt, ctp.getEntryFileMode()); + assertEquals(windows, ctp.getEntryObjectId()); + } + + public void testFreakingHugePathName() throws Exception { + final int n = AbstractTreeIterator.DEFAULT_PATH_SIZE * 4; + final StringBuilder b = new StringBuilder(n); + for (int i = 0; i < n; i++) + b.append('q'); + final String name = b.toString(); + ctp.reset(entry(m644, name, hash_a)); + assertFalse(ctp.eof()); + assertEquals(name, RawParseUtils.decode(Constants.CHARSET, ctp.path, + ctp.pathOffset, ctp.pathLen)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java new file mode 100644 index 0000000000..111264b1c9 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/EmptyTreeIteratorTest.java @@ -0,0 +1,112 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class EmptyTreeIteratorTest extends RepositoryTestCase { + public void testAtEOF() throws Exception { + final EmptyTreeIterator etp = new EmptyTreeIterator(); + assertTrue(etp.first()); + assertTrue(etp.eof()); + } + + public void testCreateSubtreeIterator() throws Exception { + final EmptyTreeIterator etp = new EmptyTreeIterator(); + final AbstractTreeIterator sub = etp.createSubtreeIterator(db); + assertNotNull(sub); + assertTrue(sub.first()); + assertTrue(sub.eof()); + assertTrue(sub instanceof EmptyTreeIterator); + } + + public void testEntryObjectId() throws Exception { + final EmptyTreeIterator etp = new EmptyTreeIterator(); + assertSame(ObjectId.zeroId(), etp.getEntryObjectId()); + assertNotNull(etp.idBuffer()); + assertEquals(0, etp.idOffset()); + assertEquals(ObjectId.zeroId(), ObjectId.fromRaw(etp.idBuffer())); + } + + public void testNextDoesNothing() throws Exception { + final EmptyTreeIterator etp = new EmptyTreeIterator(); + etp.next(1); + assertTrue(etp.first()); + assertTrue(etp.eof()); + assertEquals(ObjectId.zeroId(), ObjectId.fromRaw(etp.idBuffer())); + + etp.next(1); + assertTrue(etp.first()); + assertTrue(etp.eof()); + assertEquals(ObjectId.zeroId(), ObjectId.fromRaw(etp.idBuffer())); + } + + public void testBackDoesNothing() throws Exception { + final EmptyTreeIterator etp = new EmptyTreeIterator(); + etp.back(1); + assertTrue(etp.first()); + assertTrue(etp.eof()); + assertEquals(ObjectId.zeroId(), ObjectId.fromRaw(etp.idBuffer())); + + etp.back(1); + assertTrue(etp.first()); + assertTrue(etp.eof()); + assertEquals(ObjectId.zeroId(), ObjectId.fromRaw(etp.idBuffer())); + } + + public void testStopWalkCallsParent() throws Exception { + final boolean called[] = new boolean[1]; + assertFalse(called[0]); + + final EmptyTreeIterator parent = new EmptyTreeIterator() { + @Override + public void stopWalk() { + called[0] = true; + } + }; + parent.createSubtreeIterator(db).stopWalk(); + assertTrue(called[0]); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java new file mode 100644 index 0000000000..081290310a --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/FileTreeIteratorTest.java @@ -0,0 +1,173 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import java.io.File; +import java.security.MessageDigest; + +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.util.RawParseUtils; + +public class FileTreeIteratorTest extends RepositoryTestCase { + private final String[] paths = { "a,", "a,b", "a/b", "a0b" }; + + private long[] mtime; + + public void setUp() throws Exception { + super.setUp(); + + // We build the entries backwards so that on POSIX systems we + // are likely to get the entries in the trash directory in the + // opposite order of what they should be in for the iteration. + // This should stress the sorting code better than doing it in + // the correct order. + // + mtime = new long[paths.length]; + for (int i = paths.length - 1; i >= 0; i--) { + final String s = paths[i]; + writeTrashFile(s, s); + mtime[i] = new File(trash, s).lastModified(); + } + } + + public void testEmptyIfRootIsFile() throws Exception { + final File r = new File(trash, paths[0]); + assertTrue(r.isFile()); + final FileTreeIterator fti = new FileTreeIterator(r); + assertTrue(fti.first()); + assertTrue(fti.eof()); + } + + public void testEmptyIfRootDoesNotExist() throws Exception { + final File r = new File(trash, "not-existing-file"); + assertFalse(r.exists()); + final FileTreeIterator fti = new FileTreeIterator(r); + assertTrue(fti.first()); + assertTrue(fti.eof()); + } + + public void testEmptyIfRootIsEmpty() throws Exception { + final File r = new File(trash, "not-existing-file"); + assertFalse(r.exists()); + r.mkdir(); + assertTrue(r.isDirectory()); + + final FileTreeIterator fti = new FileTreeIterator(r); + assertTrue(fti.first()); + assertTrue(fti.eof()); + } + + public void testSimpleIterate() throws Exception { + final FileTreeIterator top = new FileTreeIterator(trash); + + assertTrue(top.first()); + assertFalse(top.eof()); + assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode); + assertEquals(paths[0], nameOf(top)); + assertEquals(paths[0].length(), top.getEntryLength()); + assertEquals(mtime[0], top.getEntryLastModified()); + + top.next(1); + assertFalse(top.first()); + assertFalse(top.eof()); + assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode); + assertEquals(paths[1], nameOf(top)); + assertEquals(paths[1].length(), top.getEntryLength()); + assertEquals(mtime[1], top.getEntryLastModified()); + + top.next(1); + assertFalse(top.first()); + assertFalse(top.eof()); + assertEquals(FileMode.TREE.getBits(), top.mode); + + final AbstractTreeIterator sub = top.createSubtreeIterator(db); + assertTrue(sub instanceof FileTreeIterator); + final FileTreeIterator subfti = (FileTreeIterator) sub; + assertTrue(sub.first()); + assertFalse(sub.eof()); + assertEquals(paths[2], nameOf(sub)); + assertEquals(paths[2].length(), subfti.getEntryLength()); + assertEquals(mtime[2], subfti.getEntryLastModified()); + + sub.next(1); + assertTrue(sub.eof()); + + top.next(1); + assertFalse(top.first()); + assertFalse(top.eof()); + assertEquals(FileMode.REGULAR_FILE.getBits(), top.mode); + assertEquals(paths[3], nameOf(top)); + assertEquals(paths[3].length(), top.getEntryLength()); + assertEquals(mtime[3], top.getEntryLastModified()); + + top.next(1); + assertTrue(top.eof()); + } + + public void testComputeFileObjectId() throws Exception { + final FileTreeIterator top = new FileTreeIterator(trash); + + final MessageDigest md = Constants.newMessageDigest(); + md.update(Constants.encodeASCII(Constants.TYPE_BLOB)); + md.update((byte) ' '); + md.update(Constants.encodeASCII(paths[0].length())); + md.update((byte) 0); + md.update(Constants.encode(paths[0])); + final ObjectId expect = ObjectId.fromRaw(md.digest()); + + assertEquals(expect, top.getEntryObjectId()); + + // Verify it was cached by removing the file and getting it again. + // + new File(trash, paths[0]).delete(); + assertEquals(expect, top.getEntryObjectId()); + } + + private static String nameOf(final AbstractTreeIterator i) { + return RawParseUtils.decode(Constants.CHARSET, i.path, 0, i.pathLen); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java new file mode 100644 index 0000000000..35298b803f --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/NameConflictTreeWalkTest.java @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import java.io.ByteArrayInputStream; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.RepositoryTestCase; + +public class NameConflictTreeWalkTest extends RepositoryTestCase { + private static final FileMode TREE = FileMode.TREE; + + private static final FileMode SYMLINK = FileMode.SYMLINK; + + private static final FileMode MISSING = FileMode.MISSING; + + private static final FileMode REGULAR_FILE = FileMode.REGULAR_FILE; + + private static final FileMode EXECUTABLE_FILE = FileMode.EXECUTABLE_FILE; + + public void testNoDF_NoGap() throws Exception { + final DirCache tree0 = DirCache.read(db); + final DirCache tree1 = DirCache.read(db); + { + final DirCacheBuilder b0 = tree0.builder(); + final DirCacheBuilder b1 = tree1.builder(); + + b0.add(makeEntry("a", REGULAR_FILE)); + b0.add(makeEntry("a.b", EXECUTABLE_FILE)); + b1.add(makeEntry("a/b", REGULAR_FILE)); + b0.add(makeEntry("a0b", SYMLINK)); + + b0.finish(); + b1.finish(); + assertEquals(3, tree0.getEntryCount()); + assertEquals(1, tree1.getEntryCount()); + } + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(tree0)); + tw.addTree(new DirCacheIterator(tree1)); + + assertModes("a", REGULAR_FILE, MISSING, tw); + assertModes("a.b", EXECUTABLE_FILE, MISSING, tw); + assertModes("a", MISSING, TREE, tw); + tw.enterSubtree(); + assertModes("a/b", MISSING, REGULAR_FILE, tw); + assertModes("a0b", SYMLINK, MISSING, tw); + } + + public void testDF_NoGap() throws Exception { + final DirCache tree0 = DirCache.read(db); + final DirCache tree1 = DirCache.read(db); + { + final DirCacheBuilder b0 = tree0.builder(); + final DirCacheBuilder b1 = tree1.builder(); + + b0.add(makeEntry("a", REGULAR_FILE)); + b0.add(makeEntry("a.b", EXECUTABLE_FILE)); + b1.add(makeEntry("a/b", REGULAR_FILE)); + b0.add(makeEntry("a0b", SYMLINK)); + + b0.finish(); + b1.finish(); + assertEquals(3, tree0.getEntryCount()); + assertEquals(1, tree1.getEntryCount()); + } + + final NameConflictTreeWalk tw = new NameConflictTreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(tree0)); + tw.addTree(new DirCacheIterator(tree1)); + + assertModes("a", REGULAR_FILE, TREE, tw); + assertTrue(tw.isSubtree()); + tw.enterSubtree(); + assertModes("a/b", MISSING, REGULAR_FILE, tw); + assertModes("a.b", EXECUTABLE_FILE, MISSING, tw); + assertModes("a0b", SYMLINK, MISSING, tw); + } + + public void testDF_GapByOne() throws Exception { + final DirCache tree0 = DirCache.read(db); + final DirCache tree1 = DirCache.read(db); + { + final DirCacheBuilder b0 = tree0.builder(); + final DirCacheBuilder b1 = tree1.builder(); + + b0.add(makeEntry("a", REGULAR_FILE)); + b0.add(makeEntry("a.b", EXECUTABLE_FILE)); + b1.add(makeEntry("a.b", EXECUTABLE_FILE)); + b1.add(makeEntry("a/b", REGULAR_FILE)); + b0.add(makeEntry("a0b", SYMLINK)); + + b0.finish(); + b1.finish(); + assertEquals(3, tree0.getEntryCount()); + assertEquals(2, tree1.getEntryCount()); + } + + final NameConflictTreeWalk tw = new NameConflictTreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(tree0)); + tw.addTree(new DirCacheIterator(tree1)); + + assertModes("a", REGULAR_FILE, TREE, tw); + assertTrue(tw.isSubtree()); + tw.enterSubtree(); + assertModes("a/b", MISSING, REGULAR_FILE, tw); + assertModes("a.b", EXECUTABLE_FILE, EXECUTABLE_FILE, tw); + assertModes("a0b", SYMLINK, MISSING, tw); + } + + public void testDF_SkipsSeenSubtree() throws Exception { + final DirCache tree0 = DirCache.read(db); + final DirCache tree1 = DirCache.read(db); + { + final DirCacheBuilder b0 = tree0.builder(); + final DirCacheBuilder b1 = tree1.builder(); + + b0.add(makeEntry("a", REGULAR_FILE)); + b1.add(makeEntry("a.b", EXECUTABLE_FILE)); + b1.add(makeEntry("a/b", REGULAR_FILE)); + b0.add(makeEntry("a0b", SYMLINK)); + b1.add(makeEntry("a0b", SYMLINK)); + + b0.finish(); + b1.finish(); + assertEquals(2, tree0.getEntryCount()); + assertEquals(3, tree1.getEntryCount()); + } + + final NameConflictTreeWalk tw = new NameConflictTreeWalk(db); + tw.reset(); + tw.addTree(new DirCacheIterator(tree0)); + tw.addTree(new DirCacheIterator(tree1)); + + assertModes("a", REGULAR_FILE, TREE, tw); + assertTrue(tw.isSubtree()); + tw.enterSubtree(); + assertModes("a/b", MISSING, REGULAR_FILE, tw); + assertModes("a.b", MISSING, EXECUTABLE_FILE, tw); + assertModes("a0b", SYMLINK, SYMLINK, tw); + } + + private DirCacheEntry makeEntry(final String path, final FileMode mode) + throws Exception { + final byte[] pathBytes = Constants.encode(path); + final DirCacheEntry ent = new DirCacheEntry(path); + ent.setFileMode(mode); + ent.setObjectId(new ObjectWriter(db).computeBlobSha1(pathBytes.length, + new ByteArrayInputStream(pathBytes))); + return ent; + } + + private static void assertModes(final String path, final FileMode mode0, + final FileMode mode1, final TreeWalk tw) throws Exception { + assertTrue("has " + path, tw.next()); + assertEquals(path, tw.getPathString()); + assertEquals(mode0, tw.getFileMode(0)); + assertEquals(mode1, tw.getFileMode(1)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java new file mode 100644 index 0000000000..d136b8f297 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/PostOrderTreeWalkTest.java @@ -0,0 +1,195 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import java.io.ByteArrayInputStream; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.dircache.DirCacheIterator; +import org.eclipse.jgit.lib.Constants; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.RepositoryTestCase; + +import static org.eclipse.jgit.lib.FileMode.REGULAR_FILE; +import static org.eclipse.jgit.lib.FileMode.TREE; + +public class PostOrderTreeWalkTest extends RepositoryTestCase { + public void testInitialize_NoPostOrder() throws Exception { + final TreeWalk tw = new TreeWalk(db); + assertFalse(tw.isPostOrderTraversal()); + } + + public void testInitialize_TogglePostOrder() throws Exception { + final TreeWalk tw = new TreeWalk(db); + assertFalse(tw.isPostOrderTraversal()); + tw.setPostOrderTraversal(true); + assertTrue(tw.isPostOrderTraversal()); + tw.setPostOrderTraversal(false); + assertFalse(tw.isPostOrderTraversal()); + } + + public void testResetDoesNotAffectPostOrder() throws Exception { + final TreeWalk tw = new TreeWalk(db); + tw.setPostOrderTraversal(true); + assertTrue(tw.isPostOrderTraversal()); + tw.reset(); + assertTrue(tw.isPostOrderTraversal()); + + tw.setPostOrderTraversal(false); + assertFalse(tw.isPostOrderTraversal()); + tw.reset(); + assertFalse(tw.isPostOrderTraversal()); + } + + public void testNoPostOrder() throws Exception { + final DirCache tree = DirCache.read(db); + { + final DirCacheBuilder b = tree.builder(); + + b.add(makeFile("a")); + b.add(makeFile("b/c")); + b.add(makeFile("b/d")); + b.add(makeFile("q")); + + b.finish(); + assertEquals(4, tree.getEntryCount()); + } + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.setPostOrderTraversal(false); + tw.addTree(new DirCacheIterator(tree)); + + assertModes("a", REGULAR_FILE, tw); + assertModes("b", TREE, tw); + assertTrue(tw.isSubtree()); + assertFalse(tw.isPostChildren()); + tw.enterSubtree(); + assertModes("b/c", REGULAR_FILE, tw); + assertModes("b/d", REGULAR_FILE, tw); + assertModes("q", REGULAR_FILE, tw); + } + + public void testWithPostOrder_EnterSubtree() throws Exception { + final DirCache tree = DirCache.read(db); + { + final DirCacheBuilder b = tree.builder(); + + b.add(makeFile("a")); + b.add(makeFile("b/c")); + b.add(makeFile("b/d")); + b.add(makeFile("q")); + + b.finish(); + assertEquals(4, tree.getEntryCount()); + } + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.setPostOrderTraversal(true); + tw.addTree(new DirCacheIterator(tree)); + + assertModes("a", REGULAR_FILE, tw); + + assertModes("b", TREE, tw); + assertTrue(tw.isSubtree()); + assertFalse(tw.isPostChildren()); + tw.enterSubtree(); + assertModes("b/c", REGULAR_FILE, tw); + assertModes("b/d", REGULAR_FILE, tw); + + assertModes("b", TREE, tw); + assertTrue(tw.isSubtree()); + assertTrue(tw.isPostChildren()); + + assertModes("q", REGULAR_FILE, tw); + } + + public void testWithPostOrder_NoEnterSubtree() throws Exception { + final DirCache tree = DirCache.read(db); + { + final DirCacheBuilder b = tree.builder(); + + b.add(makeFile("a")); + b.add(makeFile("b/c")); + b.add(makeFile("b/d")); + b.add(makeFile("q")); + + b.finish(); + assertEquals(4, tree.getEntryCount()); + } + + final TreeWalk tw = new TreeWalk(db); + tw.reset(); + tw.setPostOrderTraversal(true); + tw.addTree(new DirCacheIterator(tree)); + + assertModes("a", REGULAR_FILE, tw); + + assertModes("b", TREE, tw); + assertTrue(tw.isSubtree()); + assertFalse(tw.isPostChildren()); + + assertModes("q", REGULAR_FILE, tw); + } + + private DirCacheEntry makeFile(final String path) throws Exception { + final byte[] pathBytes = Constants.encode(path); + final DirCacheEntry ent = new DirCacheEntry(path); + ent.setFileMode(REGULAR_FILE); + ent.setObjectId(new ObjectWriter(db).computeBlobSha1(pathBytes.length, + new ByteArrayInputStream(pathBytes))); + return ent; + } + + private static void assertModes(final String path, final FileMode mode0, + final TreeWalk tw) throws Exception { + assertTrue("has " + path, tw.next()); + assertEquals(path, tw.getPathString()); + assertEquals(mode0, tw.getFileMode(0)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkBasicDiffTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkBasicDiffTest.java new file mode 100644 index 0000000000..581683e34f --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/TreeWalkBasicDiffTest.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk; + +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.lib.Tree; +import org.eclipse.jgit.treewalk.filter.TreeFilter; + +public class TreeWalkBasicDiffTest extends RepositoryTestCase { + public void testMissingSubtree_DetectFileAdded_FileModified() + throws Exception { + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId aFileId = ow.writeBlob("a".getBytes()); + final ObjectId bFileId = ow.writeBlob("b".getBytes()); + final ObjectId cFileId1 = ow.writeBlob("c-1".getBytes()); + final ObjectId cFileId2 = ow.writeBlob("c-2".getBytes()); + + // Create sub-a/empty, sub-c/empty = hello. + final ObjectId oldTree; + { + final Tree root = new Tree(db); + { + final Tree subA = root.addTree("sub-a"); + subA.addFile("empty").setId(aFileId); + subA.setId(ow.writeTree(subA)); + } + { + final Tree subC = root.addTree("sub-c"); + subC.addFile("empty").setId(cFileId1); + subC.setId(ow.writeTree(subC)); + } + oldTree = ow.writeTree(root); + } + + // Create sub-a/empty, sub-b/empty, sub-c/empty. + final ObjectId newTree; + { + final Tree root = new Tree(db); + { + final Tree subA = root.addTree("sub-a"); + subA.addFile("empty").setId(aFileId); + subA.setId(ow.writeTree(subA)); + } + { + final Tree subB = root.addTree("sub-b"); + subB.addFile("empty").setId(bFileId); + subB.setId(ow.writeTree(subB)); + } + { + final Tree subC = root.addTree("sub-c"); + subC.addFile("empty").setId(cFileId2); + subC.setId(ow.writeTree(subC)); + } + newTree = ow.writeTree(root); + } + + final TreeWalk tw = new TreeWalk(db); + tw.reset(new ObjectId[] { oldTree, newTree }); + tw.setRecursive(true); + tw.setFilter(TreeFilter.ANY_DIFF); + + assertTrue(tw.next()); + assertEquals("sub-b/empty", tw.getPathString()); + assertEquals(FileMode.MISSING, tw.getFileMode(0)); + assertEquals(FileMode.REGULAR_FILE, tw.getFileMode(1)); + assertEquals(ObjectId.zeroId(), tw.getObjectId(0)); + assertEquals(bFileId, tw.getObjectId(1)); + + assertTrue(tw.next()); + assertEquals("sub-c/empty", tw.getPathString()); + assertEquals(FileMode.REGULAR_FILE, tw.getFileMode(0)); + assertEquals(FileMode.REGULAR_FILE, tw.getFileMode(1)); + assertEquals(cFileId1, tw.getObjectId(0)); + assertEquals(cFileId2, tw.getObjectId(1)); + + assertFalse(tw.next()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/AlwaysCloneTreeFilter.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/AlwaysCloneTreeFilter.java new file mode 100644 index 0000000000..8e2cca44ae --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/AlwaysCloneTreeFilter.java @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk.filter; + +import org.eclipse.jgit.treewalk.TreeWalk; + +class AlwaysCloneTreeFilter extends TreeFilter { + @Override + public TreeFilter clone() { + return new AlwaysCloneTreeFilter(); + } + + @Override + public boolean include(final TreeWalk walker) { + return false; + } + + @Override + public boolean shouldBeRecursive() { + return false; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/NotTreeFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/NotTreeFilterTest.java new file mode 100644 index 0000000000..7c7ab3e6ae --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/NotTreeFilterTest.java @@ -0,0 +1,91 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk.filter; + +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; + +public class NotTreeFilterTest extends RepositoryTestCase { + public void testWrap() throws Exception { + final TreeWalk tw = new TreeWalk(db); + final TreeFilter a = TreeFilter.ALL; + final TreeFilter n = NotTreeFilter.create(a); + assertNotNull(n); + assertTrue(a.include(tw)); + assertFalse(n.include(tw)); + } + + public void testNegateIsUnwrap() throws Exception { + final TreeFilter a = PathFilter.create("a/b"); + final TreeFilter n = NotTreeFilter.create(a); + assertSame(a, n.negate()); + } + + public void testShouldBeRecursive_ALL() throws Exception { + final TreeFilter a = TreeFilter.ALL; + final TreeFilter n = NotTreeFilter.create(a); + assertEquals(a.shouldBeRecursive(), n.shouldBeRecursive()); + } + + public void testShouldBeRecursive_PathFilter() throws Exception { + final TreeFilter a = PathFilter.create("a/b"); + assertTrue(a.shouldBeRecursive()); + final TreeFilter n = NotTreeFilter.create(a); + assertTrue(n.shouldBeRecursive()); + } + + public void testCloneIsDeepClone() throws Exception { + final TreeFilter a = new AlwaysCloneTreeFilter(); + assertNotSame(a, a.clone()); + final TreeFilter n = NotTreeFilter.create(a); + assertNotSame(n, n.clone()); + } + + public void testCloneIsSparseWhenPossible() throws Exception { + final TreeFilter a = TreeFilter.ALL; + assertSame(a, a.clone()); + final TreeFilter n = NotTreeFilter.create(a); + assertSame(n, n.clone()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java new file mode 100644 index 0000000000..1aaefc415f --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/PathSuffixFilterTestCase.java @@ -0,0 +1,139 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk.filter; + +import java.io.IOException; +import java.util.LinkedList; +import java.util.List; + +import org.eclipse.jgit.dircache.DirCache; +import org.eclipse.jgit.dircache.DirCacheBuilder; +import org.eclipse.jgit.dircache.DirCacheEntry; +import org.eclipse.jgit.lib.FileMode; +import org.eclipse.jgit.lib.ObjectId; +import org.eclipse.jgit.lib.ObjectWriter; +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; + +public class PathSuffixFilterTestCase extends RepositoryTestCase { + + public void testNonRecursiveFiltering() throws IOException { + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId aSth = ow.writeBlob("a.sth".getBytes()); + final ObjectId aTxt = ow.writeBlob("a.txt".getBytes()); + final DirCache dc = DirCache.read(db); + final DirCacheBuilder builder = dc.builder(); + final DirCacheEntry aSthEntry = new DirCacheEntry("a.sth"); + aSthEntry.setFileMode(FileMode.REGULAR_FILE); + aSthEntry.setObjectId(aSth); + final DirCacheEntry aTxtEntry = new DirCacheEntry("a.txt"); + aTxtEntry.setFileMode(FileMode.REGULAR_FILE); + aTxtEntry.setObjectId(aTxt); + builder.add(aSthEntry); + builder.add(aTxtEntry); + builder.finish(); + final ObjectId treeId = dc.writeTree(ow); + + + final TreeWalk tw = new TreeWalk(db); + tw.setFilter(PathSuffixFilter.create(".txt")); + tw.addTree(treeId); + + List<String> paths = new LinkedList<String>(); + while (tw.next()) { + paths.add(tw.getPathString()); + } + + List<String> expected = new LinkedList<String>(); + expected.add("a.txt"); + + assertEquals(expected, paths); + } + + public void testRecursiveFiltering() throws IOException { + final ObjectWriter ow = new ObjectWriter(db); + final ObjectId aSth = ow.writeBlob("a.sth".getBytes()); + final ObjectId aTxt = ow.writeBlob("a.txt".getBytes()); + final ObjectId bSth = ow.writeBlob("b.sth".getBytes()); + final ObjectId bTxt = ow.writeBlob("b.txt".getBytes()); + final DirCache dc = DirCache.read(db); + final DirCacheBuilder builder = dc.builder(); + final DirCacheEntry aSthEntry = new DirCacheEntry("a.sth"); + aSthEntry.setFileMode(FileMode.REGULAR_FILE); + aSthEntry.setObjectId(aSth); + final DirCacheEntry aTxtEntry = new DirCacheEntry("a.txt"); + aTxtEntry.setFileMode(FileMode.REGULAR_FILE); + aTxtEntry.setObjectId(aTxt); + builder.add(aSthEntry); + builder.add(aTxtEntry); + final DirCacheEntry bSthEntry = new DirCacheEntry("sub/b.sth"); + bSthEntry.setFileMode(FileMode.REGULAR_FILE); + bSthEntry.setObjectId(bSth); + final DirCacheEntry bTxtEntry = new DirCacheEntry("sub/b.txt"); + bTxtEntry.setFileMode(FileMode.REGULAR_FILE); + bTxtEntry.setObjectId(bTxt); + builder.add(bSthEntry); + builder.add(bTxtEntry); + builder.finish(); + final ObjectId treeId = dc.writeTree(ow); + + + final TreeWalk tw = new TreeWalk(db); + tw.setRecursive(true); + tw.setFilter(PathSuffixFilter.create(".txt")); + tw.addTree(treeId); + + List<String> paths = new LinkedList<String>(); + while (tw.next()) { + paths.add(tw.getPathString()); + } + + List<String> expected = new LinkedList<String>(); + expected.add("a.txt"); + expected.add("sub/b.txt"); + + assertEquals(expected, paths); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/TreeFilterTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/TreeFilterTest.java new file mode 100644 index 0000000000..12326eade2 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/treewalk/filter/TreeFilterTest.java @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.treewalk.filter; + +import org.eclipse.jgit.lib.RepositoryTestCase; +import org.eclipse.jgit.treewalk.TreeWalk; + +public class TreeFilterTest extends RepositoryTestCase { + public void testALL_IncludesAnything() throws Exception { + final TreeWalk tw = new TreeWalk(db); + assertTrue(TreeFilter.ALL.include(tw)); + } + + public void testALL_ShouldNotBeRecursive() throws Exception { + assertFalse(TreeFilter.ALL.shouldBeRecursive()); + } + + public void testALL_IdentityClone() throws Exception { + assertSame(TreeFilter.ALL, TreeFilter.ALL.clone()); + } + + public void testNotALL_IncludesNothing() throws Exception { + final TreeWalk tw = new TreeWalk(db); + assertFalse(TreeFilter.ALL.negate().include(tw)); + } + + public void testANY_DIFF_IncludesSingleTreeCase() throws Exception { + final TreeWalk tw = new TreeWalk(db); + assertTrue(TreeFilter.ANY_DIFF.include(tw)); + } + + public void testANY_DIFF_ShouldNotBeRecursive() throws Exception { + assertFalse(TreeFilter.ANY_DIFF.shouldBeRecursive()); + } + + public void testANY_DIFF_IdentityClone() throws Exception { + assertSame(TreeFilter.ANY_DIFF, TreeFilter.ANY_DIFF.clone()); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java new file mode 100644 index 0000000000..ecabeeea5b --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/IntListTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import junit.framework.TestCase; + +public class IntListTest extends TestCase { + public void testEmpty_DefaultCapacity() { + final IntList i = new IntList(); + assertEquals(0, i.size()); + try { + i.get(0); + fail("Accepted 0 index on empty list"); + } catch (ArrayIndexOutOfBoundsException e) { + assertTrue(true); + } + } + + public void testEmpty_SpecificCapacity() { + final IntList i = new IntList(5); + assertEquals(0, i.size()); + try { + i.get(0); + fail("Accepted 0 index on empty list"); + } catch (ArrayIndexOutOfBoundsException e) { + assertTrue(true); + } + } + + public void testAdd_SmallGroup() { + final IntList i = new IntList(); + final int n = 5; + for (int v = 0; v < n; v++) + i.add(10 + v); + assertEquals(n, i.size()); + + for (int v = 0; v < n; v++) + assertEquals(10 + v, i.get(v)); + try { + i.get(n); + fail("Accepted out of bound index on list"); + } catch (ArrayIndexOutOfBoundsException e) { + assertTrue(true); + } + } + + public void testAdd_ZeroCapacity() { + final IntList i = new IntList(0); + assertEquals(0, i.size()); + i.add(1); + assertEquals(1, i.get(0)); + } + + public void testAdd_LargeGroup() { + final IntList i = new IntList(); + final int n = 500; + for (int v = 0; v < n; v++) + i.add(10 + v); + assertEquals(n, i.size()); + + for (int v = 0; v < n; v++) + assertEquals(10 + v, i.get(v)); + try { + i.get(n); + fail("Accepted out of bound index on list"); + } catch (ArrayIndexOutOfBoundsException e) { + assertTrue(true); + } + } + + public void testFillTo0() { + final IntList i = new IntList(); + i.fillTo(0, Integer.MIN_VALUE); + assertEquals(0, i.size()); + } + + public void testFillTo1() { + final IntList i = new IntList(); + i.fillTo(1, Integer.MIN_VALUE); + assertEquals(1, i.size()); + i.add(0); + assertEquals(Integer.MIN_VALUE, i.get(0)); + assertEquals(0, i.get(1)); + } + + public void testFillTo100() { + final IntList i = new IntList(); + i.fillTo(100, Integer.MIN_VALUE); + assertEquals(100, i.size()); + i.add(3); + assertEquals(Integer.MIN_VALUE, i.get(99)); + assertEquals(3, i.get(100)); + } + + public void testClear() { + final IntList i = new IntList(); + final int n = 5; + for (int v = 0; v < n; v++) + i.add(10 + v); + assertEquals(n, i.size()); + + i.clear(); + assertEquals(0, i.size()); + try { + i.get(0); + fail("Accepted 0 index on empty list"); + } catch (ArrayIndexOutOfBoundsException e) { + assertTrue(true); + } + } + + public void testToString() { + final IntList i = new IntList(); + i.add(1); + assertEquals("[1]", i.toString()); + i.add(13); + i.add(5); + assertEquals("[1, 13, 5]", i.toString()); + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java new file mode 100644 index 0000000000..37418417d3 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/JGitTestUtil.java @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * Copyright (C) 2008, Imran M Yousuf <imyousuf@smartitengineering.com> + * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk> + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import java.io.File; +import java.net.URISyntaxException; +import java.net.URL; + +public abstract class JGitTestUtil { + public static final String CLASSPATH_TO_RESOURCES = "org/eclipse/jgit/test/resources/"; + + private JGitTestUtil() { + throw new UnsupportedOperationException(); + } + + public static File getTestResourceFile(final String fileName) { + if (fileName == null || fileName.length() <= 0) { + return null; + } + final URL url = cl().getResource(CLASSPATH_TO_RESOURCES + fileName); + if (url == null) { + // If URL is null then try to load it as it was being + // loaded previously + return new File("tst", fileName); + } + try { + return new File(url.toURI()); + } catch(URISyntaxException e) { + return new File(url.getPath()); + } + } + + private static ClassLoader cl() { + return JGitTestUtil.class.getClassLoader(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/NBTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/NBTest.java new file mode 100644 index 0000000000..21fea9e9d5 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/NBTest.java @@ -0,0 +1,334 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import junit.framework.TestCase; + +public class NBTest extends TestCase { + public void testCompareUInt32() { + assertTrue(NB.compareUInt32(0, 0) == 0); + assertTrue(NB.compareUInt32(1, 0) > 0); + assertTrue(NB.compareUInt32(0, 1) < 0); + assertTrue(NB.compareUInt32(-1, 0) > 0); + assertTrue(NB.compareUInt32(0, -1) < 0); + assertTrue(NB.compareUInt32(-1, 1) > 0); + assertTrue(NB.compareUInt32(1, -1) < 0); + } + + public void testDecodeUInt16() { + assertEquals(0, NB.decodeUInt16(b(0, 0), 0)); + assertEquals(0, NB.decodeUInt16(padb(3, 0, 0), 3)); + + assertEquals(3, NB.decodeUInt16(b(0, 3), 0)); + assertEquals(3, NB.decodeUInt16(padb(3, 0, 3), 3)); + + assertEquals(0xde03, NB.decodeUInt16(b(0xde, 3), 0)); + assertEquals(0xde03, NB.decodeUInt16(padb(3, 0xde, 3), 3)); + + assertEquals(0x03de, NB.decodeUInt16(b(3, 0xde), 0)); + assertEquals(0x03de, NB.decodeUInt16(padb(3, 3, 0xde), 3)); + + assertEquals(0xffff, NB.decodeUInt16(b(0xff, 0xff), 0)); + assertEquals(0xffff, NB.decodeUInt16(padb(3, 0xff, 0xff), 3)); + } + + public void testDecodeInt32() { + assertEquals(0, NB.decodeInt32(b(0, 0, 0, 0), 0)); + assertEquals(0, NB.decodeInt32(padb(3, 0, 0, 0, 0), 3)); + + assertEquals(3, NB.decodeInt32(b(0, 0, 0, 3), 0)); + assertEquals(3, NB.decodeInt32(padb(3, 0, 0, 0, 3), 3)); + + assertEquals(0xdeadbeef, NB.decodeInt32(b(0xde, 0xad, 0xbe, 0xef), 0)); + assertEquals(0xdeadbeef, NB.decodeInt32( + padb(3, 0xde, 0xad, 0xbe, 0xef), 3)); + + assertEquals(0x0310adef, NB.decodeInt32(b(0x03, 0x10, 0xad, 0xef), 0)); + assertEquals(0x0310adef, NB.decodeInt32( + padb(3, 0x03, 0x10, 0xad, 0xef), 3)); + + assertEquals(0xffffffff, NB.decodeInt32(b(0xff, 0xff, 0xff, 0xff), 0)); + assertEquals(0xffffffff, NB.decodeInt32( + padb(3, 0xff, 0xff, 0xff, 0xff), 3)); + } + + public void testDecodeUInt32() { + assertEquals(0L, NB.decodeUInt32(b(0, 0, 0, 0), 0)); + assertEquals(0L, NB.decodeUInt32(padb(3, 0, 0, 0, 0), 3)); + + assertEquals(3L, NB.decodeUInt32(b(0, 0, 0, 3), 0)); + assertEquals(3L, NB.decodeUInt32(padb(3, 0, 0, 0, 3), 3)); + + assertEquals(0xdeadbeefL, NB.decodeUInt32(b(0xde, 0xad, 0xbe, 0xef), 0)); + assertEquals(0xdeadbeefL, NB.decodeUInt32(padb(3, 0xde, 0xad, 0xbe, + 0xef), 3)); + + assertEquals(0x0310adefL, NB.decodeUInt32(b(0x03, 0x10, 0xad, 0xef), 0)); + assertEquals(0x0310adefL, NB.decodeUInt32(padb(3, 0x03, 0x10, 0xad, + 0xef), 3)); + + assertEquals(0xffffffffL, NB.decodeUInt32(b(0xff, 0xff, 0xff, 0xff), 0)); + assertEquals(0xffffffffL, NB.decodeUInt32(padb(3, 0xff, 0xff, 0xff, + 0xff), 3)); + } + + public void testDecodeUInt64() { + assertEquals(0L, NB.decodeUInt64(b(0, 0, 0, 0, 0, 0, 0, 0), 0)); + assertEquals(0L, NB.decodeUInt64(padb(3, 0, 0, 0, 0, 0, 0, 0, 0), 3)); + + assertEquals(3L, NB.decodeUInt64(b(0, 0, 0, 0, 0, 0, 0, 3), 0)); + assertEquals(3L, NB.decodeUInt64(padb(3, 0, 0, 0, 0, 0, 0, 0, 3), 3)); + + assertEquals(0xdeadbeefL, NB.decodeUInt64(b(0, 0, 0, 0, 0xde, 0xad, + 0xbe, 0xef), 0)); + assertEquals(0xdeadbeefL, NB.decodeUInt64(padb(3, 0, 0, 0, 0, 0xde, + 0xad, 0xbe, 0xef), 3)); + + assertEquals(0x0310adefL, NB.decodeUInt64(b(0, 0, 0, 0, 0x03, 0x10, + 0xad, 0xef), 0)); + assertEquals(0x0310adefL, NB.decodeUInt64(padb(3, 0, 0, 0, 0, 0x03, + 0x10, 0xad, 0xef), 3)); + + assertEquals(0xc0ffee78deadbeefL, NB.decodeUInt64(b(0xc0, 0xff, 0xee, + 0x78, 0xde, 0xad, 0xbe, 0xef), 0)); + assertEquals(0xc0ffee78deadbeefL, NB.decodeUInt64(padb(3, 0xc0, 0xff, + 0xee, 0x78, 0xde, 0xad, 0xbe, 0xef), 3)); + + assertEquals(0x00000000ffffffffL, NB.decodeUInt64(b(0, 0, 0, 0, 0xff, + 0xff, 0xff, 0xff), 0)); + assertEquals(0x00000000ffffffffL, NB.decodeUInt64(padb(3, 0, 0, 0, 0, + 0xff, 0xff, 0xff, 0xff), 3)); + assertEquals(0xffffffffffffffffL, NB.decodeUInt64(b(0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff), 0)); + assertEquals(0xffffffffffffffffL, NB.decodeUInt64(padb(3, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), 3)); + } + + public void testEncodeInt16() { + final byte[] out = new byte[16]; + + prepareOutput(out); + NB.encodeInt16(out, 0, 0); + assertOutput(b(0, 0), out, 0); + + prepareOutput(out); + NB.encodeInt16(out, 3, 0); + assertOutput(b(0, 0), out, 3); + + prepareOutput(out); + NB.encodeInt16(out, 0, 3); + assertOutput(b(0, 3), out, 0); + + prepareOutput(out); + NB.encodeInt16(out, 3, 3); + assertOutput(b(0, 3), out, 3); + + prepareOutput(out); + NB.encodeInt16(out, 0, 0xdeac); + assertOutput(b(0xde, 0xac), out, 0); + + prepareOutput(out); + NB.encodeInt16(out, 3, 0xdeac); + assertOutput(b(0xde, 0xac), out, 3); + + prepareOutput(out); + NB.encodeInt16(out, 3, -1); + assertOutput(b(0xff, 0xff), out, 3); + } + + public void testEncodeInt32() { + final byte[] out = new byte[16]; + + prepareOutput(out); + NB.encodeInt32(out, 0, 0); + assertOutput(b(0, 0, 0, 0), out, 0); + + prepareOutput(out); + NB.encodeInt32(out, 3, 0); + assertOutput(b(0, 0, 0, 0), out, 3); + + prepareOutput(out); + NB.encodeInt32(out, 0, 3); + assertOutput(b(0, 0, 0, 3), out, 0); + + prepareOutput(out); + NB.encodeInt32(out, 3, 3); + assertOutput(b(0, 0, 0, 3), out, 3); + + prepareOutput(out); + NB.encodeInt32(out, 0, 0xdeac); + assertOutput(b(0, 0, 0xde, 0xac), out, 0); + + prepareOutput(out); + NB.encodeInt32(out, 3, 0xdeac); + assertOutput(b(0, 0, 0xde, 0xac), out, 3); + + prepareOutput(out); + NB.encodeInt32(out, 0, 0xdeac9853); + assertOutput(b(0xde, 0xac, 0x98, 0x53), out, 0); + + prepareOutput(out); + NB.encodeInt32(out, 3, 0xdeac9853); + assertOutput(b(0xde, 0xac, 0x98, 0x53), out, 3); + + prepareOutput(out); + NB.encodeInt32(out, 3, -1); + assertOutput(b(0xff, 0xff, 0xff, 0xff), out, 3); + } + + public void testEncodeInt64() { + final byte[] out = new byte[16]; + + prepareOutput(out); + NB.encodeInt64(out, 0, 0L); + assertOutput(b(0, 0, 0, 0, 0, 0, 0, 0), out, 0); + + prepareOutput(out); + NB.encodeInt64(out, 3, 0L); + assertOutput(b(0, 0, 0, 0, 0, 0, 0, 0), out, 3); + + prepareOutput(out); + NB.encodeInt64(out, 0, 3L); + assertOutput(b(0, 0, 0, 0, 0, 0, 0, 3), out, 0); + + prepareOutput(out); + NB.encodeInt64(out, 3, 3L); + assertOutput(b(0, 0, 0, 0, 0, 0, 0, 3), out, 3); + + prepareOutput(out); + NB.encodeInt64(out, 0, 0xdeacL); + assertOutput(b(0, 0, 0, 0, 0, 0, 0xde, 0xac), out, 0); + + prepareOutput(out); + NB.encodeInt64(out, 3, 0xdeacL); + assertOutput(b(0, 0, 0, 0, 0, 0, 0xde, 0xac), out, 3); + + prepareOutput(out); + NB.encodeInt64(out, 0, 0xdeac9853L); + assertOutput(b(0, 0, 0, 0, 0xde, 0xac, 0x98, 0x53), out, 0); + + prepareOutput(out); + NB.encodeInt64(out, 3, 0xdeac9853L); + assertOutput(b(0, 0, 0, 0, 0xde, 0xac, 0x98, 0x53), out, 3); + + prepareOutput(out); + NB.encodeInt64(out, 0, 0xac431242deac9853L); + assertOutput(b(0xac, 0x43, 0x12, 0x42, 0xde, 0xac, 0x98, 0x53), out, 0); + + prepareOutput(out); + NB.encodeInt64(out, 3, 0xac431242deac9853L); + assertOutput(b(0xac, 0x43, 0x12, 0x42, 0xde, 0xac, 0x98, 0x53), out, 3); + + prepareOutput(out); + NB.encodeInt64(out, 3, -1L); + assertOutput(b(0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff), out, 3); + } + + private static void prepareOutput(final byte[] buf) { + for (int i = 0; i < buf.length; i++) + buf[i] = (byte) (0x77 + i); + } + + private static void assertOutput(final byte[] expect, final byte[] buf, + final int offset) { + for (int i = 0; i < offset; i++) + assertEquals((byte) (0x77 + i), buf[i]); + for (int i = 0; i < expect.length; i++) + assertEquals(expect[i], buf[offset + i]); + for (int i = offset + expect.length; i < buf.length; i++) + assertEquals((byte) (0x77 + i), buf[i]); + } + + private static byte[] b(final int a, final int b) { + return new byte[] { (byte) a, (byte) b }; + } + + private static byte[] padb(final int len, final int a, final int b) { + final byte[] r = new byte[len + 2]; + for (int i = 0; i < len; i++) + r[i] = (byte) 0xaf; + r[len] = (byte) a; + r[len + 1] = (byte) b; + return r; + } + + private static byte[] b(final int a, final int b, final int c, final int d) { + return new byte[] { (byte) a, (byte) b, (byte) c, (byte) d }; + } + + private static byte[] padb(final int len, final int a, final int b, + final int c, final int d) { + final byte[] r = new byte[len + 4]; + for (int i = 0; i < len; i++) + r[i] = (byte) 0xaf; + r[len] = (byte) a; + r[len + 1] = (byte) b; + r[len + 2] = (byte) c; + r[len + 3] = (byte) d; + return r; + } + + private static byte[] b(final int a, final int b, final int c, final int d, + final int e, final int f, final int g, final int h) { + return new byte[] { (byte) a, (byte) b, (byte) c, (byte) d, (byte) e, + (byte) f, (byte) g, (byte) h }; + } + + private static byte[] padb(final int len, final int a, final int b, + final int c, final int d, final int e, final int f, final int g, + final int h) { + final byte[] r = new byte[len + 8]; + for (int i = 0; i < len; i++) + r[i] = (byte) 0xaf; + r[len] = (byte) a; + r[len + 1] = (byte) b; + r[len + 2] = (byte) c; + r[len + 3] = (byte) d; + r[len + 4] = (byte) e; + r[len + 5] = (byte) f; + r[len + 6] = (byte) g; + r[len + 7] = (byte) h; + return r; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneStyleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneStyleTest.java new file mode 100644 index 0000000000..b9a721a464 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneStyleTest.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import static org.eclipse.jgit.util.QuotedString.BOURNE; +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +public class QuotedStringBourneStyleTest extends TestCase { + private static void assertQuote(final String in, final String exp) { + final String r = BOURNE.quote(in); + assertNotSame(in, r); + assertFalse(in.equals(r)); + assertEquals('\'' + exp + '\'', r); + } + + private static void assertDequote(final String exp, final String in) { + final byte[] b = Constants.encode('\'' + in + '\''); + final String r = BOURNE.dequote(b, 0, b.length); + assertEquals(exp, r); + } + + public void testQuote_Empty() { + assertEquals("''", BOURNE.quote("")); + } + + public void testDequote_Empty1() { + assertEquals("", BOURNE.dequote(new byte[0], 0, 0)); + } + + public void testDequote_Empty2() { + assertEquals("", BOURNE.dequote(new byte[] { '\'', '\'' }, 0, 2)); + } + + public void testDequote_SoleSq() { + assertEquals("", BOURNE.dequote(new byte[] { '\'' }, 0, 1)); + } + + public void testQuote_BareA() { + assertQuote("a", "a"); + } + + public void testDequote_BareA() { + final String in = "a"; + final byte[] b = Constants.encode(in); + assertEquals(in, BOURNE.dequote(b, 0, b.length)); + } + + public void testDequote_BareABCZ_OnlyBC() { + final String in = "abcz"; + final byte[] b = Constants.encode(in); + final int p = in.indexOf('b'); + assertEquals("bc", BOURNE.dequote(b, p, p + 2)); + } + + public void testDequote_LoneBackslash() { + assertDequote("\\", "\\"); + } + + public void testQuote_NamedEscapes() { + assertQuote("'", "'\\''"); + assertQuote("!", "'\\!'"); + + assertQuote("a'b", "a'\\''b"); + assertQuote("a!b", "a'\\!'b"); + } + + public void testDequote_NamedEscapes() { + assertDequote("'", "'\\''"); + assertDequote("!", "'\\!'"); + + assertDequote("a'b", "a'\\''b"); + assertDequote("a!b", "a'\\!'b"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneUserPathStyleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneUserPathStyleTest.java new file mode 100644 index 0000000000..69201249c0 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringBourneUserPathStyleTest.java @@ -0,0 +1,136 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import static org.eclipse.jgit.util.QuotedString.BOURNE_USER_PATH; +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +public class QuotedStringBourneUserPathStyleTest extends TestCase { + private static void assertQuote(final String in, final String exp) { + final String r = BOURNE_USER_PATH.quote(in); + assertNotSame(in, r); + assertFalse(in.equals(r)); + assertEquals('\'' + exp + '\'', r); + } + + private static void assertDequote(final String exp, final String in) { + final byte[] b = Constants.encode('\'' + in + '\''); + final String r = BOURNE_USER_PATH.dequote(b, 0, b.length); + assertEquals(exp, r); + } + + public void testQuote_Empty() { + assertEquals("''", BOURNE_USER_PATH.quote("")); + } + + public void testDequote_Empty1() { + assertEquals("", BOURNE_USER_PATH.dequote(new byte[0], 0, 0)); + } + + public void testDequote_Empty2() { + assertEquals("", BOURNE_USER_PATH.dequote(new byte[] { '\'', '\'' }, 0, + 2)); + } + + public void testDequote_SoleSq() { + assertEquals("", BOURNE_USER_PATH.dequote(new byte[] { '\'' }, 0, 1)); + } + + public void testQuote_BareA() { + assertQuote("a", "a"); + } + + public void testDequote_BareA() { + final String in = "a"; + final byte[] b = Constants.encode(in); + assertEquals(in, BOURNE_USER_PATH.dequote(b, 0, b.length)); + } + + public void testDequote_BareABCZ_OnlyBC() { + final String in = "abcz"; + final byte[] b = Constants.encode(in); + final int p = in.indexOf('b'); + assertEquals("bc", BOURNE_USER_PATH.dequote(b, p, p + 2)); + } + + public void testDequote_LoneBackslash() { + assertDequote("\\", "\\"); + } + + public void testQuote_NamedEscapes() { + assertQuote("'", "'\\''"); + assertQuote("!", "'\\!'"); + + assertQuote("a'b", "a'\\''b"); + assertQuote("a!b", "a'\\!'b"); + } + + public void testDequote_NamedEscapes() { + assertDequote("'", "'\\''"); + assertDequote("!", "'\\!'"); + + assertDequote("a'b", "a'\\''b"); + assertDequote("a!b", "a'\\!'b"); + } + + public void testQuote_User() { + assertEquals("~foo/", BOURNE_USER_PATH.quote("~foo")); + assertEquals("~foo/", BOURNE_USER_PATH.quote("~foo/")); + assertEquals("~/", BOURNE_USER_PATH.quote("~/")); + + assertEquals("~foo/'a'", BOURNE_USER_PATH.quote("~foo/a")); + assertEquals("~/'a'", BOURNE_USER_PATH.quote("~/a")); + } + + public void testDequote_User() { + assertEquals("~foo", BOURNE_USER_PATH.dequote("~foo")); + assertEquals("~foo/", BOURNE_USER_PATH.dequote("~foo/")); + assertEquals("~/", BOURNE_USER_PATH.dequote("~/")); + + assertEquals("~foo/a", BOURNE_USER_PATH.dequote("~foo/'a'")); + assertEquals("~/a", BOURNE_USER_PATH.dequote("~/'a'")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java new file mode 100644 index 0000000000..4a161fa01c --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/QuotedStringGitPathStyleTest.java @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import static org.eclipse.jgit.util.QuotedString.GIT_PATH; + +import java.io.UnsupportedEncodingException; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +public class QuotedStringGitPathStyleTest extends TestCase { + private static void assertQuote(final String exp, final String in) { + final String r = GIT_PATH.quote(in); + assertNotSame(in, r); + assertFalse(in.equals(r)); + assertEquals('"' + exp + '"', r); + } + + private static void assertDequote(final String exp, final String in) { + final byte[] b; + try { + b = ('"' + in + '"').getBytes("ISO-8859-1"); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } + final String r = GIT_PATH.dequote(b, 0, b.length); + assertEquals(exp, r); + } + + public void testQuote_Empty() { + assertEquals("\"\"", GIT_PATH.quote("")); + } + + public void testDequote_Empty1() { + assertEquals("", GIT_PATH.dequote(new byte[0], 0, 0)); + } + + public void testDequote_Empty2() { + assertEquals("", GIT_PATH.dequote(new byte[] { '"', '"' }, 0, 2)); + } + + public void testDequote_SoleDq() { + assertEquals("\"", GIT_PATH.dequote(new byte[] { '"' }, 0, 1)); + } + + public void testQuote_BareA() { + final String in = "a"; + assertSame(in, GIT_PATH.quote(in)); + } + + public void testDequote_BareA() { + final String in = "a"; + final byte[] b = Constants.encode(in); + assertEquals(in, GIT_PATH.dequote(b, 0, b.length)); + } + + public void testDequote_BareABCZ_OnlyBC() { + final String in = "abcz"; + final byte[] b = Constants.encode(in); + final int p = in.indexOf('b'); + assertEquals("bc", GIT_PATH.dequote(b, p, p + 2)); + } + + public void testDequote_LoneBackslash() { + assertDequote("\\", "\\"); + } + + public void testQuote_NamedEscapes() { + assertQuote("\\a", "\u0007"); + assertQuote("\\b", "\b"); + assertQuote("\\f", "\f"); + assertQuote("\\n", "\n"); + assertQuote("\\r", "\r"); + assertQuote("\\t", "\t"); + assertQuote("\\v", "\u000B"); + assertQuote("\\\\", "\\"); + assertQuote("\\\"", "\""); + } + + public void testDequote_NamedEscapes() { + assertDequote("\u0007", "\\a"); + assertDequote("\b", "\\b"); + assertDequote("\f", "\\f"); + assertDequote("\n", "\\n"); + assertDequote("\r", "\\r"); + assertDequote("\t", "\\t"); + assertDequote("\u000B", "\\v"); + assertDequote("\\", "\\\\"); + assertDequote("\"", "\\\""); + } + + public void testDequote_OctalAll() { + for (int i = 0; i < 127; i++) { + assertDequote("" + (char) i, octalEscape(i)); + } + for (int i = 128; i < 256; i++) { + int f = 0xC0 | (i >> 6); + int s = 0x80 | (i & 0x3f); + assertDequote("" + (char) i, octalEscape(f)+octalEscape(s)); + } + } + + private String octalEscape(int i) { + String s = Integer.toOctalString(i); + while (s.length() < 3) { + s = "0" + s; + } + return "\\"+s; + } + + public void testQuote_OctalAll() { + assertQuote("\\001", "\1"); + assertQuote("\\176", "~"); + assertQuote("\\303\\277", "\u00ff"); // \u00ff in UTF-8 + } + + public void testDequote_UnknownEscapeQ() { + assertDequote("\\q", "\\q"); + } + + public void testDequote_FooTabBar() { + assertDequote("foo\tbar", "foo\\tbar"); + } + + public void testDequote_Latin1() { + assertDequote("\u00c5ngstr\u00f6m", "\\305ngstr\\366m"); // Latin1 + } + + public void testDequote_UTF8() { + assertDequote("\u00c5ngstr\u00f6m", "\\303\\205ngstr\\303\\266m"); + } + + public void testDequote_RawUTF8() { + assertDequote("\u00c5ngstr\u00f6m", "\303\205ngstr\303\266m"); + } + + public void testDequote_RawLatin1() { + assertDequote("\u00c5ngstr\u00f6m", "\305ngstr\366m"); + } + + public void testQuote_Ang() { + assertQuote("\\303\\205ngstr\\303\\266m", "\u00c5ngstr\u00f6m"); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_HexParseTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_HexParseTest.java new file mode 100644 index 0000000000..a2c9e9dbd1 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_HexParseTest.java @@ -0,0 +1,164 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +public class RawParseUtils_HexParseTest extends TestCase { + public void testInt4_1() { + assertEquals(0, RawParseUtils.parseHexInt4((byte) '0')); + assertEquals(1, RawParseUtils.parseHexInt4((byte) '1')); + assertEquals(2, RawParseUtils.parseHexInt4((byte) '2')); + assertEquals(3, RawParseUtils.parseHexInt4((byte) '3')); + assertEquals(4, RawParseUtils.parseHexInt4((byte) '4')); + assertEquals(5, RawParseUtils.parseHexInt4((byte) '5')); + assertEquals(6, RawParseUtils.parseHexInt4((byte) '6')); + assertEquals(7, RawParseUtils.parseHexInt4((byte) '7')); + assertEquals(8, RawParseUtils.parseHexInt4((byte) '8')); + assertEquals(9, RawParseUtils.parseHexInt4((byte) '9')); + assertEquals(10, RawParseUtils.parseHexInt4((byte) 'a')); + assertEquals(11, RawParseUtils.parseHexInt4((byte) 'b')); + assertEquals(12, RawParseUtils.parseHexInt4((byte) 'c')); + assertEquals(13, RawParseUtils.parseHexInt4((byte) 'd')); + assertEquals(14, RawParseUtils.parseHexInt4((byte) 'e')); + assertEquals(15, RawParseUtils.parseHexInt4((byte) 'f')); + + assertEquals(10, RawParseUtils.parseHexInt4((byte) 'A')); + assertEquals(11, RawParseUtils.parseHexInt4((byte) 'B')); + assertEquals(12, RawParseUtils.parseHexInt4((byte) 'C')); + assertEquals(13, RawParseUtils.parseHexInt4((byte) 'D')); + assertEquals(14, RawParseUtils.parseHexInt4((byte) 'E')); + assertEquals(15, RawParseUtils.parseHexInt4((byte) 'F')); + + assertNotHex('q'); + assertNotHex(' '); + assertNotHex('.'); + } + + private static void assertNotHex(final char c) { + try { + RawParseUtils.parseHexInt4((byte) c); + fail("Incorrectly acccepted " + c); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + } + + public void testInt16() { + assertEquals(0x0000, parse16("0000")); + assertEquals(0x0001, parse16("0001")); + assertEquals(0x1234, parse16("1234")); + assertEquals(0xdead, parse16("dead")); + assertEquals(0xBEEF, parse16("BEEF")); + assertEquals(0x4321, parse16("4321")); + assertEquals(0xffff, parse16("ffff")); + + try { + parse16("noth"); + fail("Incorrectly acccepted \"noth\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + + try { + parse16("01"); + fail("Incorrectly acccepted \"01\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + + try { + parse16("000."); + fail("Incorrectly acccepted \"000.\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + } + + private static int parse16(final String str) { + return RawParseUtils.parseHexInt16(Constants.encodeASCII(str), 0); + } + + public void testInt32() { + assertEquals(0x00000000, parse32("00000000")); + assertEquals(0x00000001, parse32("00000001")); + assertEquals(0xc0ffEE42, parse32("c0ffEE42")); + assertEquals(0xffffffff, parse32("ffffffff")); + assertEquals(-1, parse32("ffffffff")); + + try { + parse32("noth"); + fail("Incorrectly acccepted \"noth\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + + try { + parse32("notahexs"); + fail("Incorrectly acccepted \"notahexs\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + + try { + parse32("01"); + fail("Incorrectly acccepted \"01\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + + try { + parse32("0000000."); + fail("Incorrectly acccepted \"0000000.\""); + } catch (ArrayIndexOutOfBoundsException e) { + // pass + } + } + + private static int parse32(final String str) { + return RawParseUtils.parseHexInt32(Constants.encodeASCII(str), 0); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_LineMapTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_LineMapTest.java new file mode 100644 index 0000000000..6dcd56ee0d --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_LineMapTest.java @@ -0,0 +1,98 @@ +/* + * Copyright (C) 2008-2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import java.io.UnsupportedEncodingException; + +import junit.framework.TestCase; + +public class RawParseUtils_LineMapTest extends TestCase { + public void testEmpty() { + final IntList map = RawParseUtils.lineMap(new byte[] {}, 0, 0); + assertNotNull(map); + assertEquals(2, map.size()); + assertEquals(Integer.MIN_VALUE, map.get(0)); + assertEquals(0, map.get(1)); + } + + public void testOneBlankLine() { + final IntList map = RawParseUtils.lineMap(new byte[] { '\n' }, 0, 1); + assertEquals(3, map.size()); + assertEquals(Integer.MIN_VALUE, map.get(0)); + assertEquals(0, map.get(1)); + assertEquals(1, map.get(2)); + } + + public void testTwoLineFooBar() throws UnsupportedEncodingException { + final byte[] buf = "foo\nbar\n".getBytes("ISO-8859-1"); + final IntList map = RawParseUtils.lineMap(buf, 0, buf.length); + assertEquals(4, map.size()); + assertEquals(Integer.MIN_VALUE, map.get(0)); + assertEquals(0, map.get(1)); + assertEquals(4, map.get(2)); + assertEquals(buf.length, map.get(3)); + } + + public void testTwoLineNoLF() throws UnsupportedEncodingException { + final byte[] buf = "foo\nbar".getBytes("ISO-8859-1"); + final IntList map = RawParseUtils.lineMap(buf, 0, buf.length); + assertEquals(4, map.size()); + assertEquals(Integer.MIN_VALUE, map.get(0)); + assertEquals(0, map.get(1)); + assertEquals(4, map.get(2)); + assertEquals(buf.length, map.get(3)); + } + + public void testFourLineBlanks() throws UnsupportedEncodingException { + final byte[] buf = "foo\n\n\nbar\n".getBytes("ISO-8859-1"); + final IntList map = RawParseUtils.lineMap(buf, 0, buf.length); + assertEquals(6, map.size()); + assertEquals(Integer.MIN_VALUE, map.get(0)); + assertEquals(0, map.get(1)); + assertEquals(4, map.get(2)); + assertEquals(5, map.get(3)); + assertEquals(6, map.get(4)); + assertEquals(buf.length, map.get(5)); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_MatchTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_MatchTest.java new file mode 100644 index 0000000000..29459326da --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/RawParseUtils_MatchTest.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import junit.framework.TestCase; + +import org.eclipse.jgit.lib.Constants; + +public class RawParseUtils_MatchTest extends TestCase { + public void testMatch_Equal() { + final byte[] src = Constants.encodeASCII(" differ\n"); + final byte[] dst = Constants.encodeASCII("foo differ\n"); + assertTrue(RawParseUtils.match(dst, 3, src) == 3 + src.length); + } + + public void testMatch_NotEqual() { + final byte[] src = Constants.encodeASCII(" differ\n"); + final byte[] dst = Constants.encodeASCII("a differ\n"); + assertTrue(RawParseUtils.match(dst, 2, src) < 0); + } + + public void testMatch_Prefix() { + final byte[] src = Constants.encodeASCII("author "); + final byte[] dst = Constants.encodeASCII("author A. U. Thor"); + assertTrue(RawParseUtils.match(dst, 0, src) == src.length); + assertTrue(RawParseUtils.match(dst, 1, src) < 0); + } + + public void testMatch_TooSmall() { + final byte[] src = Constants.encodeASCII("author "); + final byte[] dst = Constants.encodeASCII("author autho"); + assertTrue(RawParseUtils.match(dst, src.length + 1, src) < 0); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java new file mode 100644 index 0000000000..912380dcd1 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/StringUtilsTest.java @@ -0,0 +1,84 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import junit.framework.TestCase; + +public class StringUtilsTest extends TestCase { + public void testToLowerCaseChar() { + assertEquals('a', StringUtils.toLowerCase('A')); + assertEquals('z', StringUtils.toLowerCase('Z')); + + assertEquals('a', StringUtils.toLowerCase('a')); + assertEquals('z', StringUtils.toLowerCase('z')); + + assertEquals((char) 0, StringUtils.toLowerCase((char) 0)); + assertEquals((char) 0xffff, StringUtils.toLowerCase((char) 0xffff)); + } + + public void testToLowerCaseString() { + assertEquals("\n abcdefghijklmnopqrstuvwxyz\n", StringUtils + .toLowerCase("\n ABCDEFGHIJKLMNOPQRSTUVWXYZ\n")); + } + + public void testEqualsIgnoreCase1() { + final String a = "FOO"; + assertTrue(StringUtils.equalsIgnoreCase(a, a)); + } + + public void testEqualsIgnoreCase2() { + assertFalse(StringUtils.equalsIgnoreCase("a", "")); + } + + public void testEqualsIgnoreCase3() { + assertFalse(StringUtils.equalsIgnoreCase("a", "b")); + assertFalse(StringUtils.equalsIgnoreCase("ac", "ab")); + } + + public void testEqualsIgnoreCase4() { + assertTrue(StringUtils.equalsIgnoreCase("a", "a")); + assertTrue(StringUtils.equalsIgnoreCase("A", "a")); + assertTrue(StringUtils.equalsIgnoreCase("a", "A")); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java new file mode 100644 index 0000000000..eb24172249 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TemporaryBufferTest.java @@ -0,0 +1,380 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.Arrays; + +import junit.framework.TestCase; + +public class TemporaryBufferTest extends TestCase { + public void testEmpty() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + try { + b.close(); + assertEquals(0, b.length()); + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(0, r.length); + } finally { + b.destroy(); + } + } + + public void testOneByte() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte test = (byte) new TestRng(getName()).nextInt(); + try { + b.write(test); + b.close(); + assertEquals(1, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(1, r.length); + assertEquals(test, r[0]); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(1, r.length); + assertEquals(test, r[0]); + } + } finally { + b.destroy(); + } + } + + public void testOneBlock_BulkWrite() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.Block.SZ); + try { + b.write(test, 0, 2); + b.write(test, 2, 4); + b.write(test, 6, test.length - 6 - 2); + b.write(test, test.length - 2, 2); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testOneBlockAndHalf_BulkWrite() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); + try { + b.write(test, 0, 2); + b.write(test, 2, 4); + b.write(test, 6, test.length - 6 - 2); + b.write(test, test.length - 2, 2); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testOneBlockAndHalf_SingleWrite() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); + try { + for (int i = 0; i < test.length; i++) + b.write(test[i]); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testOneBlockAndHalf_Copy() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.Block.SZ * 3 / 2); + try { + final ByteArrayInputStream in = new ByteArrayInputStream(test); + b.write(in.read()); + b.copy(in); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testLarge_SingleWrite() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3); + try { + b.write(test); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testInCoreLimit_SwitchOnAppendByte() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT + 1); + try { + b.write(test, 0, test.length - 1); + b.write(test[test.length - 1]); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testInCoreLimit_SwitchBeforeAppendByte() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 3); + try { + b.write(test, 0, test.length - 1); + b.write(test[test.length - 1]); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testInCoreLimit_SwitchOnCopy() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final byte[] test = new TestRng(getName()) + .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2); + try { + final ByteArrayInputStream in = new ByteArrayInputStream(test, + TemporaryBuffer.DEFAULT_IN_CORE_LIMIT, test.length + - TemporaryBuffer.DEFAULT_IN_CORE_LIMIT); + b.write(test, 0, TemporaryBuffer.DEFAULT_IN_CORE_LIMIT); + b.copy(in); + b.close(); + assertEquals(test.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(test.length, r.length); + assertTrue(Arrays.equals(test, r)); + } + } finally { + b.destroy(); + } + } + + public void testDestroyWhileOpen() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + try { + b.write(new TestRng(getName()) + .nextBytes(TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2)); + } finally { + b.destroy(); + } + } + + public void testRandomWrites() throws IOException { + final TemporaryBuffer b = new TemporaryBuffer(); + final TestRng rng = new TestRng(getName()); + final int max = TemporaryBuffer.DEFAULT_IN_CORE_LIMIT * 2; + final byte[] expect = new byte[max]; + try { + int written = 0; + boolean onebyte = true; + while (written < max) { + if (onebyte) { + final byte v = (byte) rng.nextInt(); + b.write(v); + expect[written++] = v; + } else { + final int len = Math + .min(rng.nextInt() & 127, max - written); + final byte[] tmp = rng.nextBytes(len); + b.write(tmp, 0, len); + System.arraycopy(tmp, 0, expect, written, len); + written += len; + } + onebyte = !onebyte; + } + assertEquals(expect.length, written); + b.close(); + + assertEquals(expect.length, b.length()); + { + final byte[] r = b.toByteArray(); + assertNotNull(r); + assertEquals(expect.length, r.length); + assertTrue(Arrays.equals(expect, r)); + } + { + final ByteArrayOutputStream o = new ByteArrayOutputStream(); + b.writeTo(o, null); + o.close(); + final byte[] r = o.toByteArray(); + assertEquals(expect.length, r.length); + assertTrue(Arrays.equals(expect, r)); + } + } finally { + b.destroy(); + } + } + +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TestRng.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TestRng.java new file mode 100644 index 0000000000..4110b55baa --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/TestRng.java @@ -0,0 +1,67 @@ +/* + * Copyright (C) 2008, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util; + +/** Toy RNG to ensure we get predictable numbers during unit tests. */ +public class TestRng { + private int next; + + public TestRng(final String seed) { + next = 0; + for (int i = 0; i < seed.length(); i++) + next = next * 11 + seed.charAt(i); + } + + public byte[] nextBytes(final int cnt) { + final byte[] r = new byte[cnt]; + for (int i = 0; i < cnt; i++) + r[i] = (byte) nextInt(); + return r; + } + + public int nextInt() { + next = next * 1103515245 + 12345; + return next; + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutInputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutInputStreamTest.java new file mode 100644 index 0000000000..cd16288b64 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutInputStreamTest.java @@ -0,0 +1,189 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util.io; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jgit.util.NB; +import org.eclipse.jgit.util.io.InterruptTimer; +import org.eclipse.jgit.util.io.TimeoutInputStream; + +import junit.framework.TestCase; + +public class TimeoutInputStreamTest extends TestCase { + private static final int timeout = 250; + + private PipedOutputStream out; + + private PipedInputStream in; + + private InterruptTimer timer; + + private TimeoutInputStream is; + + private long start; + + protected void setUp() throws Exception { + super.setUp(); + out = new PipedOutputStream(); + in = new PipedInputStream(out); + timer = new InterruptTimer(); + is = new TimeoutInputStream(in, timer); + is.setTimeout(timeout); + } + + protected void tearDown() throws Exception { + timer.terminate(); + for (Thread t : active()) + assertFalse(t instanceof InterruptTimer.AlarmThread); + super.tearDown(); + } + + public void testTimeout_readByte_Success1() throws IOException { + out.write('a'); + assertEquals('a', is.read()); + } + + public void testTimeout_readByte_Success2() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + out.write(exp); + assertEquals(exp[0], is.read()); + assertEquals(exp[1], is.read()); + assertEquals(exp[2], is.read()); + out.close(); + assertEquals(-1, is.read()); + } + + public void testTimeout_readByte_Timeout() throws IOException { + beginRead(); + try { + is.read(); + fail("incorrectly read a byte"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + } + + public void testTimeout_readBuffer_Success1() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + final byte[] act = new byte[exp.length]; + out.write(exp); + NB.readFully(is, act, 0, act.length); + assertTrue(Arrays.equals(exp, act)); + } + + public void testTimeout_readBuffer_Success2() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + final byte[] act = new byte[exp.length]; + out.write(exp); + NB.readFully(is, act, 0, 1); + NB.readFully(is, act, 1, 1); + NB.readFully(is, act, 2, 1); + assertTrue(Arrays.equals(exp, act)); + } + + public void testTimeout_readBuffer_Timeout() throws IOException { + beginRead(); + try { + NB.readFully(is, new byte[512], 0, 512); + fail("incorrectly read bytes"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + } + + public void testTimeout_skip_Success() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + out.write(exp); + assertEquals(2, is.skip(2)); + assertEquals('c', is.read()); + } + + public void testTimeout_skip_Timeout() throws IOException { + beginRead(); + try { + is.skip(1024); + fail("incorrectly skipped bytes"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + } + + private void beginRead() { + start = now(); + } + + private void assertTimeout() { + // Our timeout was supposed to be ~250 ms. Since this is a timing + // test we can't assume we spent *exactly* the timeout period, as + // there may be other activity going on in the system. Instead we + // look for the delta between the start and end times to be within + // 50 ms of the expected timeout. + // + final long wait = now() - start; + assertTrue(Math.abs(wait - timeout) < 50); + } + + private static List<Thread> active() { + Thread[] all = new Thread[16]; + int n = Thread.currentThread().getThreadGroup().enumerate(all); + while (n == all.length) { + all = new Thread[all.length * 2]; + n = Thread.currentThread().getThreadGroup().enumerate(all); + } + return Arrays.asList(all).subList(0, n); + } + + private static long now() { + return System.currentTimeMillis(); + } +} diff --git a/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutOutputStreamTest.java b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutOutputStreamTest.java new file mode 100644 index 0000000000..bba8640ff3 --- /dev/null +++ b/org.eclipse.jgit.test/tst/org/eclipse/jgit/util/io/TimeoutOutputStreamTest.java @@ -0,0 +1,285 @@ +/* + * Copyright (C) 2009, Google Inc. + * and other copyright owners as documented in the project's IP log. + * + * This program and the accompanying materials are made available + * under the terms of the Eclipse Distribution License v1.0 which + * accompanies this distribution, is reproduced below, and is + * available at http://www.eclipse.org/org/documents/edl-v10.php + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or + * without modification, are permitted provided that the following + * conditions are met: + * + * - Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * - Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following + * disclaimer in the documentation and/or other materials provided + * with the distribution. + * + * - Neither the name of the Eclipse Foundation, Inc. nor the + * names of its contributors may be used to endorse or promote + * products derived from this software without specific prior + * written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR + * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +package org.eclipse.jgit.util.io; + +import java.io.IOException; +import java.io.InterruptedIOException; +import java.io.OutputStream; +import java.io.PipedInputStream; +import java.io.PipedOutputStream; +import java.util.Arrays; +import java.util.List; + +import org.eclipse.jgit.util.NB; +import org.eclipse.jgit.util.io.InterruptTimer; +import org.eclipse.jgit.util.io.TimeoutOutputStream; + +import junit.framework.TestCase; + +public class TimeoutOutputStreamTest extends TestCase { + private static final int timeout = 250; + + private PipedOutputStream out; + + private FullPipeInputStream in; + + private InterruptTimer timer; + + private TimeoutOutputStream os; + + private long start; + + protected void setUp() throws Exception { + super.setUp(); + out = new PipedOutputStream(); + in = new FullPipeInputStream(out); + timer = new InterruptTimer(); + os = new TimeoutOutputStream(out, timer); + os.setTimeout(timeout); + } + + protected void tearDown() throws Exception { + timer.terminate(); + for (Thread t : active()) + assertFalse(t instanceof InterruptTimer.AlarmThread); + super.tearDown(); + } + + public void testTimeout_writeByte_Success1() throws IOException { + in.free(1); + os.write('a'); + in.want(1); + assertEquals('a', in.read()); + } + + public void testTimeout_writeByte_Success2() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + final byte[] act = new byte[exp.length]; + in.free(exp.length); + os.write(exp[0]); + os.write(exp[1]); + os.write(exp[2]); + in.want(exp.length); + in.read(act); + assertTrue(Arrays.equals(exp, act)); + } + + public void testTimeout_writeByte_Timeout() throws IOException { + beginWrite(); + try { + os.write('\n'); + fail("incorrectly write a byte"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + } + + public void testTimeout_writeBuffer_Success1() throws IOException { + final byte[] exp = new byte[] { 'a', 'b', 'c' }; + final byte[] act = new byte[exp.length]; + in.free(exp.length); + os.write(exp); + in.want(exp.length); + in.read(act); + assertTrue(Arrays.equals(exp, act)); + } + + public void testTimeout_writeBuffer_Timeout() throws IOException { + beginWrite(); + try { + os.write(new byte[512]); + fail("incorrectly wrote bytes"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + } + + public void testTimeout_flush_Success() throws IOException { + final boolean[] called = new boolean[1]; + os = new TimeoutOutputStream(new OutputStream() { + @Override + public void write(int b) throws IOException { + fail("should not have written"); + } + + @Override + public void flush() throws IOException { + called[0] = true; + } + }, timer); + os.setTimeout(timeout); + os.flush(); + assertTrue(called[0]); + } + + public void testTimeout_flush_Timeout() throws IOException { + final boolean[] called = new boolean[1]; + os = new TimeoutOutputStream(new OutputStream() { + @Override + public void write(int b) throws IOException { + fail("should not have written"); + } + + @Override + public void flush() throws IOException { + called[0] = true; + for (;;) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + } + }, timer); + os.setTimeout(timeout); + + beginWrite(); + try { + os.flush(); + fail("incorrectly flushed"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + assertTrue(called[0]); + } + + public void testTimeout_close_Success() throws IOException { + final boolean[] called = new boolean[1]; + os = new TimeoutOutputStream(new OutputStream() { + @Override + public void write(int b) throws IOException { + fail("should not have written"); + } + + @Override + public void close() throws IOException { + called[0] = true; + } + }, timer); + os.setTimeout(timeout); + os.close(); + assertTrue(called[0]); + } + + public void testTimeout_close_Timeout() throws IOException { + final boolean[] called = new boolean[1]; + os = new TimeoutOutputStream(new OutputStream() { + @Override + public void write(int b) throws IOException { + fail("should not have written"); + } + + @Override + public void close() throws IOException { + called[0] = true; + for (;;) { + try { + Thread.sleep(1000); + } catch (InterruptedException e) { + throw new InterruptedIOException(); + } + } + } + }, timer); + os.setTimeout(timeout); + + beginWrite(); + try { + os.close(); + fail("incorrectly closed"); + } catch (InterruptedIOException e) { + // expected + } + assertTimeout(); + assertTrue(called[0]); + } + + private void beginWrite() { + start = now(); + } + + private void assertTimeout() { + // Our timeout was supposed to be ~250 ms. Since this is a timing + // test we can't assume we spent *exactly* the timeout period, as + // there may be other activity going on in the system. Instead we + // look for the delta between the start and end times to be within + // 50 ms of the expected timeout. + // + final long wait = now() - start; + assertTrue(Math.abs(wait - timeout) < 50); + } + + private static List<Thread> active() { + Thread[] all = new Thread[16]; + int n = Thread.currentThread().getThreadGroup().enumerate(all); + while (n == all.length) { + all = new Thread[all.length * 2]; + n = Thread.currentThread().getThreadGroup().enumerate(all); + } + return Arrays.asList(all).subList(0, n); + } + + private static long now() { + return System.currentTimeMillis(); + } + + private final class FullPipeInputStream extends PipedInputStream { + FullPipeInputStream(PipedOutputStream src) throws IOException { + super(src); + src.write(new byte[PIPE_SIZE]); + } + + void want(int cnt) throws IOException { + NB.skipFully(this, PIPE_SIZE - cnt); + } + + void free(int cnt) throws IOException { + NB.skipFully(this, cnt); + } + } +} |