Merge "Adds a "revert change"-button to a submitted patchset." into stable
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 9b445b2..0984935 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -156,6 +156,10 @@
 `\^refs/heads/[a-z]\{1,8\}` matches all lower case branch names
 between 1 and 8 characters long.  Within a regular expression `.`
 is a wildcard matching any character, but may be escaped as `\.`.
+The link:http://www.brics.dk/automaton/[dk.brics.automaton library]
+is used for evaluation of regular expression access control
+rules. See the library documentation for details on this
+particular regular expression flavor.
 
 References can have the current user name automatically included,
 creating dynamic access controls that change to match the currently
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 59175b6..09b3f50 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -115,7 +115,9 @@
 with an OpenID that matches this list.  Only used if `auth.type`
 was set to OpenID (the default).
 +
-Patterns may be either a regular expression (start with `^` and
+Patterns may be either a
+link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
+Java regular expression (java.util.regex)] (start with `^` and
 end with `$`) or be a simple prefix (any other string).
 +
 By default, the list contains two values, `http://` and `https://`,
@@ -131,7 +133,9 @@
 the user account must only have OpenIDs which match at least one
 pattern from this list.
 +
-Patterns may be either a regular expression (start with `^` and
+Patterns may be either a
+link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
+Java regular expression (java.util.regex)] (start with `^` and
 end with `$`) or be a simple prefix (any other string).
 +
 By default, the list contains two values, `http://` and `https://`,
@@ -1855,10 +1859,12 @@
 
 [[trackingid.name.match]]trackingid.<name>.match::
 +
-A regular expression used to match the external tracking id part of the
-footer line. The match can result in several entries in the DB.
-If grouping is used in the regex the first group will be interpreted
-as the tracking id. Tracking ids > 20 char will be ignored.
+A link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
+Java regular expression (java.util.regex)] used to match the
+external tracking id part of the footer line. The match can
+result in several entries in the DB.  If grouping is used in the
+regex the first group will be interpreted as the tracking id.
+Tracking ids > 20 char will be ignored.
 +
 The configuration file parser eats one level of backslashes, so the
 character class `\s` requires `\\s` in the configuration file.  The
diff --git a/Documentation/config-sso.txt b/Documentation/config-sso.txt
index 064c4dd..37f5b05 100644
--- a/Documentation/config-sso.txt
+++ b/Documentation/config-sso.txt
@@ -34,8 +34,10 @@
 `Anonymous Users` and `Registered Users` groups, an account
 must only have OpenIDs which match at least one pattern from the
 `auth.trustedOpenID` list in `gerrit.config`.  Patterns may be
-either a regular expression (must start with `^` and end with `$`)
-or be a simple prefix (any other string).
+either a
+link:http://download.oracle.com/javase/6/docs/api/java/util/regex/Pattern.html[standard
+Java regular expression (java.util.regex)] (must start with `^`
+and end with `$`) or be a simple prefix (any other string).
 
 Out of the box Gerrit is configured to trust two patterns, which
 will match any OpenID provider on the Internet:
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 72d60ac..ba031db 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -101,7 +101,10 @@
 project:'PROJECT'::
 +
 Changes occuring in 'PROJECT'. If 'PROJECT' starts with `^` it
-matches project names by regular expression.
+matches project names by regular expression.  The
+link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for evaluation of such patterns.
+
 
 [[branch]]
 branch:'BRANCH'::
@@ -114,7 +117,9 @@
 'ref:refs/heads/refs/heads/master'.
 +
 If 'BRANCH' starts with `^` it matches branch names by regular
-expression patterns.
+expression patterns.  The
+link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for evaluation of such patterns.
 
 [[topic]]
 topic:'TOPIC'::
@@ -124,7 +129,9 @@
 all related changes in a series.
 +
 If 'TOPIC' starts with `^` it matches topic names by regular
-expression patterns.
+expression patterns.  The
+link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for evaluation of such patterns.
 
 [[ref]]
 ref:'REF'::
@@ -134,7 +141,9 @@
 must start with 'refs/'.
 +
 If 'REF' starts with `^` it matches reference names by regular
-expression patterns.
+expression patterns.  The
+link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for evaluation of such patterns.
 
 [[tr,bug]]
 tr:'ID', bug:'ID'::
@@ -164,6 +173,8 @@
 Matches any change where REGEX matches a file that was affected
 by the change.  The regular expression pattern must start with
 `^`.  For example, to match all XML files use `file:^.*\.xml$`.
+The link:http://www.brics.dk/automaton/[dk.brics.automaton
+library] is used for the evaluation of such patterns.
 +
 The `^` required at the beginning of the regular expression not only
 denotes a regular expression, but it also has the usual meaning of
diff --git a/ReleaseNotes/ReleaseNotes-2.1.7.txt b/ReleaseNotes/ReleaseNotes-2.1.7.txt
index 9f52170..29546d0 100644
--- a/ReleaseNotes/ReleaseNotes-2.1.7.txt
+++ b/ReleaseNotes/ReleaseNotes-2.1.7.txt
@@ -140,7 +140,7 @@
 Updated H2 Database to 1.2.147, PostgreSQL JDBC Client to 9.0-801,
 openid4java to 0.9.6, ANTLR to 3.2, GWT to 2.1.1, JSch to 0.1.44, Gson
 to 1.6, Apache Commons Net to 2.2, Apache Commons Pool to 1.5.5, JGit
-to 0.12.1.41-g4b4df4c, MINA SSHD to 0.5.1-r1095809.
+to 0.12.1.53-g5ec4977, MINA SSHD to 0.5.1-r1095809.
 
 Bug Fixes
 ---------
diff --git a/gerrit-antlr/.gitignore b/gerrit-antlr/.gitignore
new file mode 100644
index 0000000..903c6c8
--- /dev/null
+++ b/gerrit-antlr/.gitignore
@@ -0,0 +1,4 @@
+/target
+/.classpath
+/.project
+/.settings/org.maven.ide.eclipse.prefs
diff --git a/gerrit-antlr/.settings/org.eclipse.core.resources.prefs b/gerrit-antlr/.settings/org.eclipse.core.resources.prefs
new file mode 100644
index 0000000..82eb859
--- /dev/null
+++ b/gerrit-antlr/.settings/org.eclipse.core.resources.prefs
@@ -0,0 +1,3 @@
+#Tue Sep 02 16:59:24 PDT 2008
+eclipse.preferences.version=1
+encoding/<project>=UTF-8
diff --git a/gerrit-antlr/.settings/org.eclipse.core.runtime.prefs b/gerrit-antlr/.settings/org.eclipse.core.runtime.prefs
new file mode 100644
index 0000000..8667cfd
--- /dev/null
+++ b/gerrit-antlr/.settings/org.eclipse.core.runtime.prefs
@@ -0,0 +1,3 @@
+#Tue Sep 02 16:59:24 PDT 2008
+eclipse.preferences.version=1
+line.separator=\n
diff --git a/gerrit-antlr/.settings/org.eclipse.jdt.core.prefs b/gerrit-antlr/.settings/org.eclipse.jdt.core.prefs
new file mode 100644
index 0000000..134e606
--- /dev/null
+++ b/gerrit-antlr/.settings/org.eclipse.jdt.core.prefs
@@ -0,0 +1,328 @@
+#Thu May 19 09:55:53 PDT 2011
+eclipse.preferences.version=1
+org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6
+org.eclipse.jdt.core.compiler.compliance=1.6
+org.eclipse.jdt.core.compiler.problem.annotationSuperInterface=ignore
+org.eclipse.jdt.core.compiler.problem.autoboxing=ignore
+org.eclipse.jdt.core.compiler.problem.comparingIdentical=ignore
+org.eclipse.jdt.core.compiler.problem.deadCode=ignore
+org.eclipse.jdt.core.compiler.problem.deprecation=ignore
+org.eclipse.jdt.core.compiler.problem.deprecationInDeprecatedCode=disabled
+org.eclipse.jdt.core.compiler.problem.deprecationWhenOverridingDeprecatedMethod=disabled
+org.eclipse.jdt.core.compiler.problem.discouragedReference=ignore
+org.eclipse.jdt.core.compiler.problem.emptyStatement=ignore
+org.eclipse.jdt.core.compiler.problem.fallthroughCase=ignore
+org.eclipse.jdt.core.compiler.problem.fatalOptionalError=disabled
+org.eclipse.jdt.core.compiler.problem.fieldHiding=ignore
+org.eclipse.jdt.core.compiler.problem.finalParameterBound=ignore
+org.eclipse.jdt.core.compiler.problem.finallyBlockNotCompletingNormally=ignore
+org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
+org.eclipse.jdt.core.compiler.problem.hiddenCatchBlock=ignore
+org.eclipse.jdt.core.compiler.problem.incompatibleNonInheritedInterfaceMethod=ignore
+org.eclipse.jdt.core.compiler.problem.incompleteEnumSwitch=ignore
+org.eclipse.jdt.core.compiler.problem.indirectStaticAccess=ignore
+org.eclipse.jdt.core.compiler.problem.localVariableHiding=ignore
+org.eclipse.jdt.core.compiler.problem.methodWithConstructorName=ignore
+org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=ignore
+org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
+org.eclipse.jdt.core.compiler.problem.missingSerialVersion=ignore
+org.eclipse.jdt.core.compiler.problem.missingSynchronizedOnInheritedMethod=ignore
+org.eclipse.jdt.core.compiler.problem.noEffectAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.noImplicitStringConversion=ignore
+org.eclipse.jdt.core.compiler.problem.nonExternalizedStringLiteral=ignore
+org.eclipse.jdt.core.compiler.problem.nullReference=ignore
+org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=ignore
+org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
+org.eclipse.jdt.core.compiler.problem.rawTypeReference=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
+org.eclipse.jdt.core.compiler.problem.specialParameterHidingField=disabled
+org.eclipse.jdt.core.compiler.problem.staticAccessReceiver=ignore
+org.eclipse.jdt.core.compiler.problem.suppressOptionalErrors=disabled
+org.eclipse.jdt.core.compiler.problem.suppressWarnings=enabled
+org.eclipse.jdt.core.compiler.problem.syntheticAccessEmulation=ignore
+org.eclipse.jdt.core.compiler.problem.typeParameterHiding=ignore
+org.eclipse.jdt.core.compiler.problem.uncheckedTypeOperation=ignore
+org.eclipse.jdt.core.compiler.problem.undocumentedEmptyBlock=ignore
+org.eclipse.jdt.core.compiler.problem.unhandledWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryElse=ignore
+org.eclipse.jdt.core.compiler.problem.unnecessaryTypeCheck=ignore
+org.eclipse.jdt.core.compiler.problem.unqualifiedFieldAccess=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownException=ignore
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionExemptExceptionAndThrowable=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedDeclaredThrownExceptionWhenOverriding=disabled
+org.eclipse.jdt.core.compiler.problem.unusedImport=ignore
+org.eclipse.jdt.core.compiler.problem.unusedLabel=ignore
+org.eclipse.jdt.core.compiler.problem.unusedLocal=ignore
+org.eclipse.jdt.core.compiler.problem.unusedObjectAllocation=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameter=ignore
+org.eclipse.jdt.core.compiler.problem.unusedParameterIncludeDocCommentReference=enabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenImplementingAbstract=disabled
+org.eclipse.jdt.core.compiler.problem.unusedParameterWhenOverridingConcrete=disabled
+org.eclipse.jdt.core.compiler.problem.unusedPrivateMember=ignore
+org.eclipse.jdt.core.compiler.problem.unusedWarningToken=ignore
+org.eclipse.jdt.core.compiler.problem.varargsArgumentNeedCast=ignore
+org.eclipse.jdt.core.compiler.source=1.6
+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=16
+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=16
+org.eclipse.jdt.core.formatter.alignment_for_enum_constants=16
+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=0
+org.eclipse.jdt.core.formatter.blank_lines_before_first_class_body_declaration=0
+org.eclipse.jdt.core.formatter.blank_lines_before_imports=0
+org.eclipse.jdt.core.formatter.blank_lines_before_member_type=0
+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_import_groups=1
+org.eclipse.jdt.core.formatter.blank_lines_between_type_declarations=2
+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_in_block_comment=false
+org.eclipse.jdt.core.formatter.comment.clear_blank_lines_in_javadoc_comment=false
+org.eclipse.jdt.core.formatter.comment.format_block_comments=true
+org.eclipse.jdt.core.formatter.comment.format_header=true
+org.eclipse.jdt.core.formatter.comment.format_html=true
+org.eclipse.jdt.core.formatter.comment.format_javadoc_comments=true
+org.eclipse.jdt.core.formatter.comment.format_line_comments=true
+org.eclipse.jdt.core.formatter.comment.format_source_code=true
+org.eclipse.jdt.core.formatter.comment.indent_parameter_description=false
+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=do not 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=true
+org.eclipse.jdt.core.formatter.indentation.size=4
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_local_variable=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_member=insert
+org.eclipse.jdt.core.formatter.insert_new_line_after_annotation_on_parameter=do not 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=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=do not 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=do not 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=do not 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=do not 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_parenthesized_expression_in_throw=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.join_lines_in_comments=true
+org.eclipse.jdt.core.formatter.join_wrapped_lines=true
+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=true
+org.eclipse.jdt.core.formatter.keep_then_statement_on_same_line=false
+org.eclipse.jdt.core.formatter.lineSplit=80
+org.eclipse.jdt.core.formatter.never_indent_block_comments_on_first_column=false
+org.eclipse.jdt.core.formatter.never_indent_line_comments_on_first_column=false
+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=3
+org.eclipse.jdt.core.formatter.put_empty_statement_on_new_line=false
+org.eclipse.jdt.core.formatter.tabulation.char=space
+org.eclipse.jdt.core.formatter.tabulation.size=2
+org.eclipse.jdt.core.formatter.use_tabs_only_for_leading_indentations=false
+org.eclipse.jdt.core.formatter.wrap_before_binary_operator=true
diff --git a/gerrit-antlr/.settings/org.eclipse.jdt.ui.prefs b/gerrit-antlr/.settings/org.eclipse.jdt.ui.prefs
new file mode 100644
index 0000000..d4218a5
--- /dev/null
+++ b/gerrit-antlr/.settings/org.eclipse.jdt.ui.prefs
@@ -0,0 +1,61 @@
+#Wed Jul 29 11:31:38 PDT 2009
+eclipse.preferences.version=1
+editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
+formatter_profile=_Google Format
+formatter_settings_version=11
+org.eclipse.jdt.ui.ignorelowercasenames=true
+org.eclipse.jdt.ui.importorder=com.google;com;junit;net;org;java;javax;
+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" standalone\="no"?><templates/>
+sp_cleanup.add_default_serial_version_id=true
+sp_cleanup.add_generated_serial_version_id=false
+sp_cleanup.add_missing_annotations=false
+sp_cleanup.add_missing_deprecated_annotations=true
+sp_cleanup.add_missing_methods=false
+sp_cleanup.add_missing_nls_tags=false
+sp_cleanup.add_missing_override_annotations=true
+sp_cleanup.add_serial_version_id=false
+sp_cleanup.always_use_blocks=true
+sp_cleanup.always_use_parentheses_in_expressions=false
+sp_cleanup.always_use_this_for_non_static_field_access=false
+sp_cleanup.always_use_this_for_non_static_method_access=false
+sp_cleanup.convert_to_enhanced_for_loop=false
+sp_cleanup.correct_indentation=false
+sp_cleanup.format_source_code=false
+sp_cleanup.format_source_code_changes_only=false
+sp_cleanup.make_local_variable_final=true
+sp_cleanup.make_parameters_final=true
+sp_cleanup.make_private_fields_final=true
+sp_cleanup.make_type_abstract_if_missing_method=false
+sp_cleanup.make_variable_declarations_final=false
+sp_cleanup.never_use_blocks=false
+sp_cleanup.never_use_parentheses_in_expressions=true
+sp_cleanup.on_save_use_additional_actions=true
+sp_cleanup.organize_imports=false
+sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
+sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
+sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
+sp_cleanup.remove_private_constructors=true
+sp_cleanup.remove_trailing_whitespaces=true
+sp_cleanup.remove_trailing_whitespaces_all=true
+sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
+sp_cleanup.remove_unnecessary_casts=false
+sp_cleanup.remove_unnecessary_nls_tags=false
+sp_cleanup.remove_unused_imports=false
+sp_cleanup.remove_unused_local_variables=false
+sp_cleanup.remove_unused_private_fields=true
+sp_cleanup.remove_unused_private_members=false
+sp_cleanup.remove_unused_private_methods=true
+sp_cleanup.remove_unused_private_types=true
+sp_cleanup.sort_members=false
+sp_cleanup.sort_members_all=false
+sp_cleanup.use_blocks=false
+sp_cleanup.use_blocks_only_for_return_and_throw=false
+sp_cleanup.use_parentheses_in_expressions=false
+sp_cleanup.use_this_for_non_static_field_access=false
+sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
+sp_cleanup.use_this_for_non_static_method_access=false
+sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true
diff --git a/gerrit-antlr/pom.xml b/gerrit-antlr/pom.xml
new file mode 100644
index 0000000..139cb30
--- /dev/null
+++ b/gerrit-antlr/pom.xml
@@ -0,0 +1,57 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+Copyright (C) 2009 The Android Open Source Project
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.google.gerrit</groupId>
+    <artifactId>gerrit-parent</artifactId>
+    <version>2.1-SNAPSHOT</version>
+  </parent>
+
+  <artifactId>gerrit-antlr</artifactId>
+  <name>Gerrit Code Review - ANTLR</name>
+
+  <description>
+    ANTLR generated sources
+  </description>
+
+  <dependencies>
+    <dependency>
+      <groupId>org.antlr</groupId>
+      <artifactId>antlr</artifactId>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.antlr</groupId>
+        <artifactId>antlr3-maven-plugin</artifactId>
+        <executions>
+          <execution>
+            <goals>
+              <goal>antlr</goal>
+            </goals>
+          </execution>
+        </executions>
+      </plugin>
+    </plugins>
+  </build>
+</project>
diff --git a/gerrit-server/src/main/antlr3/com/google/gerrit/server/query/Query.g b/gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g
similarity index 100%
rename from gerrit-server/src/main/antlr3/com/google/gerrit/server/query/Query.g
rename to gerrit-antlr/src/main/antlr3/com/google/gerrit/server/query/Query.g
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryParseException.java b/gerrit-antlr/src/main/java/com/google/gerrit/server/query/QueryParseException.java
similarity index 100%
rename from gerrit-server/src/main/java/com/google/gerrit/server/query/QueryParseException.java
rename to gerrit-antlr/src/main/java/com/google/gerrit/server/query/QueryParseException.java
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
index 4d362fe..621f52d 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeDetailService.java
@@ -15,6 +15,7 @@
 package com.google.gerrit.common.data;
 
 import com.google.gerrit.common.auth.SignInRequired;
