summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.pgm
diff options
context:
space:
mode:
Diffstat (limited to 'org.eclipse.jgit.pgm')
-rw-r--r--org.eclipse.jgit.pgm/.classpath8
-rw-r--r--org.eclipse.jgit.pgm/.gitignore1
-rw-r--r--org.eclipse.jgit.pgm/.project17
-rw-r--r--org.eclipse.jgit.pgm/.settings/org.eclipse.core.resources.prefs3
-rw-r--r--org.eclipse.jgit.pgm/.settings/org.eclipse.core.runtime.prefs3
-rw-r--r--org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs321
-rw-r--r--org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.ui.prefs9
-rw-r--r--org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin30
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java137
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java216
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java187
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Command.java78
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandCatalog.java194
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandRef.java164
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java125
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java65
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java119
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java111
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java132
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java76
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java71
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java129
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java86
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java85
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java184
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java80
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java256
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java74
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java81
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java74
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java208
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java98
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java68
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java100
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java241
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java80
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java58
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/build/JarLinkUtil.java212
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java74
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java60
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java313
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java76
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java121
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java80
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java61
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java143
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/CmdLineParser.java177
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java101
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java108
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java84
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java146
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java114
-rw-r--r--org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java100
53 files changed, 5939 insertions, 0 deletions
diff --git a/org.eclipse.jgit.pgm/.classpath b/org.eclipse.jgit.pgm/.classpath
new file mode 100644
index 0000000000..a91b30e8bb
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.classpath
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+ <classpathentry kind="src" path="src"/>
+ <classpathentry exported="true" kind="lib" path="lib/args4j-2.0.9.jar" sourcepath="lib/args4j-2.0.9.zip"/>
+ <classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
+ <classpathentry combineaccessrules="false" exported="true" kind="src" path="/org.eclipse.jgit"/>
+ <classpathentry kind="output" path="bin"/>
+</classpath>
diff --git a/org.eclipse.jgit.pgm/.gitignore b/org.eclipse.jgit.pgm/.gitignore
new file mode 100644
index 0000000000..5e56e040ec
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.gitignore
@@ -0,0 +1 @@
+/bin
diff --git a/org.eclipse.jgit.pgm/.project b/org.eclipse.jgit.pgm/.project
new file mode 100644
index 0000000000..bbaafc2612
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.project
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+ <name>org.eclipse.jgit.pgm</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.pgm/.settings/org.eclipse.core.resources.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000000..759548b398
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Mon Aug 11 16:46:23 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/org.eclipse.jgit.pgm/.settings/org.eclipse.core.runtime.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000000..006e07ede5
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Mon Mar 24 18:55:50 EDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000000..f0c80d3632
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,321 @@
+#Sun Mar 15 19:46:39 CET 2009
+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=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocCommentsVisibility=protected
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagDescription=return_tag
+org.eclipse.jdt.core.compiler.problem.missingJavadocTags=error
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.missingJavadocTagsVisibility=protected
+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=warning
+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.pgm/.settings/org.eclipse.jdt.ui.prefs b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000000..709a44074c
--- /dev/null
+++ b/org.eclipse.jgit.pgm/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,9 @@
+#Wed May 09 00:20:24 CEST 2007
+eclipse.preferences.version=1
+formatter_profile=_JGit
+formatter_settings_version=10
+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.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin b/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
new file mode 100644
index 0000000000..9c8933f5d1
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/META-INF/services/org.eclipse.jgit.pgm.TextBuiltin
@@ -0,0 +1,30 @@
+org.eclipse.jgit.pgm.Branch
+org.eclipse.jgit.pgm.Clone
+org.eclipse.jgit.pgm.Daemon
+org.eclipse.jgit.pgm.DiffTree
+org.eclipse.jgit.pgm.Fetch
+org.eclipse.jgit.pgm.Glog
+org.eclipse.jgit.pgm.IndexPack
+org.eclipse.jgit.pgm.Init
+org.eclipse.jgit.pgm.Log
+org.eclipse.jgit.pgm.LsRemote
+org.eclipse.jgit.pgm.LsTree
+org.eclipse.jgit.pgm.MergeBase
+org.eclipse.jgit.pgm.Push
+org.eclipse.jgit.pgm.ReceivePack
+org.eclipse.jgit.pgm.RevList
+org.eclipse.jgit.pgm.RevParse
+org.eclipse.jgit.pgm.Rm
+org.eclipse.jgit.pgm.ShowRev
+org.eclipse.jgit.pgm.ShowRef
+org.eclipse.jgit.pgm.Tag
+org.eclipse.jgit.pgm.UploadPack
+org.eclipse.jgit.pgm.Version
+
+org.eclipse.jgit.pgm.debug.MakeCacheTree
+org.eclipse.jgit.pgm.debug.ReadDirCache
+org.eclipse.jgit.pgm.debug.RebuildCommitGraph
+org.eclipse.jgit.pgm.debug.ShowCacheTree
+org.eclipse.jgit.pgm.debug.ShowCommands
+org.eclipse.jgit.pgm.debug.ShowDirCache
+org.eclipse.jgit.pgm.debug.WriteDirCache
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java
new file mode 100644
index 0000000000..f5e3c504c2
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/AbstractFetchCommand.java
@@ -0,0 +1,137 @@
+/*
+ * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.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.pgm;
+
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.TrackingRefUpdate;
+import org.eclipse.jgit.transport.Transport;
+
+abstract class AbstractFetchCommand extends TextBuiltin {
+ @Option(name = "--verbose", aliases = { "-v" }, usage = "be more verbose")
+ private boolean verbose;
+
+ protected void showFetchResult(final Transport tn, final FetchResult r) {
+ boolean shownURI = false;
+ for (final TrackingRefUpdate u : r.getTrackingRefUpdates()) {
+ if (!verbose && u.getResult() == RefUpdate.Result.NO_CHANGE)
+ continue;
+
+ final char type = shortTypeOf(u.getResult());
+ final String longType = longTypeOf(u);
+ final String src = abbreviateRef(u.getRemoteName(), false);
+ final String dst = abbreviateRef(u.getLocalName(), true);
+
+ if (!shownURI) {
+ out.print("From ");
+ out.print(tn.getURI());
+ out.println();
+ shownURI = true;
+ }
+
+ out.format(" %c %-17s %-10s -> %s", type, longType, src, dst);
+ out.println();
+ }
+ }
+
+ private String longTypeOf(final TrackingRefUpdate u) {
+ final RefUpdate.Result r = u.getResult();
+ if (r == RefUpdate.Result.LOCK_FAILURE)
+ return "[lock fail]";
+ if (r == RefUpdate.Result.IO_FAILURE)
+ return "[i/o error]";
+ if (r == RefUpdate.Result.REJECTED)
+ return "[rejected]";
+ if (ObjectId.zeroId().equals(u.getNewObjectId()))
+ return "[deleted]";
+
+ if (r == RefUpdate.Result.NEW) {
+ if (u.getRemoteName().startsWith(Constants.R_HEADS))
+ return "[new branch]";
+ else if (u.getLocalName().startsWith(Constants.R_TAGS))
+ return "[new tag]";
+ return "[new]";
+ }
+
+ if (r == RefUpdate.Result.FORCED) {
+ final String aOld = u.getOldObjectId().abbreviate(db).name();
+ final String aNew = u.getNewObjectId().abbreviate(db).name();
+ return aOld + "..." + aNew;
+ }
+
+ if (r == RefUpdate.Result.FAST_FORWARD) {
+ final String aOld = u.getOldObjectId().abbreviate(db).name();
+ final String aNew = u.getNewObjectId().abbreviate(db).name();
+ return aOld + ".." + aNew;
+ }
+
+ if (r == RefUpdate.Result.NO_CHANGE)
+ return "[up to date]";
+ return "[" + r.name() + "]";
+ }
+
+ private static char shortTypeOf(final RefUpdate.Result r) {
+ if (r == RefUpdate.Result.LOCK_FAILURE)
+ return '!';
+ if (r == RefUpdate.Result.IO_FAILURE)
+ return '!';
+ if (r == RefUpdate.Result.NEW)
+ return '*';
+ if (r == RefUpdate.Result.FORCED)
+ return '+';
+ if (r == RefUpdate.Result.FAST_FORWARD)
+ return ' ';
+ if (r == RefUpdate.Result.REJECTED)
+ return '!';
+ if (r == RefUpdate.Result.NO_CHANGE)
+ return '=';
+ return ' ';
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java
new file mode 100644
index 0000000000..60dbe27acb
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Branch.java
@@ -0,0 +1,216 @@
+/*
+ * Copyright (C) 2007-2008, Charles O'Farrell <charleso@charleso.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.pgm;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.ExampleMode;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefComparator;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.pgm.opt.CmdLineParser;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+@Command(common = true, usage = "List, create, or delete branches")
+class Branch extends TextBuiltin {
+
+ @Option(name = "--remote", aliases = { "-r" }, usage = "act on remote-tracking branches")
+ private boolean remote = false;
+
+ @Option(name = "--all", aliases = { "-a" }, usage = "list both remote-tracking and local branches")
+ private boolean all = false;
+
+ @Option(name = "--delete", aliases = { "-d" }, usage = "delete fully merged branch")
+ private boolean delete = false;
+
+ @Option(name = "--delete-force", aliases = { "-D" }, usage = "delete branch (even if not merged)")
+ private boolean deleteForce = false;
+
+ @Option(name = "--create-force", aliases = { "-f" }, usage = "force create branch even exists")
+ private boolean createForce = false;
+
+ @Option(name = "--verbose", aliases = { "-v" }, usage = "be verbose")
+ private boolean verbose = false;
+
+ @Argument
+ private List<String> branches = new ArrayList<String>();
+
+ private final Map<String, Ref> printRefs = new LinkedHashMap<String, Ref>();
+
+ /** Only set for verbose branch listing at-the-moment */
+ private RevWalk rw;
+
+ private int maxNameLength;
+
+ @Override
+ protected void run() throws Exception {
+ if (delete || deleteForce)
+ delete(deleteForce);
+ else {
+ if (branches.size() > 2)
+ throw die("Too many refs given\n" + new CmdLineParser(this).printExample(ExampleMode.ALL));
+
+ if (branches.size() > 0) {
+ String newHead = branches.get(0);
+ String startBranch;
+ if (branches.size() == 2)
+ startBranch = branches.get(1);
+ else
+ startBranch = Constants.HEAD;
+ Ref startRef = db.getRef(startBranch);
+ ObjectId startAt = db.resolve(startBranch + "^0");
+ if (startRef != null)
+ startBranch = startRef.getName();
+ else
+ startBranch = startAt.name();
+ startBranch = db.shortenRefName(startBranch);
+ String newRefName = newHead;
+ if (!newRefName.startsWith(Constants.R_HEADS))
+ newRefName = Constants.R_HEADS + newRefName;
+ if (!Repository.isValidRefName(newRefName))
+ throw die(String.format("%s is not a valid ref name", newRefName));
+ if (!createForce && db.resolve(newRefName) != null)
+ throw die(String.format("branch %s already exists", newHead));
+ RefUpdate updateRef = db.updateRef(newRefName);
+ updateRef.setNewObjectId(startAt);
+ updateRef.setForceUpdate(createForce);
+ updateRef.setRefLogMessage("branch: Created from " + startBranch, false);
+ Result update = updateRef.update();
+ if (update == Result.REJECTED)
+ throw die(String.format("Could not create branch %s: %s", newHead, update.toString()));
+ } else {
+ if (verbose)
+ rw = new RevWalk(db);
+ list();
+ }
+ }
+ }
+
+ private void list() throws Exception {
+ Map<String, Ref> refs = db.getAllRefs();
+ Ref head = refs.get(Constants.HEAD);
+ // This can happen if HEAD is stillborn
+ if (head != null) {
+ String current = head.getName();
+ if (current.equals(Constants.HEAD))
+ addRef("(no branch)", head);
+ addRefs(refs, Constants.R_HEADS, !remote);
+ addRefs(refs, Constants.R_REMOTES, remote);
+ for (final Entry<String, Ref> e : printRefs.entrySet()) {
+ final Ref ref = e.getValue();
+ printHead(e.getKey(), current.equals(ref.getName()), ref);
+ }
+ }
+ }
+
+ private void addRefs(final Map<String, Ref> allRefs, final String prefix,
+ final boolean add) {
+ if (all || add) {
+ for (final Ref ref : RefComparator.sort(allRefs.values())) {
+ final String name = ref.getName();
+ if (name.startsWith(prefix))
+ addRef(name.substring(name.indexOf('/', 5) + 1), ref);
+ }
+ }
+ }
+
+ private void addRef(final String name, final Ref ref) {
+ printRefs.put(name, ref);
+ maxNameLength = Math.max(maxNameLength, name.length());
+ }
+
+ private void printHead(final String ref, final boolean isCurrent,
+ final Ref refObj) throws Exception {
+ out.print(isCurrent ? '*' : ' ');
+ out.print(' ');
+ out.print(ref);
+ if (verbose) {
+ final int spaces = maxNameLength - ref.length() + 1;
+ out.print(String.format("%" + spaces + "s", ""));
+ final ObjectId objectId = refObj.getObjectId();
+ out.print(objectId.abbreviate(db).name());
+ out.print(' ');
+ out.print(rw.parseCommit(objectId).getShortMessage());
+ }
+ out.println();
+ }
+
+ private void delete(boolean force) throws IOException {
+ String current = db.getBranch();
+ ObjectId head = db.resolve(Constants.HEAD);
+ for (String branch : branches) {
+ if (current.equals(branch)) {
+ String err = "Cannot delete the branch '%s' which you are currently on.";
+ throw die(String.format(err, branch));
+ }
+ RefUpdate update = db.updateRef((remote ? Constants.R_REMOTES
+ : Constants.R_HEADS)
+ + branch);
+ update.setNewObjectId(head);
+ update.setForceUpdate(force || remote);
+ Result result = update.delete();
+ if (result == Result.REJECTED) {
+ String err = "The branch '%s' is not an ancestor of your current HEAD.\n"
+ + "If you are sure you want to delete it, run 'jgit branch -D %1$s'.";
+ throw die(String.format(err, branch));
+ } else if (result == Result.NEW)
+ throw die(String.format("branch '%s' not found.", branch));
+ if (remote)
+ out.println(String.format("Deleted remote branch %s", branch));
+ else if (verbose)
+ out.println(String.format("Deleted branch %s", branch));
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
new file mode 100644
index 0000000000..605f9552f8
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Clone.java
@@ -0,0 +1,187 @@
+/*
+ * 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.pgm;
+
+import java.io.File;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.errors.NotSupportedException;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.GitIndex;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefComparator;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.lib.WorkDirCheckout;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteConfig;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+
+@Command(common = true, usage = "Clone a repository into a new directory")
+class Clone extends AbstractFetchCommand {
+ @Option(name = "--origin", aliases = { "-o" }, metaVar = "name", usage = "use <name> instead of 'origin' to track upstream")
+ private String remoteName = "origin";
+
+ @Argument(index = 0, required = true, metaVar = "uri-ish")
+ private String sourceUri;
+
+ @Argument(index = 1, metaVar = "directory")
+ private String localName;
+
+ @Override
+ protected final boolean requiresRepository() {
+ return false;
+ }
+
+ @Override
+ protected void run() throws Exception {
+ if (localName != null && gitdir != null)
+ throw die("conflicting usage of --git-dir and arguments");
+
+ final URIish uri = new URIish(sourceUri);
+ if (localName == null) {
+ String p = uri.getPath();
+ while (p.endsWith("/"))
+ p = p.substring(0, p.length() - 1);
+ final int s = p.lastIndexOf('/');
+ if (s < 0)
+ throw die("cannot guess local name from " + sourceUri);
+ localName = p.substring(s + 1);
+ if (localName.endsWith(".git"))
+ localName = localName.substring(0, localName.length() - 4);
+ }
+ if (gitdir == null)
+ gitdir = new File(localName, ".git");
+
+ db = new Repository(gitdir);
+ db.create();
+ db.getConfig().setBoolean("core", null, "bare", false);
+ db.getConfig().save();
+
+ out.println("Initialized empty Git repository in "
+ + gitdir.getAbsolutePath());
+ out.flush();
+
+ saveRemote(uri);
+ final FetchResult r = runFetch();
+ final Ref branch = guessHEAD(r);
+ doCheckout(branch);
+ }
+
+ private void saveRemote(final URIish uri) throws URISyntaxException,
+ IOException {
+ final RemoteConfig rc = new RemoteConfig(db.getConfig(), remoteName);
+ rc.addURI(uri);
+ rc.addFetchRefSpec(new RefSpec().setForceUpdate(true)
+ .setSourceDestination(Constants.R_HEADS + "*",
+ Constants.R_REMOTES + remoteName + "/*"));
+ rc.update(db.getConfig());
+ db.getConfig().save();
+ }
+
+ private FetchResult runFetch() throws NotSupportedException,
+ URISyntaxException, TransportException {
+ final Transport tn = Transport.open(db, remoteName);
+ final FetchResult r;
+ try {
+ r = tn.fetch(new TextProgressMonitor(), null);
+ } finally {
+ tn.close();
+ }
+ showFetchResult(tn, r);
+ return r;
+ }
+
+ private Ref guessHEAD(final FetchResult result) {
+ final Ref idHEAD = result.getAdvertisedRef(Constants.HEAD);
+ final List<Ref> availableRefs = new ArrayList<Ref>();
+ Ref head = null;
+ for (final Ref r : result.getAdvertisedRefs()) {
+ final String n = r.getName();
+ if (!n.startsWith(Constants.R_HEADS))
+ continue;
+ availableRefs.add(r);
+ if (idHEAD == null || head != null)
+ continue;
+ if (r.getObjectId().equals(idHEAD.getObjectId()))
+ head = r;
+ }
+ Collections.sort(availableRefs, RefComparator.INSTANCE);
+ if (idHEAD != null && head == null)
+ head = idHEAD;
+ return head;
+ }
+
+ private void doCheckout(final Ref branch) throws IOException {
+ if (branch == null)
+ throw die("cannot checkout; no HEAD advertised by remote");
+ if (!Constants.HEAD.equals(branch.getName()))
+ db.writeSymref(Constants.HEAD, branch.getName());
+
+ final Commit commit = db.mapCommit(branch.getObjectId());
+ final RefUpdate u = db.updateRef(Constants.HEAD);
+ u.setNewObjectId(commit.getCommitId());
+ u.forceUpdate();
+
+ final GitIndex index = new GitIndex(db);
+ final Tree tree = commit.getTree();
+ final WorkDirCheckout co;
+
+ co = new WorkDirCheckout(db, db.getWorkDir(), index, tree);
+ co.checkout();
+ index.write();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Command.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Command.java
new file mode 100644
index 0000000000..0562416a85
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Command.java
@@ -0,0 +1,78 @@
+/*
+ * 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.pgm;
+
+import static java.lang.annotation.ElementType.TYPE;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to document a {@link TextBuiltin}.
+ * <p>
+ * This is an optional annotation for TextBuiltin subclasses and it carries
+ * documentation forward into the runtime system describing what the command is
+ * and why users may want to invoke it.
+ */
+@Retention(RUNTIME)
+@Target( { TYPE })
+public @interface Command {
+ /**
+ * @return name the command is invoked as from the command line. If the
+ * (default) empty string is supplied the name will be generated
+ * from the class name.
+ */
+ public String name() default "";
+
+ /**
+ * @return one line description of the command's feature set.
+ */
+ public String usage() default "";
+
+ /**
+ * @return true if this command is considered to be commonly used.
+ */
+ public boolean common() default false;
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandCatalog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandCatalog.java
new file mode 100644
index 0000000000..700e54118a
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandCatalog.java
@@ -0,0 +1,194 @@
+/*
+ * 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.pgm;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Vector;
+
+/**
+ * List of all commands known by jgit's command line tools.
+ * <p>
+ * Commands are implementations of {@link TextBuiltin}, with an optional
+ * {@link Command} class annotation to insert additional documentation or
+ * override the default command name (which is guessed from the class name).
+ * <p>
+ * Commands may be registered by adding them to a services file in the same JAR
+ * (or classes directory) as the command implementation. The service file name
+ * is <code>META-INF/services/org.eclipse.jgit.pgm.TextBuiltin</code> and it
+ * contains one concrete implementation class name per line.
+ * <p>
+ * Command registration is identical to Java 6's services, however the catalog
+ * uses a lightweight wrapper to delay creating a command instance as much as
+ * possible. This avoids initializing the AWT or SWT GUI toolkits even if the
+ * command's constructor might require them.
+ */
+public class CommandCatalog {
+ private static final CommandCatalog INSTANCE = new CommandCatalog();
+
+ /**
+ * Locate a single command by its user friendly name.
+ *
+ * @param name
+ * name of the command. Typically in dash-lower-case-form, which
+ * was derived from the DashLowerCaseForm class name.
+ * @return the command instance; null if no command exists by that name.
+ */
+ public static CommandRef get(final String name) {
+ return INSTANCE.commands.get(name);
+ }
+
+ /**
+ * @return all known commands, sorted by command name.
+ */
+ public static CommandRef[] all() {
+ return toSortedArray(INSTANCE.commands.values());
+ }
+
+ /**
+ * @return all common commands, sorted by command name.
+ */
+ public static CommandRef[] common() {
+ final ArrayList<CommandRef> common = new ArrayList<CommandRef>();
+ for (final CommandRef c : INSTANCE.commands.values())
+ if (c.isCommon())
+ common.add(c);
+ return toSortedArray(common);
+ }
+
+ private static CommandRef[] toSortedArray(final Collection<CommandRef> c) {
+ final CommandRef[] r = c.toArray(new CommandRef[c.size()]);
+ Arrays.sort(r, new Comparator<CommandRef>() {
+ public int compare(final CommandRef o1, final CommandRef o2) {
+ return o1.getName().compareTo(o2.getName());
+ }
+ });
+ return r;
+ }
+
+ private final ClassLoader ldr;
+
+ private final Map<String, CommandRef> commands;
+
+ private CommandCatalog() {
+ ldr = Thread.currentThread().getContextClassLoader();
+ commands = new HashMap<String, CommandRef>();
+
+ final Enumeration<URL> catalogs = catalogs();
+ while (catalogs.hasMoreElements())
+ scan(catalogs.nextElement());
+ }
+
+ private Enumeration<URL> catalogs() {
+ try {
+ final String pfx = "META-INF/services/";
+ return ldr.getResources(pfx + TextBuiltin.class.getName());
+ } catch (IOException err) {
+ return new Vector<URL>().elements();
+ }
+ }
+
+ private void scan(final URL cUrl) {
+ final BufferedReader cIn;
+ try {
+ final InputStream in = cUrl.openStream();
+ cIn = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ } catch (IOException err) {
+ // If we cannot read from the service list, go to the next.
+ //
+ return;
+ }
+
+ try {
+ String line;
+ while ((line = cIn.readLine()) != null) {
+ if (line.length() > 0 && !line.startsWith("#"))
+ load(line);
+ }
+ } catch (IOException err) {
+ // If we failed during a read, ignore the error.
+ //
+ } finally {
+ try {
+ cIn.close();
+ } catch (IOException e) {
+ // Ignore the close error; we are only reading.
+ }
+ }
+ }
+
+ private void load(final String cn) {
+ final Class<? extends TextBuiltin> clazz;
+ try {
+ clazz = Class.forName(cn, false, ldr).asSubclass(TextBuiltin.class);
+ } catch (ClassNotFoundException notBuiltin) {
+ // Doesn't exist, even though the service entry is present.
+ //
+ return;
+ } catch (ClassCastException notBuiltin) {
+ // Isn't really a builtin, even though its listed as such.
+ //
+ return;
+ }
+
+ final CommandRef cr;
+ final Command a = clazz.getAnnotation(Command.class);
+ if (a != null)
+ cr = new CommandRef(clazz, a);
+ else
+ cr = new CommandRef(clazz);
+
+ commands.put(cr.getName(), cr);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandRef.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandRef.java
new file mode 100644
index 0000000000..eb68ada9b7
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/CommandRef.java
@@ -0,0 +1,164 @@
+/*
+ * 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.pgm;
+
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+
+/**
+ * Description of a command (a {@link TextBuiltin} subclass.
+ * <p>
+ * These descriptions are lightweight compared to creating a command instance
+ * and are therefore suitable for catalogs of "known" commands without linking
+ * the command's implementation and creating a dummy instance of the command.
+ */
+public class CommandRef {
+ private final Class<? extends TextBuiltin> impl;
+
+ private final String name;
+
+ private String usage;
+
+ boolean common;
+
+ CommandRef(final Class<? extends TextBuiltin> clazz) {
+ this(clazz, guessName(clazz));
+ }
+
+ CommandRef(final Class<? extends TextBuiltin> clazz, final Command cmd) {
+ this(clazz, cmd.name().length() > 0 ? cmd.name() : guessName(clazz));
+ usage = cmd.usage();
+ common = cmd.common();
+ }
+
+ private CommandRef(final Class<? extends TextBuiltin> clazz, final String cn) {
+ impl = clazz;
+ name = cn;
+ usage = "";
+ }
+
+ private static String guessName(final Class<? extends TextBuiltin> clazz) {
+ final StringBuilder s = new StringBuilder();
+ if (clazz.getName().startsWith("org.eclipse.jgit.pgm.debug."))
+ s.append("debug-");
+
+ boolean lastWasDash = true;
+ for (final char c : clazz.getSimpleName().toCharArray()) {
+ if (Character.isUpperCase(c)) {
+ if (!lastWasDash)
+ s.append('-');
+ lastWasDash = !lastWasDash;
+ s.append(Character.toLowerCase(c));
+ } else {
+ s.append(c);
+ }
+ }
+ return s.toString();
+ }
+
+ /**
+ * @return name the command is invoked as from the command line.
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @return one line description of the command's feature set.
+ */
+ public String getUsage() {
+ return usage;
+ }
+
+ /**
+ * @return true if this command is considered to be commonly used.
+ */
+ public boolean isCommon() {
+ return common;
+ }
+
+ /**
+ * @return name of the Java class which implements this command.
+ */
+ public String getImplementationClassName() {
+ return impl.getName();
+ }
+
+ /**
+ * @return loader for {@link #getImplementationClassName()}.
+ */
+ public ClassLoader getImplementationClassLoader() {
+ return impl.getClassLoader();
+ }
+
+ /**
+ * @return a new instance of the command implementation.
+ */
+ public TextBuiltin create() {
+ final Constructor<? extends TextBuiltin> c;
+ try {
+ c = impl.getDeclaredConstructor();
+ } catch (SecurityException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ } catch (NoSuchMethodException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ }
+ c.setAccessible(true);
+
+ final TextBuiltin r;
+ try {
+ r = c.newInstance();
+ } catch (InstantiationException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ } catch (InvocationTargetException e) {
+ throw new RuntimeException("Cannot create command " + getName(), e);
+ }
+ r.setCommandName(getName());
+ return r;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java
new file mode 100644
index 0000000000..88219bdd9a
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Daemon.java
@@ -0,0 +1,125 @@
+/*
+ * 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.pgm;
+
+import java.io.File;
+import java.net.InetSocketAddress;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.transport.DaemonService;
+
+@Command(common = true, usage = "Export repositories over git://")
+class Daemon extends TextBuiltin {
+ @Option(name = "--port", metaVar = "PORT", usage = "port number to listen on")
+ int port = org.eclipse.jgit.transport.Daemon.DEFAULT_PORT;
+
+ @Option(name = "--listen", metaVar = "HOSTNAME", usage = "hostname (or ip) to listen on")
+ String host;
+
+ @Option(name = "--timeout", metaVar = "SECONDS", usage = "abort connection if no activity")
+ int timeout = -1;
+
+ @Option(name = "--enable", metaVar = "SERVICE", usage = "enable the service in all repositories", multiValued = true)
+ final List<String> enable = new ArrayList<String>();
+
+ @Option(name = "--disable", metaVar = "SERVICE", usage = "disable the service in all repositories", multiValued = true)
+ final List<String> disable = new ArrayList<String>();
+
+ @Option(name = "--allow-override", metaVar = "SERVICE", usage = "configure the service in daemon.servicename", multiValued = true)
+ final List<String> canOverride = new ArrayList<String>();
+
+ @Option(name = "--forbid-override", metaVar = "SERVICE", usage = "configure the service in daemon.servicename", multiValued = true)
+ final List<String> forbidOverride = new ArrayList<String>();
+
+ @Option(name = "--export-all", usage = "export without git-daemon-export-ok")
+ boolean exportAll;
+
+ @Argument(required = true, metaVar = "DIRECTORY", usage = "directories to export")
+ final List<File> directory = new ArrayList<File>();
+
+ @Override
+ protected boolean requiresRepository() {
+ return false;
+ }
+
+ @Override
+ protected void run() throws Exception {
+ final org.eclipse.jgit.transport.Daemon d;
+
+ d = new org.eclipse.jgit.transport.Daemon(
+ host != null ? new InetSocketAddress(host, port)
+ : new InetSocketAddress(port));
+ d.setExportAll(exportAll);
+ if (0 <= timeout)
+ d.setTimeout(timeout);
+
+ for (final String n : enable)
+ service(d, n).setEnabled(true);
+ for (final String n : disable)
+ service(d, n).setEnabled(false);
+
+ for (final String n : canOverride)
+ service(d, n).setOverridable(true);
+ for (final String n : forbidOverride)
+ service(d, n).setOverridable(false);
+
+ for (final File f : directory) {
+ out.println("Exporting " + f.getAbsolutePath());
+ d.exportDirectory(f);
+ }
+ d.start();
+ out.println("Listening on " + d.getAddress());
+ }
+
+ private DaemonService service(final org.eclipse.jgit.transport.Daemon d,
+ final String n) {
+ final DaemonService svc = d.getService(n);
+ if (svc == null)
+ throw die("Service '" + n + "' not supported");
+ return svc;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java
new file mode 100644
index 0000000000..e514ca5147
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Die.java
@@ -0,0 +1,65 @@
+/*
+ * 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.pgm;
+
+/**
+ * Indicates a {@link TextBuiltin} implementation has failed during execution.
+ * <p>
+ * Typically the stack trace for a Die exception is not shown to the user as it
+ * may indicate a simple error condition that the end-user can fix on their own,
+ * without needing a screen of Java stack frames.
+ */
+public class Die extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Construct a new message explaining what has gone wrong.
+ *
+ * @param why
+ * the message to show to the end-user.
+ */
+ public Die(final String why) {
+ super(why);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java
new file mode 100644
index 0000000000..13b1c780f0
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/DiffTree.java
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+class DiffTree extends TextBuiltin {
+ @Option(name = "--recursive", usage = "recurse into subtrees", aliases = { "-r" })
+ private boolean recursive;
+
+ @Argument(index = 0, metaVar = "tree-ish", required = true)
+ void tree_0(final AbstractTreeIterator c) {
+ trees.add(c);
+ }
+
+ @Argument(index = 1, metaVar = "tree-ish", required = true)
+ private final List<AbstractTreeIterator> trees = new ArrayList<AbstractTreeIterator>();
+
+ @Option(name = "--", metaVar = "path", multiValued = true, handler = PathTreeFilterHandler.class)
+ private TreeFilter pathFilter = TreeFilter.ALL;
+
+ @Override
+ protected void run() throws Exception {
+ final TreeWalk walk = new TreeWalk(db);
+ walk.reset();
+ walk.setRecursive(recursive);
+ for (final AbstractTreeIterator i : trees)
+ walk.addTree(i);
+ walk.setFilter(AndTreeFilter.create(TreeFilter.ANY_DIFF, pathFilter));
+
+ final int nTree = walk.getTreeCount();
+ while (walk.next()) {
+ for (int i = 1; i < nTree; i++)
+ out.print(':');
+ for (int i = 0; i < nTree; i++) {
+ final FileMode m = walk.getFileMode(i);
+ final String s = m.toString();
+ for (int pad = 6 - s.length(); pad > 0; pad--)
+ out.print('0');
+ out.print(s);
+ out.print(' ');
+ }
+
+ for (int i = 0; i < nTree; i++) {
+ out.print(walk.getObjectId(i).name());
+ out.print(' ');
+ }
+
+ char chg = 'M';
+ if (nTree == 2) {
+ final int m0 = walk.getRawMode(0);
+ final int m1 = walk.getRawMode(1);
+ if (m0 == 0 && m1 != 0)
+ chg = 'A';
+ else if (m0 != 0 && m1 == 0)
+ chg = 'D';
+ else if (m0 != m1 && walk.idEqual(0, 1))
+ chg = 'T';
+ }
+ out.print(chg);
+
+ out.print('\t');
+ out.print(walk.getPathString());
+ out.println();
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
new file mode 100644
index 0000000000..7315e44cb5
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Fetch.java
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2008-2009, 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.pgm;
+
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.transport.FetchResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.Transport;
+
+@Command(common = true, usage = "Update remote refs from another repository")
+class Fetch extends AbstractFetchCommand {
+ @Option(name = "--timeout", metaVar = "SECONDS", usage = "abort connection if no activity")
+ int timeout = -1;
+
+ @Option(name = "--fsck", usage = "perform fsck style checks on receive")
+ private Boolean fsck;
+
+ @Option(name = "--no-fsck")
+ void nofsck(final boolean ignored) {
+ fsck = Boolean.FALSE;
+ }
+
+ @Option(name = "--prune", usage = "prune stale tracking refs")
+ private Boolean prune;
+
+ @Option(name = "--dry-run")
+ private boolean dryRun;
+
+ @Option(name = "--thin", usage = "fetch thin pack")
+ private Boolean thin;
+
+ @Option(name = "--no-thin")
+ void nothin(final boolean ignored) {
+ thin = Boolean.FALSE;
+ }
+
+ @Argument(index = 0, metaVar = "uri-ish")
+ private String remote = "origin";
+
+ @Argument(index = 1, metaVar = "refspec")
+ private List<RefSpec> toget;
+
+ @Override
+ protected void run() throws Exception {
+ final Transport tn = Transport.open(db, remote);
+ if (fsck != null)
+ tn.setCheckFetchedObjects(fsck.booleanValue());
+ if (prune != null)
+ tn.setRemoveDeletedRefs(prune.booleanValue());
+ tn.setDryRun(dryRun);
+ if (thin != null)
+ tn.setFetchThin(thin.booleanValue());
+ if (0 <= timeout)
+ tn.setTimeout(timeout);
+ final FetchResult r;
+ try {
+ r = tn.fetch(new TextProgressMonitor(), toget);
+ if (r.getTrackingRefUpdates().isEmpty())
+ return;
+ } finally {
+ tn.close();
+ }
+ showFetchResult(tn, r);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
new file mode 100644
index 0000000000..c799222f56
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Glog.java
@@ -0,0 +1,132 @@
+/*
+ * 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.pgm;
+
+import java.awt.BorderLayout;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.awt.event.WindowEvent;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JFrame;
+import javax.swing.JPanel;
+import javax.swing.JScrollPane;
+
+import org.eclipse.jgit.awtui.CommitGraphPane;
+import org.eclipse.jgit.revplot.PlotWalk;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+class Glog extends RevWalkTextBuiltin {
+ final JFrame frame;
+
+ final CommitGraphPane graphPane;
+
+ Glog() {
+ frame = new JFrame();
+ frame.addWindowListener(new WindowAdapter() {
+ @Override
+ public void windowClosing(final WindowEvent e) {
+ frame.dispose();
+ }
+ });
+
+ graphPane = new CommitGraphPane();
+
+ final JScrollPane graphScroll = new JScrollPane(graphPane);
+
+ final JPanel buttons = new JPanel(new FlowLayout());
+ final JButton repaint = new JButton();
+ repaint.setText("Repaint");
+ repaint.addActionListener(new ActionListener() {
+ public void actionPerformed(ActionEvent e) {
+ graphPane.repaint();
+ }
+ });
+ buttons.add(repaint);
+
+ final JPanel world = new JPanel(new BorderLayout());
+ world.add(buttons, BorderLayout.SOUTH);
+ world.add(graphScroll, BorderLayout.CENTER);
+
+ frame.getContentPane().add(world);
+ }
+
+ @Override
+ protected int walkLoop() throws Exception {
+ graphPane.getCommitList().source(walk);
+ graphPane.getCommitList().fillTo(Integer.MAX_VALUE);
+
+ frame.setTitle("[" + repoName() + "]");
+ frame.pack();
+ frame.setVisible(true);
+ return graphPane.getCommitList().size();
+ }
+
+ @Override
+ protected void show(final RevCommit c) throws Exception {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ protected RevWalk createWalk() {
+ if (objects)
+ throw die("Cannot use --objects with glog");
+ final PlotWalk w = new PlotWalk(db);
+ w.sort(RevSort.BOUNDARY, true);
+ return w;
+ }
+
+ private String repoName() {
+ final File f = db.getDirectory();
+ String n = f.getName();
+ if (".git".equals(n))
+ n = f.getParentFile().getName();
+ return n;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
new file mode 100644
index 0000000000..eb65e680ff
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/IndexPack.java
@@ -0,0 +1,76 @@
+/*
+ * Copyright (C) 2009, 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.pgm;
+
+import java.io.BufferedInputStream;
+import java.io.File;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+
+class IndexPack extends TextBuiltin {
+ @Option(name = "--fix-thin", usage = "fix a thin pack to be complete")
+ private boolean fixThin;
+
+ @Option(name = "--index-version", usage = "index file format to create")
+ private int indexVersion = -1;
+
+ @Argument(index = 0, required = true, metaVar = "base")
+ private File base;
+
+ @Override
+ protected void run() throws Exception {
+ if (indexVersion == -1)
+ indexVersion = db.getConfig().getCore().getPackIndexVersion();
+ final BufferedInputStream in;
+ final org.eclipse.jgit.transport.IndexPack ip;
+ in = new BufferedInputStream(System.in);
+ ip = new org.eclipse.jgit.transport.IndexPack(db, in, base);
+ ip.setFixThin(fixThin);
+ ip.setIndexVersion(indexVersion);
+ ip.index(new TextProgressMonitor());
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
new file mode 100644
index 0000000000..b6a4a44a9e
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Init.java
@@ -0,0 +1,71 @@
+/*
+ * Copyright (C) 2009, Constantine Plotnikov <constantine.plotnikov@gmail.com>
+ * 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.pgm;
+
+import java.io.File;
+
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Repository;
+
+@Command(common = true, usage = "Create an empty git repository")
+class Init extends TextBuiltin {
+ @Option(name = "--bare", usage = "Create a bare repository")
+ private boolean bare;
+
+ @Override
+ protected final boolean requiresRepository() {
+ return false;
+ }
+
+ @Override
+ protected void run() throws Exception {
+ if (gitdir == null)
+ gitdir = new File(bare ? "." : ".git");
+ db = new Repository(gitdir);
+ db.create(bare);
+ out.println("Initialized empty Git repository in "
+ + gitdir.getAbsolutePath());
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
new file mode 100644
index 0000000000..ecaf19bd12
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Log.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2006-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.pgm;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Locale;
+import java.util.Map;
+import java.util.Set;
+import java.util.TimeZone;
+
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+@Command(common = true, usage = "View commit history")
+class Log extends RevWalkTextBuiltin {
+ private final TimeZone myTZ = TimeZone.getDefault();
+
+ private final DateFormat fmt;
+
+ private Map<AnyObjectId, Set<Ref>> allRefsByPeeledObjectId;
+
+ @Option(name="--decorate", usage="Show ref names matching commits")
+ private boolean decorate;
+
+ Log() {
+ fmt = new SimpleDateFormat("EEE MMM dd HH:mm:ss yyyy ZZZZZ", Locale.US);
+ }
+
+ @Override
+ protected RevWalk createWalk() {
+ RevWalk ret = super.createWalk();
+ if (decorate)
+ allRefsByPeeledObjectId = getRepository().getAllRefsByPeeledObjectId();
+ return ret;
+ }
+
+ @Override
+ protected void show(final RevCommit c) throws Exception {
+ out.print("commit ");
+ c.getId().copyTo(outbuffer, out);
+ if (decorate) {
+ Collection<Ref> list = allRefsByPeeledObjectId.get(c.copy());
+ if (list != null) {
+ out.print(" (");
+ for (Iterator<Ref> i = list.iterator(); i.hasNext(); ) {
+ out.print(i.next().getOrigName());
+ if (i.hasNext())
+ out.print(" ");
+ }
+ out.print(")");
+ }
+ }
+ out.println();
+
+ final PersonIdent author = c.getAuthorIdent();
+ out.print("Author: ");
+ out.print(author.getName());
+ out.print(" <");
+ out.print(author.getEmailAddress());
+ out.print(">");
+ out.println();
+
+ final TimeZone authorTZ = author.getTimeZone();
+ fmt.setTimeZone(authorTZ != null ? authorTZ : myTZ);
+ out.print("Date: ");
+ out.print(fmt.format(author.getWhen()));
+ out.println();
+
+ out.println();
+ final String[] lines = c.getFullMessage().split("\n");
+ for (final String s : lines) {
+ out.print(" ");
+ out.print(s);
+ out.println();
+ }
+
+ out.println();
+ out.flush();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java
new file mode 100644
index 0000000000..44d1e754fe
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsRemote.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2009, Google Inc.
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.transport.FetchConnection;
+import org.eclipse.jgit.transport.Transport;
+
+class LsRemote extends TextBuiltin {
+ @Option(name = "--timeout", metaVar = "SECONDS", usage = "abort connection if no activity")
+ int timeout = -1;
+
+ @Argument(index = 0, metaVar = "uri-ish", required = true)
+ private String remote;
+
+ @Override
+ protected void run() throws Exception {
+ final Transport tn = Transport.open(db, remote);
+ if (0 <= timeout)
+ tn.setTimeout(timeout);
+ final FetchConnection c = tn.openFetch();
+ try {
+ for (final Ref r : c.getRefs()) {
+ show(r.getObjectId(), r.getName());
+ if (r.getPeeledObjectId() != null)
+ show(r.getPeeledObjectId(), r.getName() + "^{}");
+ }
+ } finally {
+ c.close();
+ tn.close();
+ }
+ }
+
+ private void show(final AnyObjectId id, final String name) {
+ out.print(id.name());
+ out.print('\t');
+ out.print(name);
+ out.println();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java
new file mode 100644
index 0000000000..1a28a9a48f
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/LsTree.java
@@ -0,0 +1,85 @@
+/*
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+import org.eclipse.jgit.treewalk.TreeWalk;
+
+class LsTree extends TextBuiltin {
+ @Option(name = "--recursive", usage = "recurse into subtrees", aliases = { "-r" })
+ private boolean recursive;
+
+ @Argument(index = 0, required = true, metaVar = "tree-ish")
+ private AbstractTreeIterator tree;
+
+ @Override
+ protected void run() throws Exception {
+ final TreeWalk walk = new TreeWalk(db);
+ walk.reset(); // drop the first empty tree, which we do not need here
+ walk.setRecursive(recursive);
+ walk.addTree(tree);
+
+ while (walk.next()) {
+ final FileMode mode = walk.getFileMode(0);
+ if (mode == FileMode.TREE)
+ out.print('0');
+ out.print(mode);
+ out.print(' ');
+ out.print(Constants.typeString(mode.getObjectType()));
+
+ out.print(' ');
+ out.print(walk.getObjectId(0).name());
+
+ out.print('\t');
+ out.print(walk.getPathString());
+ out.println();
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
new file mode 100644
index 0000000000..625132ae5a
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Main.java
@@ -0,0 +1,184 @@
+/*
+ * Copyright (C) 2008-2009, Google Inc.
+ * Copyright (C) 2008, Marek Zawirski <marek.zawirski@gmail.com>
+ * Copyright (C) 2006, 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.pgm;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.ExampleMode;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.awtui.AwtAuthenticator;
+import org.eclipse.jgit.errors.TransportException;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.pgm.opt.CmdLineParser;
+import org.eclipse.jgit.pgm.opt.SubcommandHandler;
+import org.eclipse.jgit.util.HttpSupport;
+
+/** Command line entry point. */
+public class Main {
+ @Option(name = "--help", usage = "display this help text", aliases = { "-h" })
+ private boolean help;
+
+ @Option(name = "--show-stack-trace", usage = "display the Java stack trace on exceptions")
+ private boolean showStackTrace;
+
+ @Option(name = "--git-dir", metaVar = "GIT_DIR", usage = "set the git repository to operate on")
+ private File gitdir;
+
+ @Argument(index = 0, metaVar = "command", required = true, handler = SubcommandHandler.class)
+ private TextBuiltin subcommand;
+
+ @Argument(index = 1, metaVar = "ARG")
+ private List<String> arguments = new ArrayList<String>();
+
+ /**
+ * Execute the command line.
+ *
+ * @param argv
+ * arguments.
+ */
+ public static void main(final String[] argv) {
+ final Main me = new Main();
+ try {
+ AwtAuthenticator.install();
+ HttpSupport.configureHttpProxy();
+ me.execute(argv);
+ } catch (Die err) {
+ System.err.println("fatal: " + err.getMessage());
+ if (me.showStackTrace)
+ err.printStackTrace();
+ System.exit(128);
+ } catch (Exception err) {
+ if (!me.showStackTrace && err.getCause() != null
+ && err instanceof TransportException)
+ System.err.println("fatal: " + err.getCause().getMessage());
+
+ if (err.getClass().getName().startsWith("org.eclipse.jgit.errors.")) {
+ System.err.println("fatal: " + err.getMessage());
+ if (me.showStackTrace)
+ err.printStackTrace();
+ System.exit(128);
+ }
+ err.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private void execute(final String[] argv) throws Exception {
+ final CmdLineParser clp = new CmdLineParser(this);
+ try {
+ clp.parseArgument(argv);
+ } catch (CmdLineException err) {
+ if (argv.length > 0 && !help) {
+ System.err.println("fatal: " + err.getMessage());
+ System.exit(1);
+ }
+ }
+
+ if (argv.length == 0 || help) {
+ final String ex = clp.printExample(ExampleMode.ALL);
+ System.err.println("jgit" + ex + " command [ARG ...]");
+ if (help) {
+ System.err.println();
+ clp.printUsage(System.err);
+ System.err.println();
+ } else if (subcommand == null) {
+ System.err.println();
+ System.err.println("The most commonly used commands are:");
+ final CommandRef[] common = CommandCatalog.common();
+ int width = 0;
+ for (final CommandRef c : common)
+ width = Math.max(width, c.getName().length());
+ width += 2;
+
+ for (final CommandRef c : common) {
+ System.err.print(' ');
+ System.err.print(c.getName());
+ for (int i = c.getName().length(); i < width; i++)
+ System.err.print(' ');
+ System.err.print(c.getUsage());
+ System.err.println();
+ }
+ System.err.println();
+ }
+ System.exit(1);
+ }
+
+ final TextBuiltin cmd = subcommand;
+ if (cmd.requiresRepository()) {
+ if (gitdir == null)
+ gitdir = findGitDir();
+ if (gitdir == null || !gitdir.isDirectory()) {
+ System.err.println("error: can't find git directory");
+ System.exit(1);
+ }
+ cmd.init(new Repository(gitdir), gitdir);
+ } else {
+ cmd.init(null, gitdir);
+ }
+ try {
+ cmd.execute(arguments.toArray(new String[arguments.size()]));
+ } finally {
+ if (cmd.out != null)
+ cmd.out.flush();
+ }
+ }
+
+ private static File findGitDir() {
+ File current = new File(".").getAbsoluteFile();
+ while (current != null) {
+ final File gitDir = new File(current, ".git");
+ if (gitDir.isDirectory())
+ return gitDir;
+ current = current.getParentFile();
+ }
+ return null;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java
new file mode 100644
index 0000000000..91fd7443b0
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/MergeBase.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.filter.RevFilter;
+
+class MergeBase extends TextBuiltin {
+ @Option(name = "--all", usage = "display all possible merge bases")
+ private boolean all;
+
+ @Argument(index = 0, metaVar = "commit-ish", required = true)
+ void commit_0(final RevCommit c) {
+ commits.add(c);
+ }
+
+ @Argument(index = 1, metaVar = "commit-ish", required = true)
+ private final List<RevCommit> commits = new ArrayList<RevCommit>();
+
+ @Override
+ protected void run() throws Exception {
+ for (final RevCommit c : commits)
+ argWalk.markStart(c);
+ argWalk.setRevFilter(RevFilter.MERGE_BASE);
+ int max = all ? Integer.MAX_VALUE : 1;
+ while (max-- > 0) {
+ final RevCommit b = argWalk.next();
+ if (b == null)
+ break;
+ out.println(b.getId().name());
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java
new file mode 100644
index 0000000000..8afa5227d2
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Push.java
@@ -0,0 +1,256 @@
+/*
+ * 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.pgm;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.transport.PushResult;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.transport.RemoteRefUpdate;
+import org.eclipse.jgit.transport.Transport;
+import org.eclipse.jgit.transport.URIish;
+import org.eclipse.jgit.transport.RemoteRefUpdate.Status;
+
+@Command(common = true, usage = "Update remote repository from local refs")
+class Push extends TextBuiltin {
+ @Option(name = "--timeout", metaVar = "SECONDS", usage = "abort connection if no activity")
+ int timeout = -1;
+
+ @Argument(index = 0, metaVar = "uri-ish")
+ private String remote = "origin";
+
+ @Argument(index = 1, metaVar = "refspec")
+ private final List<RefSpec> refSpecs = new ArrayList<RefSpec>();
+
+ @Option(name = "--all")
+ void addAll(final boolean ignored) {
+ refSpecs.add(Transport.REFSPEC_PUSH_ALL);
+ }
+
+ @Option(name = "--tags")
+ void addTags(final boolean ignored) {
+ refSpecs.add(Transport.REFSPEC_TAGS);
+ }
+
+ @Option(name = "--verbose", aliases = { "-v" })
+ private boolean verbose = false;
+
+ @Option(name = "--thin")
+ private boolean thin = Transport.DEFAULT_PUSH_THIN;
+
+ @Option(name = "--no-thin")
+ void nothin(final boolean ignored) {
+ thin = false;
+ }
+
+ @Option(name = "--force", aliases = { "-f" })
+ private boolean force;
+
+ @Option(name = "--receive-pack", metaVar = "path")
+ private String receivePack;
+
+ @Option(name = "--dry-run")
+ private boolean dryRun;
+
+ private boolean shownURI;
+
+ @Override
+ protected void run() throws Exception {
+ if (force) {
+ final List<RefSpec> orig = new ArrayList<RefSpec>(refSpecs);
+ refSpecs.clear();
+ for (final RefSpec spec : orig)
+ refSpecs.add(spec.setForceUpdate(true));
+ }
+
+ final List<Transport> transports;
+ transports = Transport.openAll(db, remote, Transport.Operation.PUSH);
+ for (final Transport transport : transports) {
+ if (0 <= timeout)
+ transport.setTimeout(timeout);
+ transport.setPushThin(thin);
+ if (receivePack != null)
+ transport.setOptionReceivePack(receivePack);
+ transport.setDryRun(dryRun);
+
+ final Collection<RemoteRefUpdate> toPush = transport
+ .findRemoteRefUpdatesFor(refSpecs);
+
+ final URIish uri = transport.getURI();
+ final PushResult result;
+ try {
+ result = transport.push(new TextProgressMonitor(), toPush);
+ } finally {
+ transport.close();
+ }
+ printPushResult(uri, result);
+ }
+ }
+
+ private void printPushResult(final URIish uri,
+ final PushResult result) {
+ shownURI = false;
+ boolean everythingUpToDate = true;
+
+ // at first, print up-to-date ones...
+ for (final RemoteRefUpdate rru : result.getRemoteUpdates()) {
+ if (rru.getStatus() == Status.UP_TO_DATE) {
+ if (verbose)
+ printRefUpdateResult(uri, result, rru);
+ } else
+ everythingUpToDate = false;
+ }
+
+ for (final RemoteRefUpdate rru : result.getRemoteUpdates()) {
+ // ...then successful updates...
+ if (rru.getStatus() == Status.OK)
+ printRefUpdateResult(uri, result, rru);
+ }
+
+ for (final RemoteRefUpdate rru : result.getRemoteUpdates()) {
+ // ...finally, others (problematic)
+ if (rru.getStatus() != Status.OK
+ && rru.getStatus() != Status.UP_TO_DATE)
+ printRefUpdateResult(uri, result, rru);
+ }
+
+ if (everythingUpToDate)
+ out.println("Everything up-to-date");
+ }
+
+ private void printRefUpdateResult(final URIish uri,
+ final PushResult result, final RemoteRefUpdate rru) {
+ if (!shownURI) {
+ shownURI = true;
+ out.format("To %s\n", uri);
+ }
+
+ final String remoteName = rru.getRemoteName();
+ final String srcRef = rru.isDelete() ? null : rru.getSrcRef();
+
+ switch (rru.getStatus()) {
+ case OK:
+ if (rru.isDelete())
+ printUpdateLine('-', "[deleted]", null, remoteName, null);
+ else {
+ final Ref oldRef = result.getAdvertisedRef(remoteName);
+ if (oldRef == null) {
+ final String summary;
+ if (remoteName.startsWith(Constants.R_TAGS))
+ summary = "[new tag]";
+ else
+ summary = "[new branch]";
+ printUpdateLine('*', summary, srcRef, remoteName, null);
+ } else {
+ boolean fastForward = rru.isFastForward();
+ final char flag = fastForward ? ' ' : '+';
+ final String summary = oldRef.getObjectId().abbreviate(db)
+ .name()
+ + (fastForward ? ".." : "...")
+ + rru.getNewObjectId().abbreviate(db).name();
+ final String message = fastForward ? null : "forced update";
+ printUpdateLine(flag, summary, srcRef, remoteName, message);
+ }
+ }
+ break;
+
+ case NON_EXISTING:
+ printUpdateLine('X', "[no match]", null, remoteName, null);
+ break;
+
+ case REJECTED_NODELETE:
+ printUpdateLine('!', "[rejected]", null, remoteName,
+ "remote side does not support deleting refs");
+ break;
+
+ case REJECTED_NONFASTFORWARD:
+ printUpdateLine('!', "[rejected]", srcRef, remoteName,
+ "non-fast forward");
+ break;
+
+ case REJECTED_REMOTE_CHANGED:
+ final String message = "remote ref object changed - is not expected one "
+ + rru.getExpectedOldObjectId().abbreviate(db).name();
+ printUpdateLine('!', "[rejected]", srcRef, remoteName, message);
+ break;
+
+ case REJECTED_OTHER_REASON:
+ printUpdateLine('!', "[remote rejected]", srcRef, remoteName, rru
+ .getMessage());
+ break;
+
+ case UP_TO_DATE:
+ if (verbose)
+ printUpdateLine('=', "[up to date]", srcRef, remoteName, null);
+ break;
+
+ case NOT_ATTEMPTED:
+ case AWAITING_REPORT:
+ printUpdateLine('?', "[unexpected push-process behavior]", srcRef,
+ remoteName, rru.getMessage());
+ break;
+ }
+ }
+
+ private void printUpdateLine(final char flag, final String summary,
+ final String srcRef, final String destRef, final String message) {
+ out.format(" %c %-17s", flag, summary);
+
+ if (srcRef != null)
+ out.format(" %s ->", abbreviateRef(srcRef, true));
+ out.format(" %s", abbreviateRef(destRef, true));
+
+ if (message != null)
+ out.format(" (%s)", message);
+
+ out.println();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java
new file mode 100644
index 0000000000..c6a6fd0cbf
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ReceivePack.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008-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.pgm;
+
+import java.io.File;
+
+import org.kohsuke.args4j.Argument;
+import org.eclipse.jgit.lib.Repository;
+
+@Command(common = false, usage = "Server side backend for 'jgit push'")
+class ReceivePack extends TextBuiltin {
+ @Argument(index = 0, required = true, metaVar = "DIRECTORY", usage = "Repository to receive into")
+ File dstGitdir;
+
+ @Override
+ protected final boolean requiresRepository() {
+ return false;
+ }
+
+ @Override
+ protected void run() throws Exception {
+ final org.eclipse.jgit.transport.ReceivePack rp;
+
+ if (new File(dstGitdir, ".git").isDirectory())
+ dstGitdir = new File(dstGitdir, ".git");
+ db = new Repository(dstGitdir);
+ if (!db.getObjectsDirectory().isDirectory())
+ throw die("'" + dstGitdir.getPath() + "' not a git repository");
+ rp = new org.eclipse.jgit.transport.ReceivePack(db);
+ rp.receive(System.in, System.out, System.err);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java
new file mode 100644
index 0000000000..1b8c180f91
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevList.java
@@ -0,0 +1,81 @@
+/*
+ * 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.pgm;
+
+import org.eclipse.jgit.revwalk.ObjectWalk;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevFlag;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevTree;
+
+class RevList extends RevWalkTextBuiltin {
+ @Override
+ protected void show(final RevCommit c) throws Exception {
+ if (c.has(RevFlag.UNINTERESTING))
+ out.print('-');
+ c.getId().copyTo(outbuffer, out);
+ if (parents)
+ for (int i = 0; i < c.getParentCount(); i++) {
+ out.print(' ');
+ c.getParent(i).getId().copyTo(outbuffer, out);
+ }
+ out.println();
+ }
+
+ @Override
+ protected void show(final ObjectWalk ow, final RevObject obj)
+ throws Exception {
+ if (obj.has(RevFlag.UNINTERESTING))
+ out.print('-');
+ obj.getId().copyTo(outbuffer, out);
+ final String path = ow.getPathString();
+ if (path != null) {
+ out.print(' ');
+ out.print(path);
+ } else if (obj instanceof RevTree)
+ out.print(' ');
+ out.println();
+
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
new file mode 100644
index 0000000000..98eb2ce86b
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevParse.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2009, Daniel Cheng (aka SDiZ) <git@sdiz.net>
+ * Copyright (C) 2009, Daniel Cheng (aka SDiZ) <j16sdiz+freenet@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.pgm;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Ref;
+
+class RevParse extends TextBuiltin {
+ @Option(name = "--all")
+ boolean all = false;
+
+ @Argument(index = 0, metaVar = "commit-ish")
+ private final List<ObjectId> commits = new ArrayList<ObjectId>();
+
+ @Override
+ protected void run() throws Exception {
+ if (all) {
+ Map<String, Ref> allRefs = db.getAllRefs();
+ for (final Ref r : allRefs.values())
+ out.println(r.getObjectId().name());
+ } else {
+ for (final ObjectId o : commits)
+ out.println(o.name());
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java
new file mode 100644
index 0000000000..cb0cd6d0f5
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/RevWalkTextBuiltin.java
@@ -0,0 +1,208 @@
+/*
+ * 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.pgm;
+
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
+import org.eclipse.jgit.revwalk.ObjectWalk;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevFlag;
+import org.eclipse.jgit.revwalk.RevObject;
+import org.eclipse.jgit.revwalk.RevSort;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.revwalk.filter.AndRevFilter;
+import org.eclipse.jgit.revwalk.filter.AuthorRevFilter;
+import org.eclipse.jgit.revwalk.filter.CommitterRevFilter;
+import org.eclipse.jgit.revwalk.filter.MessageRevFilter;
+import org.eclipse.jgit.revwalk.filter.RevFilter;
+import org.eclipse.jgit.treewalk.filter.AndTreeFilter;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+abstract class RevWalkTextBuiltin extends TextBuiltin {
+ RevWalk walk;
+
+ @Option(name = "--objects")
+ boolean objects = false;
+
+ @Option(name = "--parents")
+ boolean parents = false;
+
+ @Option(name = "--total-count")
+ boolean count = false;
+
+ char[] outbuffer = new char[Constants.OBJECT_ID_LENGTH * 2];
+
+ private final EnumSet<RevSort> sorting = EnumSet.noneOf(RevSort.class);
+
+ private void enableRevSort(final RevSort type, final boolean on) {
+ if (on)
+ sorting.add(type);
+ else
+ sorting.remove(type);
+ }
+
+ @Option(name = "--date-order")
+ void enableDateOrder(final boolean on) {
+ enableRevSort(RevSort.COMMIT_TIME_DESC, on);
+ }
+
+ @Option(name = "--topo-order")
+ void enableTopoOrder(final boolean on) {
+ enableRevSort(RevSort.TOPO, on);
+ }
+
+ @Option(name = "--reverse")
+ void enableReverse(final boolean on) {
+ enableRevSort(RevSort.REVERSE, on);
+ }
+
+ @Option(name = "--boundary")
+ void enableBoundary(final boolean on) {
+ enableRevSort(RevSort.BOUNDARY, on);
+ }
+
+ @Argument(index = 0, metaVar = "commit-ish")
+ private final List<RevCommit> commits = new ArrayList<RevCommit>();
+
+ @Option(name = "--", metaVar = "path", multiValued = true, handler = PathTreeFilterHandler.class)
+ private TreeFilter pathFilter = TreeFilter.ALL;
+
+ private final List<RevFilter> revLimiter = new ArrayList<RevFilter>();
+
+ @Option(name = "--author")
+ void addAuthorRevFilter(final String who) {
+ revLimiter.add(AuthorRevFilter.create(who));
+ }
+
+ @Option(name = "--committer")
+ void addCommitterRevFilter(final String who) {
+ revLimiter.add(CommitterRevFilter.create(who));
+ }
+
+ @Option(name = "--grep")
+ void addCMessageRevFilter(final String msg) {
+ revLimiter.add(MessageRevFilter.create(msg));
+ }
+
+ @Override
+ protected void run() throws Exception {
+ walk = createWalk();
+ for (final RevSort s : sorting)
+ walk.sort(s, true);
+
+ if (pathFilter != TreeFilter.ALL)
+ walk.setTreeFilter(AndTreeFilter.create(pathFilter,
+ TreeFilter.ANY_DIFF));
+
+ if (revLimiter.size() == 1)
+ walk.setRevFilter(revLimiter.get(0));
+ else if (revLimiter.size() > 1)
+ walk.setRevFilter(AndRevFilter.create(revLimiter));
+
+ if (commits.isEmpty()) {
+ final ObjectId head = db.resolve(Constants.HEAD);
+ if (head == null)
+ throw die("Cannot resolve " + Constants.HEAD);
+ commits.add(walk.parseCommit(head));
+ }
+ for (final RevCommit c : commits) {
+ final RevCommit real = argWalk == walk ? c : walk.parseCommit(c);
+ if (c.has(RevFlag.UNINTERESTING))
+ walk.markUninteresting(real);
+ else
+ walk.markStart(real);
+ }
+
+ final long start = System.currentTimeMillis();
+ final int n = walkLoop();
+ if (count) {
+ final long end = System.currentTimeMillis();
+ System.err.print(n);
+ System.err.print(' ');
+ System.err.print(end - start);
+ System.err.print(" ms");
+ System.err.println();
+ }
+ }
+
+ protected RevWalk createWalk() {
+ if (objects)
+ return new ObjectWalk(db);
+ if (argWalk == null)
+ argWalk = new RevWalk(db);
+ return argWalk;
+ }
+
+ protected int walkLoop() throws Exception {
+ int n = 0;
+ for (final RevCommit c : walk) {
+ n++;
+ show(c);
+ }
+ if (walk instanceof ObjectWalk) {
+ final ObjectWalk ow = (ObjectWalk) walk;
+ for (;;) {
+ final RevObject obj = ow.nextObject();
+ if (obj == null)
+ break;
+ show(ow, obj);
+ }
+ }
+ return n;
+ }
+
+ protected abstract void show(final RevCommit c) throws Exception;
+
+ protected void show(final ObjectWalk objectWalk,
+ final RevObject currentObject) throws Exception {
+ // Do nothing by default. Most applications cannot show an object.
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java
new file mode 100644
index 0000000000..63e6e1712d
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Rm.java
@@ -0,0 +1,98 @@
+/*
+ * 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.pgm;
+
+import java.io.File;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.kohsuke.args4j.spi.StopOptionHandler;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheBuildIterator;
+import org.eclipse.jgit.dircache.DirCacheBuilder;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.pgm.opt.PathTreeFilterHandler;
+import org.eclipse.jgit.treewalk.TreeWalk;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+@Command(usage = "Stop tracking a file", common = true)
+class Rm extends TextBuiltin {
+ @Argument(metaVar = "path", usage = "path", multiValued = true, required = true, handler = PathTreeFilterHandler.class)
+ @Option(name = "--", handler = StopOptionHandler.class)
+ private TreeFilter paths;
+
+ private File root;
+
+ @Override
+ protected void run() throws Exception {
+ root = db.getWorkDir();
+
+ final DirCache dirc = DirCache.lock(db);
+ final DirCacheBuilder edit = dirc.builder();
+
+ final TreeWalk walk = new TreeWalk(db);
+ walk.reset(); // drop the first empty tree, which we do not need here
+ walk.setRecursive(true);
+ walk.setFilter(paths);
+ walk.addTree(new DirCacheBuildIterator(edit));
+
+ while (walk.next()) {
+ final File path = new File(root, walk.getPathString());
+ final FileMode mode = walk.getFileMode(0);
+ if (mode.getObjectType() == Constants.OBJ_BLOB) {
+ // Deleting a blob is simply a matter of removing
+ // the file or symlink named by the tree entry.
+ delete(path);
+ }
+ }
+
+ edit.commit();
+ }
+
+ private void delete(File p) {
+ while (p != null && !p.equals(root) && p.delete())
+ p = p.getParentFile();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java
new file mode 100644
index 0000000000..7dbb21c5d5
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/ShowRef.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm;
+
+import java.util.TreeMap;
+
+import org.eclipse.jgit.lib.AnyObjectId;
+import org.eclipse.jgit.lib.Ref;
+
+class ShowRef extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ for (final Ref r : new TreeMap<String, Ref>(db.getAllRefs()).values()) {
+ show(r.getObjectId(), r.getName());
+ if (r.getPeeledObjectId() != null)
+ show(r.getPeeledObjectId(), r.getName() + "^{}");
+ }
+ }
+
+ private void show(final AnyObjectId id, final String name) {
+ out.print(id.name());
+ out.print('\t');
+ out.print(name);
+ out.println();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
new file mode 100644
index 0000000000..703b10baf2
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Tag.java
@@ -0,0 +1,100 @@
+/*
+ * Copyright (C) 2008, Charles O'Farrell <charleso@charleso.org>
+ * Copyright (C) 2009, Google Inc.
+ * Copyright (C) 2008, Robin Rosenberg <robin.rosenberg.lists@dewire.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.pgm;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectLoader;
+import org.eclipse.jgit.lib.PersonIdent;
+
+@Command(common = true, usage = "Create a tag")
+class Tag extends TextBuiltin {
+ @Option(name = "-f", usage = "force replacing an existing tag")
+ private boolean force;
+
+ @Option(name = "-m", metaVar = "message", usage = "tag message")
+ private String message = "";
+
+ @Argument(index = 0, required = true, metaVar = "name")
+ private String tagName;
+
+ @Argument(index = 1, metaVar = "object")
+ private ObjectId object;
+
+ @Override
+ protected void run() throws Exception {
+ if (object == null) {
+ object = db.resolve(Constants.HEAD);
+ if (object == null)
+ throw die("Cannot resolve " + Constants.HEAD);
+ }
+
+ if (!tagName.startsWith(Constants.R_TAGS))
+ tagName = Constants.R_TAGS + tagName;
+ if (!force && db.resolve(tagName) != null) {
+ throw die("fatal: tag '"
+ + tagName.substring(Constants.R_TAGS.length())
+ + "' exists");
+ }
+
+ final ObjectLoader ldr = db.openObject(object);
+ if (ldr == null)
+ throw new MissingObjectException(object, "any");
+
+ org.eclipse.jgit.lib.Tag tag = new org.eclipse.jgit.lib.Tag(db);
+ tag.setObjId(object);
+ tag.setType(Constants.typeString(ldr.getType()));
+ tag.setTagger(new PersonIdent(db));
+ tag.setMessage(message.replaceAll("\r", ""));
+ tag.setTag(tagName.substring(Constants.R_TAGS.length()));
+ tag.tag();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java
new file mode 100644
index 0000000000..edd4fbcf9b
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/TextBuiltin.java
@@ -0,0 +1,241 @@
+/*
+ * Copyright (C) 2007, 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.pgm;
+
+import static org.eclipse.jgit.lib.Constants.R_HEADS;
+import static org.eclipse.jgit.lib.Constants.R_REMOTES;
+import static org.eclipse.jgit.lib.Constants.R_TAGS;
+
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.PrintWriter;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.pgm.opt.CmdLineParser;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Abstract command which can be invoked from the command line.
+ * <p>
+ * Commands are configured with a single "current" repository and then the
+ * {@link #execute(String[])} method is invoked with the arguments that appear
+ * on the command line after the command name.
+ * <p>
+ * Command constructors should perform as little work as possible as they may be
+ * invoked very early during process loading, and the command may not execute
+ * even though it was constructed.
+ */
+public abstract class TextBuiltin {
+ private String commandName;
+
+ @Option(name = "--help", usage = "display this help text", aliases = { "-h" })
+ private boolean help;
+
+ /** Stream to output to, typically this is standard output. */
+ protected PrintWriter out;
+
+ /** Git repository the command was invoked within. */
+ protected Repository db;
+
+ /** Directory supplied via --git-dir command line option. */
+ protected File gitdir;
+
+ /** RevWalk used during command line parsing, if it was required. */
+ protected RevWalk argWalk;
+
+ final void setCommandName(final String name) {
+ commandName = name;
+ }
+
+ /** @return true if {@link #db}/{@link #getRepository()} is required. */
+ protected boolean requiresRepository() {
+ return true;
+ }
+
+ void init(final Repository repo, final File gd) {
+ try {
+ final String outputEncoding = repo != null ? repo.getConfig()
+ .getString("i18n", null, "logOutputEncoding") : null;
+ if (outputEncoding != null)
+ out = new PrintWriter(new BufferedWriter(
+ new OutputStreamWriter(System.out, outputEncoding)));
+ else
+ out = new PrintWriter(new BufferedWriter(
+ new OutputStreamWriter(System.out)));
+ } catch (IOException e) {
+ throw die("cannot create output stream");
+ }
+
+ if (repo != null) {
+ db = repo;
+ gitdir = repo.getDirectory();
+ } else {
+ db = null;
+ gitdir = gd;
+ }
+ }
+
+ /**
+ * Parse arguments and run this command.
+ *
+ * @param args
+ * command line arguments passed after the command name.
+ * @throws Exception
+ * an error occurred while processing the command. The main
+ * framework will catch the exception and print a message on
+ * standard error.
+ */
+ public final void execute(String[] args) throws Exception {
+ parseArguments(args);
+ run();
+ }
+
+ /**
+ * Parses the command line arguments prior to running.
+ * <p>
+ * This method should only be invoked by {@link #execute(String[])}, prior
+ * to calling {@link #run()}. The default implementation parses all
+ * arguments into this object's instance fields.
+ *
+ * @param args
+ * the arguments supplied on the command line, if any.
+ */
+ protected void parseArguments(final String[] args) {
+ final CmdLineParser clp = new CmdLineParser(this);
+ try {
+ clp.parseArgument(args);
+ } catch (CmdLineException err) {
+ if (!help) {
+ System.err.println("fatal: " + err.getMessage());
+ System.exit(1);
+ }
+ }
+
+ if (help) {
+ printUsageAndExit(clp);
+ }
+
+ argWalk = clp.getRevWalkGently();
+ }
+
+ /**
+ * Print the usage line
+ *
+ * @param clp
+ */
+ public void printUsageAndExit(final CmdLineParser clp) {
+ printUsageAndExit("", clp);
+ }
+
+ /**
+ * Print an error message and the usage line
+ *
+ * @param message
+ * @param clp
+ */
+ public void printUsageAndExit(final String message, final CmdLineParser clp) {
+ System.err.println(message);
+ System.err.print("jgit ");
+ System.err.print(commandName);
+ clp.printSingleLineUsage(System.err);
+ System.err.println();
+
+ System.err.println();
+ clp.printUsage(System.err);
+ System.err.println();
+
+ System.exit(1);
+ }
+
+ /**
+ * Perform the actions of this command.
+ * <p>
+ * This method should only be invoked by {@link #execute(String[])}.
+ *
+ * @throws Exception
+ * an error occurred while processing the command. The main
+ * framework will catch the exception and print a message on
+ * standard error.
+ */
+ protected abstract void run() throws Exception;
+
+ /**
+ * @return the repository this command accesses.
+ */
+ public Repository getRepository() {
+ return db;
+ }
+
+ ObjectId resolve(final String s) throws IOException {
+ final ObjectId r = db.resolve(s);
+ if (r == null)
+ throw die("Not a revision: " + s);
+ return r;
+ }
+
+ /**
+ * @param why
+ * textual explanation
+ * @return a runtime exception the caller is expected to throw
+ */
+ protected static Die die(final String why) {
+ return new Die(why);
+ }
+
+ String abbreviateRef(String dst, boolean abbreviateRemote) {
+ if (dst.startsWith(R_HEADS))
+ dst = dst.substring(R_HEADS.length());
+ else if (dst.startsWith(R_TAGS))
+ dst = dst.substring(R_TAGS.length());
+ else if (abbreviateRemote && dst.startsWith(R_REMOTES))
+ dst = dst.substring(R_REMOTES.length());
+ return dst;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java
new file mode 100644
index 0000000000..85dbbc5d9c
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/UploadPack.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008-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.pgm;
+
+import java.io.File;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.Repository;
+
+@Command(common = false, usage = "Server side backend for 'jgit fetch'")
+class UploadPack extends TextBuiltin {
+ @Option(name = "--timeout", metaVar = "SECONDS", usage = "abort connection if no activity")
+ int timeout = -1;
+
+ @Argument(index = 0, required = true, metaVar = "DIRECTORY", usage = "Repository to read from")
+ File srcGitdir;
+
+ @Override
+ protected final boolean requiresRepository() {
+ return false;
+ }
+
+ @Override
+ protected void run() throws Exception {
+ final org.eclipse.jgit.transport.UploadPack rp;
+
+ if (new File(srcGitdir, ".git").isDirectory())
+ srcGitdir = new File(srcGitdir, ".git");
+ db = new Repository(srcGitdir);
+ if (!db.getObjectsDirectory().isDirectory())
+ throw die("'" + srcGitdir.getPath() + "' not a git repository");
+ rp = new org.eclipse.jgit.transport.UploadPack(db);
+ if (0 <= timeout)
+ rp.setTimeout(timeout);
+ rp.upload(System.in, System.out, System.err);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java
new file mode 100644
index 0000000000..11b6e83523
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/Version.java
@@ -0,0 +1,58 @@
+/*
+ * 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.pgm;
+
+@Command(common = true, usage = "Display the version of jgit")
+class Version extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final Package pkg = getClass().getPackage();
+ if (pkg == null || pkg.getImplementationVersion() == null)
+ throw die("Cannot read package information.");
+
+ out.print("jgit version ");
+ out.print(pkg.getImplementationVersion());
+ out.println();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/build/JarLinkUtil.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/build/JarLinkUtil.java
new file mode 100644
index 0000000000..e63f39c01e
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/build/JarLinkUtil.java
@@ -0,0 +1,212 @@
+/*
+ * 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.pgm.build;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipFile;
+import java.util.zip.ZipOutputStream;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+import org.kohsuke.args4j.spi.MapOptionHandler;
+
+/**
+ * Combines multiple JAR and directory sources into a single JAR file.
+ * <p>
+ * This is a crude command line utility to combine multiple JAR files into a
+ * single JAR file, without first needing to unpack the individual JARs.
+ * <p>
+ * The output ZIP stream is sent to standard out and can be redirected onto the
+ * end of a shell script which starts the JRE.
+ */
+public class JarLinkUtil {
+ /**
+ * Combine multiple JARs.
+ *
+ * @param argv
+ * the command line arguments indicating the files to pack.
+ * @throws IOException
+ * a source file could not be read.
+ */
+ public static void main(final String[] argv) throws IOException {
+ final JarLinkUtil util = new JarLinkUtil();
+ final CmdLineParser clp = new CmdLineParser(util);
+ try {
+ clp.parseArgument(argv);
+ } catch (CmdLineException e) {
+ clp.printSingleLineUsage(System.err);
+ System.exit(1);
+ }
+ util.run();
+ }
+
+ @Option(name = "-include", required = true)
+ private List<File> includes = new ArrayList<File>();
+
+ @Option(name = "-file", handler = MapOptionHandler.class)
+ private Map<String, String> files = new HashMap<String, String>();
+
+ private final Map<String, File> chosenSources = new HashMap<String, File>();
+
+ private long creationTime;
+
+ private ZipOutputStream zos;
+
+ private JarLinkUtil() {
+ // Command line utility only.
+ }
+
+ private void run() throws IOException {
+ for (final File src : includes) {
+ if (src.isFile())
+ scanJar(src);
+ else
+ scanDirectory(src, src, "");
+ }
+ for (final Map.Entry<String, String> e : files.entrySet())
+ chosenSources.put(e.getKey(), new File(e.getValue()));
+
+ creationTime = System.currentTimeMillis();
+ zos = new ZipOutputStream(System.out);
+ zos.setLevel(9);
+
+ for (final File src : includes) {
+ if (src.isFile())
+ appendJar(src);
+ else
+ appendDirectory(src, src, "");
+ }
+ for (final String name : files.keySet())
+ appendFile(chosenSources.get(name), name);
+
+ zos.close();
+ }
+
+ private void scanJar(final File jarPath) throws IOException {
+ final ZipFile zf = new ZipFile(jarPath);
+ final Enumeration<? extends ZipEntry> e = zf.entries();
+ while (e.hasMoreElements())
+ chosenSources.put(e.nextElement().getName(), jarPath);
+ zf.close();
+ }
+
+ private void scanDirectory(final File rootPath, final File dirPath,
+ final String pfx) throws IOException {
+ final File[] entries = dirPath.listFiles();
+ if (entries == null)
+ return;
+ for (final File e : entries) {
+ if (e.getName().equals(".") || e.getName().equals(".."))
+ continue;
+
+ if (e.isDirectory())
+ scanDirectory(rootPath, e, pfx + e.getName() + "/");
+ else
+ chosenSources.put(pfx + e.getName(), rootPath);
+ }
+ }
+
+ private void appendJar(final File jarPath) throws IOException {
+ final ZipFile zf = new ZipFile(jarPath);
+ final Enumeration<? extends ZipEntry> e = zf.entries();
+ while (e.hasMoreElements()) {
+ final ZipEntry ze = e.nextElement();
+ final String name = ze.getName();
+ if (chosenSources.get(name) == jarPath)
+ appendEntry(name, ze.getSize(), ze.getTime(), zf
+ .getInputStream(ze));
+ }
+ zf.close();
+ }
+
+ private void appendDirectory(final File rootDir, final File dirPath,
+ final String pfx) throws IOException {
+ final File[] entries = dirPath.listFiles();
+ if (entries == null)
+ return;
+ for (final File e : entries) {
+ if (e.getName().equals(".") || e.getName().equals(".."))
+ continue;
+
+ if (e.isDirectory())
+ appendDirectory(rootDir, e, pfx + e.getName() + "/");
+ else if (chosenSources.get(pfx + e.getName()) == rootDir)
+ appendFile(e, pfx + e.getName());
+ }
+ }
+
+ private void appendFile(final File path, final String name)
+ throws IOException {
+ final long len = path.length();
+ final InputStream is = new FileInputStream(path);
+ appendEntry(name, len, creationTime, is);
+ }
+
+ private void appendEntry(final String name, final long len,
+ final long time, final InputStream is) throws IOException {
+ final ZipEntry ze = new ZipEntry(name);
+ ze.setSize(len);
+ ze.setTime(time);
+ zos.putNextEntry(ze);
+ try {
+ final byte[] buf = new byte[4096];
+ int n;
+ while ((n = is.read(buf)) >= 0)
+ zos.write(buf, 0, n);
+ } finally {
+ is.close();
+ }
+ zos.closeEntry();
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
new file mode 100644
index 0000000000..8949cbce6d
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/MakeCacheTree.java
@@ -0,0 +1,74 @@
+/*
+ * 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.pgm.debug;
+
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheTree;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+class MakeCacheTree extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final DirCache cache = DirCache.read(db);
+ final DirCacheTree tree = cache.getCacheTree(true);
+ show(tree);
+ }
+
+ private void show(final DirCacheTree tree) {
+ out.print("\"");
+ out.print(tree.getPathString());
+ out.print("\"");
+ out.print(": ");
+ out.print(tree.getEntrySpan());
+ out.print(" entries");
+ out.print(", ");
+ out.print(tree.getChildCount());
+ out.print(" children");
+ out.println();
+
+ for (int i = 0; i < tree.getChildCount(); i++)
+ show(tree.getChild(i));
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
new file mode 100644
index 0000000000..b0c1c77fdb
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ReadDirCache.java
@@ -0,0 +1,60 @@
+/*
+ * 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.pgm.debug;
+
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+class ReadDirCache extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final int cnt = 100;
+ final long start = System.currentTimeMillis();
+ for (int i = 0; i < cnt; i++)
+ DirCache.read(db);
+ final long end = System.currentTimeMillis();
+ out.println(" average " + ((end - start) / cnt) + " ms/read");
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
new file mode 100644
index 0000000000..50b889849e
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/RebuildCommitGraph.java
@@ -0,0 +1,313 @@
+/*
+ * 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.pgm.debug;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Map;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.errors.ObjectWritingException;
+import org.eclipse.jgit.lib.Commit;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.LockFile;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectWriter;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.ProgressMonitor;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefWriter;
+import org.eclipse.jgit.lib.TextProgressMonitor;
+import org.eclipse.jgit.lib.Tree;
+import org.eclipse.jgit.pgm.TextBuiltin;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+/**
+ * Recreates a repository from another one's commit graph.
+ * <p>
+ * <b>Do not run this on a repository unless you want to destroy it.</b>
+ * <p>
+ * To create the input files, in the source repository use:
+ *
+ * <pre>
+ * git for-each-ref &gt;in.refs
+ * git log --all '--pretty=format:%H %ct %P' &gt;in.dag
+ * </pre>
+ * <p>
+ * Run the rebuild in either an empty repository, or a clone of the source. Any
+ * missing commits (which might be the entire graph) will be created. All refs
+ * will be modified to match the input exactly, which means some refs may be
+ * deleted from the current repository.
+ * <p>
+ */
+class RebuildCommitGraph extends TextBuiltin {
+ private final String REALLY = "--destroy-this-repository";
+
+ @Option(name = REALLY, usage = "approve destruction of repository")
+ boolean really;
+
+ @Argument(index = 0, required = true, metaVar = "REFS", usage = "for-each-ref output")
+ File refList;
+
+ @Argument(index = 1, required = true, metaVar = "DAG", usage = "log --all '--pretty=format:%H %ct %P' output")
+ File graph;
+
+ private final ProgressMonitor pm = new TextProgressMonitor();
+
+ private Map<ObjectId, ObjectId> rewrites = new HashMap<ObjectId, ObjectId>();
+
+ @Override
+ protected void run() throws Exception {
+ if (!really && !db.getAllRefs().isEmpty()) {
+ final StringBuilder m = new StringBuilder();
+ m.append("fatal: ");
+ m.append("This program will destroy the repository:");
+ m.append("\n");
+ m.append("fatal:\n");
+ m.append("fatal: ");
+ m.append(db.getDirectory().getAbsolutePath());
+ m.append("\n");
+ m.append("fatal:\n");
+ m.append("fatal: ");
+ m.append("To continue, add ");
+ m.append(REALLY);
+ m.append(" to the command line");
+ m.append("\n");
+ m.append("fatal:");
+ System.err.println(m);
+ throw die("Need approval to destroy current repository");
+ }
+ if (!refList.isFile())
+ throw die("no such file: " + refList.getPath());
+ if (!graph.isFile())
+ throw die("no such file: " + graph.getPath());
+
+ recreateCommitGraph();
+ detachHead();
+ deleteAllRefs();
+ recreateRefs();
+ }
+
+ private void recreateCommitGraph() throws IOException {
+ final RevWalk rw = new RevWalk(db);
+ final Map<ObjectId, ToRewrite> toRewrite = new HashMap<ObjectId, ToRewrite>();
+ List<ToRewrite> queue = new ArrayList<ToRewrite>();
+ final BufferedReader br = new BufferedReader(new InputStreamReader(
+ new FileInputStream(graph), Constants.CHARSET));
+ try {
+ String line;
+ while ((line = br.readLine()) != null) {
+ final String[] parts = line.split("[ \t]{1,}");
+ final ObjectId oldId = ObjectId.fromString(parts[0]);
+ try {
+ rw.parseCommit(oldId);
+ // We have it already. Don't rewrite it.
+ continue;
+ } catch (MissingObjectException mue) {
+ // Fall through and rewrite it.
+ }
+
+ final long time = Long.parseLong(parts[1]) * 1000L;
+ final ObjectId[] parents = new ObjectId[parts.length - 2];
+ for (int i = 0; i < parents.length; i++) {
+ parents[i] = ObjectId.fromString(parts[2 + i]);
+ }
+
+ final ToRewrite t = new ToRewrite(oldId, time, parents);
+ toRewrite.put(oldId, t);
+ queue.add(t);
+ }
+ } finally {
+ br.close();
+ }
+
+ pm.beginTask("Rewriting commits", queue.size());
+ final ObjectWriter ow = new ObjectWriter(db);
+ final ObjectId emptyTree = ow.writeTree(new Tree(db));
+ final PersonIdent me = new PersonIdent("jgit rebuild-commitgraph",
+ "rebuild-commitgraph@localhost");
+ while (!queue.isEmpty()) {
+ final ListIterator<ToRewrite> itr = queue
+ .listIterator(queue.size());
+ queue = new ArrayList<ToRewrite>();
+ REWRITE: while (itr.hasPrevious()) {
+ final ToRewrite t = itr.previous();
+ final ObjectId[] newParents = new ObjectId[t.oldParents.length];
+ for (int k = 0; k < t.oldParents.length; k++) {
+ final ToRewrite p = toRewrite.get(t.oldParents[k]);
+ if (p != null) {
+ if (p.newId == null) {
+ // Must defer until after the parent is rewritten.
+ queue.add(t);
+ continue REWRITE;
+ } else {
+ newParents[k] = p.newId;
+ }
+ } else {
+ // We have the old parent object. Use it.
+ //
+ newParents[k] = t.oldParents[k];
+ }
+ }
+
+ final Commit newc = new Commit(db);
+ newc.setTreeId(emptyTree);
+ newc.setAuthor(new PersonIdent(me, new Date(t.commitTime)));
+ newc.setCommitter(newc.getAuthor());
+ newc.setParentIds(newParents);
+ newc.setMessage("ORIGINAL " + t.oldId.name() + "\n");
+ t.newId = ow.writeCommit(newc);
+ rewrites.put(t.oldId, t.newId);
+ pm.update(1);
+ }
+ }
+ pm.endTask();
+ }
+
+ private static class ToRewrite {
+ final ObjectId oldId;
+
+ final long commitTime;
+
+ final ObjectId[] oldParents;
+
+ ObjectId newId;
+
+ ToRewrite(final ObjectId o, final long t, final ObjectId[] p) {
+ oldId = o;
+ commitTime = t;
+ oldParents = p;
+ }
+ }
+
+ private void detachHead() throws IOException {
+ final String head = db.getFullBranch();
+ final ObjectId id = db.resolve(Constants.HEAD);
+ if (!ObjectId.isId(head) && id != null) {
+ final LockFile lf;
+ lf = new LockFile(new File(db.getDirectory(), Constants.HEAD));
+ if (!lf.lock())
+ throw new IOException("Cannot lock HEAD");
+ lf.write(id);
+ if (!lf.commit())
+ throw new IOException("Cannot deatch HEAD");
+ }
+ }
+
+ private void deleteAllRefs() throws Exception {
+ final RevWalk rw = new RevWalk(db);
+ for (final Ref r : db.getAllRefs().values()) {
+ if (Constants.HEAD.equals(r.getName()))
+ continue;
+ final RefUpdate u = db.updateRef(r.getName());
+ u.setForceUpdate(true);
+ u.delete(rw);
+ }
+ }
+
+ private void recreateRefs() throws Exception {
+ final Map<String, Ref> refs = computeNewRefs();
+ new RefWriter(refs.values()) {
+ @Override
+ protected void writeFile(final String name, final byte[] content)
+ throws IOException {
+ final File file = new File(db.getDirectory(), name);
+ final LockFile lck = new LockFile(file);
+ if (!lck.lock())
+ throw new ObjectWritingException("Can't write " + file);
+ try {
+ lck.write(content);
+ } catch (IOException ioe) {
+ throw new ObjectWritingException("Can't write " + file);
+ }
+ if (!lck.commit())
+ throw new ObjectWritingException("Can't write " + file);
+ }
+ }.writePackedRefs();
+ }
+
+ private Map<String, Ref> computeNewRefs() throws IOException {
+ final RevWalk rw = new RevWalk(db);
+ final Map<String, Ref> refs = new HashMap<String, Ref>();
+ final BufferedReader br = new BufferedReader(new InputStreamReader(
+ new FileInputStream(refList), Constants.CHARSET));
+ try {
+ String line;
+ while ((line = br.readLine()) != null) {
+ final String[] parts = line.split("[ \t]{1,}");
+ final ObjectId origId = ObjectId.fromString(parts[0]);
+ final String type = parts[1];
+ final String name = parts[2];
+
+ ObjectId id = rewrites.get(origId);
+ if (id == null)
+ id = origId;
+ try {
+ rw.parseAny(id);
+ } catch (MissingObjectException mue) {
+ if (!Constants.TYPE_COMMIT.equals(type)) {
+ System.err.println("skipping " + type + " " + name);
+ continue;
+ }
+ throw new MissingObjectException(id, type);
+ }
+ refs.put(name, new Ref(Ref.Storage.PACKED, name, id));
+ }
+ } finally {
+ br.close();
+ }
+ return refs;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
new file mode 100644
index 0000000000..29cdc98a83
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCacheTree.java
@@ -0,0 +1,76 @@
+/*
+ * 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.pgm.debug;
+
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheTree;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+class ShowCacheTree extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final DirCache cache = DirCache.read(db);
+ final DirCacheTree tree = cache.getCacheTree(false);
+ if (tree == null)
+ throw die("no 'TREE' section in index");
+ show(tree);
+ }
+
+ private void show(final DirCacheTree tree) {
+ out.print("\"");
+ out.print(tree.getPathString());
+ out.print("\"");
+ out.print(": ");
+ out.print(tree.getEntrySpan());
+ out.print(" entries");
+ out.print(", ");
+ out.print(tree.getChildCount());
+ out.print(" children");
+ out.println();
+
+ for (int i = 0; i < tree.getChildCount(); i++)
+ show(tree.getChild(i));
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java
new file mode 100644
index 0000000000..063cab5acf
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowCommands.java
@@ -0,0 +1,121 @@
+/*
+ * 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.pgm.debug;
+
+import java.net.URL;
+
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.pgm.Command;
+import org.eclipse.jgit.pgm.CommandCatalog;
+import org.eclipse.jgit.pgm.CommandRef;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+@Command(usage = "Display a list of all registered jgit commands")
+class ShowCommands extends TextBuiltin {
+ @Option(name = "--pretty", usage = "alter the detail shown")
+ private Format pretty = Format.USAGE;
+
+ @Override
+ protected void run() throws Exception {
+ final CommandRef[] list = CommandCatalog.all();
+
+ int width = 0;
+ for (final CommandRef c : list)
+ width = Math.max(width, c.getName().length());
+ width += 2;
+
+ for (final CommandRef c : list) {
+ System.err.print(c.isCommon() ? '*' : ' ');
+ System.err.print(' ');
+
+ System.err.print(c.getName());
+ for (int i = c.getName().length(); i < width; i++)
+ System.err.print(' ');
+
+ pretty.print(c);
+ System.err.println();
+ }
+ System.err.println();
+ }
+
+ static enum Format {
+ /** */
+ USAGE {
+ void print(final CommandRef c) {
+ System.err.print(c.getUsage());
+ }
+ },
+
+ /** */
+ CLASSES {
+ void print(final CommandRef c) {
+ System.err.print(c.getImplementationClassName());
+ }
+ },
+
+ /** */
+ URLS {
+ void print(final CommandRef c) {
+ final ClassLoader ldr = c.getImplementationClassLoader();
+
+ String cn = c.getImplementationClassName();
+ cn = cn.replace('.', '/') + ".class";
+
+ final URL url = ldr.getResource(cn);
+ if (url == null) {
+ System.err.print("!! NOT FOUND !!");
+ return;
+ }
+
+ String rn = url.toExternalForm();
+ if (rn.endsWith(cn))
+ rn = rn.substring(0, rn.length() - cn.length());
+
+ System.err.print(rn);
+ }
+ };
+
+ abstract void print(CommandRef c);
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
new file mode 100644
index 0000000000..854596c97b
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/ShowDirCache.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2008, Google Inc.
+ * Copyright (C) 2008, Jonas Fonseca <fonseca@diku.dk>
+ * 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.pgm.debug;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheEntry;
+import org.eclipse.jgit.lib.FileMode;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+class ShowDirCache extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final SimpleDateFormat fmt;
+ fmt = new SimpleDateFormat("yyyyMMdd,HHmmss.SSS");
+
+ final DirCache cache = DirCache.read(db);
+ for (int i = 0; i < cache.getEntryCount(); i++) {
+ final DirCacheEntry ent = cache.getEntry(i);
+ final FileMode mode = FileMode.fromBits(ent.getRawMode());
+ final int len = ent.getLength();
+ final Date mtime = new Date(ent.getLastModified());
+
+ out.print(mode);
+ out.format(" %6d", len);
+ out.print(' ');
+ out.print(fmt.format(mtime));
+ out.print(' ');
+ out.print(ent.getObjectId().name());
+ out.print('\t');
+ out.print(ent.getPathString());
+ out.println();
+ }
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
new file mode 100644
index 0000000000..54301dd041
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/debug/WriteDirCache.java
@@ -0,0 +1,61 @@
+/*
+ * 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.pgm.debug;
+
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+class WriteDirCache extends TextBuiltin {
+ @Override
+ protected void run() throws Exception {
+ final DirCache cache = DirCache.read(db);
+ if (!cache.lock())
+ throw die("failed to lock index");
+ cache.read();
+ cache.write();
+ if (!cache.commit())
+ throw die("failed to commit index");
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
new file mode 100644
index 0000000000..c31676d72f
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/AbstractTreeIteratorHandler.java
@@ -0,0 +1,143 @@
+/*
+ * Copyright (C) 2008-2009, 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.pgm.opt;
+
+import java.io.File;
+import java.io.IOException;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.dircache.DirCache;
+import org.eclipse.jgit.dircache.DirCacheIterator;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.WindowCursor;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+import org.eclipse.jgit.treewalk.CanonicalTreeParser;
+import org.eclipse.jgit.treewalk.FileTreeIterator;
+
+/**
+ * Custom argument handler {@link AbstractTreeIterator} from string values.
+ * <p>
+ * Assumes the parser has been initialized with a Repository.
+ */
+public class AbstractTreeIteratorHandler extends
+ OptionHandler<AbstractTreeIterator> {
+ private final org.eclipse.jgit.pgm.opt.CmdLineParser clp;
+
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public AbstractTreeIteratorHandler(final CmdLineParser parser,
+ final OptionDef option,
+ final Setter<? super AbstractTreeIterator> setter) {
+ super(parser, option, setter);
+ clp = (org.eclipse.jgit.pgm.opt.CmdLineParser) parser;
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ final String name = params.getParameter(0);
+
+ if (new File(name).isDirectory()) {
+ setter.addValue(new FileTreeIterator(new File(name)));
+ return 1;
+ }
+
+ if (new File(name).isFile()) {
+ final DirCache dirc;
+ try {
+ dirc = DirCache.read(new File(name));
+ } catch (IOException e) {
+ throw new CmdLineException(name + " is not an index file", e);
+ }
+ setter.addValue(new DirCacheIterator(dirc));
+ return 1;
+ }
+
+ final ObjectId id;
+ try {
+ id = clp.getRepository().resolve(name);
+ } catch (IOException e) {
+ throw new CmdLineException(e.getMessage());
+ }
+ if (id == null)
+ throw new CmdLineException(name + " is not a tree");
+
+ final CanonicalTreeParser p = new CanonicalTreeParser();
+ final WindowCursor curs = new WindowCursor();
+ try {
+ p.reset(clp.getRepository(), clp.getRevWalk().parseTree(id), curs);
+ } catch (MissingObjectException e) {
+ throw new CmdLineException(name + " is not a tree");
+ } catch (IncorrectObjectTypeException e) {
+ throw new CmdLineException(name + " is not a tree");
+ } catch (IOException e) {
+ throw new CmdLineException("cannot read " + name + ": "
+ + e.getMessage());
+ } finally {
+ curs.release();
+ }
+
+ setter.addValue(p);
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "tree-ish";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/CmdLineParser.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/CmdLineParser.java
new file mode 100644
index 0000000000..a126fb1d85
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/CmdLineParser.java
@@ -0,0 +1,177 @@
+/*
+ * 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.pgm.opt;
+
+import java.util.ArrayList;
+
+import org.kohsuke.args4j.Argument;
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.IllegalAnnotationError;
+import org.kohsuke.args4j.Option;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.pgm.TextBuiltin;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevTree;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.RefSpec;
+import org.eclipse.jgit.treewalk.AbstractTreeIterator;
+
+/**
+ * Extended command line parser which handles --foo=value arguments.
+ * <p>
+ * The args4j package does not natively handle --foo=value and instead prefers
+ * to see --foo value on the command line. Many users are used to the GNU style
+ * --foo=value long option, so we convert from the GNU style format to the
+ * args4j style format prior to invoking args4j for parsing.
+ */
+public class CmdLineParser extends org.kohsuke.args4j.CmdLineParser {
+ static {
+ registerHandler(AbstractTreeIterator.class,
+ AbstractTreeIteratorHandler.class);
+ registerHandler(ObjectId.class, ObjectIdHandler.class);
+ registerHandler(RefSpec.class, RefSpecHandler.class);
+ registerHandler(RevCommit.class, RevCommitHandler.class);
+ registerHandler(RevTree.class, RevTreeHandler.class);
+ }
+
+ private final Repository db;
+
+ private RevWalk walk;
+
+ /**
+ * Creates a new command line owner that parses arguments/options and set
+ * them into the given object.
+ *
+ * @param bean
+ * instance of a class annotated by {@link Option} and
+ * {@link Argument}. this object will receive values.
+ *
+ * @throws IllegalAnnotationError
+ * if the option bean class is using args4j annotations
+ * incorrectly.
+ */
+ public CmdLineParser(final Object bean) {
+ this(bean, null);
+ }
+
+ /**
+ * Creates a new command line owner that parses arguments/options and set
+ * them into the given object.
+ *
+ * @param bean
+ * instance of a class annotated by {@link Option} and
+ * {@link Argument}. this object will receive values.
+ * @param repo
+ * repository this parser can translate options through.
+ * @throws IllegalAnnotationError
+ * if the option bean class is using args4j annotations
+ * incorrectly.
+ */
+ public CmdLineParser(final Object bean, Repository repo) {
+ super(bean);
+ if (repo == null && bean instanceof TextBuiltin)
+ repo = ((TextBuiltin) bean).getRepository();
+ this.db = repo;
+ }
+
+ @Override
+ public void parseArgument(final String... args) throws CmdLineException {
+ final ArrayList<String> tmp = new ArrayList<String>(args.length);
+ for (int argi = 0; argi < args.length; argi++) {
+ final String str = args[argi];
+ if (str.equals("--")) {
+ while (argi < args.length)
+ tmp.add(args[argi++]);
+ break;
+ }
+
+ if (str.startsWith("--")) {
+ final int eq = str.indexOf('=');
+ if (eq > 0) {
+ tmp.add(str.substring(0, eq));
+ tmp.add(str.substring(eq + 1));
+ continue;
+ }
+ }
+
+ tmp.add(str);
+ }
+
+ super.parseArgument(tmp.toArray(new String[tmp.size()]));
+ }
+
+ /**
+ * Get the repository this parser translates values through.
+ *
+ * @return the repository, if specified during construction.
+ */
+ public Repository getRepository() {
+ if (db == null)
+ throw new IllegalStateException("No Git repository configured.");
+ return db;
+ }
+
+ /**
+ * Get the revision walker used to support option parsing.
+ *
+ * @return the revision walk used by this option parser.
+ */
+ public RevWalk getRevWalk() {
+ if (walk == null)
+ walk = new RevWalk(getRepository());
+ return walk;
+ }
+
+ /**
+ * Get the revision walker used to support option parsing.
+ * <p>
+ * This method does not initialize the RevWalk and may return null.
+ *
+ * @return the revision walk used by this option parser, or null.
+ */
+ public RevWalk getRevWalkGently() {
+ return walk;
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java
new file mode 100644
index 0000000000..d3f460c89d
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/ObjectIdHandler.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2009, 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.pgm.opt;
+
+import java.io.IOException;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.lib.ObjectId;
+
+/**
+ * Custom argument handler {@link ObjectId} from string values.
+ * <p>
+ * Assumes the parser has been initialized with a Repository.
+ */
+public class ObjectIdHandler extends OptionHandler<ObjectId> {
+ private final org.eclipse.jgit.pgm.opt.CmdLineParser clp;
+
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public ObjectIdHandler(final CmdLineParser parser, final OptionDef option,
+ final Setter<? super ObjectId> setter) {
+ super(parser, option, setter);
+ clp = (org.eclipse.jgit.pgm.opt.CmdLineParser) parser;
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ final String name = params.getParameter(0);
+ final ObjectId id;
+ try {
+ id = clp.getRepository().resolve(name);
+ } catch (IOException e) {
+ throw new CmdLineException(e.getMessage());
+ }
+ if (id != null) {
+ setter.addValue(id);
+ return 1;
+ }
+
+ throw new CmdLineException(name + " is not an object");
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "object";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java
new file mode 100644
index 0000000000..bebf3d9a7d
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/PathTreeFilterHandler.java
@@ -0,0 +1,108 @@
+/*
+ * 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.pgm.opt;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.Option;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.treewalk.filter.PathFilter;
+import org.eclipse.jgit.treewalk.filter.PathFilterGroup;
+import org.eclipse.jgit.treewalk.filter.TreeFilter;
+
+/**
+ * Create a {@link TreeFilter} to patch math names.
+ * <p>
+ * This handler consumes all arguments to the end of the command line, and is
+ * meant to be used on an {@link Option} of name "--".
+ */
+public class PathTreeFilterHandler extends OptionHandler<TreeFilter> {
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public PathTreeFilterHandler(final CmdLineParser parser,
+ final OptionDef option, final Setter<? super TreeFilter> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ final List<PathFilter> filters = new ArrayList<PathFilter>();
+ for (int idx = 0;; idx++) {
+ final String path;
+ try {
+ path = params.getParameter(idx);
+ } catch (CmdLineException cle) {
+ break;
+ }
+ filters.add(PathFilter.create(path));
+ }
+
+ if (filters.size() == 0)
+ return 0;
+ if (filters.size() == 1) {
+ setter.addValue(filters.get(0));
+ return 1;
+ }
+ setter.addValue(PathFilterGroup.create(filters));
+ return filters.size();
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "path ...";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java
new file mode 100644
index 0000000000..133c5f8db8
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RefSpecHandler.java
@@ -0,0 +1,84 @@
+/*
+ * 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.pgm.opt;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.transport.RefSpec;
+
+/**
+ * Custom argument handler {@link RefSpec} from string values.
+ * <p>
+ * Assumes the parser has been initialized with a Repository.
+ */
+public class RefSpecHandler extends OptionHandler<RefSpec> {
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public RefSpecHandler(final CmdLineParser parser, final OptionDef option,
+ final Setter<? super RefSpec> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ setter.addValue(new RefSpec(params.getParameter(0)));
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "refspec";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java
new file mode 100644
index 0000000000..01caaf2018
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevCommitHandler.java
@@ -0,0 +1,146 @@
+/*
+ * Copyright (C) 2009, 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.pgm.opt;
+
+import java.io.IOException;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevFlag;
+
+/**
+ * Custom argument handler {@link RevCommit} from string values.
+ * <p>
+ * Assumes the parser has been initialized with a Repository.
+ */
+public class RevCommitHandler extends OptionHandler<RevCommit> {
+ private final org.eclipse.jgit.pgm.opt.CmdLineParser clp;
+
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public RevCommitHandler(final CmdLineParser parser, final OptionDef option,
+ final Setter<? super RevCommit> setter) {
+ super(parser, option, setter);
+ clp = (org.eclipse.jgit.pgm.opt.CmdLineParser) parser;
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ String name = params.getParameter(0);
+
+ boolean interesting = true;
+ if (name.startsWith("^")) {
+ name = name.substring(1);
+ interesting = false;
+ }
+
+ final int dot2 = name.indexOf("..");
+ if (dot2 != -1) {
+ if (!option.isMultiValued())
+ throw new CmdLineException("Only one " + option.metaVar()
+ + " expected in " + name + "." + "");
+
+ final String left = name.substring(0, dot2);
+ final String right = name.substring(dot2 + 2);
+ addOne(left, false);
+ addOne(right, true);
+ return 1;
+ }
+
+ addOne(name, interesting);
+ return 1;
+ }
+
+ private void addOne(final String name, final boolean interesting)
+ throws CmdLineException {
+ final ObjectId id;
+ try {
+ id = clp.getRepository().resolve(name);
+ } catch (IOException e) {
+ throw new CmdLineException(e.getMessage());
+ }
+ if (id == null)
+ throw new CmdLineException(name + " is not a commit");
+
+ final RevCommit c;
+ try {
+ c = clp.getRevWalk().parseCommit(id);
+ } catch (MissingObjectException e) {
+ throw new CmdLineException(name + " is not a commit");
+ } catch (IncorrectObjectTypeException e) {
+ throw new CmdLineException(name + " is not a commit");
+ } catch (IOException e) {
+ throw new CmdLineException("cannot read " + name + ": "
+ + e.getMessage());
+ }
+
+ if (interesting)
+ c.remove(RevFlag.UNINTERESTING);
+ else
+ c.add(RevFlag.UNINTERESTING);
+
+ setter.addValue(c);
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "commit-ish";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java
new file mode 100644
index 0000000000..c564b9b011
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/RevTreeHandler.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (C) 2009, 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.pgm.opt;
+
+import java.io.IOException;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.revwalk.RevTree;
+
+/**
+ * Custom argument handler {@link RevTree} from string values.
+ * <p>
+ * Assumes the parser has been initialized with a Repository.
+ */
+public class RevTreeHandler extends OptionHandler<RevTree> {
+ private final org.eclipse.jgit.pgm.opt.CmdLineParser clp;
+
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public RevTreeHandler(final CmdLineParser parser, final OptionDef option,
+ final Setter<? super RevTree> setter) {
+ super(parser, option, setter);
+ clp = (org.eclipse.jgit.pgm.opt.CmdLineParser) parser;
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ final String name = params.getParameter(0);
+ final ObjectId id;
+ try {
+ id = clp.getRepository().resolve(name);
+ } catch (IOException e) {
+ throw new CmdLineException(e.getMessage());
+ }
+ if (id == null)
+ throw new CmdLineException(name + " is not a tree");
+
+ final RevTree c;
+ try {
+ c = clp.getRevWalk().parseTree(id);
+ } catch (MissingObjectException e) {
+ throw new CmdLineException(name + " is not a tree");
+ } catch (IncorrectObjectTypeException e) {
+ throw new CmdLineException(name + " is not a tree");
+ } catch (IOException e) {
+ throw new CmdLineException("cannot read " + name + ": "
+ + e.getMessage());
+ }
+ setter.addValue(c);
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "tree-ish";
+ }
+}
diff --git a/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java
new file mode 100644
index 0000000000..3378f38c19
--- /dev/null
+++ b/org.eclipse.jgit.pgm/src/org/eclipse/jgit/pgm/opt/SubcommandHandler.java
@@ -0,0 +1,100 @@
+/*
+ * 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.pgm.opt;
+
+import java.text.MessageFormat;
+
+import org.kohsuke.args4j.CmdLineException;
+import org.kohsuke.args4j.CmdLineParser;
+import org.kohsuke.args4j.OptionDef;
+import org.kohsuke.args4j.spi.OptionHandler;
+import org.kohsuke.args4j.spi.Parameters;
+import org.kohsuke.args4j.spi.Setter;
+import org.eclipse.jgit.pgm.CommandCatalog;
+import org.eclipse.jgit.pgm.CommandRef;
+import org.eclipse.jgit.pgm.TextBuiltin;
+
+/**
+ * Custom Argument handler for jgit command selection.
+ * <p>
+ * Translates a single argument string to a {@link TextBuiltin} instance which
+ * we can execute at runtime with the remaining arguments of the parser.
+ */
+public class SubcommandHandler extends OptionHandler<TextBuiltin> {
+ /**
+ * Create a new handler for the command name.
+ * <p>
+ * This constructor is used only by args4j.
+ *
+ * @param parser
+ * @param option
+ * @param setter
+ */
+ public SubcommandHandler(final CmdLineParser parser,
+ final OptionDef option, final Setter<? super TextBuiltin> setter) {
+ super(parser, option, setter);
+ }
+
+ @Override
+ public int parseArguments(final Parameters params) throws CmdLineException {
+ final String name = params.getParameter(0);
+ final CommandRef cr = CommandCatalog.get(name);
+ if (cr == null)
+ throw new CmdLineException(MessageFormat.format(
+ "{0} is not a jgit command", name));
+
+ // Force option parsing to stop. Everything after us should
+ // be arguments known only to this command and must not be
+ // recognized by the current parser.
+ //
+ owner.stopOptionParsing();
+ setter.addValue(cr.create());
+ return 1;
+ }
+
+ @Override
+ public String getDefaultMetaVariable() {
+ return "command";
+ }
+}