summaryrefslogtreecommitdiffstats
path: root/org.eclipse.jgit.pgm
diff options
context:
space:
mode:
authorGit Development Community <git@vger.kernel.org>2009-09-29 16:47:03 -0700
committerShawn O. Pearce <spearce@spearce.org>2009-09-29 16:47:03 -0700
commit1a6964c8274c50f0253db75f010d78ef0e739343 (patch)
treeca833cc7cf6fc8c7b9850dee258f3a356c790ffc /org.eclipse.jgit.pgm
downloadjgit-1a6964c8274c50f0253db75f010d78ef0e739343.tar.gz
jgit-1a6964c8274c50f0253db75f010d78ef0e739343.zip
Initial JGit contribution to eclipse.org
Per CQ 3448 this is the initial contribution of the JGit project to eclipse.org. It is derived from the historical JGit repository at commit 3a2dd9921c8a08740a9e02c421469e5b1a9e47cb. Signed-off-by: Shawn O. Pearce <spearce@spearce.org>
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";
+ }
+}