+import com.google.gerrit.reviewdb.AccountDiffPreference;
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.PatchSet;
 import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -28,7 +29,8 @@
 
   void includedInDetail(Change.Id id, AsyncCallback<IncludedInDetail> callback);
 
-  void patchSetDetail(PatchSet.Id key, AsyncCallback<PatchSetDetail> callback);
+  void patchSetDetail(PatchSet.Id keyA, PatchSet.Id keyB,
+      AccountDiffPreference diffPrefs, AsyncCallback<PatchSetDetail> callback);
 
   @SignInRequired
   void patchSetPublishDetail(PatchSet.Id key,
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java
index 1cf9592..937bbd4 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/GitwebLink.java
@@ -40,8 +40,8 @@
     ParamertizedString pattern = new ParamertizedString(type.getRevision());
 
     final Map<String, String> p = new HashMap<String, String>();
-    p.put("project", URL.encodeComponent(project.get()));
-    p.put("commit", URL.encodeComponent(ps.getRevision().get()));
+    p.put("project", URL.encodeQueryString(project.get()));
+    p.put("commit", URL.encodeQueryString(ps.getRevision().get()));
     return baseUrl + pattern.replace(p);
   }
 
@@ -49,7 +49,7 @@
     ParamertizedString pattern = new ParamertizedString(type.getProject());
 
     final Map<String, String> p = new HashMap<String, String>();
-    p.put("project", URL.encodeComponent(project.get()));
+    p.put("project", URL.encodeQueryString(project.get()));
     return baseUrl + pattern.replace(p);
   }
 
@@ -57,8 +57,8 @@
     ParamertizedString pattern = new ParamertizedString(type.getBranch());
 
     final Map<String, String> p = new HashMap<String, String>();
-    p.put("project", URL.encodeComponent(branch.getParentKey().get()));
-    p.put("branch", URL.encodeComponent(branch.get()));
+    p.put("project", URL.encodeQueryString(branch.getParentKey().get()));
+    p.put("branch", URL.encodeQueryString(branch.get()));
     return baseUrl + pattern.replace(p);
   }
 }
diff --git a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java b/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
index f054a2b..1834cdf 100644
--- a/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
+++ b/gerrit-gwtdebug/src/main/java/com/google/gerrit/gwtdebug/GerritDebugLauncher.java
@@ -268,12 +268,9 @@
     private final ClassLoader systemClassLoader =
         Thread.currentThread().getContextClassLoader();
 
-    private final TreeLogger logger;
-
     @SuppressWarnings("unchecked")
-    private MyWebAppContext(TreeLogger logger, String webApp, String contextPath) {
+    private MyWebAppContext(String webApp, String contextPath) {
       super(webApp, contextPath);
-      this.logger = logger;
 
       // Prevent file locking on Windows; pick up file changes.
       getInitParams().put(
@@ -397,7 +394,7 @@
     // Create a new web app in the war directory.
     //
     WebAppContext wac =
-        new MyWebAppContext(logger, warDir.getAbsolutePath(), "/");
+        new MyWebAppContext(warDir.getAbsolutePath(), "/");
     wac.setDescriptor(webxml.getAbsolutePath());
 
     RequestLogHandler logHandler = new RequestLogHandler();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
index 81a9dd5..c915d1e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/FormatUtil.java
@@ -25,9 +25,9 @@
 public class FormatUtil {
   private static final long ONE_YEAR = 182L * 24 * 60 * 60 * 1000;
 
-  private static DateTimeFormat sTime = DateTimeFormat.getShortTimeFormat();
+  private static DateTimeFormat sTime = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.TIME_SHORT);
   private static DateTimeFormat sDate = DateTimeFormat.getFormat("MMM d");
-  private static DateTimeFormat mDate = DateTimeFormat.getMediumDateFormat();
+  private static DateTimeFormat mDate = DateTimeFormat.getFormat(DateTimeFormat.PredefinedFormat.DATE_MEDIUM);
   private static DateTimeFormat dtfmt;
 
   public static void setPreferences(AccountGeneralPreferences pref) {
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
index b421e48..c2afb84 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/Gerrit.java
@@ -239,7 +239,7 @@
     KeyUtil.setEncoderImpl(new KeyUtil.Encoder() {
       @Override
       public String encode(String e) {
-        e = URL.encodeComponent(e);
+        e = URL.encodeQueryString(e);
         e = fixPathImpl(e);
         e = fixColonImpl(e);
         return e;
@@ -247,7 +247,7 @@
 
       @Override
       public String decode(final String e) {
-        return URL.decodeComponent(e);
+        return URL.decodeQueryString(e);
       }
 
       private native String fixPathImpl(String path)
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
index e988540..993d06a 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/GerritCss.java
@@ -133,10 +133,12 @@
   String menuScreenMenuBar();
   String missingApproval();
   String missingApprovalList();
+  String monospace();
   String needsReview();
   String negscore();
   String noLineLineNumber();
   String noborder();
+  String parentsTable();
   String patchBrowserPopup();
   String patchBrowserPopupBody();
   String patchComments();
@@ -188,4 +190,6 @@
   String usernameField();
   String version();
   String watchedProjectFilter();
+  String selectPatchSetOldVersion();
+  String patchCellReverseDiff();
 }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
index db5094d..d1f1296 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/SearchPanel.java
@@ -29,7 +29,6 @@
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
-import com.google.gwtexpui.globalkey.client.NpTextBox;
 
 class SearchPanel extends Composite {
   private final HintTextBox searchBox;
@@ -46,7 +45,7 @@
     searchBox.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(final KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doSearch();
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java
index 224ff93..41f0540 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/MyWatchedProjectsScreen.java
@@ -19,7 +19,6 @@
 import com.google.gerrit.client.rpc.ScreenLoadCallback;
 import com.google.gerrit.client.ui.HintTextBox;
 import com.google.gerrit.client.ui.ProjectNameSuggestOracle;
-import com.google.gerrit.client.ui.RPCSuggestOracle;
 import com.google.gerrit.client.ui.ProjectsTable;
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.data.AccountProjectWatchInfo;
@@ -42,6 +41,7 @@
 import com.google.gwt.user.client.ui.PopupPanel;
 import com.google.gwt.user.client.ui.ScrollPanel;
 import com.google.gwt.user.client.ui.SuggestBox;
+import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.HidePopupPanelCommand;
@@ -173,8 +173,9 @@
       public void onKeyPress(KeyPressEvent event) {
         submitOnSelection = false;
 
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
-          if (nameTxt.isSuggestionListShowing()) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
+          if (((DefaultSuggestionDisplay) nameTxt.getSuggestionDisplay())
+              .isSuggestionListShowing()) {
             submitOnSelection = true;
           } else {
             doAddNew();
@@ -198,7 +199,7 @@
     filterTxt.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doAddNew();
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
index 73e784b..bee1636 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/UsernameField.java
@@ -58,7 +58,7 @@
       userNameTxt.addKeyPressHandler(new KeyPressHandler() {
         @Override
         public void onKeyPress(KeyPressEvent event) {
-          if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+          if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
             doSetUserName();
           }
         }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java
index 59e439d..a0f36b9 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/account/Util.java
@@ -17,7 +17,6 @@
 import com.google.gerrit.common.data.AccountSecurity;
 import com.google.gerrit.common.data.AccountService;
 import com.google.gerrit.common.data.ProjectAdminService;
-import com.google.gerrit.reviewdb.Project;
 import com.google.gwt.core.client.GWT;
 import com.google.gwtjsonrpc.client.JsonUtil;
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessRightEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessRightEditor.java
index ce4f094..8f6831b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessRightEditor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccessRightEditor.java
@@ -108,7 +108,7 @@
     referenceTxt.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doAddNewRight();
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
index bb386b0..593ab34 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/AccountGroupScreen.java
@@ -386,7 +386,7 @@
     externalNameFilter.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(final KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doExternalSearch();
         }
       }
@@ -665,13 +665,6 @@
       }
     }
 
-    void insertMember(final AccountGroupMember k) {
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-      populate(row, k);
-    }
-
     void display(final List<AccountGroupMember> result) {
       while (1 < table.getRowCount())
         table.removeRow(table.getRowCount() - 1);
@@ -750,13 +743,6 @@
       }
     }
 
-    void insertMember(final AccountGroupInclude k) {
-      final int row = table.getRowCount();
-      table.insertRow(row);
-      applyDataRowStyle(row);
-      populate(row, k);
-    }
-
     void display(final List<AccountGroupInclude> result) {
       while (1 < table.getRowCount())
         table.removeRow(table.getRowCount() - 1);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
index 45ed2f6..a6dbedc 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/GroupListScreen.java
@@ -75,7 +75,7 @@
     addTxt.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doCreateGroup();
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
index eb74aa8..b87f6f1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectAccessScreen.java
@@ -87,10 +87,10 @@
     parentName = new Hyperlink("", "");
 
     showInherited = new CheckBox();
-    showInherited.setChecked(true);
+    showInherited.setValue(true);
     showInherited.addClickHandler(new ClickHandler() {
       public void onClick(ClickEvent event) {
-        rights.showInherited(showInherited.isChecked());
+        rights.showInherited(showInherited.getValue());
       }
     });
 
@@ -215,7 +215,7 @@
       for (final InheritedRefRight r : refRights) {
         final int row = table.getRowCount();
         table.insertRow(row);
-        if (! showInherited.isChecked() && r.isInherited()) {
+        if (! showInherited.getValue() && r.isInherited()) {
           table.getRowFormatter().setVisible(row, false);
         }
         applyDataRowStyle(row);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
index 77c431a..8c8f2f0 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/ProjectBranchesScreen.java
@@ -27,21 +27,21 @@
 import com.google.gerrit.common.errors.InvalidRevisionException;
 import com.google.gerrit.reviewdb.Branch;
 import com.google.gerrit.reviewdb.Project;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.CheckBox;
+import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Label;
-import com.google.gwt.user.client.ui.FlexTable.FlexCellFormatter;
 import com.google.gwtjsonrpc.client.RemoteJsonException;
 
 import java.util.HashSet;
@@ -112,7 +112,7 @@
     nameTxtBox.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doAddNewBranch();
         }
       }
@@ -126,7 +126,7 @@
     irevTxtBox.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           doAddNewBranch();
         }
       }
@@ -169,7 +169,7 @@
     String rev = irevTxtBox.getText();
     if ("".equals(rev)) {
       irevTxtBox.setText("HEAD");
-      DeferredCommand.addCommand(new Command() {
+      Scheduler.get().scheduleDeferred(new ScheduledCommand() {
         @Override
         public void execute() {
           irevTxtBox.selectAll();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSignInDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSignInDialog.java
index df229a6..78d98d5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSignInDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/openid/OpenIdSignInDialog.java
@@ -22,6 +22,8 @@
 import com.google.gerrit.common.auth.openid.DiscoveryResult;
 import com.google.gerrit.common.auth.openid.OpenIdProviderPattern;
 import com.google.gerrit.common.auth.openid.OpenIdUrls;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.dom.client.FormElement;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
@@ -29,22 +31,20 @@
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.dom.client.KeyPressHandler;
 import com.google.gwt.resources.client.ImageResource;
-import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.Cookies;
 import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.ui.Anchor;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.FormPanel;
+import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwt.user.client.ui.FormSubmitCompleteEvent;
 import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Hidden;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.InlineLabel;
-import com.google.gwt.user.client.ui.FormPanel.SubmitEvent;
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 
 import java.util.Map;
@@ -111,7 +111,7 @@
   public void show() {
     super.show();
     providerId.selectAll();
-    DeferredCommand.addCommand(new Command() {
+    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
       @Override
       public void execute() {
         providerId.setFocus(true);
@@ -181,7 +181,7 @@
     providerId.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(final KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           event.preventDefault();
           form.submit();
         }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
index c4709a5..dfcddf5 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/auth/userpass/UserPassSignInDialog.java
@@ -21,14 +21,14 @@
 import com.google.gerrit.common.PageLinks;
 import com.google.gerrit.common.auth.SignInMode;
 import com.google.gerrit.common.auth.userpass.LoginResult;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.dom.client.KeyPressHandler;
-import com.google.gwt.user.client.Command;
 import com.google.gwt.user.client.DOM;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.Window.Location;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.FlowPanel;
@@ -73,7 +73,7 @@
   @Override
   public void show() {
     super.show();
-    DeferredCommand.addCommand(new Command() {
+    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
       @Override
       public void execute() {
         username.setFocus(true);
@@ -114,7 +114,7 @@
     username.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(final KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           event.preventDefault();
           password.selectAll();
           password.setFocus(true);
@@ -128,7 +128,7 @@
     password.addKeyPressHandler(new KeyPressHandler() {
       @Override
       public void onKeyPress(final KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           event.preventDefault();
           onLogin();
         }
@@ -215,7 +215,7 @@
           showError(Util.C.invalidLogin());
           enable(true);
           password.selectAll();
-          DeferredCommand.addCommand(new Command() {
+          Scheduler.get().scheduleDeferred(new ScheduledCommand() {
             @Override
             public void execute() {
               password.setFocus(true);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
index f87b5c2..e4fe6d2 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.java
@@ -99,6 +99,8 @@
   String patchSetInfoAuthor();
   String patchSetInfoCommitter();
   String patchSetInfoDownload();
+  String patchSetInfoParents();
+  String initialCommit();
 
   String buttonRevertChangeBegin();
   String buttonRevertChangeSend();
@@ -111,6 +113,8 @@
   String buttonAbandonChangeCancel();
   String headingAbandonMessage();
   String abandonChangeTitle();
+  String oldVersionHistory();
+  String baseDiffItem();
 
   String buttonReview();
   String buttonPublishCommentsSend();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
index 5dc259c..7032dda 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeConstants.properties
@@ -76,12 +76,16 @@
 patchSetInfoAuthor = Author
 patchSetInfoCommitter = Committer
 patchSetInfoDownload = Download
+patchSetInfoParents = Parent(s)
+initialCommit = Initial Commit
 
 buttonAbandonChangeBegin = Abandon Change
 buttonAbandonChangeSend = Abandon Change
 buttonAbandonChangeCancel = Cancel
 headingAbandonMessage = Abandon Message:
 abandonChangeTitle = Code Review - Abandon Change
+oldVersionHistory = Old Version History:
+baseDiffItem = Base
 
 buttonRevertChangeBegin = Revert Change
 buttonRevertChangeSend = Revert Change
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
index 7213d88..edb25e4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeScreen.java
@@ -29,9 +29,11 @@
 import com.google.gerrit.common.data.ToggleStarRequest;
 import com.google.gerrit.reviewdb.Account;
 import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Change.Status;
 import com.google.gerrit.reviewdb.ChangeMessage;
 import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.Change.Status;
+import com.google.gwt.event.dom.client.ChangeEvent;
+import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyPressEvent;
@@ -39,9 +41,11 @@
 import com.google.gwt.i18n.client.LocaleInfo;
 import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.Grid;
 import com.google.gwt.user.client.ui.HorizontalPanel;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
+import com.google.gwt.user.client.ui.ListBox;
 import com.google.gwt.user.client.ui.Panel;
 import com.google.gwtexpui.globalkey.client.GlobalKey;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
@@ -77,9 +81,30 @@
   private HandlerRegistration regNavigation;
   private HandlerRegistration regAction;
 
+  private Grid patchesGrid;
+  private ListBox patchesList;
+
+  /**
+   * The change id for which the old version history is valid.
+   */
+  private static Change.Id currentChangeId;
+
+  /**
+   * Which patch set id is the diff base.
+   */
+  private static PatchSet.Id diffBaseId;
+
   public ChangeScreen(final Change.Id toShow) {
     changeId = toShow;
     openPatchSetId = null;
+
+    // If we have any diff stored, make sure they are applicable to the
+    // current change, discard them otherwise.
+    //
+    if (currentChangeId != null && !currentChangeId.equals(toShow)) {
+      diffBaseId = null;
+    }
+    currentChangeId = toShow;
   }
 
   public ChangeScreen(final PatchSet.Id toShow) {
@@ -123,6 +148,9 @@
     super.registerKeys();
     regNavigation = GlobalKey.add(this, keysNavigation);
     regAction = GlobalKey.add(this, keysAction);
+    if (openPatchSetId != null) {
+      patchSetsBlock.activate(openPatchSetId);
+    }
   }
 
   public void refresh() {
@@ -202,6 +230,30 @@
     dependenciesPanel.setContent(dependencies);
     add(dependenciesPanel);
 
+    patchesList = new ListBox();
+    patchesList.addChangeHandler(new ChangeHandler() {
+      @Override
+      public void onChange(ChangeEvent event) {
+        final int index = patchesList.getSelectedIndex();
+        final String selectedPatchSet = patchesList.getValue(index);
+        if (index == 0) {
+          diffBaseId = null;
+        } else {
+          diffBaseId = PatchSet.Id.parse(selectedPatchSet);
+        }
+        if (patchSetsBlock != null) {
+          patchSetsBlock.refresh(diffBaseId);
+        }
+      }
+    });
+    patchesList.addItem(Util.C.baseDiffItem());
+
+    patchesGrid = new Grid(1, 2);
+    patchesGrid.setStyleName(Gerrit.RESOURCES.css().selectPatchSetOldVersion());
+    patchesGrid.setText(0, 0, Util.C.oldVersionHistory());
+    patchesGrid.setWidget(0, 1, patchesList);
+    add(patchesGrid);
+
     patchSetsBlock = new PatchSetsBlock(this);
     add(patchSetsBlock);
 
@@ -257,10 +309,18 @@
     approvals.display(detail.getChange(), detail.getMissingApprovals(), detail
         .getApprovals());
 
-    patchSetsBlock.display(detail);
-    if (openPatchSetId != null) {
-      patchSetsBlock.activate(openPatchSetId);
+    for (PatchSet pId : detail.getPatchSets()) {
+      if (patchesList != null) {
+        patchesList.addItem(Util.M.patchSetHeader(pId.getPatchSetId()), pId
+            .getId().toString());
+      }
     }
+
+    if (diffBaseId != null && patchesList != null) {
+      patchesList.setSelectedIndex(diffBaseId.get());
+    }
+
+    patchSetsBlock.display(detail, diffBaseId);
     addComments(detail);
 
     // If any dependency change is still open, show our dependency list.
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
index 602d45c..eb7014e 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/ChangeTable.java
@@ -48,7 +48,6 @@
 import com.google.gwt.resources.client.ImageResource;
 import com.google.gwt.user.client.DOM;
 import com.google.gwt.user.client.ui.FlowPanel;
-import com.google.gwt.user.client.ui.HTML;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.UIObject;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java
index d725ac0..01d6299 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/CommentedChangeActionDialog.java
@@ -14,7 +14,6 @@
 
 package com.google.gerrit.client.changes;
 
-import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.SmallHeading;
 import com.google.gerrit.common.data.ChangeDetail;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
index a65c05d..efa971b 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetComplexDisclosurePanel.java
@@ -20,13 +20,13 @@
 import com.google.gerrit.client.rpc.GerritCallback;
 import com.google.gerrit.client.ui.AccountDashboardLink;
 import com.google.gerrit.client.ui.ComplexDisclosurePanel;
+import com.google.gerrit.client.ui.ListenableAccountDiffPreference;
 import com.google.gerrit.common.data.ChangeDetail;
 import com.google.gerrit.common.data.GitwebLink;
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.AccountDiffPreference;
 import com.google.gerrit.reviewdb.AccountGeneralPreferences;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadCommand;
-import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadScheme;
 import com.google.gerrit.reviewdb.ApprovalCategory;
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.ChangeMessage;
@@ -35,6 +35,8 @@
 import com.google.gerrit.reviewdb.PatchSetInfo;
 import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.reviewdb.UserIdentity;
+import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadCommand;
+import com.google.gerrit.reviewdb.AccountGeneralPreferences.DownloadScheme;
 import com.google.gwt.core.client.GWT;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
@@ -47,20 +49,22 @@
 import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.Grid;
-import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwt.user.client.ui.InlineLabel;
 import com.google.gwt.user.client.ui.Panel;
+import com.google.gwt.user.client.ui.HTMLTable.CellFormatter;
 import com.google.gwtexpui.clippy.client.CopyableLabel;
 
 import java.util.Collections;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Set;
 
 class PatchSetComplexDisclosurePanel extends ComplexDisclosurePanel implements OpenHandler<DisclosurePanel> {
   private static final int R_AUTHOR = 0;
   private static final int R_COMMITTER = 1;
-  private static final int R_DOWNLOAD = 2;
-  private static final int R_CNT = 3;
+  private static final int R_PARENTS = 2;
+  private static final int R_DOWNLOAD = 3;
+  private static final int R_CNT = 4;
 
   private final ChangeScreen changeScreen;
   private final ChangeDetail changeDetail;
@@ -72,6 +76,8 @@
   private PatchTable patchTable;
   private final Set<ClickHandler> registeredClickHandler =  new HashSet<ClickHandler>();
 
+  private PatchSet.Id diffBaseId;
+
   /**
    * Creates a closed complex disclosure panel for a patch set.
    * The patch set details are loaded when the complex disclosure panel is opened.
@@ -114,6 +120,10 @@
     }
   }
 
+  public void setDiffBaseId(PatchSet.Id diffBaseId) {
+    this.diffBaseId = diffBaseId;
+  }
+
   /**
    * Display the table showing the Author, Committer and Download links,
    * followed by the action buttons.
@@ -125,6 +135,7 @@
 
     initRow(R_AUTHOR, Util.C.patchSetInfoAuthor());
     initRow(R_COMMITTER, Util.C.patchSetInfoCommitter());
+    initRow(R_PARENTS, Util.C.patchSetInfoParents());
     initRow(R_DOWNLOAD, Util.C.patchSetInfoDownload());
 
     final CellFormatter itfmt = infoTable.getCellFormatter();
@@ -139,29 +150,32 @@
     final PatchSetInfo info = detail.getInfo();
     displayUserIdentity(R_AUTHOR, info.getAuthor());
     displayUserIdentity(R_COMMITTER, info.getCommitter());
+    displayParents(info.getParents());
     displayDownload();
 
-
-    patchTable = new PatchTable();
-    patchTable.setSavePointerId("PatchTable " + patchSet.getId());
-    patchTable.display(detail);
-
     body.add(infoTable);
 
-    actionsPanel = new FlowPanel();
-    actionsPanel.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
-    body.add(actionsPanel);
-    if (Gerrit.isSignedIn()) {
-      populateReviewAction();
-      if (changeDetail.isCurrentPatchSet(detail)) {
-        populateActions(detail);
-      }
-    }
-    populateDiffAllActions(detail);
-    body.add(patchTable);
+    if (!patchSet.getId().equals(diffBaseId)) {
+      patchTable = new PatchTable();
+      patchTable.setSavePointerId("PatchTable " + patchSet.getId());
+      patchTable.setPatchSetIdToCompareWith(diffBaseId);
+      patchTable.display(detail);
 
-    for(ClickHandler clickHandler : registeredClickHandler) {
-      patchTable.addClickHandler(clickHandler);
+      actionsPanel = new FlowPanel();
+      actionsPanel.setStyleName(Gerrit.RESOURCES.css().patchSetActions());
+      body.add(actionsPanel);
+      if (Gerrit.isSignedIn()) {
+        populateReviewAction();
+        if (changeDetail.isCurrentPatchSet(detail)) {
+          populateActions(detail);
+        }
+      }
+      populateDiffAllActions(detail);
+      body.add(patchTable);
+
+      for(ClickHandler clickHandler : registeredClickHandler) {
+        patchTable.addClickHandler(clickHandler);
+      }
     }
   }
 
@@ -363,6 +377,28 @@
     infoTable.setWidget(row, 1, fp);
   }
 
+  private void displayParents(final List<PatchSetInfo.ParentInfo> parents) {
+    if (parents.size() == 0) {
+      infoTable.setWidget(R_PARENTS, 1, new InlineLabel(Util.C.initialCommit()));
+      return;
+    }
+    final Grid parentsTable = new Grid(parents.size(), 2);
+
+    parentsTable.setStyleName(Gerrit.RESOURCES.css().parentsTable());
+    parentsTable.addStyleName(Gerrit.RESOURCES.css().noborder());
+    final CellFormatter ptfmt = parentsTable.getCellFormatter();
+    int row = 0;
+    for (PatchSetInfo.ParentInfo parent : parents) {
+      parentsTable.setWidget(row, 0, new InlineLabel(parent.id.get()));
+      ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().noborder());
+      ptfmt.addStyleName(row, 0, Gerrit.RESOURCES.css().monospace());
+      parentsTable.setWidget(row, 1, new InlineLabel(parent.shortMessage));
+      ptfmt.addStyleName(row, 1, Gerrit.RESOURCES.css().noborder());
+      row++;
+    }
+    infoTable.setWidget(R_PARENTS, 1, parentsTable);
+  }
+
   private void populateActions(final PatchSetDetail detail) {
     final boolean isOpen = changeDetail.getChange().getStatus().isOpen();
     Set<ApprovalCategory.Id> allowed = changeDetail.getCurrentActions();
@@ -494,10 +530,51 @@
     actionsPanel.add(b);
   }
 
+  public void refresh() {
+    AccountDiffPreference diffPrefs;
+    if (patchTable == null) {
+      diffPrefs = new ListenableAccountDiffPreference().get();
+    } else {
+      diffPrefs = patchTable.getPreferences().get();
+    }
+
+    Util.DETAIL_SVC.patchSetDetail(patchSet.getId(), diffBaseId, diffPrefs,
+        new GerritCallback<PatchSetDetail>() {
+          @Override
+          public void onSuccess(PatchSetDetail result) {
+
+            if (patchSet.getId().equals(diffBaseId)) {
+              patchTable.setVisible(false);
+              actionsPanel.setVisible(false);
+            } else {
+
+              if (patchTable != null) {
+                patchTable.removeFromParent();
+              }
+              patchTable = new PatchTable();
+              patchTable.setPatchSetIdToCompareWith(diffBaseId);
+              patchTable.display(result);
+              body.add(patchTable);
+
+              for (ClickHandler clickHandler : registeredClickHandler) {
+                patchTable.addClickHandler(clickHandler);
+              }
+            }
+          }
+        });
+  }
+
   @Override
   public void onOpen(final OpenEvent<DisclosurePanel> event) {
     if (infoTable == null) {
-      Util.DETAIL_SVC.patchSetDetail(patchSet.getId(),
+      AccountDiffPreference diffPrefs;
+      if (diffBaseId == null) {
+        diffPrefs = null;
+      } else {
+        diffPrefs = new ListenableAccountDiffPreference().get();
+      }
+
+      Util.DETAIL_SVC.patchSetDetail(patchSet.getId(), diffBaseId, diffPrefs,
           new GerritCallback<PatchSetDetail>() {
             public void onSuccess(final PatchSetDetail result) {
               ensureLoaded(result);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
index f453b4f..e854cab 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchSetsBlock.java
@@ -32,6 +32,7 @@
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.globalkey.client.KeyCommandSet;
 
+import java.util.ArrayList;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
@@ -50,6 +51,8 @@
   private final FlowPanel body;
   private HandlerRegistration regNavigation;
 
+  private List<PatchSetComplexDisclosurePanel> patchSetPanelsList;
+
   /**
    * the patch set id of the patch set for which is the keyboard navigation is
    * currently enabled
@@ -69,13 +72,19 @@
   }
 
   /** Adds UI elements for each patch set of the given change to this composite. */
-  public void display(final ChangeDetail detail) {
+  public void display(final ChangeDetail detail, final PatchSet.Id diffBaseId) {
     clear();
 
     final PatchSet currps = detail.getCurrentPatchSet();
     currentPatchSetId = currps.getId();
     patchSets = detail.getPatchSets();
 
+    final List<PatchSet.Id> changePatchSets = new ArrayList<PatchSet.Id>();
+
+    for (final PatchSet ps : patchSets) {
+      changePatchSets.add(ps.getId());
+    }
+
     if (Gerrit.isSignedIn()) {
       final AccountGeneralPreferences p =
           Gerrit.getUserAccount().getGeneralPreferences();
@@ -84,13 +93,25 @@
       }
     }
 
+    patchSetPanelsList = new ArrayList<PatchSetComplexDisclosurePanel>();
+
     for (final PatchSet ps : patchSets) {
+      final PatchSetComplexDisclosurePanel p;
       if (ps == currps) {
-        add(new PatchSetComplexDisclosurePanel(parent, detail, detail
-            .getCurrentPatchSetDetail()));
+        p = new PatchSetComplexDisclosurePanel(parent, detail, detail
+            .getCurrentPatchSetDetail());
+        if (diffBaseId != null) {
+          p.setDiffBaseId(diffBaseId);
+          p.refresh();
+        }
       } else {
-        add(new PatchSetComplexDisclosurePanel(parent, detail, ps));
+        p = new PatchSetComplexDisclosurePanel(parent, detail, ps);
+        if (diffBaseId != null) {
+          p.setDiffBaseId(diffBaseId);
+        }
       }
+      add(p);
+      patchSetPanelsList.add(p);
     }
   }
 
@@ -100,6 +121,17 @@
     patchSetPanels.clear();
   }
 
+  public void refresh(final PatchSet.Id diffBaseId) {
+    if (patchSetPanelsList != null) {
+      for (final PatchSetComplexDisclosurePanel p : patchSetPanelsList) {
+        p.setDiffBaseId(diffBaseId);
+        if (p.isOpen()) {
+          p.refresh();
+        }
+      }
+    }
+  }
+
   /**
    * Adds the given patch set panel to this composite and ensures that handler
    * to activate / deactivate keyboard navigation for the patch set panel are
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
index 33b37c8..2a2fec3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PatchTable.java
@@ -22,23 +22,24 @@
 import com.google.gerrit.client.ui.PatchLink;
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.reviewdb.Patch;
+import com.google.gerrit.reviewdb.PatchSet;
 import com.google.gerrit.reviewdb.Patch.ChangeType;
 import com.google.gerrit.reviewdb.Patch.Key;
 import com.google.gerrit.reviewdb.Patch.PatchType;
 import com.google.gwt.core.client.GWT;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.RepeatingCommand;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
-import com.google.gwt.user.client.IncrementalCommand;
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
+import com.google.gwt.user.client.ui.HTMLTable.Cell;
 import com.google.gwt.user.client.ui.Image;
 import com.google.gwt.user.client.ui.Label;
 import com.google.gwt.user.client.ui.Widget;
-import com.google.gwt.user.client.ui.HTMLTable.Cell;
 import com.google.gwtexpui.globalkey.client.KeyCommand;
 import com.google.gwtexpui.progress.client.ProgressBar;
 import com.google.gwtexpui.safehtml.client.SafeHtml;
@@ -61,6 +62,8 @@
   private boolean active;
   private boolean registerKeys;
 
+  private PatchSet.Id patchSetIdToCompareWith;
+
   public PatchTable(ListenableAccountDiffPreference prefs) {
     listenablePrefs = prefs;
     myBody = new FlowPanel();
@@ -85,10 +88,10 @@
     this.patchList = detail.getPatches();
     myTable = null;
 
-    final DisplayCommand cmd = new DisplayCommand(patchList);
+    final DisplayCommand cmd = new DisplayCommand(patchList, patchSetIdToCompareWith);
     if (cmd.execute()) {
       cmd.initMeter();
-      DeferredCommand.addCommand(cmd);
+      Scheduler.get().scheduleIncremental(cmd);
     } else {
       cmd.showTable();
     }
@@ -272,6 +275,14 @@
     listenablePrefs = prefs;
   }
 
+  public PatchSet.Id getPatchSetIdToCompareWith() {
+    return patchSetIdToCompareWith;
+  }
+
+  public void setPatchSetIdToCompareWith(final PatchSet.Id psId) {
+    patchSetIdToCompareWith = psId;
+  }
+
   private class MyTable extends NavigationTable<Patch> {
     private static final int C_PATH = 2;
     private static final int C_DRAFT = 3;
@@ -279,6 +290,8 @@
     private static final int C_SIDEBYSIDE = 5;
     private int activeRow = -1;
 
+    private PatchSet.Id patchSetIdToCompareWith;
+
     MyTable() {
       keysNavigation.add(new PrevKeyCommand(0, 'k', Util.C.patchTablePrev()));
       keysNavigation.add(new NextKeyCommand(0, 'j', Util.C.patchTableNext()));
@@ -463,7 +476,8 @@
       m.closeTr();
     }
 
-    void appendRow(final SafeHtmlBuilder m, final Patch p) {
+    void appendRow(final SafeHtmlBuilder m, final Patch p,
+        final boolean isReverseDiff) {
       m.openTr();
 
       m.openTd();
@@ -474,6 +488,10 @@
 
       m.openTd();
       m.setStyleName(Gerrit.RESOURCES.css().changeTypeCell());
+      if (isReverseDiff) {
+        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
+      }
+
       if (Patch.COMMIT_MSG.equals(p.getFileName())) {
         m.nbsp();
       } else {
@@ -494,7 +512,12 @@
 
       m.openTd();
       m.addStyleName(Gerrit.RESOURCES.css().dataCell());
+
       m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
+      if (isReverseDiff) {
+        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
+      }
+
       appendSize(m, p);
       m.closeTd();
 
@@ -559,7 +582,8 @@
       m.closeTr();
     }
 
-    void appendTotals(final SafeHtmlBuilder m, int ins, int dels) {
+    void appendTotals(final SafeHtmlBuilder m, int ins, int dels,
+        final boolean isReverseDiff) {
       m.openTr();
 
       m.openTd();
@@ -576,6 +600,11 @@
       m.addStyleName(Gerrit.RESOURCES.css().dataCell());
       m.addStyleName(Gerrit.RESOURCES.css().patchSizeCell());
       m.addStyleName(Gerrit.RESOURCES.css().leftMostCell());
+
+      if (isReverseDiff) {
+        m.addStyleName(Gerrit.RESOURCES.css().patchCellReverseDiff());
+      }
+
       m.append(Util.M.patchTableSize_Modify(ins, dels));
       m.closeTd();
 
@@ -686,7 +715,7 @@
     }
   }
 
-  private final class DisplayCommand implements IncrementalCommand {
+  private final class DisplayCommand implements RepeatingCommand {
     private final MyTable table;
     private final List<Patch> list;
     private boolean attached;
@@ -699,9 +728,12 @@
     private int insertions;
     private int deletions;
 
-    private DisplayCommand(final List<Patch> list) {
+    private final PatchSet.Id psIdToCompareWith;
+
+    private DisplayCommand(final List<Patch> list, final PatchSet.Id psIdToCompareWith) {
       this.table = new MyTable();
       this.list = list;
+      this.psIdToCompareWith = psIdToCompareWith;
     }
 
     /**
@@ -722,24 +754,31 @@
         return false;
       }
 
+      boolean isReverseDiff = false;
+
+      if (psIdToCompareWith != null
+          && list.get(0).getKey().getParentKey().get() < psIdToCompareWith.get()) {
+        isReverseDiff = true;
+      }
+
       start = System.currentTimeMillis();
       switch (stage) {
         case 0:
           if (row == 0) {
             table.appendHeader(nc);
-            table.appendRow(nc, list.get(row++));
+            table.appendRow(nc, list.get(row++), isReverseDiff);
           }
           while (row < list.size()) {
             Patch p = list.get(row);
             insertions += p.getInsertions();
             deletions += p.getDeletions();
-            table.appendRow(nc, p);
+            table.appendRow(nc, p, isReverseDiff);
             if ((++row % 10) == 0 && longRunning()) {
               updateMeter();
               return true;
             }
           }
-          table.appendTotals(nc, insertions, deletions);
+          table.appendTotals(nc, insertions, deletions, isReverseDiff);
           table.resetHtml(nc);
           nc = null;
           stage = 1;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
index f9e55be..0ed58b4 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/changes/PublishCommentScreen.java
@@ -367,6 +367,12 @@
             saveStateOnUnload = false;
             goChange();
           }
+
+          @Override
+          public void onFailure(Throwable caught) {
+            goChange();
+            super.onFailure(caught);
+          }
         });
   }
 
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
index 84354f7..c81920d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/gerrit.css
@@ -421,6 +421,10 @@
   color: #ff5555;
 }
 
+.changeTable .patchCellReverseDiff {
+  color: red;
+}
+
 .changeTable .patchSizeCell {
   text-align: right;
   white-space: nowrap;
@@ -905,6 +909,12 @@
   font-size: 8pt;
 }
 
+.selectPatchSetOldVersion {
+  font-weight: bold;
+  margin-right: 30px;
+  margin-top: 5px;
+}
+
 .changeScreen .approvalTable {
   margin-top: 1em;
   margin-bottom: 1em;
@@ -972,6 +982,28 @@
   width: 30em;
 }
 
+.parentsTable {
+  border-style: none;
+  border: 1px 1px 1px 0px;
+  outline: 0px;
+  padding: 0px;
+  border-spacing: 0px;
+  text-align: left;
+  font-family: mono-font;
+  font-size: 10px;
+}
+
+.parentsTable td.noborder {
+  border: none;
+}
+
+.parentsTable td.monospace {
+  font-family: mono-font;
+  font-size: 10px;
+  margin: 0px;
+  padding-left: 0px;
+}
+
 /** SideBySideScreen **/
 .sideBySideScreenSideBySideTable {
   width: 100%;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
index 98f0c95..5df1e14 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/CommentEditorPanel.java
@@ -26,7 +26,6 @@
 import com.google.gwt.event.dom.client.KeyDownEvent;
 import com.google.gwt.event.dom.client.KeyDownHandler;
 import com.google.gwt.user.client.Timer;
-import com.google.gwt.user.client.Window;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.Button;
 import com.google.gwt.user.client.ui.Widget;
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
index cad371e..342d390 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScreen.java
@@ -33,6 +33,8 @@
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.Patch;
 import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.KeyPressEvent;
 import com.google.gwt.event.logical.shared.CloseEvent;
 import com.google.gwt.event.logical.shared.CloseHandler;
@@ -41,8 +43,6 @@
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.event.shared.HandlerRegistration;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.rpc.AsyncCallback;
 import com.google.gwt.user.client.ui.DisclosurePanel;
 import com.google.gwt.user.client.ui.FlowPanel;
@@ -156,16 +156,15 @@
     patchSetDetail = detail;
     fileList = patchTable;
 
-    // If we have any diff side stored, make sure they are applicable to the
-    // current change, discard them otherwise.
-    //
-    Change.Id thisChangeId = id.getParentKey().getParentKey();
-    if (currentChangeId != null && !currentChangeId.equals(thisChangeId)) {
+    if (patchTable != null) {
+      diffSideA = patchTable.getPatchSetIdToCompareWith();
+    } else {
       diffSideA = null;
-      diffSideB = null;
+    }
+    if (diffSideA == null) {
       historyOpen = null;
     }
-    currentChangeId = thisChangeId;
+
     idSideA = diffSideA; // null here means we're diff'ing from the Base
     idSideB = diffSideB != null ? diffSideB : id.getParentKey();
     this.patchIndex = patchIndex;
@@ -205,7 +204,7 @@
       lastScript.setDiffPrefs(dp);
       RpcStatus.INSTANCE.onRpcStart(null);
       settingsPanel.setEnabled(false);
-      DeferredCommand.addCommand(new Command() {
+      Scheduler.get().scheduleDeferred(new ScheduledCommand() {
         @Override
         public void execute() {
           try {
@@ -324,7 +323,7 @@
   protected void onLoad() {
     super.onLoad();
     if (patchSetDetail == null) {
-      Util.DETAIL_SVC.patchSetDetail(idSideB,
+      Util.DETAIL_SVC.patchSetDetail(idSideB, null, null,
           new GerritCallback<PatchSetDetail>() {
             @Override
             public void onSuccess(PatchSetDetail result) {
@@ -407,7 +406,7 @@
       commitMessageBlock.display(patchSetDetail.getInfo().getMessage());
     } else {
       commitMessageBlock.setVisible(false);
-      Util.DETAIL_SVC.patchSetDetail(idSideB,
+      Util.DETAIL_SVC.patchSetDetail(idSideB, null, null,
           new GerritCallback<PatchSetDetail>() {
             @Override
             public void onSuccess(PatchSetDetail result) {
@@ -501,7 +500,7 @@
         final PatchSet.Id psid = patchKey.getParentKey();
         fileList = new PatchTable(prefs);
         fileList.setSavePointerId("PatchTable " + psid);
-        Util.DETAIL_SVC.patchSetDetail(psid,
+        Util.DETAIL_SVC.patchSetDetail(psid, null, null,
             new GerritCallback<PatchSetDetail>() {
               public void onSuccess(final PatchSetDetail result) {
                 fileList.display(result);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
index 5c777ff..404eeeb 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/patches/PatchScriptSettingsPanel.java
@@ -117,7 +117,7 @@
     KeyPressHandler onEnter = new KeyPressHandler() {
       @Override
       public void onKeyPress(KeyPressEvent event) {
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
           update();
         }
       }
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddIncludedGroupBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddIncludedGroupBox.java
index 02e2745..60b8ccb1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddIncludedGroupBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddIncludedGroupBox.java
@@ -28,6 +28,7 @@
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.SuggestBox;
+import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
 public class AddIncludedGroupBox extends Composite {
@@ -51,8 +52,9 @@
       public void onKeyPress(KeyPressEvent event) {
         submitOnSelection = false;
 
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
-          if (nameTxt.isSuggestionListShowing()) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
+          if (((DefaultSuggestionDisplay) nameTxt.getSuggestionDisplay())
+              .isSuggestionListShowing()) {
             submitOnSelection = true;
           } else {
             doAdd();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java
index b2d25e4..c63ae84 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AddMemberBox.java
@@ -14,10 +14,7 @@
 
 package com.google.gerrit.client.ui;
 
-import com.google.gerrit.client.Gerrit;
 import com.google.gerrit.client.admin.Util;
-import com.google.gerrit.client.ui.HintTextBox;
-import com.google.gerrit.client.ui.RPCSuggestOracle;
 import com.google.gwt.event.dom.client.ClickEvent;
 import com.google.gwt.event.dom.client.ClickHandler;
 import com.google.gwt.event.dom.client.KeyCodes;
@@ -29,6 +26,7 @@
 import com.google.gwt.user.client.ui.Composite;
 import com.google.gwt.user.client.ui.FlowPanel;
 import com.google.gwt.user.client.ui.SuggestBox;
+import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
 import com.google.gwt.user.client.ui.SuggestOracle.Suggestion;
 
 public class AddMemberBox extends Composite {
@@ -52,8 +50,9 @@
       public void onKeyPress(KeyPressEvent event) {
         submitOnSelection = false;
 
-        if (event.getCharCode() == KeyCodes.KEY_ENTER) {
-          if (nameTxt.isSuggestionListShowing()) {
+        if (event.getNativeEvent().getKeyCode() == KeyCodes.KEY_ENTER) {
+          if (((DefaultSuggestionDisplay) nameTxt.getSuggestionDisplay())
+              .isSuggestionListShowing()) {
             submitOnSelection = true;
           } else {
             doAdd();
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
index 6575b61..814fb1f 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/HintTextBox.java
@@ -27,6 +27,7 @@
 import com.google.gwtexpui.globalkey.client.NpTextBox;
 import com.google.gwt.user.client.ui.SuggestBox;
 import com.google.gwt.user.client.ui.Widget;
+import com.google.gwt.user.client.ui.SuggestBox.DefaultSuggestionDisplay;
 
 
 public class HintTextBox extends NpTextBox {
@@ -152,7 +153,8 @@
         ((SuggestBox)p).showSuggestionList();
 
         // The suggestion list lingers if we don't hide it.
-        ((SuggestBox)p).hideSuggestionList();
+        ((DefaultSuggestionDisplay) ((SuggestBox) p).getSuggestionDisplay())
+            .hideSuggestions();
       }
 
       setFocus(false);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java
index 932fb5e..b574db1 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/OnEditEnabler.java
@@ -14,6 +14,8 @@
 
 package com.google.gerrit.client.ui;
 
+import com.google.gwt.core.client.Scheduler;
+import com.google.gwt.core.client.Scheduler.ScheduledCommand;
 import com.google.gwt.event.dom.client.ChangeEvent;
 import com.google.gwt.event.dom.client.ChangeHandler;
 import com.google.gwt.event.dom.client.FocusEvent;
@@ -24,12 +26,9 @@
 import com.google.gwt.event.dom.client.KeyPressHandler;
 import com.google.gwt.event.dom.client.MouseUpEvent;
 import com.google.gwt.event.dom.client.MouseUpHandler;
-
 import com.google.gwt.event.logical.shared.ValueChangeEvent;
 import com.google.gwt.event.logical.shared.ValueChangeHandler;
 import com.google.gwt.event.shared.GwtEvent;
-import com.google.gwt.user.client.Command;
-import com.google.gwt.user.client.DeferredCommand;
 import com.google.gwt.user.client.ui.CheckBox;
 import com.google.gwt.user.client.ui.FocusWidget;
 import com.google.gwt.user.client.ui.ListBox;
@@ -43,7 +42,7 @@
  *  registered input widget.
  */
 public class OnEditEnabler implements KeyPressHandler, KeyDownHandler,
-   MouseUpHandler, ChangeHandler, ValueChangeHandler {
+   MouseUpHandler, ChangeHandler, ValueChangeHandler<Object> {
 
   private final FocusWidget widget;
   private Map<TextBoxBase, String> strings = new HashMap<TextBoxBase, String>();
@@ -102,8 +101,9 @@
     lb.addChangeHandler(this);
   }
 
+  @SuppressWarnings({"unchecked", "rawtypes"})
   public void listenTo(final CheckBox cb) {
-    cb.addValueChangeHandler(this);
+    cb.addValueChangeHandler((ValueChangeHandler) this);
   }
 
 
@@ -129,12 +129,13 @@
     on(e);
   }
 
+  @SuppressWarnings("rawtypes")
   @Override
   public void onValueChange(final ValueChangeEvent e) {
     on(e);
   }
 
-  private void on(final GwtEvent e) {
+  private void on(final GwtEvent<?> e) {
     if (widget.isEnabled() ||
         ! (e.getSource() instanceof FocusWidget) ||
         ! ((FocusWidget) e.getSource()).isEnabled() ) {
@@ -153,7 +154,7 @@
 
   private void onTextBoxBase(final TextBoxBase tb) {
     // The text appears to not get updated until the handlers complete.
-    DeferredCommand.add(new Command() {
+    Scheduler.get().scheduleDeferred(new ScheduledCommand() {
       @Override
       public void execute() {
         String orig = strings.get(tb);
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RPCSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RPCSuggestOracle.java
index cc3d510..1068c3d 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RPCSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/RPCSuggestOracle.java
@@ -15,9 +15,6 @@
 package com.google.gerrit.client.ui;
 
 import com.google.gwt.user.client.ui.SuggestOracle;
-import com.google.gwt.user.client.ui.SuggestOracle.Callback;
-import com.google.gwt.user.client.ui.SuggestOracle.Request;
-import com.google.gwt.user.client.ui.SuggestOracle.Response;
 
 /** This class will proxy SuggestOracle requests to another SuggestOracle
  *  while keeping track of the latest request.  Any repsonse that belongs
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
index 97debbc..468c6d8 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ChangeQueryServlet.java
@@ -30,6 +30,7 @@
 
 @Singleton
 public class ChangeQueryServlet extends HttpServlet {
+  private static final long serialVersionUID = 1L;
   private final Provider<QueryProcessor> processor;
 
   @Inject
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectServlet.java
index 5eea773..c4db309 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/ProjectServlet.java
@@ -73,6 +73,7 @@
 /** Serves Git repositories over HTTP. */
 @Singleton
 public class ProjectServlet extends GitServlet {
+  private static final long serialVersionUID = 1L;
   private static final Logger log =
       LoggerFactory.getLogger(ProjectServlet.class);
 
@@ -131,6 +132,8 @@
     super.init(config);
 
     serveRegex("^/(.*?)/?$").with(new HttpServlet() {
+      private static final long serialVersionUID = 1L;
+
       @Override
       protected void doGet(HttpServletRequest req, HttpServletResponse rsp)
           throws IOException {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpsClientSslCertLoginServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpsClientSslCertLoginServlet.java
index 6125405..20b6352 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpsClientSslCertLoginServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/container/HttpsClientSslCertLoginServlet.java
@@ -15,7 +15,6 @@
 package com.google.gerrit.httpd.auth.container;
 
 import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.httpd.WebSession;
 import com.google.gerrit.server.config.CanonicalWebUrl;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
@@ -41,13 +40,10 @@
 public class HttpsClientSslCertLoginServlet extends HttpServlet {
   private static final long serialVersionUID = 1L;
 
-  private final Provider<WebSession> webSession;
   private final Provider<String> urlProvider;
 
   @Inject
-  public HttpsClientSslCertLoginServlet(final Provider<WebSession> webSession,
-      @CanonicalWebUrl @Nullable final Provider<String> urlProvider) {
-    this.webSession = webSession;
+  public HttpsClientSslCertLoginServlet(@CanonicalWebUrl @Nullable final Provider<String> urlProvider) {
     this.urlProvider = urlProvider;
   }
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
index 068855f..3dce967 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/OpenIdServiceImpl.java
@@ -146,6 +146,7 @@
         "auth", null, "maxOpenIdSessionAge", -1, TimeUnit.SECONDS);
   }
 
+  @SuppressWarnings("unchecked")
   public void discover(final String openidIdentifier, final SignInMode mode,
       final boolean remember, final String returnToken,
       final AsyncCallback<DiscoveryResult> cb) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java
index 5bcb852..98ad11d 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/auth/openid/XrdsServlet.java
@@ -28,6 +28,7 @@
 
 @Singleton
 class XrdsServlet extends HttpServlet {
+  private static final long serialVersionUID = 1L;
   private static final String ENC = "UTF-8";
   static final String LOCATION = "OpenID.XRDS";
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
index 03e588a..a4df147 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/gitweb/GitWebCssServlet.java
@@ -32,7 +32,6 @@
 
 @SuppressWarnings("serial")
 abstract class GitWebCssServlet extends HttpServlet {
-  @SuppressWarnings("serial")
   @Singleton
   static class Site extends GitWebCssServlet {
     @Inject
@@ -41,7 +40,6 @@
     }
   }
 
-  @SuppressWarnings("serial")
   @Singleton
   static class Default extends GitWebCssServlet {
     @Inject
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
index 14f67a3..4a688aa 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/raw/ToolServlet.java
@@ -42,6 +42,7 @@
 /** Sends the client side tools we keep within our software. */
 @Singleton
 public class ToolServlet extends HttpServlet {
+  private static final long serialVersionUID = 1L;
   private final ToolsCatalog toc;
 
   @Inject
@@ -80,10 +81,6 @@
     rsp.setDateHeader(HDR_EXPIRES, 0L);
     rsp.setHeader(HDR_PRAGMA, "no-cache");
     rsp.setHeader(HDR_CACHE_CONTROL, "no-cache, must-revalidate");
-    if (false) {
-      rsp.setHeader("Content-Disposition", "attachment; filename=\""
-          + ent.getName() + "\"");
-    }
     rsp.setContentType("application/octet-stream");
     rsp.setContentLength(tosend.length);
     final OutputStream out = rsp.getOutputStream();
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
index 8f9d96e..ed21b39 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/BaseServiceImplementation.java
@@ -39,7 +39,6 @@
     this.currentUser = currentUser;
   }
 
-  @Deprecated
   protected Account.Id getAccountId() {
     CurrentUser u = currentUser.get();
     if (u instanceof IdentifiedUser) {
@@ -97,7 +96,6 @@
   }
 
   /** Exception whose cause is passed into onFailure. */
-  @Deprecated
   public static class Failure extends Exception {
     private static final long serialVersionUID = 1L;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
index 332e262..5c19e11 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/ChangeListServiceImpl.java
@@ -162,7 +162,7 @@
       }
 
       if (s instanceof ChangeDataSource) {
-        ArrayList<Change> r = new ArrayList();
+        ArrayList<Change> r = new ArrayList<Change>();
         HashSet<Change.Id> want = new HashSet<Change.Id>();
         for (ChangeData d : ((ChangeDataSource) s).read()) {
           if (d.hasChange()) {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
index 4fd8e28..3951554 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/AccountServiceImpl.java
@@ -103,7 +103,6 @@
       AsyncCallback<VoidResult> callback) {
     run(callback, new Action<VoidResult>(){
       public VoidResult run(ReviewDb db) throws OrmException {
-        Account.Id accountId = getAccountId();
         if (!diffPref.getAccountId().equals(getAccountId())) {
           throw new IllegalArgumentException("diffPref.getAccountId() "
               + diffPref.getAccountId() + " doesn't match"
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
index d5cd0ff..874cc74 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/CreateGroup.java
@@ -20,7 +20,6 @@
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.account.PerformCreateGroup;
-import com.google.gerrit.server.account.PerformCreateGroup;
 import com.google.gwtorm.client.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
index 9e8a24d..a564907 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/account/GroupAdminServiceImpl.java
@@ -46,7 +46,6 @@
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Comparator;
-import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
 
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
index 00d83e2..560b155 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailFactory.java
@@ -194,7 +194,7 @@
       NoSuchEntityException, PatchSetInfoNotAvailableException,
       NoSuchChangeException {
     final PatchSet.Id psId = detail.getChange().currentPatchSetId();
-    final PatchSetDetailFactory loader = patchSetDetail.create(psId);
+    final PatchSetDetailFactory loader = patchSetDetail.create(psId, null, null);
     loader.patchSet = detail.getCurrentPatchSet();
     loader.control = control;
     detail.setCurrentPatchSetDetail(loader.call());
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
index ebb4502..f131123 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/ChangeDetailServiceImpl.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.common.data.IncludedInDetail;
 import com.google.gerrit.common.data.PatchSetDetail;
 import com.google.gerrit.common.data.PatchSetPublishDetail;
+import com.google.gerrit.reviewdb.AccountDiffPreference;
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.PatchSet;
 import com.google.gwt.user.client.rpc.AsyncCallback;
@@ -51,9 +52,10 @@
     includedInDetail.create(id).to(callback);
   }
 
-  public void patchSetDetail(final PatchSet.Id id,
+  public void patchSetDetail(final PatchSet.Id idA, final PatchSet.Id idB,
+      final AccountDiffPreference diffPrefs,
       final AsyncCallback<PatchSetDetail> callback) {
-    patchSetDetail.create(id).to(callback);
+    patchSetDetail.create(idA, idB, diffPrefs).to(callback);
   }
 
   public void patchSetPublishDetail(final PatchSet.Id id,
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
index 0fcdf40..d7c5fc7 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/PatchSetDetailFactory.java
@@ -18,15 +18,20 @@
 import com.google.gerrit.common.errors.NoSuchEntityException;
 import com.google.gerrit.httpd.rpc.Handler;
 import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.AccountDiffPreference;
 import com.google.gerrit.reviewdb.AccountPatchReview;
 import com.google.gerrit.reviewdb.Patch;
 import com.google.gerrit.reviewdb.PatchLineComment;
 import com.google.gerrit.reviewdb.PatchSet;
+import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.reviewdb.AccountDiffPreference.Whitespace;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.GitRepositoryManager;
 import com.google.gerrit.server.patch.PatchList;
 import com.google.gerrit.server.patch.PatchListCache;
+import com.google.gerrit.server.patch.PatchListKey;
 import com.google.gerrit.server.patch.PatchSetInfoFactory;
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.ChangeControl;
@@ -35,54 +40,92 @@
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.Repository;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import javax.annotation.Nullable;
+
 /** Creates a {@link PatchSetDetail} from a {@link PatchSet}. */
 class PatchSetDetailFactory extends Handler<PatchSetDetail> {
+
+  private static final Logger log =
+    LoggerFactory.getLogger(PatchSetDetailFactory.class);
+
   interface Factory {
-    PatchSetDetailFactory create(PatchSet.Id id);
+    PatchSetDetailFactory create(@Assisted("psIdNew") PatchSet.Id psIdA,
+        @Assisted("psIdOld") PatchSet.Id psIdB, AccountDiffPreference diffPrefs);
   }
 
+  private final GitRepositoryManager repoManager;
+
   private final PatchSetInfoFactory infoFactory;
   private final ReviewDb db;
   private final PatchListCache patchListCache;
   private final ChangeControl.Factory changeControlFactory;
 
-  private final PatchSet.Id psId;
+  private Project.NameKey projectKey;
+  private final PatchSet.Id psIdNew;
+  private final PatchSet.Id psIdOld;
+  private final AccountDiffPreference diffPrefs;
+  private ObjectId oldId;
+  private ObjectId newId;
 
   private PatchSetDetail detail;
   ChangeControl control;
   PatchSet patchSet;
 
   @Inject
-  PatchSetDetailFactory(final PatchSetInfoFactory psif, final ReviewDb db,
+  PatchSetDetailFactory(final GitRepositoryManager grm,
+      final PatchSetInfoFactory psif, final ReviewDb db,
       final PatchListCache patchListCache,
       final ChangeControl.Factory changeControlFactory,
-      @Assisted final PatchSet.Id id) {
+      @Assisted("psIdNew") final PatchSet.Id psIdNew,
+      @Assisted("psIdOld") @Nullable final PatchSet.Id psIdOld,
+      @Assisted @Nullable final AccountDiffPreference diffPrefs) {
+    this.repoManager = grm;
     this.infoFactory = psif;
     this.db = db;
     this.patchListCache = patchListCache;
     this.changeControlFactory = changeControlFactory;
 
-    this.psId = id;
+    this.psIdNew = psIdNew;
+    this.psIdOld = psIdOld;
+    this.diffPrefs = diffPrefs;
   }
 
+  @SuppressWarnings("deprecation")
   @Override
   public PatchSetDetail call() throws OrmException, NoSuchEntityException,
       PatchSetInfoNotAvailableException, NoSuchChangeException {
     if (control == null || patchSet == null) {
-      control = changeControlFactory.validateFor(psId.getParentKey());
-      patchSet = db.patchSets().get(psId);
+      control = changeControlFactory.validateFor(psIdNew.getParentKey());
+      patchSet = db.patchSets().get(psIdNew);
       if (patchSet == null) {
         throw new NoSuchEntityException();
       }
     }
 
-    final PatchList list = patchListCache.get(control.getChange(), patchSet);
-    if (list == null) {
-      throw new NoSuchEntityException();
+    final PatchList list;
+
+    if (psIdOld != null) {
+      newId = toObjectId(psIdNew);
+      oldId = psIdOld != null ? toObjectId(psIdOld) : null;
+
+      projectKey = control.getProject().getNameKey();
+
+      list = listFor(keyFor(diffPrefs.getIgnoreWhitespace()));
+    } else { // OK, means use base to compare
+      list = patchListCache.get(control.getChange(), patchSet);
+      if (list == null) {
+        throw new NoSuchEntityException();
+      }
     }
 
     final List<Patch> patches = list.toPatchList(patchSet.getId());
@@ -91,7 +134,7 @@
       byKey.put(p.getKey(), p);
     }
 
-    for (final PatchLineComment c : db.patchComments().published(psId)) {
+    for (final PatchLineComment c : db.patchComments().published(psIdNew)) {
       final Patch p = byKey.get(c.getKey().getParentKey());
       if (p != null) {
         p.setCommentCount(p.getCommentCount() + 1);
@@ -101,7 +144,7 @@
     detail = new PatchSetDetail();
     detail.setPatchSet(patchSet);
 
-    detail.setInfo(infoFactory.get(psId));
+    detail.setInfo(infoFactory.get(psIdNew));
     detail.setPatches(patches);
 
     final CurrentUser user = control.getCurrentUser();
@@ -111,14 +154,14 @@
       // quickly locate where they have pending drafts, and review them.
       //
       final Account.Id me = ((IdentifiedUser) user).getAccountId();
-      for (final PatchLineComment c : db.patchComments().draft(psId, me)) {
+      for (final PatchLineComment c : db.patchComments().draft(psIdNew, me)) {
         final Patch p = byKey.get(c.getKey().getParentKey());
         if (p != null) {
           p.setDraftCount(p.getDraftCount() + 1);
         }
       }
 
-      for (AccountPatchReview r : db.accountPatchReviews().byReviewer(me, psId)) {
+      for (AccountPatchReview r : db.accountPatchReviews().byReviewer(me, psIdNew)) {
         final Patch p = byKey.get(r.getKey().getPatchKey());
         if (p != null) {
           p.setReviewedByCurrentUser(true);
@@ -128,4 +171,27 @@
 
     return detail;
   }
+
+  private ObjectId toObjectId(final PatchSet.Id psId) throws OrmException,
+      NoSuchEntityException {
+    final PatchSet ps = db.patchSets().get(psId);
+    if (ps == null) {
+      throw new NoSuchEntityException();
+    }
+
+    try {
+      return ObjectId.fromString(ps.getRevision().get());
+    } catch (IllegalArgumentException e) {
+      log.error("Patch set " + psId + " has invalid revision");
+      throw new NoSuchEntityException();
+    }
+  }
+
+  private PatchListKey keyFor(final Whitespace whitespace) {
+    return new PatchListKey(projectKey, oldId, newId, whitespace);
+  }
+
+  private PatchList listFor(final PatchListKey key) {
+    return patchListCache.get(key);
+  }
 }
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChange.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChange.java
index 4a67260..f951439 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChange.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/changedetail/RestoreChange.java
@@ -26,14 +26,11 @@
 import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
 import com.google.gerrit.server.project.ChangeControl;
 import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.client.AtomicUpdate;
 import com.google.gwtorm.client.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
 
 import javax.annotation.Nullable;
-import java.util.Collections;
-import java.util.List;
 
 class RestoreChange extends Handler<ChangeDetail> {
   interface Factory {
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java
index 9d508e2..efe93f5 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/patch/AddReviewer.java
@@ -132,11 +132,16 @@
 
     // Email the reviewers
     //
-    final AddReviewerSender cm;
-    cm = addReviewerSenderFactory.create(control.getChange());
-    cm.setFrom(currentUser.getAccountId());
-    cm.addReviewers(added);
-    cm.send();
+    // The user knows they added themselves, don't bother emailing them.
+    added.remove(currentUser.getAccountId());
+    if (!added.isEmpty()) {
+      final AddReviewerSender cm;
+
+      cm = addReviewerSenderFactory.create(control.getChange());
+      cm.setFrom(currentUser.getAccountId());
+      cm.addReviewers(added);
+      cm.send();
+    }
 
     result.setChange(changeDetailFactory.create(changeId).call());
     return result;
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
index 30176ef..6870ca4 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/http/jetty/ProjectQoSFilter.java
@@ -90,7 +90,6 @@
   private final ServletContext context;
   private final long maxWait;
 
-  @SuppressWarnings("unchecked")
   @Inject
   ProjectQoSFilter(final Provider<CurrentUser> userProvider,
       QueueProvider queue, final ServletContext context,
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
index 780cc72..a5c7d9b 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/InitAuth.java
@@ -75,9 +75,8 @@
         ldap.string("LDAP username", "username", null);
         ldap.password("username", "password");
 
-        final String def_dn = dnOf(server);
-        String aBase = ldap.string("Account BaseDN", "accountBase", def_dn);
-        String gBase = ldap.string("Group BaseDN", "groupBase", aBase);
+        String aBase = ldap.string("Account BaseDN", "accountBase", dnOf(server));
+        ldap.string("Group BaseDN", "groupBase", aBase);
         break;
       }
     }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
index e5ca2c6..8e3306b 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -32,7 +32,6 @@
 import com.google.inject.name.Names;
 import com.google.inject.spi.Message;
 
-import org.apache.commons.dbcp.SQLNestedException;
 import org.kohsuke.args4j.Option;
 
 import java.io.File;
@@ -176,10 +175,7 @@
       if (why instanceof OrmException && why.getCause() != null
           && "Unable to determine driver URL".equals(why.getMessage())) {
         why = why.getCause();
-        if (why instanceof SQLNestedException
-            && why.getCause() != null
-            && why.getMessage().startsWith(
-                "Cannot create PoolableConnectionFactory")) {
+        if (isCannotCreatePoolException(why)) {
           throw die("Cannot connect to SQL database", why.getCause());
         }
         throw die("Cannot connect to SQL database", why);
@@ -200,4 +196,12 @@
       throw die(buf.toString(), new RuntimeException("DbInjector failed", ce));
     }
   }
+
+  @SuppressWarnings("deprecation")
+  private static boolean isCannotCreatePoolException(Throwable why) {
+    return why instanceof org.apache.commons.dbcp.SQLNestedException
+        && why.getCause() != null
+        && why.getMessage().startsWith(
+            "Cannot create PoolableConnectionFactory");
+  }
 }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java
index e4ae63d..a869423 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/Change.java
@@ -370,13 +370,11 @@
   }
 
   /** Legacy 32 bit integer identity for a change. */
-  @Deprecated
   public Change.Id getId() {
     return changeId;
   }
 
   /** Legacy 32 bit integer identity for a change. */
-  @Deprecated
   public int getChangeId() {
     return changeId.get();
   }
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java
index 39fd8fa..839dbfd 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/PatchSetInfo.java
@@ -14,11 +14,26 @@
 
 package com.google.gerrit.reviewdb;
 
+import java.util.List;
+
 
 /**
  * Additional data about a {@link PatchSet} not normally loaded.
  */
 public final class PatchSetInfo {
+  public static class ParentInfo {
+    public RevId id;
+    public String shortMessage;
+
+    public ParentInfo(final RevId id, final String shortMessage) {
+      this.id = id;
+      this.shortMessage = shortMessage;
+    }
+
+    protected ParentInfo() {
+    }
+  }
+
   protected PatchSet.Id key;
 
   /** First line of {@link #message}. */
@@ -33,6 +48,9 @@
   /** Identity of who committed the patch set to the VCS. */
   protected UserIdentity committer;
 
+  /** List of parents of the patch set. */
+  protected List<ParentInfo> parents;
+
   protected PatchSetInfo() {
   }
 
@@ -79,4 +97,12 @@
   public void setCommitter(final UserIdentity u) {
     committer = u;
   }
+
+  public void setParents(final List<ParentInfo> p) {
+    parents = p;
+  }
+
+  public List<ParentInfo> getParents() {
+    return parents;
+  }
 }
diff --git a/gerrit-server/pom.xml b/gerrit-server/pom.xml
index 0a9ece3..974302b 100644
--- a/gerrit-server/pom.xml
+++ b/gerrit-server/pom.xml
@@ -91,11 +91,6 @@
     </dependency>
 
     <dependency>
-      <groupId>org.antlr</groupId>
-      <artifactId>antlr</artifactId>
-    </dependency>
-
-    <dependency>
       <groupId>com.google.code.guice</groupId>
       <artifactId>guice</artifactId>
     </dependency>
@@ -117,6 +112,12 @@
 
     <dependency>
       <groupId>com.google.gerrit</groupId>
+      <artifactId>gerrit-antlr</artifactId>
+      <version>${project.version}</version>
+    </dependency>
+
+    <dependency>
+      <groupId>com.google.gerrit</groupId>
       <artifactId>gerrit-common</artifactId>
       <version>${project.version}</version>
     </dependency>
@@ -154,20 +155,4 @@
       <artifactId>automaton</artifactId>
     </dependency>
   </dependencies>
-
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.antlr</groupId>
-        <artifactId>antlr3-maven-plugin</artifactId>
-        <executions>
-          <execution>
-            <goals>
-              <goal>antlr</goal>
-            </goals>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
 </project>
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
index 751d215..0d8d19a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/CurrentUser.java
@@ -69,7 +69,6 @@
     return getEffectiveGroups().contains(authConfig.getBatchUsersGroup());
   }
 
-  @Deprecated
   public final boolean isAdministrator() {
     return getEffectiveGroups().contains(authConfig.getAdministratorsGroup());
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/MimeUtilFileTypeRegistry.java b/gerrit-server/src/main/java/com/google/gerrit/server/MimeUtilFileTypeRegistry.java
index 36e9327..792c1e7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/MimeUtilFileTypeRegistry.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/MimeUtilFileTypeRegistry.java
@@ -60,6 +60,7 @@
     mimeUtil.registerMimeDetector(name);
   }
 
+  @SuppressWarnings("unchecked")
   public MimeType getMimeType(final String path, final byte[] content) {
     Set<MimeType> mimeTypes = new HashSet<MimeType>();
     if (content != null && content.length > 0) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
index e422b19..26dec09 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/PeerDaemonUser.java
@@ -17,7 +17,6 @@
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.AccountProjectWatch;
 import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project.NameKey;
 import com.google.gerrit.server.config.AuthConfig;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapType.java b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapType.java
index 56a6eec..3c4a54b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapType.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/auth/ldap/LdapType.java
@@ -84,8 +84,6 @@
   }
 
   private static class ActiveDirectory extends LdapType {
-    private final String defaultDomain;
-
     ActiveDirectory(final Attributes atts) throws NamingException {
       // Convert "defaultNamingContext: DC=foo,DC=example,DC=com" into
       // the a standard DNS name as we would expect to find in the suffix
@@ -95,17 +93,6 @@
       if (defaultNamingContext == null || defaultNamingContext.size() < 1) {
         throw new NamingException("rootDSE has no defaultNamingContext");
       }
-
-      final StringBuilder b = new StringBuilder();
-      for (String n : ((String) defaultNamingContext.get(0)).split(", *")) {
-        if (n.toUpperCase().startsWith("DC=")) {
-          if (b.length() > 0) {
-            b.append('.');
-          }
-          b.append(n.substring(3));
-        }
-      }
-      defaultDomain = b.toString();
     }
 
     @Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/cache/ProxyEhcache.java b/gerrit-server/src/main/java/com/google/gerrit/server/cache/ProxyEhcache.java
index 8b3179a..bcead63 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/cache/ProxyEhcache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/cache/ProxyEhcache.java
@@ -105,7 +105,7 @@
     return self().get(key);
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   public Map getAllWithLoader(Collection keys, Object loaderArgument)
       throws CacheException {
     return self().getAllWithLoader(keys, loaderArgument);
@@ -151,17 +151,17 @@
     return self().getGuid();
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   public List getKeys() throws IllegalStateException, CacheException {
     return self().getKeys();
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   public List getKeysNoDuplicateCheck() throws IllegalStateException {
     return self().getKeysNoDuplicateCheck();
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   public List getKeysWithExpiryCheck() throws IllegalStateException,
       CacheException {
     return self().getKeysWithExpiryCheck();
@@ -251,7 +251,7 @@
     self().load(key);
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   public void loadAll(Collection keys, Object argument) throws CacheException {
     self().loadAll(keys, argument);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
index 927e88ee..f24dcc5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/ConfigUtil.java
@@ -152,7 +152,6 @@
    *        Must not be null as the enumeration values are derived from this.
    * @return the selected enumeration values list, or {@code defaultValue}.
    */
-  @SuppressWarnings("unchecked")
   public static <T extends Enum<?>> List<T> getEnumList(final Config config,
       final String section, final String subsection, final String setting,
       final T defaultValue) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
index c3ee776..f6dad7d 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritRequestModule.java
@@ -22,6 +22,7 @@
 import com.google.gerrit.server.account.AccountResolver;
 import com.google.gerrit.server.account.GroupControl;
 import com.google.gerrit.server.account.PerformCreateGroup;
+import com.google.gerrit.server.git.CreateCodeReviewNotes;
 import com.google.gerrit.server.git.MergeOp;
 import com.google.gerrit.server.git.ReceiveCommits;
 import com.google.gerrit.server.mail.AbandonedSender;
@@ -58,6 +59,7 @@
     factory(ChangeQueryBuilder.Factory.class);
     factory(ReceiveCommits.Factory.class);
     factory(MergeOp.Factory.class);
+    factory(CreateCodeReviewNotes.Factory.class);
 
     // Not really per-request, but dammit, I don't know where else to
     // easily park this stuff.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewNoteCreationException.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewNoteCreationException.java
new file mode 100644
index 0000000..90de785
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CodeReviewNoteCreationException.java
@@ -0,0 +1,35 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+package com.google.gerrit.server.git;
+
+/**
+ * Thrown when creation of a code review note fails.
+ */
+public class CodeReviewNoteCreationException extends Exception {
+  private static final long serialVersionUID = 1L;
+
+  public CodeReviewNoteCreationException(final String msg) {
+    super(msg);
+  }
+
+  public CodeReviewNoteCreationException(final Throwable why) {
+    super(why);
+  }
+
+  public CodeReviewNoteCreationException(final CodeReviewCommit commit,
+      final Throwable cause) {
+    super("Couldn't create code review note for the following commit: "
+        + commit, cause);
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
new file mode 100644
index 0000000..67705e4
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/CreateCodeReviewNotes.java
@@ -0,0 +1,260 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import com.google.gerrit.common.data.ApprovalTypes;
+import com.google.gerrit.reviewdb.ApprovalCategory;
+import com.google.gerrit.reviewdb.PatchSetApproval;
+import com.google.gerrit.reviewdb.ReviewDb;
+import com.google.gerrit.server.GerritPersonIdent;
+import com.google.gerrit.server.account.AccountCache;
+import com.google.gerrit.server.config.CanonicalWebUrl;
+import com.google.gwtorm.client.OrmException;
+import com.google.gwtorm.client.ResultSet;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+import org.eclipse.jgit.lib.CommitBuilder;
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.ObjectId;
+import org.eclipse.jgit.lib.ObjectInserter;
+import org.eclipse.jgit.lib.ObjectReader;
+import org.eclipse.jgit.lib.PersonIdent;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefUpdate;
+import org.eclipse.jgit.lib.RefUpdate.Result;
+import org.eclipse.jgit.lib.Repository;
+import org.eclipse.jgit.notes.DefaultNoteMerger;
+import org.eclipse.jgit.notes.Note;
+import org.eclipse.jgit.notes.NoteMap;
+import org.eclipse.jgit.notes.NoteMapMerger;
+import org.eclipse.jgit.revwalk.FooterKey;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * This class create code review notes for given {@link CodeReviewCommit}s.
+ * <p>
+ * After the {@link #create(List, PersonIdent)} method is invoked once this
+ * instance must not be reused. Create a new instance of this class if needed.
+ */
+public class CreateCodeReviewNotes {
+  public interface Factory {
+    CreateCodeReviewNotes create(Repository db);
+  }
+
+  static final String REFS_NOTES_REVIEW = "refs/notes/review";
+  private static final int MAX_LOCK_FAILURE_CALLS = 10;
+  private static final int SLEEP_ON_LOCK_FAILURE_MS = 25;
+  private static final FooterKey CHANGE_ID = new FooterKey("Change-Id");
+
+  private final ReviewDb schema;
+  private final PersonIdent gerritIdent;
+  private final AccountCache accountCache;
+  private final ApprovalTypes approvalTypes;
+  private final String canonicalWebUrl;
+  private final Repository db;
+  private final RevWalk revWalk;
+  private final ObjectInserter inserter;
+  private final ObjectReader reader;
+
+  private RevCommit baseCommit;
+  private NoteMap base;
+
+  private RevCommit oursCommit;
+  private NoteMap ours;
+
+  private List<CodeReviewCommit> commits;
+  private PersonIdent author;
+
+  @Inject
+  CreateCodeReviewNotes(final ReviewDb reviewDb,
+      @GerritPersonIdent final PersonIdent gerritIdent,
+      final AccountCache accountCache,
+      final ApprovalTypes approvalTypes,
+      @CanonicalWebUrl final String canonicalWebUrl,
+      @Assisted final Repository db) {
+    schema = reviewDb;
+    this.gerritIdent = gerritIdent;
+    this.accountCache = accountCache;
+    this.approvalTypes = approvalTypes;
+    this.canonicalWebUrl = canonicalWebUrl;
+    this.db = db;
+
+    revWalk = new RevWalk(db);
+    inserter = db.newObjectInserter();
+    reader = db.newObjectReader();
+  }
+
+  public void create(List<CodeReviewCommit> commits, PersonIdent author)
+      throws CodeReviewNoteCreationException {
+    try {
+      this.commits = commits;
+      this.author = author;
+      setBase();
+      setOurs();
+
+      int remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
+      RefUpdate refUpdate = createRefUpdate(oursCommit, baseCommit);
+
+      for (;;) {
+        Result result = refUpdate.update();
+
+        if (result == Result.LOCK_FAILURE) {
+          if (--remainingLockFailureCalls > 0) {
+            Thread.sleep(SLEEP_ON_LOCK_FAILURE_MS);
+          } else {
+            throw new CodeReviewNoteCreationException(
+                "Failed to lock the ref: " + REFS_NOTES_REVIEW);
+          }
+
+        } else if (result == Result.REJECTED) {
+          RevCommit theirsCommit =
+              revWalk.parseCommit(refUpdate.getOldObjectId());
+          NoteMap theirs =
+              NoteMap.read(revWalk.getObjectReader(), theirsCommit);
+          NoteMapMerger merger = new NoteMapMerger(db);
+          NoteMap merged = merger.merge(base, ours, theirs);
+          RevCommit mergeCommit =
+              createCommit(merged, gerritIdent, "Merged note commits\n",
+                  theirsCommit, oursCommit);
+          refUpdate = createRefUpdate(mergeCommit, theirsCommit);
+          remainingLockFailureCalls = MAX_LOCK_FAILURE_CALLS;
+
+        } else if (result == Result.IO_FAILURE) {
+          throw new CodeReviewNoteCreationException(
+              "Couldn't create code review notes because of IO_FAILURE");
+        } else {
+          break;
+        }
+      }
+
+    } catch (IOException e) {
+      throw new CodeReviewNoteCreationException(e);
+    } catch (InterruptedException e) {
+      throw new CodeReviewNoteCreationException(e);
+    } finally {
+      reader.release();
+      inserter.release();
+      revWalk.release();
+    }
+  }
+
+  private void setBase() throws IOException {
+    Ref notesBranch = db.getRef(REFS_NOTES_REVIEW);
+    if (notesBranch != null) {
+      baseCommit = revWalk.parseCommit(notesBranch.getObjectId());
+      base = NoteMap.read(revWalk.getObjectReader(), baseCommit);
+    }
+  }
+
+  private void setOurs() throws IOException, CodeReviewNoteCreationException {
+    if (baseCommit != null) {
+      ours = NoteMap.read(db.newObjectReader(), baseCommit);
+    } else {
+      ours = NoteMap.newEmptyMap();
+    }
+
+    StringBuilder message =
+        new StringBuilder("Update notes for submitted changes\n\n");
+    for (CodeReviewCommit c : commits) {
+      ObjectId noteContent = createNoteContent(c);
+      if (ours.contains(c)) {
+        // merge the existing and the new note as if they are both new
+        // means: base == null
+        // there is not really a common ancestry for these two note revisions
+        // use the same NoteMerger that is used from the NoteMapMerger
+        DefaultNoteMerger noteMerger = new DefaultNoteMerger();
+        Note newNote = new Note(c, noteContent);
+        noteContent =
+            noteMerger.merge(null, newNote, base.getNote(c), reader, inserter)
+                .getData();
+      }
+      ours.set(c, noteContent);
+
+      message.append("* ").append(c.getShortMessage()).append("\n");
+    }
+
+    if (baseCommit != null) {
+      oursCommit = createCommit(ours, author, message.toString(), baseCommit);
+    } else {
+      oursCommit = createCommit(ours, author, message.toString());
+    }
+  }
+
+  private ObjectId createNoteContent(CodeReviewCommit commit)
+      throws CodeReviewNoteCreationException, IOException {
+    try {
+      ReviewNoteHeaderFormatter formatter =
+        new ReviewNoteHeaderFormatter(author.getTimeZone());
+      final List<String> idList = commit.getFooterLines(CHANGE_ID);
+      if (idList.isEmpty())
+        formatter.appendChangeId(commit.change.getKey());
+      ResultSet<PatchSetApproval> approvals =
+        schema.patchSetApprovals().byPatchSet(commit.patchsetId);
+      PatchSetApproval submit = null;
+      for (PatchSetApproval a : approvals) {
+        if (ApprovalCategory.SUBMIT.equals(a.getCategoryId())) {
+          submit = a;
+        } else {
+          formatter.appendApproval(
+              approvalTypes.getApprovalType(a.getCategoryId()).getCategory(),
+              a.getValue(),
+              accountCache.get(a.getAccountId()).getAccount());
+        }
+      }
+
+      formatter.appendSubmittedBy(accountCache.get(submit.getAccountId()).getAccount());
+      formatter.appendSubmittedAt(submit.getGranted());
+
+      formatter.appendReviewedOn(canonicalWebUrl, commit.change.getId());
+      formatter.appendProject(commit.change.getProject().get());
+      formatter.appendBranch(commit.change.getDest());
+      return inserter.insert(Constants.OBJ_BLOB, formatter.toString().getBytes("UTF-8"));
+    } catch (OrmException e) {
+      throw new CodeReviewNoteCreationException(commit, e);
+    }
+  }
+
+  private RevCommit createCommit(NoteMap map, PersonIdent author,
+      String message, RevCommit... parents) throws IOException {
+    CommitBuilder b = new CommitBuilder();
+    b.setTreeId(map.writeTree(inserter));
+    b.setAuthor(author);
+    b.setCommitter(gerritIdent);
+    if (parents.length > 0) {
+      b.setParentIds(parents);
+    }
+    b.setMessage(message);
+    ObjectId commitId = inserter.insert(b);
+    inserter.flush();
+    return revWalk.parseCommit(commitId);
+  }
+
+
+  private RefUpdate createRefUpdate(ObjectId newObjectId, ObjectId expectedOldObjectId) throws IOException {
+    RefUpdate refUpdate = db.updateRef(REFS_NOTES_REVIEW);
+    refUpdate.setNewObjectId(newObjectId);
+    if (expectedOldObjectId == null) {
+      refUpdate.setExpectedOldObjectId(ObjectId.zeroId());
+    } else {
+      refUpdate.setExpectedOldObjectId(expectedOldObjectId);
+    }
+    return refUpdate;
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index f8b287c..60016e5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -156,6 +156,7 @@
 
   private final ChangeHookRunner hooks;
   private final AccountCache accountCache;
+  private final CreateCodeReviewNotes.Factory codeReviewNotesFactory;
 
   @Inject
   MergeOp(final GitRepositoryManager grm, final SchemaFactory<ReviewDb> sf,
@@ -167,7 +168,8 @@
       final IdentifiedUser.GenericFactory iuf,
       @GerritPersonIdent final PersonIdent myIdent,
       final MergeQueue mergeQueue, @Assisted final Branch.NameKey branch,
-      final ChangeHookRunner hooks, final AccountCache accountCache) {
+      final ChangeHookRunner hooks, final AccountCache accountCache,
+      final CreateCodeReviewNotes.Factory crnf) {
     repoManager = grm;
     schemaFactory = sf;
     functionState = fs;
@@ -182,6 +184,7 @@
     this.mergeQueue = mergeQueue;
     this.hooks = hooks;
     this.accountCache = accountCache;
+    codeReviewNotesFactory = crnf;
 
     this.myIdent = myIdent;
     destBranch = branch;
@@ -527,8 +530,22 @@
       }
     }
 
+    PersonIdent authorIdent = computeAuthor(merged);
+
+    final CommitBuilder mergeCommit = new CommitBuilder();
+    mergeCommit.setTreeId(m.getResultTreeId());
+    mergeCommit.setParentIds(mergeTip, n);
+    mergeCommit.setAuthor(authorIdent);
+    mergeCommit.setCommitter(myIdent);
+    mergeCommit.setMessage(msgbuf.toString());
+
+    mergeTip = (CodeReviewCommit) rw.parseCommit(commit(m, mergeCommit));
+  }
+
+  private PersonIdent computeAuthor(
+      final List<CodeReviewCommit> codeReviewCommits) {
     PatchSetApproval submitter = null;
-    for (final CodeReviewCommit c : merged) {
+    for (final CodeReviewCommit c : codeReviewCommits) {
       PatchSetApproval s = getSubmitter(c.patchsetId);
       if (submitter == null
           || (s != null && s.getGranted().compareTo(submitter.getGranted()) > 0)) {
@@ -547,7 +564,7 @@
       IdentifiedUser who =
           identifiedUserFactory.create(submitter.getAccountId());
       Set<String> emails = new HashSet<String>();
-      for (RevCommit c : merged) {
+      for (RevCommit c : codeReviewCommits) {
         emails.add(c.getAuthorIdent().getEmailAddress());
       }
 
@@ -555,22 +572,15 @@
       final TimeZone tz = myIdent.getTimeZone();
       if (emails.size() == 1
           && who.getEmailAddresses().contains(emails.iterator().next())) {
-        authorIdent = new PersonIdent(merged.get(0).getAuthorIdent(), dt, tz);
+        authorIdent =
+            new PersonIdent(codeReviewCommits.get(0).getAuthorIdent(), dt, tz);
       } else {
         authorIdent = who.newCommitterIdent(dt, tz);
       }
     } else {
       authorIdent = myIdent;
     }
-
-    final CommitBuilder mergeCommit = new CommitBuilder();
-    mergeCommit.setTreeId(m.getResultTreeId());
-    mergeCommit.setParentIds(mergeTip, n);
-    mergeCommit.setAuthor(authorIdent);
-    mergeCommit.setCommitter(myIdent);
-    mergeCommit.setMessage(msgbuf.toString());
-
-    mergeTip = (CodeReviewCommit) rw.parseCommit(commit(m, mergeCommit));
+    return authorIdent;
   }
 
   private void markCleanMerges() throws MergeException {
@@ -899,7 +909,9 @@
     }
   }
 
-  private void updateChangeStatus() {
+  private void updateChangeStatus() throws MergeException {
+    List<CodeReviewCommit> merged = new ArrayList<CodeReviewCommit>();
+
     for (final Change c : submitted) {
       final CodeReviewCommit commit = commits.get(c.getId());
       final CommitMergeStatus s = commit != null ? commit.statusCode : null;
@@ -915,6 +927,7 @@
           final String txt =
               "Change has been successfully merged into the git repository.";
           setMerged(c, message(c, txt));
+          merged.add(commit);
           break;
         }
 
@@ -923,11 +936,13 @@
               "Change has been successfully cherry-picked as " + commit.name()
                   + ".";
           setMerged(c, message(c, txt));
+          merged.add(commit);
           break;
         }
 
         case ALREADY_MERGED:
           setMerged(c, null);
+          merged.add(commit);
           break;
 
         case PATH_CONFLICT: {
@@ -976,6 +991,15 @@
           break;
       }
     }
+
+    CreateCodeReviewNotes codeReviewNotes = codeReviewNotesFactory.create(db);
+    try {
+      codeReviewNotes.create(merged, computeAuthor(merged));
+    } catch (CodeReviewNoteCreationException e) {
+      log.error(e.getMessage());
+    }
+    replication.scheduleUpdate(destBranch.getParentKey(),
+        CreateCodeReviewNotes.REFS_NOTES_REVIEW);
   }
 
   private void dependencyError(final CodeReviewCommit commit) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index 712afa8..445974f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -735,14 +735,14 @@
     destBranchCtl = projectControl.controlForRef(destBranch);
     if (!destBranchCtl.canUpload()) {
       reject(cmd);
+      return;
     }
 
-    // Validate that the new commits are connected with the existing heads
-    // or tags of this repository. If they aren't, we want to abort. We do
-    // this check by coloring the tip CONNECTED and letting a RevWalk push
-    // that color through the graph until it reaches at least one of our
-    // already existing heads or tags. We then test to see if that color
-    // made it back onto that set.
+    // Validate that the new commits are connected with the target branch.
+    // If they aren't, we want to abort. We do this check by coloring the
+    // tip CONNECTED and letting a RevWalk push that color through the graph
+    // until it reaches the head of the target branch. We then test to see
+    // if that color made it back onto that set.
     //
     try {
       final RevWalk walk = rp.getRevWalk();
@@ -762,33 +762,28 @@
       tip.add(SIDE_NEW);
       walk.markStart(tip);
 
-      boolean haveHeads = false;
-      for (final Ref r : rp.getAdvertisedRefs().values()) {
-        if (isHead(r) || isTag(r)) {
-          try {
-            final RevCommit h = walk.parseCommit(r.getObjectId());
-            h.add(SIDE_HAVE);
-            walk.markStart(h);
-            haveHeads = true;
-          } catch (IOException e) {
-            continue;
-          }
-        }
+      Ref targetRef = rp.getAdvertisedRefs().get(destBranchName);
+      if (targetRef == null || targetRef.getObjectId() == null) {
+        // The destination branch does not yet exist. Assume the
+        // history being sent for review will start it and thus
+        // is "connected" to the branch.
+        return;
       }
 
-      if (haveHeads) {
-        boolean isConnected = false;
-        RevCommit c;
-        while ((c = walk.next()) != null) {
-          if (c.hasAll(COMMON)) {
-            isConnected = true;
-            break;
-          }
+      final RevCommit h = walk.parseCommit(targetRef.getObjectId());
+      h.add(SIDE_HAVE);
+      walk.markStart(h);
+      boolean isConnected = false;
+      RevCommit c;
+      while ((c = walk.next()) != null) {
+        if (c.hasAll(COMMON)) {
+          isConnected = true;
+          break;
         }
-        if (!isConnected) {
-          reject(newChange, "no common ancestry");
-          return;
-        }
+      }
+      if (!isConnected) {
+        reject(newChange, "no common ancestry");
+        return;
       }
     } catch (IOException e) {
       newChange.setResult(Result.REJECTED_MISSING_OBJECT);
@@ -1617,7 +1612,9 @@
     if (idList.isEmpty()) {
       if (project.isRequireChangeID() && (cmd.getRefName().startsWith(NEW_CHANGE)
   || NEW_PATCHSET.matcher(cmd.getRefName()).matches())) {
-        reject(cmd, "missing Change-Id in commit message");
+        String errMsg = "missing Change-Id in commit message";
+        reject(cmd, errMsg);
+        rp.sendMessage(getFixedCommitMsgWithChangeId(errMsg, c));
         return false;
       }
     } else if (idList.size() > 1) {
@@ -1626,7 +1623,9 @@
     } else {
       final String v = idList.get(idList.size() - 1).trim();
       if (!v.matches("^I[0-9a-f]{8,}.*$")) {
-        reject(cmd, "invalid Change-Id line format in commit message ");
+        final String errMsg = "missing or invalid Change-Id line format in commit message";
+        reject(cmd, errMsg);
+        rp.sendMessage(getFixedCommitMsgWithChangeId(errMsg, c));
         return false;
       }
     }
@@ -1640,6 +1639,44 @@
     return true;
   }
 
+  private String getFixedCommitMsgWithChangeId(String errMsg, RevCommit c) {
+    // We handle 3 cases:
+    // 1. No change id in the commit message at all.
+    // 2. change id last in the commit message but missing empty line to create the footer.
+    // 3. there is a change-id somewhere in the commit message, but we ignore it.
+    final String changeId = "Change-Id:";
+    StringBuilder sb = new StringBuilder();
+    sb.append("ERROR: ").append(errMsg);
+    sb.append("\n");
+    sb.append("Suggestion for commit message:\n");
+
+    if (c.getFullMessage().indexOf(changeId)==-1) {
+      sb.append(c.getFullMessage());
+      sb.append("\n");
+      sb.append(changeId).append(" I").append(c.name());
+    } else {
+      String lines[] = c.getFullMessage().trim().split("\n");
+      String lastLine = lines.length > 0 ? lines[lines.length - 1] : "";
+
+      if (lastLine.indexOf(changeId)==0) {
+        for (int i = 0; i < lines.length - 1; i++) {
+          sb.append(lines[i]);
+          sb.append("\n");
+        }
+
+        sb.append("\n");
+        sb.append(lastLine);
+      } else {
+        sb.append(c.getFullMessage());
+        sb.append("\n");
+        sb.append(changeId).append(" I").append(c.name());
+        sb.append("\nHint: A potential Change-Id was found, but it was not in the footer of the commit message.");
+      }
+    }
+
+    return sb.toString();
+  }
+
   private void sendInvalidEmailError(RevCommit c, String type, PersonIdent who) {
     StringBuilder sb = new StringBuilder();
     sb.append("\n");
@@ -1817,7 +1854,7 @@
       msgBuf.append(" into ");
       if (mergedIntoRef.startsWith(Constants.R_HEADS)) {
         msgBuf.append("branch ");
-        msgBuf.append(repo.shortenRefName(mergedIntoRef));
+        msgBuf.append(Repository.shortenRefName(mergedIntoRef));
       } else {
         msgBuf.append(mergedIntoRef);
       }
@@ -1849,8 +1886,6 @@
         final MergedSender cm = mergedSenderFactory.create(result.change);
         cm.setFrom(currentUser.getAccountId());
         cm.setPatchSet(result.patchSet, result.info);
-        cm.setDest(new Branch.NameKey(project.getNameKey(),
-            result.mergedIntoRef));
         cm.send();
       } catch (EmailException e) {
         final PatchSet.Id psi = result.patchSet.getId();
@@ -1888,14 +1923,6 @@
     cmd.setResult(ReceiveCommand.Result.REJECTED_OTHER_REASON, why);
   }
 
-  private static boolean isTag(final Ref ref) {
-    return ref.getName().startsWith(Constants.R_TAGS);
-  }
-
-  private static boolean isTag(final ReceiveCommand cmd) {
-    return cmd.getRefName().startsWith(Constants.R_TAGS);
-  }
-
   private static boolean isHead(final Ref ref) {
     return ref.getName().startsWith(Constants.R_HEADS);
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java
new file mode 100644
index 0000000..d54dcec
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReviewNoteHeaderFormatter.java
@@ -0,0 +1,112 @@
+// Copyright (C) 2010 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.server.git;
+
+import com.google.gerrit.reviewdb.Account;
+import com.google.gerrit.reviewdb.ApprovalCategory;
+import com.google.gerrit.reviewdb.Branch;
+import com.google.gerrit.reviewdb.Change;
+
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Formatters for code review note headers.
+ * <p>
+ * This class provides a builder like interface for building the content of a
+ * code review note. After instantiation, call as many as necessary
+ * <code>append...(...)</code> methods and, at the end, call the
+ * {@link #toString()} method to get the built note content.
+ */
+class ReviewNoteHeaderFormatter {
+
+  private final DateFormat rfc2822DateFormatter;
+  private final StringBuilder sb = new StringBuilder();
+
+  ReviewNoteHeaderFormatter(TimeZone tz) {
+    rfc2822DateFormatter =
+        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
+    rfc2822DateFormatter.setCalendar(Calendar.getInstance(tz, Locale.US));
+  }
+
+  void appendChangeId(Change.Key changeKey) {
+    sb.append("Change-Id: ").append(changeKey.get()).append("\n");
+  }
+
+  void appendApproval(ApprovalCategory category,
+      short value, Account user) {
+    // TODO: use category.getLabel() when available
+    sb.append(category.getName().replace(' ', '-'));
+    sb.append(value < 0 ? "-" : "+").append(Math.abs(value)).append(": ");
+    appendUserData(user);
+    sb.append("\n");
+  }
+
+  private void appendUserData(Account user) {
+    boolean needSpace = false;
+    boolean wroteData = false;
+
+    if (user.getFullName() != null && ! user.getFullName().isEmpty()) {
+      sb.append(user.getFullName());
+      needSpace = true;
+      wroteData = true;
+    }
+
+    if (user.getPreferredEmail() != null && ! user.getPreferredEmail().isEmpty()) {
+      if (needSpace) {
+        sb.append(" ");
+      }
+      sb.append("<").append(user.getPreferredEmail()).append(">");
+      wroteData = true;
+    }
+
+    if (!wroteData) {
+      sb.append("Anonymous Coward #").append(user.getId());
+    }
+  }
+
+  void appendProject(String projectName) {
+    sb.append("Project: ").append(projectName).append("\n");
+  }
+
+  void appendBranch(Branch.NameKey branch) {
+    sb.append("Branch: ").append(branch.get()).append("\n");
+  }
+
+  void appendSubmittedBy(Account user) {
+    sb.append("Submitted-by: ");
+    appendUserData(user);
+    sb.append("\n");
+  }
+
+  void appendSubmittedAt(Date date) {
+    sb.append("Submitted-at: ").append(rfc2822DateFormatter.format(date))
+        .append("\n");
+  }
+
+  void appendReviewedOn(String canonicalWebUrl, Change.Id changeId) {
+    sb.append("Reviewed-on: ").append(canonicalWebUrl).append(changeId.get())
+        .append("\n");
+  }
+
+  @Override
+  public String toString() {
+    return sb.toString();
+  }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
index 8e4d8ea..a692fdd 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/VisibleRefFilter.java
@@ -224,8 +224,7 @@
     // Traverse the history until the tag is found.
     //
     rw.markUninteresting(tagged);
-    RevCommit c;
-    while ((c = rw.next()) != null) {
+    while (rw.next() != null) {
     }
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
index b2a1c44..9dbabe6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/MergedSender.java
@@ -18,12 +18,11 @@
 import com.google.gerrit.common.data.ApprovalTypes;
 import com.google.gerrit.reviewdb.Account;
 import com.google.gerrit.reviewdb.AccountProjectWatch;
+import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
 import com.google.gerrit.reviewdb.ApprovalCategory;
 import com.google.gerrit.reviewdb.ApprovalCategoryValue;
-import com.google.gerrit.reviewdb.Branch;
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.PatchSetApproval;
-import com.google.gerrit.reviewdb.AccountProjectWatch.NotifyType;
 import com.google.gwtorm.client.OrmException;
 import com.google.inject.Inject;
 import com.google.inject.assistedinject.Assisted;
@@ -38,19 +37,13 @@
   }
 
   private final ApprovalTypes approvalTypes;
-  private Branch.NameKey dest;
 
   @Inject
   public MergedSender(EmailArguments ea, ApprovalTypes at, @Assisted Change c) {
     super(ea, c, "merged");
-    dest = c.getDest();
     approvalTypes = at;
   }
 
-  public void setDest(final Branch.NameKey key) {
-    dest = key;
-  }
-
   @Override
   protected void init() throws EmailException {
     super.init();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
index 9e78cab..186f57a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/NewChangeSender.java
@@ -23,7 +23,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
index 02e5000..e6a1ebc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/OutgoingEmail.java
@@ -22,7 +22,6 @@
 import org.apache.commons.lang.StringUtils;
 import org.apache.velocity.VelocityContext;
 import org.apache.velocity.app.Velocity;
-import org.apache.velocity.exception.ResourceNotFoundException;
 import org.eclipse.jgit.util.SystemReader;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
index 0c8ca9a..2ae27fa 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/ReplacePatchSetSender.java
@@ -25,7 +25,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
index 0ac1af2..358d3ba 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/IntraLineLoader.java
@@ -133,16 +133,21 @@
             + " comparing " + key.getBlobA().name() //
             + ".." + key.getBlobB().name() //
             + ".  Killing " + thread.getName());
-        try {
-          thread.stop();
-        } catch (Throwable error) {
-          // Ignore any reason the thread won't stop.
-          log.error("Cannot stop runaway thread " + thread.getName(), error);
-        }
+        forcefullyKillThreadInAnUglyWay();
         return Result.TIMEOUT;
       }
     }
 
+    @SuppressWarnings("deprecation")
+    private void forcefullyKillThreadInAnUglyWay() {
+      try {
+        thread.stop();
+      } catch (Throwable error) {
+        // Ignore any reason the thread won't stop.
+        log.error("Cannot stop runaway thread " + thread.getName(), error);
+      }
+    }
+
     void end() {
       if (!input.offer(Input.END_THREAD)) {
         log.error("Cannot gracefully stop thread " + thread.getName());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
index 1c2c97d..646d4ce 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/patch/PatchSetInfoFactory.java
@@ -19,6 +19,7 @@
 import com.google.gerrit.reviewdb.PatchSet;
 import com.google.gerrit.reviewdb.PatchSetInfo;
 import com.google.gerrit.reviewdb.Project;
+import com.google.gerrit.reviewdb.RevId;
 import com.google.gerrit.reviewdb.ReviewDb;
 import com.google.gerrit.reviewdb.UserIdentity;
 import com.google.gerrit.server.account.AccountByEmailCache;
@@ -28,6 +29,7 @@
 import com.google.inject.Inject;
 import com.google.inject.Singleton;
 
+import org.eclipse.jgit.errors.MissingObjectException;
 import org.eclipse.jgit.lib.ObjectId;
 import org.eclipse.jgit.lib.PersonIdent;
 import org.eclipse.jgit.lib.Repository;
@@ -36,6 +38,8 @@
 
 import java.io.IOException;
 import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.List;
 import java.util.Set;
 
 
@@ -81,7 +85,9 @@
       try {
         final RevCommit src =
             rw.parseCommit(ObjectId.fromString(patchSet.getRevision().get()));
-        return get(src, patchSetId);
+        PatchSetInfo info = get(src, patchSetId);
+        info.setParents(toParentInfos(src.getParents(), rw));
+        return info;
       } finally {
         rw.release();
       }
@@ -117,4 +123,17 @@
     return u;
   }
 
+  private List<PatchSetInfo.ParentInfo> toParentInfos(final RevCommit[] parents,
+      final RevWalk walk) throws IOException, MissingObjectException {
+    List<PatchSetInfo.ParentInfo> pInfos =
+      new ArrayList<PatchSetInfo.ParentInfo>(parents.length);
+    for (RevCommit parent : parents) {
+      walk.parseBody(parent);
+      RevId rev = new RevId(parent.getId().name());
+      String msg = parent.getShortMessage();
+      pInfos.add(new PatchSetInfo.ParentInfo(rev, msg));
+    }
+    return pInfos;
+  }
+
 }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
index 68e80ee..0b8e83a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/ProjectState.java
@@ -46,7 +46,7 @@
 
   private final Project project;
   private final Collection<RefRight> localRights;
-  private final Set<AccountGroup.Id> owners;
+  private final Set<AccountGroup.Id> localOwners;
 
   private volatile Collection<RefRight> inheritedRights;
 
@@ -78,11 +78,12 @@
     final HashSet<AccountGroup.Id> groups = new HashSet<AccountGroup.Id>();
     for (final RefRight right : rights) {
       if (ApprovalCategory.OWN.equals(right.getApprovalCategoryId())
-          && right.getMaxValue() > 0) {
+          && right.getMaxValue() > 0
+          && right.getRefPattern().equals(RefRight.ALL)) {
         groups.add(right.getAccountGroupId());
       }
     }
-    owners = Collections.unmodifiableSet(groups);
+    localOwners = Collections.unmodifiableSet(groups);
   }
 
   public Project getProject() {
@@ -209,8 +210,41 @@
     return project.getNameKey().equals(wildProject);
   }
 
+  /**
+   * @return all {@link AccountGroup}'s to which the owner privilege for
+   *         'refs/*' is assigned for this project (the local owners), if there
+   *         are no local owners the local owners of the nearest parent project
+   *         that has local owners are returned
+   */
   public Set<AccountGroup.Id> getOwners() {
-    return owners;
+    if (!localOwners.isEmpty() || isSpecialWildProject()
+        || project.getParent() == null) {
+      return localOwners;
+    }
+
+    final ProjectState parent = projectCache.get(project.getParent());
+    if (parent != null) {
+      return parent.getOwners();
+    }
+
+    return Collections.emptySet();
+  }
+
+  /**
+   * @return all {@link AccountGroup}'s that are allowed to administrate the
+   *         complete project. This includes all groups to which the owner
+   *         privilege for 'refs/*' is assigned for this project (the local
+   *         owners) and all groups to which the owner privilege for 'refs/*' is
+   *         assigned for one of the parent projects (the inherited owners).
+   */
+  public Set<AccountGroup.Id> getAllOwners() {
+    final HashSet<AccountGroup.Id> owners = new HashSet<AccountGroup.Id>();
+    for (final RefRight right : getAllRights(ApprovalCategory.OWN, true)) {
+      if (right.getMaxValue() > 0 && right.getRefPattern().equals(RefRight.ALL)) {
+        owners.add(right.getAccountGroupId());
+      }
+    }
+    return Collections.unmodifiableSet(owners);
   }
 
   public ProjectControl controlForAnonymousUser() {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
index 4c9d0a4..8ddf585 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/project/RefControl.java
@@ -539,7 +539,7 @@
   private Set<RefRight> resolveOwnerGroups(final RefRight refRight) {
     final Set<RefRight> resolvedRefRights = new HashSet<RefRight>();
     if (refRight.getAccountGroupId().equals(systemConfig.ownerGroupId)) {
-      for (final AccountGroup.Id ownerGroup : getProjectState().getOwners()) {
+      for (final AccountGroup.Id ownerGroup : getProjectState().getAllOwners()) {
         if (!ownerGroup.equals(systemConfig.ownerGroupId)) {
           resolvedRefRights.add(new RefRight(refRight, ownerGroup));
         }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
index 2455cbd..485087f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/Predicate.java
@@ -65,7 +65,6 @@
   }
 
   /** Invert the passed node. */
-  @SuppressWarnings("unchecked")
   public static <T> Predicate<T> not(final Predicate<T> that) {
     if (that instanceof NotPredicate) {
       // Negate of a negate is the original predicate.
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
index a0aeb58..5aa6cdc 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryBuilder.java
@@ -109,10 +109,10 @@
     }
   }
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   private final Map<String, OperatorFactory> opFactories;
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   protected QueryBuilder(Definition<T, ? extends QueryBuilder<T>> def) {
     opFactories = (Map) def.opFactories;
   }
@@ -200,7 +200,8 @@
   @SuppressWarnings("unchecked")
   private Predicate<T> operator(final String name, final String value)
       throws QueryParseException {
-    final OperatorFactory f = opFactories.get(name);
+    @SuppressWarnings("rawtypes")
+    OperatorFactory f = opFactories.get(name);
     if (f == null) {
       throw error("Unsupported operator " + name + ":" + value);
     }
@@ -272,7 +273,7 @@
   public <P extends OperatorPredicate<T>> P find(Predicate<T> p,
       Class<P> clazz, String name) {
     if (p instanceof OperatorPredicate
-        && ((OperatorPredicate) p).getOperator().equals(name)
+        && ((OperatorPredicate<?>) p).getOperator().equals(name)
         && clazz.isAssignableFrom(p.getClass())) {
       return (P) p;
     }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java
index fea37e1..b3c10ef 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/QueryRewriter.java
@@ -81,7 +81,7 @@
           if ((m.getModifiers() & Modifier.ABSTRACT) != Modifier.ABSTRACT
               && (m.getModifiers() & Modifier.PUBLIC) == Modifier.PUBLIC
               && rp != null) {
-            rewriteRules.add(new MethodRewrite(qb, rp.value(), m));
+            rewriteRules.add(new MethodRewrite<T>(qb, rp.value(), m));
           }
         }
         c = c.getSuperclass();
@@ -237,7 +237,6 @@
       }
     }
 
-    final int cnt = pattern.getChildCount();
     if ((isAND(pattern) && isAND(actual)) //
         || (isOR(pattern) && isOR(actual)) //
         || (isNOT(pattern) && isNOT(actual)) //
@@ -415,7 +414,7 @@
         return null;
       }
 
-      final Predicate[] argList = new Predicate[argNames.length];
+      final Predicate<T>[] argList = new Predicate[argNames.length];
       for (int i = 0; i < argList.length; i++) {
         argList[i] = args.get(argNames[i]);
         if (argList[i] == null) {
@@ -439,7 +438,7 @@
       }
 
       if (rep instanceof RewritePredicate) {
-        ((RewritePredicate) rep).init(method.getName(), argList);
+        ((RewritePredicate<T>) rep).init(method.getName(), argList);
       }
 
       if (res.extra == null) {
@@ -501,17 +500,14 @@
     }
   }
 
-  @SuppressWarnings("unchecked")
   private static <T> boolean isAND(final Predicate<T> p) {
     return p instanceof AndPredicate;
   }
 
-  @SuppressWarnings("unchecked")
   private static <T> boolean isOR(final Predicate<T> p) {
     return p instanceof OrPredicate;
   }
 
-  @SuppressWarnings("unchecked")
   private static <T> boolean isNOT(final Predicate<T> p) {
     return p instanceof NotPredicate;
   }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java
index 35fbc1c..1c5c89c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/RewritePredicate.java
@@ -39,7 +39,7 @@
   @Override
   public boolean equals(Object other) {
     if (other instanceof RewritePredicate) {
-      RewritePredicate that = (RewritePredicate<T>) other;
+      RewritePredicate<T> that = (RewritePredicate<T>) other;
       if (this.init && that.init) {
         return this.getClass() == that.getClass()
             && this.name.equals(that.name)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
index 054cef1..577c5af 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -473,10 +473,9 @@
 
   @SuppressWarnings("unchecked")
   public int getLimit(Predicate<ChangeData> p) {
-    return ((IntPredicate) find(p, IntPredicate.class, FIELD_LIMIT)).intValue();
+    return ((IntPredicate<?>) find(p, IntPredicate.class, FIELD_LIMIT)).intValue();
   }
 
-  @SuppressWarnings("unchecked")
   public boolean hasSortKey(Predicate<ChangeData> p) {
     return find(p, SortKeyPredicate.class, "sortkey_after") != null
         || find(p, SortKeyPredicate.class, "sortkey_before") != null;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
index 6fbd060..717b487 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryRewriter.java
@@ -94,7 +94,6 @@
     return and(new SortKeyPredicate.Before(dbProvider, cut), a);
   }
 
-  @SuppressWarnings("unchecked")
   @NoCostComputation
   @Rewrite("A=(limit:*) B=(limit:*)")
   public Predicate<ChangeData> r00_smallestLimit(
@@ -103,7 +102,6 @@
     return a.intValue() <= b.intValue() ? a : b;
   }
 
-  @SuppressWarnings("unchecked")
   @NoCostComputation
   @Rewrite("A=(sortkey_before:*) B=(sortkey_before:*)")
   public Predicate<ChangeData> r00_oldestSortKey(
@@ -112,7 +110,6 @@
     return a.getValue().compareTo(b.getValue()) <= 0 ? a : b;
   }
 
-  @SuppressWarnings("unchecked")
   @NoCostComputation
   @Rewrite("A=(sortkey_after:*) B=(sortkey_after:*)")
   public Predicate<ChangeData> r00_newestSortKey(
@@ -519,7 +516,6 @@
     return or(r30_byReviewerOpen(r), r30_byReviewerClosed(r));
   }
 
-  @SuppressWarnings("unchecked")
   @Rewrite("status:submitted")
   public Predicate<ChangeData> r99_allSubmitted() {
     return new ChangeSource(50) {
@@ -535,7 +531,6 @@
     };
   }
 
-  @SuppressWarnings("unchecked")
   @Rewrite("P=(project:*)")
   public Predicate<ChangeData> r99_byProject(
       @Named("P") final ProjectPredicate p) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
index 6c9fbc0..a975f1b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryProcessor.java
@@ -20,7 +20,6 @@
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.events.ChangeAttribute;
 import com.google.gerrit.server.events.EventFactory;
-import com.google.gerrit.server.events.PatchSetAttribute;
 import com.google.gerrit.server.events.QueryStats;
 import com.google.gerrit.server.query.Predicate;
 import com.google.gerrit.server.query.QueryParseException;
@@ -283,7 +282,6 @@
     }
   }
 
-  @SuppressWarnings( {"cast", "unchecked"})
   private void showTextValue(Object value, int depth) {
     if (isPrimitive(value)) {
       out.print(' ');
@@ -292,7 +290,7 @@
 
     } else if (value instanceof Collection) {
       out.print('\n');
-      for (Object thing : ((Collection) value)) {
+      for (Object thing : ((Collection<?>) value)) {
         if (isPrimitive(thing)) {
           out.print(' ');
           out.print(value);
@@ -308,7 +306,6 @@
     }
   }
 
-  @SuppressWarnings("unchecked")
   private static boolean isPrimitive(Object value) {
     return value instanceof String //
         || value instanceof Number //
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
index f8ab33f..2fb6694 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/SingleGroupUser.java
@@ -17,7 +17,6 @@
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.reviewdb.AccountProjectWatch;
 import com.google.gerrit.reviewdb.Change;
-import com.google.gerrit.reviewdb.Project;
 import com.google.gerrit.server.AccessPath;
 import com.google.gerrit.server.CurrentUser;
 import com.google.gerrit.server.config.AuthConfig;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
index b0cb88a..978a152 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/SchemaVersion.java
@@ -120,7 +120,6 @@
    * Invoked between updateSchema (adds new columns/tables) and pruneSchema
    * (removes deleted columns/tables).
    */
-  @SuppressWarnings("unused")
   protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
   }
 
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_50.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_50.java
index 6c9c5cf..4a90c1f 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_50.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_50.java
@@ -14,20 +14,9 @@
 
 package com.google.gerrit.server.schema;
 
-import com.google.gerrit.reviewdb.AccountProjectWatch;
-import com.google.gerrit.reviewdb.ReviewDb;
-import com.google.gwtorm.client.OrmException;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.DialectH2;
-import com.google.gwtorm.schema.sql.DialectMySQL;
-import com.google.gwtorm.schema.sql.DialectPostgreSQL;
-import com.google.gwtorm.schema.sql.SqlDialect;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-import java.sql.SQLException;
-import java.sql.Statement;
-
 public class Schema_50 extends SchemaVersion {
   @Inject
   Schema_50(Provider<Schema_49> prior) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/AndPredicateTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/AndPredicateTest.java
index 589440d..0ec23d5 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/AndPredicateTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/AndPredicateTest.java
@@ -43,6 +43,7 @@
     return new TestPredicate(name, value);
   }
 
+  @SuppressWarnings("unchecked")
   public void testChildren() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -52,6 +53,7 @@
     assertSame(b, n.getChild(1));
   }
 
+  @SuppressWarnings("unchecked")
   public void testChildrenUnmodifiable() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -81,6 +83,7 @@
     assertEquals(o + " did not affect child", l, p.getChildren());
   }
 
+  @SuppressWarnings("unchecked")
   public void testToString() {
     final TestPredicate a = f("q", "alice");
     final TestPredicate b = f("q", "bob");
@@ -89,6 +92,7 @@
     assertEquals("(q:alice q:bob q:charlie)", and(a, b, c).toString());
   }
 
+  @SuppressWarnings("unchecked")
   public void testEquals() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -103,6 +107,7 @@
     assertFalse(and(a, c).equals(a));
   }
 
+  @SuppressWarnings("unchecked")
   public void testHashCode() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -113,6 +118,7 @@
     assertFalse(and(a, c).hashCode() == and(a, b).hashCode());
   }
 
+  @SuppressWarnings("unchecked")
   public void testCopy() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/NotPredicateTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/NotPredicateTest.java
index 8e86e95..90b9ca7 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/NotPredicateTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/NotPredicateTest.java
@@ -45,7 +45,7 @@
 
   public void testNotNot() {
     final TestPredicate p = f("author", "bob");
-    final Predicate n = not(p);
+    final Predicate<String> n = not(p);
     assertTrue(n instanceof NotPredicate);
     assertNotSame(p, n);
     assertSame(p, not(n));
@@ -53,14 +53,14 @@
 
   public void testChildren() {
     final TestPredicate p = f("author", "bob");
-    final Predicate n = not(p);
+    final Predicate<String> n = not(p);
     assertEquals(1, n.getChildCount());
     assertSame(p, n.getChild(0));
   }
 
   public void testChildrenUnmodifiable() {
     final TestPredicate p = f("author", "bob");
-    final Predicate n = not(p);
+    final Predicate<String> n = not(p);
 
     try {
       n.getChildren().clear();
@@ -81,7 +81,8 @@
     assertOnlyChild("remove(0)", p, n);
   }
 
-  private static void assertOnlyChild(String o, Predicate c, Predicate p) {
+  private static void assertOnlyChild(String o, Predicate<String> c,
+      Predicate<String> p) {
     assertEquals(o + " did not affect child", 1, p.getChildCount());
     assertSame(o + " did not affect child", c, p.getChild(0));
   }
@@ -102,6 +103,7 @@
     assertFalse(not(f("a", "b")).hashCode() == not(f("a", "a")).hashCode());
   }
 
+  @SuppressWarnings({"rawtypes", "unchecked"})
   public void testCopy() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/query/OrPredicateTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/query/OrPredicateTest.java
index be820b9..7f3ce50 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/query/OrPredicateTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/query/OrPredicateTest.java
@@ -43,19 +43,21 @@
     return new TestPredicate(name, value);
   }
 
+  @SuppressWarnings("unchecked")
   public void testChildren() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
-    final Predicate n = or(a, b);
+    final Predicate<String> n = or(a, b);
     assertEquals(2, n.getChildCount());
     assertSame(a, n.getChild(0));
     assertSame(b, n.getChild(1));
   }
 
+  @SuppressWarnings("unchecked")
   public void testChildrenUnmodifiable() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
-    final Predicate n = or(a, b);
+    final Predicate<String> n = or(a, b);
 
     try {
       n.getChildren().clear();
@@ -76,11 +78,12 @@
     assertChildren("remove(0)", n, list(a, b));
   }
 
-  private static void assertChildren(String o, Predicate p,
-      final List<Predicate> l) {
+  private static void assertChildren(String o, Predicate<String> p,
+      final List<Predicate<String>> l) {
     assertEquals(o + " did not affect child", l, p.getChildren());
   }
 
+  @SuppressWarnings("unchecked")
   public void testToString() {
     final TestPredicate a = f("q", "alice");
     final TestPredicate b = f("q", "bob");
@@ -89,6 +92,7 @@
     assertEquals("(q:alice OR q:bob OR q:charlie)", or(a, b, c).toString());
   }
 
+  @SuppressWarnings("unchecked")
   public void testEquals() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -103,6 +107,7 @@
     assertFalse(or(a, c).equals(a));
   }
 
+  @SuppressWarnings("unchecked")
   public void testHashCode() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
@@ -113,26 +118,27 @@
     assertFalse(or(a, c).hashCode() == or(a, b).hashCode());
   }
 
+  @SuppressWarnings("unchecked")
   public void testCopy() {
     final TestPredicate a = f("author", "alice");
     final TestPredicate b = f("author", "bob");
     final TestPredicate c = f("author", "charlie");
-    final List<Predicate> s2 = list(a, b);
-    final List<Predicate> s3 = list(a, b, c);
-    final Predicate n2 = or(a, b);
+    final List<Predicate<String>> s2 = list(a, b);
+    final List<Predicate<String>> s3 = list(a, b, c);
+    final Predicate<String> n2 = or(a, b);
 
     assertNotSame(n2, n2.copy(s2));
     assertEquals(s2, n2.copy(s2).getChildren());
     assertEquals(s3, n2.copy(s3).getChildren());
 
     try {
-      n2.copy(Collections.<Predicate> emptyList());
+      n2.copy(Collections.<Predicate<String>> emptyList());
     } catch (IllegalArgumentException e) {
       assertEquals("Need at least two predicates", e.getMessage());
     }
   }
 
-  private static List<Predicate> list(final Predicate... predicates) {
+  private static <T> List<Predicate<T>> list(final Predicate<T>... predicates) {
     return Arrays.asList(predicates);
   }
 }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorProvider.java
index 7b13605..a66386f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorProvider.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/CommandExecutorProvider.java
@@ -15,15 +15,10 @@
 package com.google.gerrit.sshd;
 
 import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.config.GerritServerConfig;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.inject.Inject;
 import com.google.inject.Provider;
 
-import org.eclipse.jgit.lib.Config;
-
-import java.util.concurrent.ThreadFactory;
-
 class CommandExecutorProvider implements Provider<WorkQueue.Executor> {
 
   private final QueueProvider queues;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommandProvider.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommandProvider.java
index 9492d42..0b69228 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommandProvider.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/DispatchCommandProvider.java
@@ -85,7 +85,8 @@
       }
     }
 
-    return Collections.unmodifiableMap(new LinkedHashMap(m));
+    return Collections.unmodifiableMap(
+        new LinkedHashMap<String, Provider<Command>>(m));
   }
 
   private static final TypeLiteral<Command> type =
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
index 770eebb..2052343 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshDaemon.java
@@ -479,7 +479,6 @@
         ));
   }
 
-  @SuppressWarnings("unchecked")
   private void initSubsystems() {
     setSubsystemFactories(Collections.<NamedFactory<Command>> emptyList());
   }
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
index 0479bc2..5b8edf0 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SshModule.java
@@ -28,7 +28,6 @@
 import com.google.gerrit.server.account.ChangeUserName;
 import com.google.gerrit.server.config.FactoryModule;
 import com.google.gerrit.server.config.GerritRequestModule;
-import com.google.gerrit.server.git.TransferConfig;
 import com.google.gerrit.server.git.WorkQueue;
 import com.google.gerrit.server.project.ProjectControl;
 import com.google.gerrit.server.ssh.SshInfo;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
index 45aaad5..199d210 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/SuExec.java
@@ -75,8 +75,6 @@
   public void start(Environment env) throws IOException {
     try {
       if (caller.get() instanceof PeerDaemonUser) {
-        final PeerDaemonUser peer = (PeerDaemonUser) caller.get();
-
         parseCommandLine();
 
         final Context ctx = callingContext.subContext(newSession(), join(args));
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
index 13ff1b1..f269541 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountGroupIdHandler.java
@@ -29,7 +29,7 @@
 public class AccountGroupIdHandler extends OptionHandler<AccountGroup.Id> {
   private final GroupCache groupCache;
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public AccountGroupIdHandler(final GroupCache groupCache,
       @Assisted final CmdLineParser parser, @Assisted final OptionDef option,
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
index 8add857..b8bf0fd 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/AccountIdHandler.java
@@ -35,7 +35,7 @@
   private final AccountResolver accountResolver;
   private final AccountManager accountManager;
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public AccountIdHandler(final AccountResolver accountResolver,
       final AccountManager accountManager,
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
index 5b24ce5..847184d 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/PatchSetIdHandler.java
@@ -26,7 +26,7 @@
 import org.kohsuke.args4j.spi.Setter;
 
 public class PatchSetIdHandler extends OptionHandler<PatchSet.Id> {
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public PatchSetIdHandler(@Assisted final CmdLineParser parser,
       @Assisted final OptionDef option, @Assisted final Setter setter) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
index 4c962f0..48733c03b 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/ProjectControlHandler.java
@@ -30,7 +30,7 @@
 public class ProjectControlHandler extends OptionHandler<ProjectControl> {
   private final ProjectControl.Factory projectControlFactory;
 
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public ProjectControlHandler(
       final ProjectControl.Factory projectControlFactory,
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
index 75defd4..50e41ae 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SocketAddressHandler.java
@@ -28,7 +28,7 @@
 import java.net.SocketAddress;
 
 public class SocketAddressHandler extends OptionHandler<SocketAddress> {
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public SocketAddressHandler(@Assisted final CmdLineParser parser,
       @Assisted final OptionDef option, @Assisted final Setter setter) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
index 4eedca0..434230f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/args4j/SubcommandHandler.java
@@ -25,7 +25,7 @@
 import org.kohsuke.args4j.spi.Setter;
 
 public class SubcommandHandler extends OptionHandler<String> {
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings({"unchecked", "rawtypes"})
   @Inject
   public SubcommandHandler(@Assisted final CmdLineParser parser,
       @Assisted final OptionDef option, @Assisted final Setter setter) {
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminCreateGroup.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminCreateGroup.java
index 36e064b..8622741 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminCreateGroup.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/AdminCreateGroup.java
@@ -18,7 +18,6 @@
 import com.google.gerrit.reviewdb.Account;
 import com.google.gerrit.reviewdb.AccountGroup;
 import com.google.gerrit.server.account.PerformCreateGroup;
-import com.google.gerrit.server.account.PerformCreateGroup;
 import com.google.gerrit.sshd.AdminCommand;
 import com.google.gerrit.sshd.BaseCommand;
 import com.google.gwtorm.client.OrmException;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
index cdcaf56..3511c71 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -41,6 +41,7 @@
     command(gerrit, "show-connections").to(AdminShowConnections.class);
     command(gerrit, "show-queue").to(ShowQueue.class);
     command(gerrit, "stream-events").to(StreamEvents.class);
+    command(gerrit, "version").to(VersionCommand.class);
 
     command(git).toProvider(new DispatchCommandProvider(git));
     command(git, "receive-pack").to(Commands.key(gerrit, "receive-pack"));
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
index 5a4e39a..47bae4f 100644
--- a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/ReviewCommand.java
@@ -20,7 +20,6 @@
 import com.google.gerrit.reviewdb.ApprovalCategory;
 import com.google.gerrit.reviewdb.ApprovalCategoryValue;
 import com.google.gerrit.reviewdb.Branch;
-import com.google.gerrit.reviewdb.Branch.NameKey;
 import com.google.gerrit.reviewdb.Change;
 import com.google.gerrit.reviewdb.PatchSet;
 import com.google.gerrit.reviewdb.PatchSetApproval;
@@ -29,7 +28,6 @@
 import com.google.gerrit.server.ChangeUtil;
 import com.google.gerrit.server.IdentifiedUser;
 import com.google.gerrit.server.git.MergeOp;
-import com.google.gerrit.server.git.MergeOp.Factory;
 import com.google.gerrit.server.git.MergeQueue;
 import com.google.gerrit.server.mail.AbandonedSender;
 import com.google.gerrit.server.mail.EmailException;
diff --git a/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/VersionCommand.java b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/VersionCommand.java
new file mode 100644
index 0000000..001863b
--- /dev/null
+++ b/gerrit-sshd/src/main/java/com/google/gerrit/sshd/commands/VersionCommand.java
@@ -0,0 +1,43 @@
+// Copyright (C) 2011 The Android Open Source Project
+//
+// Licensed under the Apache License, Version 2.0 (the "License");
+// you may not use this file except in compliance with the License.
+// You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+
+package com.google.gerrit.sshd.commands;
+
+import com.google.gerrit.common.Version;
+import com.google.gerrit.sshd.BaseCommand;
+
+import org.apache.sshd.server.Environment;
+
+import java.io.PrintWriter;
+
+final class VersionCommand extends BaseCommand {
+  @Override
+  public void start(final Environment env) {
+    startThread(new CommandRunnable() {
+      @Override
+      public void run() throws Failure {
+        parseCommandLine();
+
+        String v = Version.getVersion();
+        if (v == null) {
+          throw new Failure(1, "fatal: version unavailable");
+        }
+
+        final PrintWriter stdout = toPrintWriter(out);
+        stdout.println("gerrit version " + v);
+        stdout.flush();
+      }
+    });
+  }
+}
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
index f83d852..d5a2a98 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/CmdLineParser.java
@@ -132,7 +132,7 @@
       super(bean);
     }
 
-    @SuppressWarnings("unchecked")
+    @SuppressWarnings({"unchecked", "rawtypes"})
     @Override
     protected OptionHandler createOptionHandler(final OptionDef option,
         final Setter setter) {
@@ -157,13 +157,11 @@
       return option.handler() != OptionHandler.class;
     }
 
-    @SuppressWarnings("unchecked")
-    private boolean isEnum(final Setter setter) {
+    private <T> boolean isEnum(Setter<T> setter) {
       return Enum.class.isAssignableFrom(setter.getType());
     }
 
-    @SuppressWarnings("unchecked")
-    private boolean isPrimitive(final Setter setter) {
+    private <T> boolean isPrimitive(Setter<T> setter) {
       return setter.getType().isPrimitive();
     }
   }
diff --git a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
index ee5b9b6..0009d05 100644
--- a/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
+++ b/gerrit-util-cli/src/main/java/com/google/gerrit/util/cli/OptionHandlerFactory.java
@@ -20,7 +20,7 @@
 
 /** Creates an args4j OptionHandler through a Guice Injector. */
 public interface OptionHandlerFactory<T> {
-  @SuppressWarnings("unchecked")
+  @SuppressWarnings("rawtypes")
   OptionHandler create(org.kohsuke.args4j.CmdLineParser cmdLineParser,
       OptionDef optionDef, Setter setter);
 }
diff --git a/pom.xml b/pom.xml
index 087546d..c20a149 100644
--- a/pom.xml
+++ b/pom.xml
@@ -46,7 +46,7 @@
   </issueManagement>
 
   <properties>
-    <jgitVersion>0.12.1.41-g4b4df4c</jgitVersion>
+    <jgitVersion>0.12.1.53-g5ec4977</jgitVersion>
     <gwtormVersion>1.1.4</gwtormVersion>
     <gwtjsonrpcVersion>1.2.3</gwtjsonrpcVersion>
     <gwtexpuiVersion>1.2.2</gwtexpuiVersion>
@@ -72,6 +72,7 @@
     <module>gerrit-util-cli</module>
     <module>gerrit-util-ssl</module>
 
+    <module>gerrit-antlr</module>
     <module>gerrit-common</module>
     <module>gerrit-httpd</module>
     <module>gerrit-launcher</module>