Merge changes I9c3b5d5b,I33b24787
* changes:
SubmitRequirementsAdapter: Fix label status for custom submit rules
SubmitRequirementsAdapter: Add fine logging statement
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index 9e73f6f..76e1f82 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -5340,13 +5340,27 @@
[[tracing.traceid.requestUriPattern]]tracing.<trace-id>.requestUriPattern::
+
Regular expression to match request URIs for which request tracing
-should be always enabled. Request URIs are only available for REST
-requests. Request URIs never include the '/a' prefix.
+should be enabled except if they match
+link:tracing.traceid.excludedRequestUriPattern[excludedRequestUriPattern].
+Request URIs are only available for REST requests. Request URIs never include
+the '/a' prefix.
+
May be specified multiple times.
+
By default, unset (all request URIs are matched).
+[[tracing.traceid.excludedRequestUriPattern]]tracing.<trace-id>.excludedRequestUriPattern::
++
+Regular expression to match request URIs for which request tracing
+should not be enabled even if they match
+link:#tracing.traceid.requestUriPattern[requestUriPattern].
+Request URIs are only available for REST requests. Request URIs never include
+the '/a' prefix.
++
+May be specified multiple times.
++
+By default, unset (no request URIs are excluded).
+
[[tracing.traceid.account]]tracing.<trace-id>.account::
+
Account ID of an account for which request tracing should be always
@@ -5413,7 +5427,9 @@
[[deadline.id.requestUriPattern]]deadline.<id>.requestUriPattern::
+
-Regular expression to match request URIs to which the deadline applies. Request
+Regular expression to match request URIs to which the deadline applies except if
+they match
+link:#deadline.id.excludedRequestUriPattern[excludedRequestUriPattern]. Request
URIs are only available for REST requests. Request URIs never include the '/a'
prefix.
+
@@ -5421,6 +5437,17 @@
+
By default, unset (all request URIs are matched).
+[[deadline.id.excludedRequestUriPattern]]deadline.<id>.excludedRequestUriPattern::
++
+Regular expression to match request URIs to which the deadline should not be
+applied even if they match
+link:#deadline.id.requestUriPattern[requestUriPattern]. Request URIs are only
+available for REST requests. Request URIs never include the '/a' prefix.
++
+May be specified multiple times.
++
+By default, unset (no request URIs are excluded).
+
[[deadline.id.account]]deadline.<id>.account::
+
Account ID of an account to which the deadline applies.
diff --git a/Documentation/metrics.txt b/Documentation/metrics.txt
index e84a698..36b3473 100644
--- a/Documentation/metrics.txt
+++ b/Documentation/metrics.txt
@@ -12,35 +12,121 @@
* `build/label`: Version of Gerrit server software.
* `events`: Triggered events.
+** `type`:
+ The type of the event.
=== Actions
* `action/retry_attempt_count`: Number of retry attempts made
-by RetryHelper to execute an action (0 == single attempt, no retry)
+ by RetryHelper to execute an action (0 == single attempt, no retry)
+** `action_type`:
+ The type of the action that was retried.
+** `operation_name`:
+ The name of the operation that was retried.
+** `cause`:
+ The original cause that triggered the retry.
* `action/retry_timeout_count`: Number of action executions of RetryHelper
-that ultimately timed out
+ that ultimately timed out
+** `action_type`:
+ The type of the action that was retried.
+** `operation_name`:
+ The name of the operation that was retried.
+** `cause`:
+ The original cause that triggered the retry.
* `action/auto_retry_count`: Number of automatic retries with tracing
+** `action_type`:
+ The type of the action that was retried.
+** `operation_name`:
+ The name of the operation that was retried.
+** `cause`:
+ The cause for the retry.
* `action/failures_on_auto_retry_count`: Number of failures on auto retry
+** `action_type`:
+ The type of the action that was retried.
+** `operation_name`:
+ The name of the operation that was retried.
+** `cause`:
+ The cause for the retry.
[[cancellations]]
=== Cancellations
* `cancellation/advisory_deadline_count`: Exceeded advisory deadlines by request
+** `request_type`:
+ The type of the request to which the advisory deadline applied.
+** `request_uri`:
+ The redacted URI of the request to which the advisory deadline applied (only
+ set for request_type = REST).
+** `deadline_id`:
+ The ID of the advisory deadline.
* `cancellation/cancelled_requests_count`: Number of request cancellations by
request
+** `request_type`:
+ The type of the request that was cancelled.
+** `request_uri`:
+ The redacted URI of the request that was cancelled (only set for
+ request_type = REST).
+** `cancellation_reason`:
+ The reason why the request was cancelled.
* `cancellation/receive_timeout_count`: Number of requests that are cancelled
because link:config.html#receive.timeout[receive.timout] is exceeded
+** `cancellation_type`:
+ The cancellation type (graceful or forceful).
+
+[[performance]]
+=== Performance
+
+* `performance/operations`: Latency of performing operations
+** `operation_name`:
+ The operation that was performed.
+** `change_identifier`:
+ The ID of the change for which the operation was performed (format =
+ '<project>~<numeric-change-id>').
+** `trace_id`:
+ The ID of the trace if tracing was done.
+* `performance/operations_count`: Number of performed operations
+** `operation_name`:
+ The operation that was performed.
+** `trace_id`:
+ The ID of the trace if tracing was done.
+** `request`:
+ The request for which the operation was performed (format = '<request-type>
+ <redacted-request-uri>').
+* `performance/plugin_operations_count`: Number of performed operations by
+ plugin
+** `operation_name`:
+ The operation that was performed.
+** `plugin`:
+ The name of the plugin that performed the operation.
+** `trace_id`:
+ The ID of the trace if tracing was done.
+
=== Pushes
-* `receivecommits/changes`: histogram of number of changes processed
-in a single upload, split up by update type (change created/updated,
-change autoclosed).
-* `receivecommits/latency`: latency per change for processing a push,
-split up by update type (create+replace, and autoclose)
-* `receivecommits/push_latency`: total latency for processing a push,
-split up by update type (create+replace, autoclose, normal)
-* `receivecommits/timeout`: number of timeouts during push processing.
+* `receivecommits/changes`: histogram of number of changes processed in a single
+ upload
+** `type`:
+ type of push (create/replace, autoclose)
+* `receivecommits/latency_per_push`: processing delay for a processing single
+ push
+** `type`:
+ type of push (create/replace, autoclose, normal)
+* `receivecommits/latency_per_push_per_change`: Processing delay per push
+ divided by the number of changes in said push. (Only includes pushes which
+ contain changes.)
+** `type`:
+ type of push (create/replace, autoclose, normal)
+* `receivecommits/timeout`: rate of push timeouts
+* `receivecommits/ps_revision_missing`: errors due to patch set revision missing
+* `receivecommits/push_count`: number of pushes
+** `kind`:
+ The push kind (direct vs. magic).
+** `project`:
+ The name of the project for which the push is done.
+** `type`:
+ The type of the update (CREATE, UPDATE, CREATE/UPDATE, UPDATE_NONFASTFORWARD,
+ DELETE).
=== Process
@@ -58,27 +144,58 @@
* `proc/jvm/memory/object_pending_finalization_count`: Approximate number of
objects needing finalization.
* `proc/jvm/gc/count`: Number of GCs.
+** `gc_name`:
+ The name of the garbage collector.
* `proc/jvm/gc/time`: Approximate accumulated GC elapsed time.
-* `proc/jvm/memory/pool/committed/<pool name>`: Committed amount of memory for pool.
-* `proc/jvm/memory/pool/max/<pool name>`: Maximum amount of memory for pool.
-* `proc/jvm/memory/pool/used/<pool name>`: Used amount of memory for pool.
+** `gc_name`:
+ The name of the garbage collector.
+* `proc/jvm/memory/pool/committed`: Committed amount of memory for pool.
+** `pool_name`:
+ The name of the memory pool.
+* `proc/jvm/memory/pool/max`: Maximum amount of memory for pool.
+** `pool_name`:
+ The name of the memory pool.
+* `proc/jvm/memory/pool/used`: Used amount of memory for pool.
+** `pool_name`:
+ The name of the memory pool.
* `proc/jvm/thread/num_live`: Current live thread count.
* `proc/jvm/thread/num_daemon_live`: Current live daemon threads count.
-* `proc/jvm/thread/num_peak_live`: Peak live thread count since the Java virtual machine started or peak was reset.
-* `proc/jvm/thread/num_total_started`: Total number of threads created and also started since the Java virtual machine started.
-* `proc/jvm/thread/num_deadlocked_threads`: Number of threads that are deadlocked waiting for object monitors or ownable synchronizers.
- If deadlocks waiting for ownable synchronizers can be monitored depends on the capabilities of the used JVM.
+* `proc/jvm/thread/num_peak_live`: Peak live thread count since the Java virtual
+ machine started or peak was reset.
+* `proc/jvm/thread/num_total_started`: Total number of threads created and also
+ started since the Java virtual machine started.
+* `proc/jvm/thread/num_deadlocked_threads`: Number of threads that are
+ deadlocked waiting for object monitors or ownable synchronizers.
+ If deadlocks waiting for ownable synchronizers can be monitored depends on the
+ capabilities of the used JVM.
=== Caches
* `caches/memory_cached`: Memory entries.
+** `cache_name`:
+ The name of the cache.
* `caches/memory_hit_ratio`: Memory hit ratio.
+** `cache_name`:
+ The name of the cache.
* `caches/memory_eviction_count`: Memory eviction count.
+** `cache_name`:
+ The name of the cache.
* `caches/disk_cached`: Disk entries used by persistent cache.
+** `cache_name`:
+ The name of the cache.
* `caches/disk_hit_ratio`: Disk hit ratio for persistent cache.
-* `caches/refresh_count`: The number of refreshes per cache with an indicator if a reload was necessary.
-* `caches/diff/timeouts`: The number of git file diff computations that resulted in timeouts.
-* `caches/diff/legacy/timeouts`: The number of git file diff computations (using the legacy cache) that resulted in timeouts.
+** `cache_name`:
+ The name of the cache.
+* `caches/refresh_count`: The number of refreshes per cache with an indicator if
+ a reload was necessary.
+** `cache`:
+ The name of the cache.
+** `outdated`:
+ Whether the cache entry was outdated on reload.
+* `caches/diff/timeouts`: The number of git file diff computations that resulted
+ in timeouts.
+* `caches/diff/legacy/timeouts`: The number of git file diff computations (using
+ the legacy cache) that resulted in timeouts.
Cache disk metrics are expensive to compute on larger installations and are not
computed by default. They can be enabled via the
@@ -87,66 +204,110 @@
=== Change
-* `change/submit_rule_evaluation`: Latency for evaluating submit rules on a change.
-* `change/submit_type_evaluation`: Latency for evaluating the submit type on a change.
-* `change/post_review/draft_handling`: Total number of draft handling option (KEEP, PUBLISH, PUBLISH_ALL_REVISIONS) selected by users while posting a review.
+* `change/submit_rule_evaluation`: Latency for evaluating submit rules on a
+ change.
+* `change/submit_type_evaluation`: Latency for evaluating the submit type on a
+ change.
+* `change/post_review/draft_handling`: Total number of draft handling option
+ (KEEP, PUBLISH, PUBLISH_ALL_REVISIONS) selected by users while posting a
+ review.
+** `type`:
+ The type of the draft handling option (KEEP, PUBLISH, PUBLISH_ALL_REVISIONS).
=== Comments
-* `ported_comments/as_patchset_level`: Total number of comments ported as patchset-level comments.
-* `ported_comments/as_file_level`: Total number of comments ported as file-level comments.
-* `ported_comments/as_range_comments`: Total number of comments having line/range values in the ported patchset.
+* `ported_comments/as_patchset_level`: Total number of comments ported as
+ patchset-level comments.
+* `ported_comments/as_file_level`: Total number of comments ported as file-level
+ comments.
+* `ported_comments/as_range_comments`: Total number of comments having
+ line/range values in the ported patchset.
=== HTTP
==== Jetty
-* `http/server/jetty/connections/connections`: The current number of open connections
-* `http/server/jetty/connections/connections_total`: The total number of connections opened
-* `http/server/jetty/connections/connections_duration_max`: The max duration of a connection in ms
-* `http/server/jetty/connections/connections_duration_mean`: The mean duration of a connection in ms
-* `http/server/jetty/connections/connections_duration_stdev`: The standard deviation of the duration of a connection in ms
-* `http/server/jetty/connections/received_messages`: The total number of messages received
-* `http/server/jetty/connections/sent_messages`: The total number of messages sent
-* `http/server/jetty/connections/received_bytes`: Total number of bytes received by tracked connections
-* `http/server/jetty/connections/sent_bytes`: Total number of bytes sent by tracked connections"
+* `http/server/jetty/connections/connections`: The current number of open
+ connections
+* `http/server/jetty/connections/connections_total`: The total number of
+ connections opened
+* `http/server/jetty/connections/connections_duration_max`: The max duration of
+ a connection in ms
+* `http/server/jetty/connections/connections_duration_mean`: The mean duration
+ of a connection in ms
+* `http/server/jetty/connections/connections_duration_stdev`: The standard
+ deviation of the duration of a connection in ms
+* `http/server/jetty/connections/received_messages`: The total number of
+ messages received
+* `http/server/jetty/connections/sent_messages`: The total number of messages
+ sent
+* `http/server/jetty/connections/received_bytes`: Total number of bytes received
+ by tracked connections
+* `http/server/jetty/connections/sent_bytes`: Total number of bytes sent by
+ tracked connections
* `http/server/jetty/threadpool/active_threads`: Active threads
* `http/server/jetty/threadpool/idle_threads`: Idle threads
* `http/server/jetty/threadpool/reserved_threads`: Reserved threads
* `http/server/jetty/threadpool/max_pool_size`: Maximum thread pool size
* `http/server/jetty/threadpool/min_pool_size`: Minimum thread pool size
* `http/server/jetty/threadpool/pool_size`: Current thread pool size
-* `http/server/jetty/threadpool/queue_size`: Queued requests waiting for a thread
+* `http/server/jetty/threadpool/queue_size`: Queued requests waiting for a
+ thread
+* `http/server/jetty/threadpool/is_low_on_threads`: Whether thread pool is low
+ on threads
==== LDAP
* `ldap/login_latency`: Latency of logins.
* `ldap/user_search_latency`: Latency for searching the user account.
-* `ldap/group_search_latency`: Latency for querying the group memberships of an account.
+* `ldap/group_search_latency`: Latency for querying the group memberships of an
+ account.
* `ldap/group_expansion_latency`: Latency for expanding nested groups.
==== REST API
* `http/server/error_count`: Rate of REST API error responses.
+** `status`:
+ HTTP status code
* `http/server/success_count`: Rate of REST API success responses.
+** `status`:
+ HTTP status code
* `http/server/rest_api/count`: Rate of REST API calls by view.
+** `view`:
+ view implementation class
* `http/server/rest_api/change_id_type`: Rate of REST API calls by change ID type.
+** `change_id_type`:
+ The type of the change identifier.
* `http/server/rest_api/error_count`: Rate of REST API calls by view.
+** `view`:
+ view implementation class
+** `error_code`:
+ HTTP status code
+** `cause`:
+ The cause of the error.
* `http/server/rest_api/server_latency`: REST API call latency by view.
+** `view`:
+ view implementation class
* `http/server/rest_api/response_bytes`: Size of REST API response on network
-(may be gzip compressed) by view.
+ (may be gzip compressed) by view.
+** `view`:
+ view implementation class
* `http/server/rest_api/change_json/to_change_info_latency`: Latency for
-toChangeInfo invocations in ChangeJson.
+ toChangeInfo invocations in ChangeJson.
* `http/server/rest_api/change_json/to_change_infos_latency`: Latency for
-toChangeInfos invocations in ChangeJson.
+ toChangeInfos invocations in ChangeJson.
* `http/server/rest_api/change_json/format_query_results_latency`: Latency for
-formatQueryResults invocations in ChangeJson.
-* `http/server/rest_api/ui_actions/latency`: Latency for RestView#getDescription calls.
+ formatQueryResults invocations in ChangeJson.
+* `http/server/rest_api/ui_actions/latency`: Latency for RestView#getDescription
+ calls.
+** `view`:
+ view implementation class
=== Query
* `query/query_latency`: Successful query latency, accumulated over the life
-of the process.
+ of the process.
+** `index`: index name
=== Core Queues
@@ -165,11 +326,15 @@
Each queue provides the following metrics:
* `queue/<queue_name>/pool_size`: Current number of threads in the pool
-* `queue/<queue_name>/max_pool_size`: Maximum allowed number of threads in the pool
-* `queue/<queue_name>/active_threads`: Number of threads that are actively executing tasks
+* `queue/<queue_name>/max_pool_size`: Maximum allowed number of threads in the
+ pool
+* `queue/<queue_name>/active_threads`: Number of threads that are actively
+ executing tasks
* `queue/<queue_name>/scheduled_tasks`: Number of scheduled tasks in the queue
-* `queue/<queue_name>/total_scheduled_tasks_count`: Total number of tasks that have been scheduled
-* `queue/<queue_name>/total_completed_tasks_count`: Total number of tasks that have completed execution
+* `queue/<queue_name>/total_scheduled_tasks_count`: Total number of tasks that
+ have been scheduled
+* `queue/<queue_name>/total_completed_tasks_count`: Total number of tasks that
+ have completed execution
=== SSH sessions
@@ -181,7 +346,7 @@
* `topic/cross_project_submit`: number of cross-project topic submissions.
* `topic/cross_project_submit_completed`: number of cross-project
-topic submissions that concluded successfully.
+ topic submissions that concluded successfully.
=== JGit
@@ -198,23 +363,34 @@
* `load_success_count` : Successful cache loads for JGit block cache.
* `miss_count` : Cache misses for JGit block cache.
* `miss_ratio` : Cache miss ratio for JGit block cache.
-* `cache_used_per_repository` : Bytes of memory retained per repository for the top N repositories
-having most data in the cache. The number N of reported repositories is limited to 1000.
+* `cache_used_per_repository` : Bytes of memory retained per repository for the
+ top N repositories having most data in the cache. The number N of reported
+ repositories is limited to 1000.
+** `repository_name`: The name of the repository.
=== Git
* `git/upload-pack/request_count`: Total number of git-upload-pack requests.
+** `operation`:
+ The name of the operation (CLONE, FETCH).
* `git/upload-pack/phase_counting`: Time spent in the 'Counting...' phase.
+** `operation`:
+ The name of the operation (CLONE, FETCH).
* `git/upload-pack/phase_compressing`: Time spent in the 'Compressing...' phase.
+** `operation`:
+ The name of the operation (CLONE, FETCH).
* `git/upload-pack/phase_writing`: Time spent transferring bytes to client.
+** `operation`:
+ The name of the operation (CLONE, FETCH).
* `git/upload-pack/pack_bytes`: Distribution of sizes of packs sent to clients.
+** `operation`:
+ The name of the operation (CLONE, FETCH).
* `git/auto-merge/num_operations`: Number of auto merge operations and context.
+** `operation`:
+ The type of the operation (CACHE_LOAD, IN_MEMORY_WRITE, ON_DISK_WRITE).
* `git/auto-merge/latency`: Latency of auto merge operations and context.
-
-=== BatchUpdate
-
-* `batch_update/execute_change_ops`: BatchUpdate change update latency,
-excluding reindexing
+** `operation`:
+ The type of the operation (CACHE_LOAD, IN_MEMORY_WRITE, ON_DISK_WRITE).
=== NoteDb
@@ -224,43 +400,63 @@
* `notedb/parse_latency`: NoteDb parse latency for changes.
* `notedb/external_id_cache_load_count`: Total number of times the external ID
cache loader was called.
-* `notedb/external_id_partial_read_latency`: Latency for generating a new external ID
- cache state from a prior state.
+** `partial`:
+ Whether the reload was partial.
+* `notedb/external_id_partial_read_latency`: Latency for generating a new
+ external ID cache state from a prior state.
* `notedb/external_id_update_count`: Total number of external ID updates.
* `notedb/read_all_external_ids_latency`: Latency for reading all
-external ID's from NoteDb.
+ external ID's from NoteDb.
* `notedb/read_single_account_config_latency`: Latency for reading a single
-account config from NoteDb.
+ account config from NoteDb.
* `notedb/read_single_external_id_latency`: Latency for reading a single
-external ID from NoteDb.
+ external ID from NoteDb.
=== Permissions
-* `permissions/permission_collection/filter_latency`: Latency to filter access sections
-by user and ref.
+* `permissions/permission_collection/filter_latency`: Latency for access filter
+ computations in PermissionCollection
* `permissions/ref_filter/full_filter_count`: Rate of full ref filter operations
-* `permissions/ref_filter/skip_filter_count`: Rate of ref filter operations where
-we skip full evaluation because the user can read all refs
+* `permissions/ref_filter/skip_filter_count`: Rate of ref filter operations
+ where we skip full evaluation because the user can read all refs
=== Reviewer Suggestion
* `reviewer_suggestion/query_accounts`: Latency for querying accounts for
-reviewer suggestion.
+ reviewer suggestion.
* `reviewer_suggestion/recommend_accounts`: Latency for recommending accounts
-for reviewer suggestion.
+ for reviewer suggestion.
* `reviewer_suggestion/load_accounts`: Latency for loading accounts for
-reviewer suggestion.
+ reviewer suggestion.
* `reviewer_suggestion/query_groups`: Latency for querying groups for reviewer
-suggestion.
+ suggestion.
+* `reviewer_suggestion/filter_visibility`: Latency for removing users that can't
+ see the change
=== Repo Sequences
* `sequence/next_id_latency`: Latency of requesting IDs from repo sequences.
+** `sequence`:
+ The sequence from which IDs were retrieved.
+** `multiple`:
+ Whether more than one ID was retrieved.
=== Plugin
* `plugin/latency`: Latency for plugin invocation.
+** `plugin_name`"
+ The name of the plugin.
+** `class`:
+ The class of the plugin that was invoked.
+** `export_value`:
+ The export name under which the invoked class is registered.
* `plugin/error_count`: Number of plugin errors.
+** `plugin_name`"
+ The name of the plugin.
+** `class`:
+ The class of the plugin that was invoked.
+** `export_value`:
+ The export name under which the invoked class is registered.
=== Group
@@ -269,11 +465,19 @@
=== Replication Plugin
* `plugins/replication/replication_latency`: Time spent pushing to remote
-destination.
+ destination.
+** `destination`: The destination of the replication.
* `plugins/replication/replication_delay`: Time spent waiting before pushing to
-remote destination.
+ remote destination.
+** `destination`: The destination of the replication.
* `plugins/replication/replication_retries`: Number of retries when pushing to
-remote destination.
+ remote destination.
+** `destination`: The destination of the replication.
+* `plugins/replication/latency_slower_than_threshold`: latency for project to
+ destination, where latency was slower than threshold
+** `slow_threshold`: The threshold.
+** `project`: The name of the project.
+** `destination`: The destination of the replication.
=== License
diff --git a/Documentation/rest-api-accounts.txt b/Documentation/rest-api-accounts.txt
index a613c7e..ae0c0a6 100644
--- a/Documentation/rest-api-accounts.txt
+++ b/Documentation/rest-api-accounts.txt
@@ -1343,6 +1343,7 @@
"time_format": "HHMM_12",
"size_bar_in_change_table": true,
"disable_keyboard_shortcuts": true,
+ "disable_token_highlighting": true,
"diff_view": "SIDE_BY_SIDE",
"mute_common_path_prefixes": true,
"my": [
@@ -1394,6 +1395,7 @@
"diff_view": "SIDE_BY_SIDE",
"publish_comments_on_push": true,
"disable_keyboard_shortcuts": true,
+ "disable_token_highlighting": true,
"work_in_progress_by_default": true,
"mute_common_path_prefixes": true,
"my": [
@@ -2704,6 +2706,8 @@
Allowed values are `AUTO_MERGE` and `FIRST_PARENT`.
|`disable_keyboard_shortcuts` |not set if `false`|
Whether to disable all keyboard shortcuts.
+|`disable_token_highlighting` [not set if `false`]
+Whether to disable token highlighting on hover.
|`publish_comments_on_push` |not set if `false`|
Whether to link:user-upload.html#publish-comments[publish draft comments] on
push by default.
diff --git a/Documentation/user-search.txt b/Documentation/user-search.txt
index 444c9ee..3977278 100644
--- a/Documentation/user-search.txt
+++ b/Documentation/user-search.txt
@@ -737,6 +737,10 @@
to one of the fields in the
link:rest-api-changes.html#submit-record[SubmitRecord] REST API entity.
+`label:Code-Review\<=-1`::
++
+Matches changes with either a -1, -2, or any lower score.
+
`label:Code-Review=MAX`::
+
Matches changes with label voted with the highest possible score.
@@ -787,10 +791,6 @@
Matches changes with a +1 code review where the reviewer is in the
ldap/linux.workflow group.
-`label:Code-Review\<=-1`::
-+
-Matches changes with either a -1, -2, or any lower score.
-
`is:open label:Code-Review+2 label:Verified+1 NOT label:Verified-1 NOT label:Code-Review-2`::
`is:open label:Code-Review=ok label:Verified=ok`::
+
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 9732d2c..4d87f4d 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -293,7 +293,6 @@
* @param baseConfig default config values; merged with config from {@code desc} and then written
* into {@code site/etc/gerrit.config}.
* @param site temp directory where site will live.
- * @throws Exception
*/
public static void init(Description desc, Config baseConfig, Path site) throws Exception {
checkArgument(!desc.memory(), "can't initialize site path for in-memory test: %s", desc);
@@ -347,7 +346,6 @@
* @param testSysModule additional Guice module to use.
* @param testSshModule additional Guice module to use.
* @return started server.
- * @throws Exception
*/
public static GerritServer initAndStart(
TemporaryFolder temporaryFolder,
@@ -384,7 +382,6 @@
* @param additionalArgs additional command-line arguments for the daemon program; only allowed if
* the test is not in-memory.
* @return started server.
- * @throws Exception
*/
public static GerritServer start(
Description desc,
diff --git a/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
index ae88e37..87063c9 100644
--- a/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
+++ b/java/com/google/gerrit/acceptance/config/GlobalPluginConfig.java
@@ -28,12 +28,12 @@
/** Name of the plugin, corresponding to {@code $site/etc/@pluginName.config}. */
String pluginName();
- /** @see GerritConfig#name() */
+ /** See {@link GerritConfig#name()} */
String name();
- /** @see GerritConfig#value() */
+ /** See {@link GerritConfig#value()} */
String value() default "";
- /** @see GerritConfig#values() */
+ /** See {@link GerritConfig#values()} */
String[] values() default "";
}
diff --git a/java/com/google/gerrit/common/data/GitwebType.java b/java/com/google/gerrit/common/data/GitwebType.java
index 9cc408b..e69eacf 100644
--- a/java/com/google/gerrit/common/data/GitwebType.java
+++ b/java/com/google/gerrit/common/data/GitwebType.java
@@ -29,7 +29,7 @@
private char pathSeparator = '/';
private boolean urlEncode = true;
- /** @return name displayed in links. */
+ /** Returns name displayed in links. */
public String getLinkName() {
return name;
}
@@ -43,7 +43,7 @@
this.name = name;
}
- /** @return parameterized string for the branch URL. */
+ /** Returns parameterized string for the branch URL. */
public String getBranch() {
return branch;
}
@@ -57,7 +57,7 @@
branch = str;
}
- /** @return parameterized string for the tag URL. */
+ /** Returns parameterized string for the tag URL. */
public String getTag() {
return tag;
}
@@ -71,7 +71,7 @@
tag = str;
}
- /** @return parameterized string for the file URL. */
+ /** Returns parameterized string for the file URL. */
public String getFile() {
return file;
}
@@ -85,7 +85,7 @@
file = str;
}
- /** @return parameterized string for the file history URL. */
+ /** Returns parameterized string for the file history URL. */
public String getFileHistory() {
return fileHistory;
}
@@ -99,7 +99,7 @@
fileHistory = str;
}
- /** @return parameterized string for the project URL. */
+ /** Returns parameterized string for the project URL. */
public String getProject() {
return project;
}
@@ -113,7 +113,7 @@
project = str;
}
- /** @return parameterized string for the revision URL. */
+ /** Returns parameterized string for the revision URL. */
public String getRevision() {
return revision;
}
@@ -127,7 +127,7 @@
revision = str;
}
- /** @return parameterized string for the root tree URL. */
+ /** Returns parameterized string for the root tree URL. */
public String getRootTree() {
return rootTree;
}
@@ -141,7 +141,7 @@
rootTree = str;
}
- /** @return path separator used for branch and project names. */
+ /** Returns path separator used for branch and project names. */
public char getPathSeparator() {
return pathSeparator;
}
@@ -155,7 +155,7 @@
this.pathSeparator = separator;
}
- /** @return whether to URL encode path segments. */
+ /** Returns whether to URL encode path segments. */
public boolean getUrlEncode() {
return urlEncode;
}
diff --git a/java/com/google/gerrit/common/data/GlobalCapability.java b/java/com/google/gerrit/common/data/GlobalCapability.java
index 8bfd960..253266d 100644
--- a/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -165,17 +165,17 @@
}
}
- /** @return all valid capability names. */
+ /** Returns all valid capability names. */
public static Collection<String> getAllNames() {
return Collections.unmodifiableList(NAMES_ALL);
}
- /** @return true if the name is recognized as a capability name. */
+ /** Returns true if the name is recognized as a capability name. */
public static boolean isGlobalCapability(String varName) {
return NAMES_LC.contains(varName.toLowerCase());
}
- /** @return true if the capability should have a range attached. */
+ /** Returns true if the capability should have a range attached. */
public static boolean hasRange(String varName) {
for (String n : RANGE_NAMES) {
if (n.equalsIgnoreCase(varName)) {
@@ -189,7 +189,7 @@
return Collections.unmodifiableList(Arrays.asList(RANGE_NAMES));
}
- /** @return the valid range for the capability if it has one, otherwise null. */
+ /** Returns the valid range for the capability if it has one, otherwise null. */
public static PermissionRange.WithDefaults getRange(String varName) {
if (QUERY_LIMIT.equalsIgnoreCase(varName)) {
return new PermissionRange.WithDefaults(
diff --git a/java/com/google/gerrit/elasticsearch/ElasticVersion.java b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
index c6400df..b5bf44b 100644
--- a/java/com/google/gerrit/elasticsearch/ElasticVersion.java
+++ b/java/com/google/gerrit/elasticsearch/ElasticVersion.java
@@ -45,7 +45,6 @@
*
* @param version for which to return an ElasticVersion
* @return the corresponding ElasticVersion if supported
- * @throws UnsupportedVersion
*/
public static ElasticVersion forVersion(String version) {
for (ElasticVersion value : ElasticVersion.values()) {
diff --git a/java/com/google/gerrit/entities/AccessSection.java b/java/com/google/gerrit/entities/AccessSection.java
index d97bca8..69a234a 100644
--- a/java/com/google/gerrit/entities/AccessSection.java
+++ b/java/com/google/gerrit/entities/AccessSection.java
@@ -52,7 +52,7 @@
return new AutoValue_AccessSection.Builder().setName(name).setPermissions(ImmutableList.of());
}
- /** @return true if the name is likely to be a valid reference section name. */
+ /** Returns true if the name is likely to be a valid reference section name. */
public static boolean isValidRefSectionName(String name) {
return name.startsWith("refs/") || name.startsWith("^refs/");
}
diff --git a/java/com/google/gerrit/entities/AccountGroup.java b/java/com/google/gerrit/entities/AccountGroup.java
index 0b2a346..001a544 100644
--- a/java/com/google/gerrit/entities/AccountGroup.java
+++ b/java/com/google/gerrit/entities/AccountGroup.java
@@ -54,7 +54,7 @@
return uuid();
}
- /** @return true if the UUID is for a group managed within Gerrit. */
+ /** Returns true if the UUID is for a group managed within Gerrit. */
public boolean isInternalGroup() {
return get().matches("^[0-9a-f]{40}$");
}
diff --git a/java/com/google/gerrit/entities/GroupDescription.java b/java/com/google/gerrit/entities/GroupDescription.java
index e950257..7054bed 100644
--- a/java/com/google/gerrit/entities/GroupDescription.java
+++ b/java/com/google/gerrit/entities/GroupDescription.java
@@ -22,22 +22,22 @@
public class GroupDescription {
/** The Basic information required to be exposed by any Group. */
public interface Basic {
- /** @return the non-null UUID of the group. */
+ /** Returns the non-null UUID of the group. */
AccountGroup.UUID getGroupUUID();
- /** @return the non-null name of the group. */
+ /** Returns the non-null name of the group. */
String getName();
/**
- * @return optional email address to send to the group's members. If provided, Gerrit will use
- * this email address to send change notifications to the group.
+ * Returns optional email address to send to the group's members. If provided, Gerrit will use
+ * this email address to send change notifications to the group.
*/
@Nullable
String getEmailAddress();
/**
- * @return optional URL to information about the group. Typically a URL to a web page that
- * permits users to apply to join the group, or manage their membership.
+ * Returns optional URL to information about the group. Typically a URL to a web page that
+ * permits users to apply to join the group, or manage their membership.
*/
@Nullable
String getUrl();
diff --git a/java/com/google/gerrit/entities/ImmutableConfig.java b/java/com/google/gerrit/entities/ImmutableConfig.java
index a5efc14..83a44d1 100644
--- a/java/com/google/gerrit/entities/ImmutableConfig.java
+++ b/java/com/google/gerrit/entities/ImmutableConfig.java
@@ -51,27 +51,27 @@
return cfg;
}
- /** @see Config#getSections() */
+ /** See {@link Config#getSections()} */
public Set<String> getSections() {
return cfg.getSections();
}
- /** @see Config#getNames(String) */
+ /** See {@link Config#getNames(String)} */
public Set<String> getNames(String section) {
return cfg.getNames(section);
}
- /** @see Config#getNames(String, String) */
+ /** See {@link Config#getNames(String, String)} */
public Set<String> getNames(String section, String subsection) {
return cfg.getNames(section, subsection);
}
- /** @see Config#getStringList(String, String, String) */
+ /** See {@link Config#getStringList(String, String, String)} */
public String[] getStringList(String section, String subsection, String name) {
return cfg.getStringList(section, subsection, name);
}
- /** @see Config#getSubsections(String) */
+ /** See {@link Config#getSubsections(String)} */
public Set<String> getSubsections(String section) {
return cfg.getSubsections(section);
}
diff --git a/java/com/google/gerrit/entities/PatchSetApproval.java b/java/com/google/gerrit/entities/PatchSetApproval.java
index a4bb251..f853f77 100644
--- a/java/com/google/gerrit/entities/PatchSetApproval.java
+++ b/java/com/google/gerrit/entities/PatchSetApproval.java
@@ -41,7 +41,7 @@
}
public static Builder builder() {
- return new AutoValue_PatchSetApproval.Builder().postSubmit(false);
+ return new AutoValue_PatchSetApproval.Builder().postSubmit(false).copied(false);
}
@AutoValue.Builder
@@ -72,6 +72,8 @@
public abstract Builder postSubmit(boolean isPostSubmit);
+ public abstract Builder copied(boolean isCopied);
+
abstract PatchSetApproval autoBuild();
public PatchSetApproval build() {
@@ -111,10 +113,12 @@
public abstract boolean postSubmit();
+ public abstract boolean copied();
+
public abstract Builder toBuilder();
public PatchSetApproval copyWithPatchSet(PatchSet.Id psId) {
- return toBuilder().key(key(psId, key().accountId(), key().labelId())).build();
+ return toBuilder().key(key(psId, key().accountId(), key().labelId())).copied(true).build();
}
public PatchSet.Id patchSetId() {
diff --git a/java/com/google/gerrit/entities/Permission.java b/java/com/google/gerrit/entities/Permission.java
index 322c79e..95164bd 100644
--- a/java/com/google/gerrit/entities/Permission.java
+++ b/java/com/google/gerrit/entities/Permission.java
@@ -95,7 +95,7 @@
LABEL_AS_INDEX = NAMES_LC.indexOf(Permission.LABEL_AS.toLowerCase());
}
- /** @return true if the name is recognized as a permission name. */
+ /** Returns true if the name is recognized as a permission name. */
public static boolean isPermission(String varName) {
return isLabel(varName) || isLabelAs(varName) || NAMES_LC.contains(varName.toLowerCase());
}
@@ -104,22 +104,22 @@
return isLabel(varName) || isLabelAs(varName);
}
- /** @return true if the permission name is actually for a review label. */
+ /** Returns true if the permission name is actually for a review label. */
public static boolean isLabel(String varName) {
return varName.startsWith(LABEL) && LABEL.length() < varName.length();
}
- /** @return true if the permission is for impersonated review labels. */
+ /** Returns true if the permission is for impersonated review labels. */
public static boolean isLabelAs(String var) {
return var.startsWith(LABEL_AS) && LABEL_AS.length() < var.length();
}
- /** @return permission name for the given review label. */
+ /** Returns permission name for the given review label. */
public static String forLabel(String labelName) {
return LABEL + labelName;
}
- /** @return permission name to apply a label for another user. */
+ /** Returns permission name to apply a label for another user. */
public static String forLabelAs(String labelName) {
return LABEL_AS + labelName;
}
diff --git a/java/com/google/gerrit/entities/PermissionRange.java b/java/com/google/gerrit/entities/PermissionRange.java
index fa9f4c2..d283069 100644
--- a/java/com/google/gerrit/entities/PermissionRange.java
+++ b/java/com/google/gerrit/entities/PermissionRange.java
@@ -46,7 +46,7 @@
defaultMax = max;
}
- /** @return all values between {@link #getMin()} and {@link #getMax()} */
+ /** Returns all values between {@link #getMin()} and {@link #getMax()} */
public List<Integer> getValuesAsList() {
ArrayList<Integer> r = new ArrayList<>(getRangeSize());
for (int i = min; i <= max; i++) {
@@ -55,7 +55,7 @@
return r;
}
- /** @return number of values between {@link #getMin()} and {@link #getMax()} */
+ /** Returns number of values between {@link #getMin()} and {@link #getMax()} */
public int getRangeSize() {
return max - min;
}
diff --git a/java/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverter.java b/java/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverter.java
index 78a35ff..9e77025 100644
--- a/java/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverter.java
+++ b/java/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverter.java
@@ -39,7 +39,8 @@
.setKey(patchSetApprovalKeyProtoConverter.toProto(patchSetApproval.key()))
.setValue(patchSetApproval.value())
.setGranted(patchSetApproval.granted().getTime())
- .setPostSubmit(patchSetApproval.postSubmit());
+ .setPostSubmit(patchSetApproval.postSubmit())
+ .setCopied(patchSetApproval.copied());
patchSetApproval.tag().ifPresent(builder::setTag);
Account.Id realAccountId = patchSetApproval.realAccountId();
@@ -61,7 +62,8 @@
.key(patchSetApprovalKeyProtoConverter.fromProto(proto.getKey()))
.value(proto.getValue())
.granted(new Timestamp(proto.getGranted()))
- .postSubmit(proto.getPostSubmit());
+ .postSubmit(proto.getPostSubmit())
+ .copied(proto.getCopied());
if (proto.hasTag()) {
builder.tag(proto.getTag());
}
diff --git a/java/com/google/gerrit/extensions/BUILD b/java/com/google/gerrit/extensions/BUILD
index 21949f7..f36018b 100644
--- a/java/com/google/gerrit/extensions/BUILD
+++ b/java/com/google/gerrit/extensions/BUILD
@@ -34,6 +34,7 @@
"//java/com/google/gerrit/common:annotations",
"//lib:guava",
"//lib/auto:auto-value-annotations",
+ "//lib/errorprone:annotations",
"//lib/guice",
"//lib/guice:guice-assistedinject",
],
diff --git a/java/com/google/gerrit/extensions/api/accounts/Accounts.java b/java/com/google/gerrit/extensions/api/accounts/Accounts.java
index 15fca9a..285b385 100644
--- a/java/com/google/gerrit/extensions/api/accounts/Accounts.java
+++ b/java/com/google/gerrit/extensions/api/accounts/Accounts.java
@@ -38,7 +38,11 @@
*/
AccountApi id(String id) throws RestApiException;
- /** @see #id(String) */
+ /**
+ * Look up an account by ID. #id(String)
+ *
+ * <p>See #id(String)
+ */
AccountApi id(int id) throws RestApiException;
/**
diff --git a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
index ab98aa6..690ba4e 100644
--- a/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/ChangeApi.java
@@ -324,7 +324,6 @@
* Get hashtags on a change.
*
* @return hashtags
- * @throws RestApiException
*/
Set<String> getHashtags() throws RestApiException;
@@ -359,7 +358,6 @@
*
* @return comments in a map keyed by path; comments have the {@code revision} field set to
* indicate their patch set.
- * @throws RestApiException
* @deprecated Callers should use {@link #commentsRequest()} instead
*/
@Deprecated
@@ -372,7 +370,6 @@
*
* @return comments as a list; comments have the {@code revision} field set to indicate their
* patch set.
- * @throws RestApiException
* @deprecated Callers should use {@link #commentsRequest()} instead
*/
@Deprecated
@@ -393,7 +390,6 @@
*
* @return robot comments in a map keyed by path; robot comments have the {@code revision} field
* set to indicate their patch set.
- * @throws RestApiException
*/
Map<String, List<RobotCommentInfo>> robotComments() throws RestApiException;
@@ -402,7 +398,6 @@
*
* @return drafts in a map keyed by path; comments have the {@code revision} field set to indicate
* their patch set.
- * @throws RestApiException
*/
default Map<String, List<CommentInfo>> drafts() throws RestApiException {
return draftsRequest().get();
@@ -413,7 +408,6 @@
*
* @return drafts as a list; comments have the {@code revision} field set to indicate their patch
* set.
- * @throws RestApiException
*/
default List<CommentInfo> draftsAsList() throws RestApiException {
return draftsRequest().getAsList();
@@ -443,7 +437,6 @@
* Get all messages of a change with detailed account info.
*
* @return a list of messages sorted by their creation time.
- * @throws RestApiException
*/
List<ChangeMessageInfo> messages() throws RestApiException;
@@ -466,7 +459,6 @@
*
* @return comments in a map keyed by path; comments have the {@code revision} field set to
* indicate their patch set.
- * @throws RestApiException
*/
public abstract Map<String, List<CommentInfo>> get() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/changes/FileApi.java b/java/com/google/gerrit/extensions/api/changes/FileApi.java
index 26f9452..e20ac56 100644
--- a/java/com/google/gerrit/extensions/api/changes/FileApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/FileApi.java
@@ -29,10 +29,18 @@
/** Diff against the revision's parent version of the file. */
DiffInfo diff() throws RestApiException;
- /** @param base revision id of the revision to be used as the diff base */
+ /**
+ * Diff against the specified base
+ *
+ * @param base revision id of the revision to be used as the diff base
+ */
DiffInfo diff(String base) throws RestApiException;
- /** @param parent 1-based parent number to diff against */
+ /**
+ * Diff against the specified parent
+ *
+ * @param parent 1-based parent number to diff against
+ */
DiffInfo diff(int parent) throws RestApiException;
/**
diff --git a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
index 229b9d4..1307516 100644
--- a/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
+++ b/java/com/google/gerrit/extensions/api/changes/RevisionApi.java
@@ -160,7 +160,6 @@
*
* @param format the format of the archive
* @return the archive as {@link BinaryResult}
- * @throws RestApiException
*/
BinaryResult getArchive(ArchiveFormat format) throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/config/Config.java b/java/com/google/gerrit/extensions/api/config/Config.java
index eb7288d..041e1dd 100644
--- a/java/com/google/gerrit/extensions/api/config/Config.java
+++ b/java/com/google/gerrit/extensions/api/config/Config.java
@@ -17,7 +17,7 @@
import com.google.gerrit.extensions.restapi.NotImplementedException;
public interface Config {
- /** @return An API for getting server related configurations. */
+ /** Returns an API for getting server related configurations. */
Server server();
/**
diff --git a/java/com/google/gerrit/extensions/api/config/ConsistencyCheckInfo.java b/java/com/google/gerrit/extensions/api/config/ConsistencyCheckInfo.java
index e582f1b..9fb57ad 100644
--- a/java/com/google/gerrit/extensions/api/config/ConsistencyCheckInfo.java
+++ b/java/com/google/gerrit/extensions/api/config/ConsistencyCheckInfo.java
@@ -14,6 +14,7 @@
package com.google.gerrit.extensions.api.config;
+import com.google.errorprone.annotations.FormatMethod;
import java.util.List;
import java.util.Objects;
@@ -80,10 +81,12 @@
return status.name() + ": " + message;
}
+ @FormatMethod
public static ConsistencyProblemInfo warning(String fmt, Object... args) {
return new ConsistencyProblemInfo(Status.WARNING, String.format(fmt, args));
}
+ @FormatMethod
public static ConsistencyProblemInfo error(String fmt, Object... args) {
return new ConsistencyProblemInfo(Status.ERROR, String.format(fmt, args));
}
diff --git a/java/com/google/gerrit/extensions/api/config/Server.java b/java/com/google/gerrit/extensions/api/config/Server.java
index 70d1bff..8b69ded 100644
--- a/java/com/google/gerrit/extensions/api/config/Server.java
+++ b/java/com/google/gerrit/extensions/api/config/Server.java
@@ -24,7 +24,7 @@
import java.util.List;
public interface Server {
- /** @return Version of server. */
+ /** Returns version of server. */
String getVersion() throws RestApiException;
ServerInfo getInfo() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/groups/GroupApi.java b/java/com/google/gerrit/extensions/api/groups/GroupApi.java
index 067f120..e1b3a9f 100644
--- a/java/com/google/gerrit/extensions/api/groups/GroupApi.java
+++ b/java/com/google/gerrit/extensions/api/groups/GroupApi.java
@@ -24,53 +24,49 @@
import java.util.List;
public interface GroupApi {
- /** @return group info with no {@code ListGroupsOption}s set. */
+ /** Returns group info with no {@code ListGroupsOption}s set. */
GroupInfo get() throws RestApiException;
- /** @return group info with all {@code ListGroupsOption}s set. */
+ /** Returns group info with all {@code ListGroupsOption}s set. */
GroupInfo detail() throws RestApiException;
- /** @return group name. */
+ /** Returns group name. */
String name() throws RestApiException;
/**
* Set group name.
*
* @param name new name.
- * @throws RestApiException
*/
void name(String name) throws RestApiException;
- /** @return owning group info. */
+ /** Returns owning group info. */
GroupInfo owner() throws RestApiException;
/**
* Set group owner.
*
* @param owner identifier of new group owner.
- * @throws RestApiException
*/
void owner(String owner) throws RestApiException;
- /** @return group description. */
+ /** Returns group description. */
String description() throws RestApiException;
/**
* Set group decsription.
*
* @param description new description.
- * @throws RestApiException
*/
void description(String description) throws RestApiException;
- /** @return group options. */
+ /** Returns group options. */
GroupOptionsInfo options() throws RestApiException;
/**
* Set group options.
*
* @param options new options.
- * @throws RestApiException
*/
void options(GroupOptionsInfo options) throws RestApiException;
@@ -78,7 +74,6 @@
* List group members, non-recursively.
*
* @return group members.
- * @throws RestApiException
*/
List<AccountInfo> members() throws RestApiException;
@@ -87,7 +82,6 @@
*
* @param recursive whether to recursively included groups.
* @return group members.
- * @throws RestApiException
*/
List<AccountInfo> members(boolean recursive) throws RestApiException;
@@ -96,7 +90,6 @@
*
* @param members list of member identifiers, in any format accepted by {@link
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
- * @throws RestApiException
*/
void addMembers(List<String> members) throws RestApiException;
@@ -105,7 +98,6 @@
*
* @param members list of member identifiers, in any format accepted by {@link
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
- * @throws RestApiException
*/
default void addMembers(String... members) throws RestApiException {
addMembers(Arrays.asList(members));
@@ -116,7 +108,6 @@
*
* @param members list of member identifiers, in any format accepted by {@link
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
- * @throws RestApiException
*/
void removeMembers(List<String> members) throws RestApiException;
@@ -125,7 +116,6 @@
*
* @param members list of member identifiers, in any format accepted by {@link
* com.google.gerrit.extensions.api.accounts.Accounts#id(String)}
- * @throws RestApiException
*/
default void removeMembers(String... members) throws RestApiException {
removeMembers(Arrays.asList(members));
@@ -135,7 +125,6 @@
* Lists the subgroups of this group.
*
* @return the found subgroups
- * @throws RestApiException
*/
List<GroupInfo> includedGroups() throws RestApiException;
@@ -143,7 +132,6 @@
* Adds subgroups to this group.
*
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
- * @throws RestApiException
*/
void addGroups(List<String> groups) throws RestApiException;
@@ -151,7 +139,6 @@
* Adds subgroups to this group.
*
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
- * @throws RestApiException
*/
default void addGroups(String... groups) throws RestApiException {
addGroups(Arrays.asList(groups));
@@ -161,7 +148,6 @@
* Removes subgroups from this group.
*
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
- * @throws RestApiException
*/
void removeGroups(List<String> groups) throws RestApiException;
@@ -169,7 +155,6 @@
* Removes subgroups from this group.
*
* @param groups list of group identifiers, in any format accepted by {@link Groups#id(String)}
- * @throws RestApiException
*/
default void removeGroups(String... groups) throws RestApiException {
removeGroups(Arrays.asList(groups));
@@ -179,7 +164,6 @@
* Returns the audit log of the group.
*
* @return list of audit events of the group.
- * @throws RestApiException
*/
List<? extends GroupAuditEventInfo> auditLog() throws RestApiException;
@@ -187,8 +171,6 @@
* Reindexes the group.
*
* <p>Only supported for internal groups.
- *
- * @throws RestApiException
*/
void index() throws RestApiException;
diff --git a/java/com/google/gerrit/extensions/api/groups/Groups.java b/java/com/google/gerrit/extensions/api/groups/Groups.java
index 81b5f47..1a46930 100644
--- a/java/com/google/gerrit/extensions/api/groups/Groups.java
+++ b/java/com/google/gerrit/extensions/api/groups/Groups.java
@@ -47,7 +47,7 @@
/** Create a new group. */
GroupApi create(GroupInput input) throws RestApiException;
- /** @return new request for listing groups. */
+ /** Returns new request for listing groups. */
ListRequest list();
/**
diff --git a/java/com/google/gerrit/extensions/auth/oauth/OAuthServiceProvider.java b/java/com/google/gerrit/extensions/auth/oauth/OAuthServiceProvider.java
index 417f55a..c3d760b 100644
--- a/java/com/google/gerrit/extensions/auth/oauth/OAuthServiceProvider.java
+++ b/java/com/google/gerrit/extensions/auth/oauth/OAuthServiceProvider.java
@@ -40,9 +40,7 @@
* After establishing of secure communication channel, this method supossed to access the
* protected resoure and retrieve the username.
*
- * @param token
* @return OAuth user information
- * @throws IOException
*/
OAuthUserInfo getUserInfo(OAuthToken token) throws IOException;
diff --git a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
index 21b319e..b26f435 100644
--- a/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
+++ b/java/com/google/gerrit/extensions/client/GeneralPreferencesInfo.java
@@ -148,6 +148,7 @@
public DefaultBase defaultBaseForMerges;
public Boolean publishCommentsOnPush;
public Boolean disableKeyboardShortcuts;
+ public Boolean disableTokenHighlighting;
public Boolean workInProgressByDefault;
public List<MenuItem> my;
public List<String> changeTable;
@@ -207,6 +208,7 @@
p.defaultBaseForMerges = DefaultBase.FIRST_PARENT;
p.publishCommentsOnPush = false;
p.disableKeyboardShortcuts = false;
+ p.disableTokenHighlighting = false;
p.workInProgressByDefault = false;
return p;
}
diff --git a/java/com/google/gerrit/extensions/common/ChangeInfoDiffer.java b/java/com/google/gerrit/extensions/common/ChangeInfoDiffer.java
index 0447e80..ba5e323 100644
--- a/java/com/google/gerrit/extensions/common/ChangeInfoDiffer.java
+++ b/java/com/google/gerrit/extensions/common/ChangeInfoDiffer.java
@@ -143,7 +143,7 @@
}
}
- /** @return {@code null} if nothing has been added to {@code oldCollection} */
+ /** Returns {@code null} if nothing has been added to {@code oldCollection} */
private static ImmutableList<?> getAddedForCollection(
Collection<?> oldCollection, Collection<?> newCollection) {
ImmutableList<?> notInOldCollection = getAdditions(oldCollection, newCollection);
@@ -165,7 +165,7 @@
return duplicatesMap.values().stream().flatMap(Collection::stream).collect(toImmutableList());
}
- /** @return {@code null} if nothing has been added to {@code oldMap} */
+ /** Returns {@code null} if nothing has been added to {@code oldMap} */
private static ImmutableMap<Object, Object> getAddedForMap(Map<?, ?> oldMap, Map<?, ?> newMap) {
ImmutableMap.Builder<Object, Object> additionsBuilder = ImmutableMap.builder();
for (Map.Entry<?, ?> entry : newMap.entrySet()) {
diff --git a/java/com/google/gerrit/extensions/common/TestSubmitRuleInfo.java b/java/com/google/gerrit/extensions/common/TestSubmitRuleInfo.java
index deb03b0..2af9a767 100644
--- a/java/com/google/gerrit/extensions/common/TestSubmitRuleInfo.java
+++ b/java/com/google/gerrit/extensions/common/TestSubmitRuleInfo.java
@@ -19,7 +19,7 @@
import java.util.Objects;
public class TestSubmitRuleInfo {
- /** @see com.google.gerrit.entities.SubmitRecord.Status */
+ /** See {@link com.google.gerrit.entities.SubmitRecord.Status} */
public String status;
public String errorMessage;
diff --git a/java/com/google/gerrit/extensions/conditions/BooleanCondition.java b/java/com/google/gerrit/extensions/conditions/BooleanCondition.java
index 162dd99..97543af 100644
--- a/java/com/google/gerrit/extensions/conditions/BooleanCondition.java
+++ b/java/com/google/gerrit/extensions/conditions/BooleanCondition.java
@@ -48,7 +48,7 @@
BooleanCondition() {}
- /** @return evaluate the condition and return its value. */
+ /** Evaluates the condition and return its value. */
public abstract boolean value();
/**
diff --git a/java/com/google/gerrit/extensions/config/DownloadScheme.java b/java/com/google/gerrit/extensions/config/DownloadScheme.java
index d81657a..96b5878 100644
--- a/java/com/google/gerrit/extensions/config/DownloadScheme.java
+++ b/java/com/google/gerrit/extensions/config/DownloadScheme.java
@@ -26,12 +26,12 @@
*/
public abstract String getUrl(String project);
- /** @return whether this scheme requires authentication */
+ /** Returns whether this scheme requires authentication */
public abstract boolean isAuthRequired();
- /** @return whether this scheme supports authentication */
+ /** Returns whether this scheme supports authentication */
public abstract boolean isAuthSupported();
- /** @return whether the download scheme is enabled */
+ /** Returns whether the download scheme is enabled */
public abstract boolean isEnabled();
}
diff --git a/java/com/google/gerrit/extensions/events/GarbageCollectorListener.java b/java/com/google/gerrit/extensions/events/GarbageCollectorListener.java
index edb3e69..45c33c9 100644
--- a/java/com/google/gerrit/extensions/events/GarbageCollectorListener.java
+++ b/java/com/google/gerrit/extensions/events/GarbageCollectorListener.java
@@ -22,8 +22,9 @@
public interface GarbageCollectorListener {
interface Event extends ProjectEvent {
/**
- * @return Properties describing the result of the garbage collection performed by JGit.
- * @see org.eclipse.jgit.api.GarbageCollectCommand#call()
+ * Returns properties describing the result of the garbage collection performed by JGit.
+ *
+ * <p>See {@link org.eclipse.jgit.api.GarbageCollectCommand#call }
*/
Properties getStatistics();
}
diff --git a/java/com/google/gerrit/extensions/restapi/BinaryResult.java b/java/com/google/gerrit/extensions/restapi/BinaryResult.java
index bdddfd9..2ee376e 100644
--- a/java/com/google/gerrit/extensions/restapi/BinaryResult.java
+++ b/java/com/google/gerrit/extensions/restapi/BinaryResult.java
@@ -63,7 +63,7 @@
private boolean base64;
private String attachmentName;
- /** @return the MIME type of the result, for HTTP clients. */
+ /** Returns the MIME type of the result, for HTTP clients. */
public String getContentType() {
Charset enc = getCharacterEncoding();
if (enc != null) {
@@ -100,7 +100,7 @@
return this;
}
- /** @return length in bytes of the result; -1 if not known. */
+ /** Returns length in bytes of the result; -1 if not known. */
public long getContentLength() {
return contentLength;
}
@@ -111,7 +111,7 @@
return this;
}
- /** @return true if this result can be gzip compressed to clients. */
+ /** Returns true if this result can be gzip compressed to clients. */
public boolean canGzip() {
return gzip;
}
@@ -122,7 +122,7 @@
return this;
}
- /** @return true if the result must be base64 encoded. */
+ /** Returns true if the result must be base64 encoded. */
public boolean isBase64() {
return base64;
}
diff --git a/java/com/google/gerrit/extensions/restapi/IdString.java b/java/com/google/gerrit/extensions/restapi/IdString.java
index 736c3ba..b2538fa 100644
--- a/java/com/google/gerrit/extensions/restapi/IdString.java
+++ b/java/com/google/gerrit/extensions/restapi/IdString.java
@@ -36,17 +36,17 @@
urlEncoded = s;
}
- /** @return the decoded value of the string. */
+ /** Returns the decoded value of the string. */
public String get() {
return Url.decode(urlEncoded);
}
- /** @return true if the string is the empty string. */
+ /** Returns true if the string is the empty string. */
public boolean isEmpty() {
return urlEncoded.isEmpty();
}
- /** @return the original URL encoding supplied by the client. */
+ /** Returns the original URL encoding supplied by the client. */
public String encoded() {
return urlEncoded;
}
diff --git a/java/com/google/gerrit/extensions/restapi/RestResource.java b/java/com/google/gerrit/extensions/restapi/RestResource.java
index cc5d48d..3c8144a 100644
--- a/java/com/google/gerrit/extensions/restapi/RestResource.java
+++ b/java/com/google/gerrit/extensions/restapi/RestResource.java
@@ -26,7 +26,7 @@
/** A resource with a last modification date. */
public interface HasLastModified {
- /** @return time for the Last-Modified header. HTTP truncates the header value to seconds. */
+ /** Returns time for the Last-Modified header. HTTP truncates the header value to seconds. */
Timestamp getLastModified();
}
diff --git a/java/com/google/gerrit/extensions/webui/WebUiPlugin.java b/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
index 2d49e1c..4f129b0 100644
--- a/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
+++ b/java/com/google/gerrit/extensions/webui/WebUiPlugin.java
@@ -44,7 +44,7 @@
private String pluginName;
- /** @return installed name of the plugin that provides this UI feature. */
+ /** Returns installed name of the plugin that provides this UI feature. */
public final String getPluginName() {
return pluginName;
}
@@ -54,7 +54,7 @@
this.pluginName = pluginName;
}
- /** @return path to initialization script within the plugin's JAR. */
+ /** Returns path to initialization script within the plugin's JAR. */
public abstract String getJavaScriptResourcePath();
@Override
diff --git a/java/com/google/gerrit/git/GitUpdateFailureException.java b/java/com/google/gerrit/git/GitUpdateFailureException.java
index 76ef217..7fcb828 100644
--- a/java/com/google/gerrit/git/GitUpdateFailureException.java
+++ b/java/com/google/gerrit/git/GitUpdateFailureException.java
@@ -46,12 +46,12 @@
.collect(toImmutableList());
}
- /** @return the names of the refs for which the update failed. */
+ /** Returns the names of the refs for which the update failed. */
public ImmutableList<String> getFailedRefs() {
return failures.stream().map(GitUpdateFailure::ref).collect(toImmutableList());
}
- /** @return the failures that caused this exception. */
+ /** Returns the failures that caused this exception. */
@UsedAt(UsedAt.Project.GOOGLE)
public ImmutableList<GitUpdateFailure> getFailures() {
return failures;
diff --git a/java/com/google/gerrit/gpg/CheckResult.java b/java/com/google/gerrit/gpg/CheckResult.java
index 8655b2a..2743e74 100644
--- a/java/com/google/gerrit/gpg/CheckResult.java
+++ b/java/com/google/gerrit/gpg/CheckResult.java
@@ -62,22 +62,22 @@
this.problems = problems;
}
- /** @return whether the result has status {@link Status#OK} or better. */
+ /** Returns whether the result has status {@link Status#OK} or better. */
public boolean isOk() {
return status.compareTo(Status.OK) >= 0;
}
- /** @return whether the result has status {@link Status#TRUSTED} or better. */
+ /** Returns whether the result has status {@link Status#TRUSTED} or better. */
public boolean isTrusted() {
return status.compareTo(Status.TRUSTED) >= 0;
}
- /** @return the status enum value associated with the object. */
+ /** Returns the status enum value associated with the object. */
public Status getStatus() {
return status;
}
- /** @return any problems encountered during checking. */
+ /** Returns any problems encountered during checking. */
public List<String> getProblems() {
return problems;
}
diff --git a/java/com/google/gerrit/gpg/PushCertificateChecker.java b/java/com/google/gerrit/gpg/PushCertificateChecker.java
index 82b3892..36a4af7 100644
--- a/java/com/google/gerrit/gpg/PushCertificateChecker.java
+++ b/java/com/google/gerrit/gpg/PushCertificateChecker.java
@@ -154,8 +154,11 @@
protected abstract Repository getRepository() throws IOException;
/**
+ * Specifies whether this repository should be closed before returning froms {@link
+ * #check(PushCertificate)}
+ *
* @param repo a repository previously returned by {@link #getRepository()}.
- * @return whether this repository should be closed before returning from {@link
+ * @return true if this repository should be closed before returning from {@link
* #check(PushCertificate)}.
*/
protected abstract boolean shouldClose(Repository repo);
diff --git a/java/com/google/gerrit/httpd/RequestMetricsFilter.java b/java/com/google/gerrit/httpd/RequestMetricsFilter.java
index c97b9ad..0ff1a79 100644
--- a/java/com/google/gerrit/httpd/RequestMetricsFilter.java
+++ b/java/com/google/gerrit/httpd/RequestMetricsFilter.java
@@ -55,17 +55,17 @@
startedMemory = threadMxBean.getCurrentThreadAllocatedBytes();
}
- /** @return total CPU time in milliseconds for executing request */
+ /** Returns total CPU time in milliseconds for executing request */
public long getTotalCpuTime() {
return (threadMxBean.getCurrentThreadCpuTime() - startedTotalCpu) / 1_000_000;
}
- /** @return CPU time in user mode in milliseconds for executing request */
+ /** Returns CPU time in user mode in milliseconds for executing request */
public long getUserCpuTime() {
return (threadMxBean.getCurrentThreadUserTime() - startedUserCpu) / 1_000_000;
}
- /** @return memory allocated in bytes for executing request */
+ /** Returns memory allocated in bytes for executing request */
public long getAllocatedMemory() {
return startedMemory == -1
? -1
diff --git a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
index 3c39ea1..369ea29 100644
--- a/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
+++ b/java/com/google/gerrit/httpd/restapi/RestApiServlet.java
@@ -768,13 +768,12 @@
}
} else {
res.reset();
- traceContext.getTraceId().ifPresent(traceId -> res.addHeader(X_GERRIT_TRACE, traceId));
+ TraceContext.getTraceId().ifPresent(traceId -> res.addHeader(X_GERRIT_TRACE, traceId));
if (status.isPresent()) {
- responseBytes = reply(req, res, e, status.get(), getUserMessages(traceContext, e));
+ responseBytes = reply(req, res, e, status.get(), getUserMessages(e));
} else {
- responseBytes =
- replyInternalServerError(req, res, e, getUserMessages(traceContext, e));
+ responseBytes = replyInternalServerError(req, res, e, getUserMessages(e));
}
}
}
@@ -984,7 +983,7 @@
throws Exception {
RetryableAction<T> retryableAction = globals.retryHelper.action(actionType, caller, action);
AtomicReference<Optional<String>> traceId = new AtomicReference<>(Optional.empty());
- if (!traceContext.isTracing()) {
+ if (!TraceContext.isTracing()) {
// enable automatic retry with tracing in case of non-recoverable failure
retryableAction
.retryWithTrace(t -> !(t instanceof RestApiException))
@@ -1427,7 +1426,6 @@
* @param config config parameters for the JSON formatting
* @param result the object that should be formatted as JSON
* @return the length of the response
- * @throws IOException
*/
public static long replyJson(
@Nullable HttpServletRequest req,
@@ -1876,9 +1874,9 @@
.findFirst();
}
- private ImmutableList<String> getUserMessages(TraceContext traceContext, Throwable err) {
+ private ImmutableList<String> getUserMessages(Throwable err) {
return globals.exceptionHooks.stream()
- .flatMap(h -> h.getUserMessages(err, traceContext.getTraceId().orElse(null)).stream())
+ .flatMap(h -> h.getUserMessages(err, TraceContext.getTraceId().orElse(null)).stream())
.collect(toImmutableList());
}
@@ -1971,7 +1969,6 @@
* set to {@code true} if the reply may contain sensitive data
* @param text the text reply
* @return the length of the response
- * @throws IOException
*/
static long replyText(
@Nullable HttpServletRequest req, HttpServletResponse res, boolean allowTracing, String text)
diff --git a/java/com/google/gerrit/index/FieldDef.java b/java/com/google/gerrit/index/FieldDef.java
index eb64c1d..76aa7cc 100644
--- a/java/com/google/gerrit/index/FieldDef.java
+++ b/java/com/google/gerrit/index/FieldDef.java
@@ -138,17 +138,17 @@
return name;
}
- /** @return name of the field. */
+ /** Returns name of the field. */
public String getName() {
return name;
}
- /** @return type of the field; for repeatable fields, the inner type, not the iterable type. */
+ /** Returns type of the field; for repeatable fields, the inner type, not the iterable type. */
public FieldType<?> getType() {
return type;
}
- /** @return whether the field should be stored in the index. */
+ /** Returns whether the field should be stored in the index. */
public boolean isStored() {
return stored;
}
@@ -203,7 +203,7 @@
return false;
}
- /** @return whether the field is repeatable. */
+ /** Returns whether the field is repeatable. */
public boolean isRepeatable() {
return repeatable;
}
diff --git a/java/com/google/gerrit/index/Index.java b/java/com/google/gerrit/index/Index.java
index 529cd78..ead302d 100644
--- a/java/com/google/gerrit/index/Index.java
+++ b/java/com/google/gerrit/index/Index.java
@@ -33,7 +33,7 @@
* <p>Implementations must be thread-safe and should batch inserts/updates where appropriate.
*/
public interface Index<K, V> {
- /** @return the schema version used by this index. */
+ /** Returns the schema version used by this index. */
Schema<V> getSchema();
/** Close this index. */
diff --git a/java/com/google/gerrit/index/IndexConfig.java b/java/com/google/gerrit/index/IndexConfig.java
index 29b8ea6..8676fb2 100644
--- a/java/com/google/gerrit/index/IndexConfig.java
+++ b/java/com/google/gerrit/index/IndexConfig.java
@@ -101,27 +101,27 @@
}
/**
- * @return maximum limit supported by the underlying index, or limited for performance reasons.
+ * Returns maximum limit supported by the underlying index, or limited for performance reasons.
*/
public abstract int maxLimit();
/**
- * @return maximum number of pages (limit / start) supported by the underlying index, or limited
- * for performance reasons.
+ * Returns maximum number of pages (limit / start) supported by the underlying index, or limited
+ * for performance reasons.
*/
public abstract int maxPages();
/**
- * @return maximum number of total index query terms supported by the underlying index, or limited
- * for performance reasons.
+ * Returns maximum number of total index query terms supported by the underlying index, or limited
+ * for performance reasons.
*/
public abstract int maxTerms();
- /** @return index type. */
+ /** Returns index type. */
public abstract String type();
/**
- * @return whether different subsets of changes may be stored in different physical sub-indexes.
+ * Returns whether different subsets of changes may be stored in different physical sub-indexes.
*/
public abstract boolean separateChangeSubIndexes();
}
diff --git a/java/com/google/gerrit/index/Schema.java b/java/com/google/gerrit/index/Schema.java
index 3aa9de0..91c3f70 100644
--- a/java/com/google/gerrit/index/Schema.java
+++ b/java/com/google/gerrit/index/Schema.java
@@ -134,7 +134,7 @@
return fields;
}
- /** @return all fields in this schema where {@link FieldDef#isStored()} is true. */
+ /** Returns all fields in this schema where {@link FieldDef#isStored()} is true. */
public final ImmutableMap<String, FieldDef<T, ?>> getStoredFields() {
return storedFields;
}
diff --git a/java/com/google/gerrit/index/query/DataSource.java b/java/com/google/gerrit/index/query/DataSource.java
index 2c2ba53..518d153 100644
--- a/java/com/google/gerrit/index/query/DataSource.java
+++ b/java/com/google/gerrit/index/query/DataSource.java
@@ -15,12 +15,12 @@
package com.google.gerrit.index.query;
public interface DataSource<T> {
- /** @return an estimate of the number of results from {@link #read()}. */
+ /** Returns an estimate of the number of results from {@link #read()}. */
int getCardinality();
- /** @return read from the database and return the results. */
+ /** Returns read from the database and return the results. */
ResultSet<T> read();
- /** @return read from the database and return the raw results. */
+ /** Returns read from the database and return the raw results. */
ResultSet<FieldBundle> readRaw();
}
diff --git a/java/com/google/gerrit/index/query/Matchable.java b/java/com/google/gerrit/index/query/Matchable.java
index 7a16ae8..f416149 100644
--- a/java/com/google/gerrit/index/query/Matchable.java
+++ b/java/com/google/gerrit/index/query/Matchable.java
@@ -18,6 +18,6 @@
/** Does this predicate match this object? */
boolean match(T object);
- /** @return a cost estimate to run this predicate, higher figures cost more. */
+ /** Returns a cost estimate to run this predicate, higher figures cost more. */
int getCost();
}
diff --git a/java/com/google/gerrit/index/query/Predicate.java b/java/com/google/gerrit/index/query/Predicate.java
index 2382d30..2791f2c 100644
--- a/java/com/google/gerrit/index/query/Predicate.java
+++ b/java/com/google/gerrit/index/query/Predicate.java
@@ -159,7 +159,7 @@
return (Matchable<T>) this;
}
- /** @return a cost estimate to run this predicate, higher figures cost more. */
+ /** Returns a cost estimate to run this predicate, higher figures cost more. */
public int estimateCost() {
if (!isMatchable()) {
return 1;
diff --git a/java/com/google/gerrit/index/query/QueryResult.java b/java/com/google/gerrit/index/query/QueryResult.java
index 33fcef0..d03a68b 100644
--- a/java/com/google/gerrit/index/query/QueryResult.java
+++ b/java/com/google/gerrit/index/query/QueryResult.java
@@ -34,19 +34,19 @@
return new AutoValue_QueryResult<>(query, predicate, ImmutableList.copyOf(entities), more);
}
- /** @return the original query string, or null if the query was created programmatically. */
+ /** Returns the original query string, or null if the query was created programmatically. */
@Nullable
public abstract String query();
- /** @return the predicate after all rewriting and other modification by the query subsystem. */
+ /** Returns the predicate after all rewriting and other modification by the query subsystem. */
public abstract Predicate<T> predicate();
- /** @return the query results. */
+ /** Returns the query results. */
public abstract ImmutableList<T> entities();
/**
- * @return whether the query could be retried with a higher start/limit to produce more results.
- * Never true if {@link #entities()} is empty.
+ * Returns whether the query could be retried with a higher start/limit to produce more results.
+ * Never true if {@link #entities()} is empty.
*/
public abstract boolean more();
}
diff --git a/java/com/google/gerrit/json/OutputFormat.java b/java/com/google/gerrit/json/OutputFormat.java
index 3e7c319..c5504bb 100644
--- a/java/com/google/gerrit/json/OutputFormat.java
+++ b/java/com/google/gerrit/json/OutputFormat.java
@@ -42,12 +42,12 @@
*/
JSON_COMPACT;
- /** @return true when the format is either JSON or JSON_COMPACT. */
+ /** Returns true when the format is either JSON or JSON_COMPACT. */
public boolean isJson() {
return this == JSON_COMPACT || this == JSON;
}
- /** @return a new Gson instance configured according to the format. */
+ /** Returns a new Gson instance configured according to the format. */
public GsonBuilder newGsonBuilder() {
if (!isJson()) {
throw new IllegalStateException(String.format("%s is not JSON", this));
@@ -63,7 +63,7 @@
return gb;
}
- /** @return a new Gson instance configured according to the format. */
+ /** Returns a new Gson instance configured according to the format. */
public Gson newGson() {
return newGsonBuilder().create();
}
diff --git a/java/com/google/gerrit/lifecycle/LifecycleModule.java b/java/com/google/gerrit/lifecycle/LifecycleModule.java
index 0fb4653..efe1518 100644
--- a/java/com/google/gerrit/lifecycle/LifecycleModule.java
+++ b/java/com/google/gerrit/lifecycle/LifecycleModule.java
@@ -24,13 +24,16 @@
/** Module to support registering a unique LifecyleListener. */
public abstract class LifecycleModule extends FactoryModule {
/**
- * @return a unique listener binding.
- * <p>To create a listener binding use:
- * <pre>
+ * Returns a unique listener binding.
+ *
+ * <p>To create a listener binding use:
+ *
+ * <pre>
* listener().to(MyListener.class);
* </pre>
- * where {@code MyListener} is a {@link Singleton} implementing the {@link LifecycleListener}
- * interface.
+ *
+ * where {@code MyListener} is a {@link Singleton} implementing the {@link LifecycleListener}
+ * interface.
*/
protected LinkedBindingBuilder<LifecycleListener> listener() {
final Annotation id = UniqueAnnotations.create();
diff --git a/java/com/google/gerrit/mail/TextParser.java b/java/com/google/gerrit/mail/TextParser.java
index 95ab10c..c43d200 100644
--- a/java/com/google/gerrit/mail/TextParser.java
+++ b/java/com/google/gerrit/mail/TextParser.java
@@ -30,7 +30,7 @@
/**
* Parses comments from plaintext email.
*
- * @param email @param email the message as received from the email service
+ * @param email the message as received from the email service
* @param comments list of {@link HumanComment}s previously persisted on the change that caused
* the original notification email to be sent out. Ordering must be the same as in the
* outbound email
diff --git a/java/com/google/gerrit/metrics/Description.java b/java/com/google/gerrit/metrics/Description.java
index 10568bc..f5963af 100644
--- a/java/com/google/gerrit/metrics/Description.java
+++ b/java/com/google/gerrit/metrics/Description.java
@@ -133,27 +133,27 @@
return this;
}
- /** @return true if the metric value never changes after startup. */
+ /** Returns true if the metric value never changes after startup. */
public boolean isConstant() {
return TRUE_VALUE.equals(annotations.get(CONSTANT));
}
- /** @return true if the metric may be interpreted as a rate over time. */
+ /** Returns true if the metric may be interpreted as a rate over time. */
public boolean isRate() {
return TRUE_VALUE.equals(annotations.get(RATE));
}
- /** @return true if the metric is an instantaneous sample. */
+ /** Returns true if the metric is an instantaneous sample. */
public boolean isGauge() {
return TRUE_VALUE.equals(annotations.get(GAUGE));
}
- /** @return true if the metric accumulates over the lifespan of the process. */
+ /** Returns true if the metric accumulates over the lifespan of the process. */
public boolean isCumulative() {
return TRUE_VALUE.equals(annotations.get(CUMULATIVE));
}
- /** @return the suggested field ordering. */
+ /** Returns the suggested field ordering. */
public FieldOrdering getFieldOrdering() {
String o = annotations.get(FIELD_ORDERING);
return o != null ? FieldOrdering.valueOf(o) : FieldOrdering.AT_END;
@@ -187,7 +187,7 @@
return u;
}
- /** @return immutable copy of all annotations (configurable properties). */
+ /** Returns an immutable copy of all annotations (configurable properties). */
public ImmutableMap<String, String> getAnnotations() {
return ImmutableMap.copyOf(annotations);
}
diff --git a/java/com/google/gerrit/metrics/Field.java b/java/com/google/gerrit/metrics/Field.java
index bdae854..5508819 100644
--- a/java/com/google/gerrit/metrics/Field.java
+++ b/java/com/google/gerrit/metrics/Field.java
@@ -102,19 +102,19 @@
.metadataMapper(metadataMapper);
}
- /** @return name of this field within the metric. */
+ /** Returns name of this field within the metric. */
public abstract String name();
- /** @return type of value used within the field. */
+ /** Returns type of value used within the field. */
public abstract Class<T> valueType();
- /** @return mapper that maps a field value to a field in the {@link Metadata} class. */
+ /** Returns mapper that maps a field value to a field in the {@link Metadata} class. */
public abstract BiConsumer<Metadata.Builder, T> metadataMapper();
- /** @return description text for the field explaining its range of values. */
+ /** Returns description text for the field explaining its range of values. */
public abstract Optional<String> description();
- /** @return formatter to format field values. */
+ /** Returns formatter to format field values. */
public abstract Function<T, String> formatter();
@AutoValue.Builder
diff --git a/java/com/google/gerrit/metrics/TimerContext.java b/java/com/google/gerrit/metrics/TimerContext.java
index 62eb030..a3754c5 100644
--- a/java/com/google/gerrit/metrics/TimerContext.java
+++ b/java/com/google/gerrit/metrics/TimerContext.java
@@ -29,7 +29,7 @@
*/
public abstract void record(long elapsed);
- /** @return the start time in system time nanoseconds. */
+ /** Returns the start time in system time nanoseconds. */
public long getStartTime() {
return startNanos;
}
diff --git a/java/com/google/gerrit/metrics/proc/JGitMetricModule.java b/java/com/google/gerrit/metrics/proc/JGitMetricModule.java
index e8611b3..d64bd19 100644
--- a/java/com/google/gerrit/metrics/proc/JGitMetricModule.java
+++ b/java/com/google/gerrit/metrics/proc/JGitMetricModule.java
@@ -184,7 +184,9 @@
+ "having most data in the cache.")
.setGauge()
.setUnit("byte"),
- Field.ofString("repository_name", Metadata.Builder::projectName).build());
+ Field.ofString("repository_name", Metadata.Builder::projectName)
+ .description("The name of the repository.")
+ .build());
metrics.newTrigger(
repoEnt,
() -> {
diff --git a/java/com/google/gerrit/pgm/ChangeExternalIdCaseSensitivity.java b/java/com/google/gerrit/pgm/ChangeExternalIdCaseSensitivity.java
index fbc6065..01c76c1 100644
--- a/java/com/google/gerrit/pgm/ChangeExternalIdCaseSensitivity.java
+++ b/java/com/google/gerrit/pgm/ChangeExternalIdCaseSensitivity.java
@@ -27,6 +27,7 @@
import com.google.gerrit.server.account.externalids.DisabledExternalIdCache;
import com.google.gerrit.server.account.externalids.ExternalId;
import com.google.gerrit.server.account.externalids.ExternalIdFactory;
+import com.google.gerrit.server.account.externalids.ExternalIdKeyFactory;
import com.google.gerrit.server.account.externalids.ExternalIdNotes;
import com.google.gerrit.server.account.externalids.ExternalIdUpsertPreprocessor;
import com.google.gerrit.server.account.externalids.ExternalIds;
@@ -157,8 +158,15 @@
private void recomputeExternalIdNoteId(ExternalIdNotes extIdNotes, ExternalId extId)
throws DuplicateKeyException, IOException {
if (extId.isScheme(SCHEME_GERRIT) || extId.isScheme(SCHEME_USERNAME)) {
- ExternalId.Key updatedKey =
- ExternalId.Key.create(extId.key().scheme(), extId.key().id(), !isUserNameCaseInsensitive);
+ ExternalIdKeyFactory keyFactory =
+ new ExternalIdKeyFactory(
+ new ExternalIdKeyFactory.Config() {
+ @Override
+ public boolean isUserNameCaseInsensitive() {
+ return !isUserNameCaseInsensitive;
+ }
+ });
+ ExternalId.Key updatedKey = keyFactory.create(extId.key().scheme(), extId.key().id());
if (!extId.key().sha1().getName().equals(updatedKey.sha1().getName())) {
logger.atInfo().log("Converting note name of external ID: %s", extId.key());
ExternalId updatedExtId =
diff --git a/java/com/google/gerrit/pgm/init/BaseInit.java b/java/com/google/gerrit/pgm/init/BaseInit.java
index c4b0040..c083296 100644
--- a/java/com/google/gerrit/pgm/init/BaseInit.java
+++ b/java/com/google/gerrit/pgm/init/BaseInit.java
@@ -164,7 +164,6 @@
* Invoked before site init is called.
*
* @param init initializer instance.
- * @throws Exception
*/
protected boolean beforeInit(SiteInit init) throws Exception {
return false;
@@ -174,7 +173,6 @@
* Invoked after site init is called.
*
* @param run completed run instance.
- * @throws Exception
*/
protected void afterInit(SiteRun run) throws Exception {}
diff --git a/java/com/google/gerrit/pgm/init/InitAuth.java b/java/com/google/gerrit/pgm/init/InitAuth.java
index c15cff3..948ec49 100644
--- a/java/com/google/gerrit/pgm/init/InitAuth.java
+++ b/java/com/google/gerrit/pgm/init/InitAuth.java
@@ -26,6 +26,7 @@
import com.google.gerrit.pgm.init.api.InitFlags;
import com.google.gerrit.pgm.init.api.InitStep;
import com.google.gerrit.pgm.init.api.Section;
+import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.mail.SignedToken;
import com.google.inject.Inject;
import com.google.inject.Singleton;
@@ -42,11 +43,13 @@
private final Section ldap;
private final Section receive;
private final InitFlags flags;
+ private final SitePaths site;
@Inject
- InitAuth(InitFlags flags, ConsoleUI ui, Section.Factory sections) {
+ InitAuth(InitFlags flags, ConsoleUI ui, final SitePaths site, Section.Factory sections) {
this.flags = flags;
this.ui = ui;
+ this.site = site;
this.auth = sections.get("auth", null);
this.ldap = sections.get("ldap", null);
this.receive = sections.get(RECEIVE, null);
@@ -62,6 +65,10 @@
}
initSignedPush();
+
+ if (site.isNew) {
+ initUserNameCaseSensitivity();
+ }
}
private void initAuthType() {
@@ -156,4 +163,9 @@
boolean enable = ui.yesno(def, "Enable signed push support");
receive.set("enableSignedPush", Boolean.toString(enable));
}
+
+ private void initUserNameCaseSensitivity() {
+ boolean enableCaseInsensitivity = ui.yesno(true, "Use case insensitive usernames");
+ auth.set("userNameCaseInsensitive", Boolean.toString(enableCaseInsensitivity));
+ }
}
diff --git a/java/com/google/gerrit/pgm/init/InitJGitConfig.java b/java/com/google/gerrit/pgm/init/InitJGitConfig.java
index bad55b4..b68e9f7 100644
--- a/java/com/google/gerrit/pgm/init/InitJGitConfig.java
+++ b/java/com/google/gerrit/pgm/init/InitJGitConfig.java
@@ -53,7 +53,8 @@
ConfigConstants.CONFIG_RECEIVE_SECTION, null, ConfigConstants.CONFIG_KEY_AUTOGC, false);
jgitConfig.save();
ui.error(
- "Auto-configured \"receive.autogc = false\" to disable auto-gc after git-receive-pack.");
+ "Auto-configured \"receive.autogc = false\" to disable auto-gc after"
+ + " git-receive-pack.");
} else if (jgitConfig.getBoolean(
ConfigConstants.CONFIG_RECEIVE_SECTION, ConfigConstants.CONFIG_KEY_AUTOGC, true)) {
ui.error(
@@ -72,12 +73,9 @@
ConfigConstants.CONFIG_PROTOCOL_SECTION, null, ConfigConstants.CONFIG_KEY_VERSION);
if (!TransferConfig.ProtocolVersion.V2.version().equals(version)) {
ui.error(
- String.format(
- "HINT: JGit option \"%s.%s = %s\". It's recommended to activate git\n"
- + "wire protocol version 2 to improve git fetch performance.",
- ConfigConstants.CONFIG_PROTOCOL_SECTION,
- ConfigConstants.CONFIG_KEY_VERSION,
- version));
+ "HINT: JGit option \"%s.%s = %s\". It's recommended to activate git\n"
+ + "wire protocol version 2 to improve git fetch performance.",
+ ConfigConstants.CONFIG_PROTOCOL_SECTION, ConfigConstants.CONFIG_KEY_VERSION, version);
}
}
} catch (IOException e) {
diff --git a/java/com/google/gerrit/pgm/init/PluginsDistribution.java b/java/com/google/gerrit/pgm/init/PluginsDistribution.java
index 73720c4..65c96ec 100644
--- a/java/com/google/gerrit/pgm/init/PluginsDistribution.java
+++ b/java/com/google/gerrit/pgm/init/PluginsDistribution.java
@@ -24,6 +24,8 @@
public interface Processor {
/**
+ * Processes the plugin
+ *
* @param pluginName the name of the plugin (without the .jar extension)
* @param in the content of the plugin .jar file. Implementors don't have to close this stream.
* @throws IOException implementations will typically propagate any IOException caused by
diff --git a/java/com/google/gerrit/pgm/init/api/BUILD b/java/com/google/gerrit/pgm/init/api/BUILD
index 693d319..733b9e3 100644
--- a/java/com/google/gerrit/pgm/init/api/BUILD
+++ b/java/com/google/gerrit/pgm/init/api/BUILD
@@ -11,6 +11,7 @@
"//java/com/google/gerrit/server",
"//lib:guava",
"//lib:jgit",
+ "//lib/errorprone:annotations",
"//lib/flogger:api",
"//lib/guice",
"//lib/guice:guice-assistedinject",
diff --git a/java/com/google/gerrit/pgm/init/api/ConsoleUI.java b/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
index ea39a44..dffdde7 100644
--- a/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
+++ b/java/com/google/gerrit/pgm/init/api/ConsoleUI.java
@@ -14,6 +14,8 @@
package com.google.gerrit.pgm.init.api;
+import com.google.errorprone.annotations.FormatMethod;
+import com.google.errorprone.annotations.FormatString;
import com.google.gerrit.common.Die;
import java.io.Console;
import java.util.EnumSet;
@@ -37,7 +39,7 @@
return new Die("aborted by user");
}
- /** @return true if this is a batch UI that has no user interaction. */
+ /** Returns true if this is a batch UI that has no user interaction. */
public abstract boolean isBatch();
/** Display a header message before a series of prompts. */
@@ -75,6 +77,7 @@
public abstract String password(String fmt, Object... args);
/** Display an error message on the system stderr. */
+ @FormatMethod
public void error(String format, Object... args) {
System.err.println(String.format(format, args));
System.err.flush();
@@ -97,6 +100,7 @@
}
@Override
+ @FormatMethod
public boolean yesno(Boolean def, String fmt, Object... args) {
final String prompt = String.format(fmt, args);
for (; ; ) {
@@ -135,7 +139,8 @@
}
@Override
- public String readString(String def, String fmt, Object... args) {
+ @FormatMethod
+ public String readString(String def, @FormatString String fmt, Object... args) {
final String prompt = String.format(fmt, args);
String r;
if (def != null) {
@@ -154,7 +159,9 @@
}
@Override
- public String readString(String def, Set<String> allowedValues, String fmt, Object... args) {
+ @FormatMethod
+ public String readString(
+ String def, Set<String> allowedValues, @FormatString String fmt, Object... args) {
for (; ; ) {
String r = readString(def, fmt, args);
if (allowedValues.contains(r.toLowerCase())) {
@@ -171,6 +178,7 @@
}
@Override
+ @FormatMethod
public String password(String fmt, Object... args) {
final String prompt = String.format(fmt, args);
for (; ; ) {
@@ -195,6 +203,7 @@
}
@Override
+ @FormatMethod
public <T extends Enum<?>, A extends EnumSet<? extends T>> T readEnum(
T def, A options, String fmt, Object... args) {
final String prompt = String.format(fmt, args);
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index c3be0a4..3b620d9 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -64,7 +64,7 @@
this.sitePath = sitePath.normalize();
}
- /** @return the site path specified on the command line. */
+ /** Returns the site path specified on the command line. */
protected Path getSitePath() {
return sitePath;
}
@@ -76,12 +76,12 @@
}
}
- /** @return provides database connectivity and site path. */
+ /** Provides database connectivity and site path. */
protected Injector createDbInjector() {
return createDbInjector(false);
}
- /** @return provides database connectivity and site path. */
+ /** Provides database connectivity and site path. */
protected Injector createDbInjector(boolean enableMetrics) {
List<Module> modules = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/CancellationMetrics.java b/java/com/google/gerrit/server/CancellationMetrics.java
index 2d0b878..f534ccb 100644
--- a/java/com/google/gerrit/server/CancellationMetrics.java
+++ b/java/com/google/gerrit/server/CancellationMetrics.java
@@ -14,11 +14,6 @@
package com.google.gerrit.server;
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Splitter;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.metrics.Counter1;
import com.google.gerrit.metrics.Counter3;
@@ -48,7 +43,7 @@
.build(),
Field.ofString("request_uri", Metadata.Builder::restViewName)
.description(
- "The URI of the request to which the advisory deadline applied"
+ "The redacted URI of the request to which the advisory deadline applied"
+ " (only set for request_type = REST).")
.build(),
Field.ofString("deadline_id", (metadataBuilder, resolveAllUsers) -> {})
@@ -64,7 +59,7 @@
.build(),
Field.ofString("request_uri", Metadata.Builder::restViewName)
.description(
- "The URI of the request that was cancelled"
+ "The redacted URI of the request that was cancelled"
+ " (only set for request_type = REST).")
.build(),
Field.ofEnum(
@@ -87,17 +82,13 @@
public void countAdvisoryDeadline(RequestInfo requestInfo, String deadlineId) {
advisoryDeadlineCount.increment(
- requestInfo.requestType(),
- requestInfo.requestUri().map(CancellationMetrics::redactRequestUri).orElse(""),
- deadlineId);
+ requestInfo.requestType(), requestInfo.redactedRequestUri().orElse(""), deadlineId);
}
public void countCancelledRequest(
RequestInfo requestInfo, RequestStateProvider.Reason cancellationReason) {
cancelledRequestsCount.increment(
- requestInfo.requestType(),
- requestInfo.requestUri().map(CancellationMetrics::redactRequestUri).orElse(""),
- cancellationReason);
+ requestInfo.requestType(), requestInfo.redactedRequestUri().orElse(""), cancellationReason);
}
public void countCancelledRequest(
@@ -105,7 +96,7 @@
String requestUri,
RequestStateProvider.Reason cancellationReason) {
cancelledRequestsCount.increment(
- requestType.name(), CancellationMetrics.redactRequestUri(requestUri), cancellationReason);
+ requestType.name(), RequestInfo.redactRequestUri(requestUri), cancellationReason);
}
@UsedAt(UsedAt.Project.GOOGLE)
@@ -123,58 +114,4 @@
public void countForcefulReceiveTimeout() {
receiveTimeoutCount.increment("forceful");
}
-
- /**
- * Redacts resource IDs from the given request URI.
- *
- * <p>resource IDs in the request URI are replaced with '*'.
- *
- * @param requestUri a REST URI that has path segments that alternate between view name and
- * resource IDs (e.g. "/<view>", "/<view>/<id>", "/<view>/<id>/<view>",
- * "/<view>/<id>/<view>/<id>", "/<view>/<id>/<view>/<id>/<view>" etc.), must be given without
- * the '/a' prefix
- * @return the redacted request URI
- */
- @VisibleForTesting
- static String redactRequestUri(String requestUri) {
- requireNonNull(requestUri, "requestUri");
- checkState(
- !requestUri.startsWith("/a/"), "request URI must not start with '/a/': %s", requestUri);
-
- StringBuilder redactedRequestUri = new StringBuilder();
-
- boolean hasLeadingSlash = false;
- boolean hasTrailingSlash = false;
- if (requestUri.startsWith("/")) {
- hasLeadingSlash = true;
- requestUri = requestUri.substring(1);
- }
- if (requestUri.endsWith("/")) {
- hasTrailingSlash = true;
- requestUri = requestUri.substring(0, requestUri.length() - 1);
- }
-
- boolean idPathSegment = false;
- for (String pathSegment : Splitter.on('/').split(requestUri)) {
- if (!idPathSegment) {
- redactedRequestUri.append("/" + pathSegment);
- idPathSegment = true;
- } else {
- redactedRequestUri.append("/");
- if (!pathSegment.isEmpty()) {
- redactedRequestUri.append("*");
- }
- idPathSegment = false;
- }
- }
-
- if (!hasLeadingSlash) {
- redactedRequestUri.deleteCharAt(0);
- }
- if (hasTrailingSlash) {
- redactedRequestUri.append('/');
- }
-
- return redactedRequestUri.toString();
- }
}
diff --git a/java/com/google/gerrit/server/ChangeMessagesUtil.java b/java/com/google/gerrit/server/ChangeMessagesUtil.java
index d8b5d87..8366b09 100644
--- a/java/com/google/gerrit/server/ChangeMessagesUtil.java
+++ b/java/com/google/gerrit/server/ChangeMessagesUtil.java
@@ -127,8 +127,9 @@
}
/**
+ * Determines whether the tag starts with the autogenerated prefix
+ *
* @param tag value of a tag, or null.
- * @return whether the tag starts with the autogenerated prefix.
*/
public static boolean isAutogenerated(@Nullable String tag) {
return tag != null && tag.startsWith(AUTOGENERATED_TAG_PREFIX);
diff --git a/java/com/google/gerrit/server/ChangeUtil.java b/java/com/google/gerrit/server/ChangeUtil.java
index 46e8d33..d9edf42 100644
--- a/java/com/google/gerrit/server/ChangeUtil.java
+++ b/java/com/google/gerrit/server/ChangeUtil.java
@@ -53,7 +53,7 @@
public static final Ordering<PatchSet> PS_ID_ORDER =
Ordering.from(comparingInt(PatchSet::number));
- /** @return a new unique identifier for change message entities. */
+ /** Returns a new unique identifier for change message entities. */
public static String messageUuid() {
byte[] buf = new byte[8];
UUID_RANDOM.nextBytes(buf);
diff --git a/java/com/google/gerrit/server/CurrentUser.java b/java/com/google/gerrit/server/CurrentUser.java
index 7012944..0b5600d 100644
--- a/java/com/google/gerrit/server/CurrentUser.java
+++ b/java/com/google/gerrit/server/CurrentUser.java
@@ -103,7 +103,7 @@
return Optional.empty();
}
- /** @return unique name of the user for logging, never {@code null} */
+ /** Returns unique name of the user for logging, never {@code null} */
public String getLoggableName() {
return getUserName().orElseGet(() -> getClass().getSimpleName());
}
diff --git a/java/com/google/gerrit/server/IdentifiedUser.java b/java/com/google/gerrit/server/IdentifiedUser.java
index 24ea9d2..eb3e324 100644
--- a/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/java/com/google/gerrit/server/IdentifiedUser.java
@@ -343,15 +343,15 @@
}
/**
- * @return the user's user name; null if one has not been selected/assigned or if the user name is
- * empty.
+ * Returns the user's user name; null if one has not been selected/assigned or if the user name is
+ * empty.
*/
@Override
public Optional<String> getUserName() {
return state().userName();
}
- /** @return unique name of the user for logging, never {@code null} */
+ /** Returns unique name of the user for logging, never {@code null} */
@Override
public String getLoggableName() {
return getUserName()
diff --git a/java/com/google/gerrit/server/PerformanceMetrics.java b/java/com/google/gerrit/server/PerformanceMetrics.java
new file mode 100644
index 0000000..85452ce
--- /dev/null
+++ b/java/com/google/gerrit/server/PerformanceMetrics.java
@@ -0,0 +1,137 @@
+// Copyright (C) 2021 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;
+
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.metrics.Counter3;
+import com.google.gerrit.metrics.Description;
+import com.google.gerrit.metrics.Field;
+import com.google.gerrit.metrics.MetricMaker;
+import com.google.gerrit.metrics.Timer3;
+import com.google.gerrit.server.logging.Metadata;
+import com.google.gerrit.server.logging.PerformanceLogger;
+import com.google.gerrit.server.logging.TraceContext;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import java.util.concurrent.TimeUnit;
+
+/** Performance logger that records the execution times as a metric. */
+@Singleton
+public class PerformanceMetrics implements PerformanceLogger {
+ private static final String OPERATION_LATENCY_METRIC_NAME = "performance/operations";
+ private static final String OPERATION_COUNT_METRIC_NAME = "performance/operations_count";
+ private static final String PLUGIN_OPERATION_COUNT_METRIC_NAME =
+ "performance/plugin_operations_count";
+
+ public final Timer3<String, String, String> operationsLatency;
+ public final Counter3<String, String, String> operationsCounter;
+ public final Counter3<String, String, String> pluginOperationsCounter;
+
+ @Inject
+ PerformanceMetrics(MetricMaker metricMaker) {
+ Field<String> operationNameField =
+ Field.ofString(
+ "operation_name",
+ (metadataBuilder, fieldValue) -> metadataBuilder.operationName(fieldValue))
+ .description("The operation that was performed.")
+ .build();
+ Field<String> changeIdentifierField =
+ Field.ofString("change_identifier", (metadataBuilder, fieldValue) -> {})
+ .description(
+ "The ID of the change for which the operation was performed"
+ + " (format = '<project>~<numeric-change-id>').")
+ .build();
+ Field<String> traceIdField =
+ Field.ofString("trace_id", (metadataBuilder, fieldValue) -> {})
+ .description("The ID of the trace if tracing was done.")
+ .build();
+ Field<String> requestField =
+ Field.ofString("request", (metadataBuilder, fieldValue) -> {})
+ .description(
+ "The request for which the operation was performed"
+ + " (format = '<request-type> <redacted-request-uri>').")
+ .build();
+ Field<String> pluginField =
+ Field.ofString(
+ "plugin", (metadataBuilder, fieldValue) -> metadataBuilder.pluginName(fieldValue))
+ .description("The name of the plugin that performed the operation.")
+ .build();
+
+ this.operationsLatency =
+ metricMaker.newTimer(
+ OPERATION_LATENCY_METRIC_NAME,
+ new Description("Latency of performing operations")
+ .setCumulative()
+ .setUnit(Description.Units.MILLISECONDS),
+ operationNameField,
+ changeIdentifierField,
+ traceIdField);
+ this.operationsCounter =
+ metricMaker.newCounter(
+ OPERATION_COUNT_METRIC_NAME,
+ new Description("Number of performed operations").setRate(),
+ operationNameField,
+ traceIdField,
+ requestField);
+ this.pluginOperationsCounter =
+ metricMaker.newCounter(
+ PLUGIN_OPERATION_COUNT_METRIC_NAME,
+ new Description("Number of performed operations by plugin").setRate(),
+ operationNameField,
+ pluginField,
+ traceIdField);
+ }
+
+ @Override
+ public void log(String operation, long durationMs) {
+ log(operation, durationMs, /* metadata= */ null);
+ }
+
+ @Override
+ public void log(String operation, long durationMs, @Nullable Metadata metadata) {
+ if (OPERATION_LATENCY_METRIC_NAME.equals(operation)) {
+ // Recording the timer metric below triggers writing a performance log entry. If we are called
+ // for this performance log entry we must abort to avoid an endless loop.
+ // In practice this should not happen since PerformanceLoggers are only called on close() of
+ // the PerformanceLogContext, and hence the performance log that gets written by the metric
+ // below gets ignored.
+ return;
+ }
+
+ String traceId = TraceContext.getTraceId().orElse("");
+
+ operationsLatency.record(
+ operation, formatChangeIdentifier(metadata), traceId, durationMs, TimeUnit.MILLISECONDS);
+
+ String requestTag = TraceContext.getTag(TraceRequestListener.TAG_REQUEST).orElse("");
+ operationsCounter.increment(operation, traceId, requestTag);
+
+ TraceContext.getPluginTag()
+ .ifPresent(pluginName -> pluginOperationsCounter.increment(operation, pluginName, traceId));
+ }
+
+ private String formatChangeIdentifier(@Nullable Metadata metadata) {
+ if (metadata == null
+ || (!metadata.projectName().isPresent() && !metadata.changeId().isPresent())) {
+ return "";
+ }
+
+ StringBuilder sb = new StringBuilder();
+ sb.append(metadata.projectName().orElse("n/a"));
+ sb.append('~');
+ sb.append(metadata.changeId().map(String::valueOf).orElse("n/a"));
+ return sb.toString();
+ }
+}
diff --git a/java/com/google/gerrit/server/RequestConfig.java b/java/com/google/gerrit/server/RequestConfig.java
index 960907d..83cea5b 100644
--- a/java/com/google/gerrit/server/RequestConfig.java
+++ b/java/com/google/gerrit/server/RequestConfig.java
@@ -41,6 +41,7 @@
RequestConfig.Builder requestConfig = RequestConfig.builder(cfg, section, id);
requestConfig.requestTypes(parseRequestTypes(cfg, section, id));
requestConfig.requestUriPatterns(parseRequestUriPatterns(cfg, section, id));
+ requestConfig.excludedRequestUriPatterns(parseExcludedRequestUriPatterns(cfg, section, id));
requestConfig.accountIds(parseAccounts(cfg, section, id));
requestConfig.projectPatterns(parseProjectPatterns(cfg, section, id));
requestConfigs.add(requestConfig.build());
@@ -61,6 +62,11 @@
return parsePatterns(cfg, section, id, "requestUriPattern");
}
+ private static ImmutableSet<Pattern> parseExcludedRequestUriPatterns(
+ Config cfg, String section, String id) throws ConfigInvalidException {
+ return parsePatterns(cfg, section, id, "excludedRequestUriPattern");
+ }
+
private static ImmutableSet<Account.Id> parseAccounts(Config cfg, String section, String id)
throws ConfigInvalidException {
ImmutableSet.Builder<Account.Id> accountIds = ImmutableSet.builder();
@@ -115,6 +121,9 @@
/** pattern matching request URIs */
abstract ImmutableSet<Pattern> requestUriPatterns();
+ /** pattern matching request URIs to be excluded */
+ abstract ImmutableSet<Pattern> excludedRequestUriPatterns();
+
/** accounts IDs matching calling user */
abstract ImmutableSet<Account.Id> accountIds();
@@ -154,6 +163,13 @@
}
}
+ // If the request URI matches an excluded request URI pattern, then the request is not matched.
+ if (requestInfo.requestUri().isPresent()
+ && excludedRequestUriPatterns().stream()
+ .anyMatch(p -> p.matcher(requestInfo.requestUri().get()).matches())) {
+ return false;
+ }
+
// If in the request config accounts are set and none of them matches, then the request is not
// matched.
if (!accountIds().isEmpty()) {
@@ -200,6 +216,8 @@
abstract Builder requestUriPatterns(ImmutableSet<Pattern> requestUriPatterns);
+ abstract Builder excludedRequestUriPatterns(ImmutableSet<Pattern> excludedRequestUriPatterns);
+
abstract Builder accountIds(ImmutableSet<Account.Id> accountIds);
abstract Builder projectPatterns(ImmutableSet<Pattern> projectPatterns);
diff --git a/java/com/google/gerrit/server/RequestInfo.java b/java/com/google/gerrit/server/RequestInfo.java
index 053b3ac..791e228 100644
--- a/java/com/google/gerrit/server/RequestInfo.java
+++ b/java/com/google/gerrit/server/RequestInfo.java
@@ -14,7 +14,12 @@
package com.google.gerrit.server;
+import static com.google.common.base.Preconditions.checkState;
+import static java.util.Objects.requireNonNull;
+
import com.google.auto.value.AutoValue;
+import com.google.auto.value.extension.memoized.Memoized;
+import com.google.common.base.Splitter;
import com.google.gerrit.common.UsedAt;
import com.google.gerrit.entities.Project;
import com.google.gerrit.server.logging.TraceContext;
@@ -55,6 +60,16 @@
*/
public abstract Optional<String> requestUri();
+ /**
+ * Redacted request URI.
+ *
+ * <p>Request URI where resource IDs are replaced by '*'.
+ */
+ @Memoized
+ public Optional<String> redactedRequestUri() {
+ return requestUri().map(RequestInfo::redactRequestUri);
+ }
+
/** The user that has sent the request. */
public abstract CurrentUser callingUser();
@@ -68,6 +83,67 @@
*/
public abstract Optional<Project.NameKey> project();
+ @Memoized
+ public String formatForLogging() {
+ StringBuilder sb = new StringBuilder();
+ sb.append(requestType());
+ redactedRequestUri().ifPresent(redactedRequestUri -> sb.append(' ').append(redactedRequestUri));
+ return sb.toString();
+ }
+
+ /**
+ * Redacts resource IDs from the given request URI.
+ *
+ * <p>resource IDs in the request URI are replaced with '*'.
+ *
+ * @param requestUri a REST URI that has path segments that alternate between view name and
+ * resource IDs (e.g. "/<view>", "/<view>/<id>", "/<view>/<id>/<view>",
+ * "/<view>/<id>/<view>/<id>", "/<view>/<id>/<view>/<id>/<view>" etc.), must be given without
+ * the '/a' prefix
+ * @return the redacted request URI
+ */
+ static String redactRequestUri(String requestUri) {
+ requireNonNull(requestUri, "requestUri");
+ checkState(
+ !requestUri.startsWith("/a/"), "request URI must not start with '/a/': %s", requestUri);
+
+ StringBuilder redactedRequestUri = new StringBuilder();
+
+ boolean hasLeadingSlash = false;
+ boolean hasTrailingSlash = false;
+ if (requestUri.startsWith("/")) {
+ hasLeadingSlash = true;
+ requestUri = requestUri.substring(1);
+ }
+ if (requestUri.endsWith("/")) {
+ hasTrailingSlash = true;
+ requestUri = requestUri.substring(0, requestUri.length() - 1);
+ }
+
+ boolean idPathSegment = false;
+ for (String pathSegment : Splitter.on('/').split(requestUri)) {
+ if (!idPathSegment) {
+ redactedRequestUri.append("/" + pathSegment);
+ idPathSegment = true;
+ } else {
+ redactedRequestUri.append("/");
+ if (!pathSegment.isEmpty()) {
+ redactedRequestUri.append("*");
+ }
+ idPathSegment = false;
+ }
+ }
+
+ if (!hasLeadingSlash) {
+ redactedRequestUri.deleteCharAt(0);
+ }
+ if (hasTrailingSlash) {
+ redactedRequestUri.append('/');
+ }
+
+ return redactedRequestUri.toString();
+ }
+
public static RequestInfo.Builder builder(
RequestType requestType, CurrentUser callingUser, TraceContext traceContext) {
return builder().requestType(requestType).callingUser(callingUser).traceContext(traceContext);
diff --git a/java/com/google/gerrit/server/TraceRequestListener.java b/java/com/google/gerrit/server/TraceRequestListener.java
index 7136e47..6cc0982 100644
--- a/java/com/google/gerrit/server/TraceRequestListener.java
+++ b/java/com/google/gerrit/server/TraceRequestListener.java
@@ -28,6 +28,9 @@
*/
@Singleton
public class TraceRequestListener implements RequestListener {
+ public static String TAG_REQUEST = "request";
+
+ private static String TAG_PROJECT = "project";
private static String SECTION_TRACING = "tracing";
private final ImmutableList<RequestConfig> traceConfigs;
@@ -39,7 +42,8 @@
@Override
public void onRequest(RequestInfo requestInfo) {
- requestInfo.project().ifPresent(p -> requestInfo.traceContext().addTag("project", p));
+ requestInfo.traceContext().addTag(TAG_REQUEST, requestInfo.formatForLogging());
+ requestInfo.project().ifPresent(p -> requestInfo.traceContext().addTag(TAG_PROJECT, p));
traceConfigs.stream()
.filter(traceConfig -> traceConfig.matches(requestInfo))
.forEach(
diff --git a/java/com/google/gerrit/server/WebLinks.java b/java/com/google/gerrit/server/WebLinks.java
index 53a7661..3c69573 100644
--- a/java/com/google/gerrit/server/WebLinks.java
+++ b/java/com/google/gerrit/server/WebLinks.java
@@ -92,11 +92,12 @@
}
/**
+ * Returns links for patch sets
+ *
* @param project Project name.
* @param commit SHA1 of commit.
* @param commitMessage the commit message of the commit.
* @param branchName branch of the commit.
- * @return Links for patch sets.
*/
public ImmutableList<WebLinkInfo> getPatchSetLinks(
Project.NameKey project, String commit, String commitMessage, String branchName) {
@@ -106,11 +107,12 @@
}
/**
+ * Returns links for resolving conflicts
+ *
* @param project Project name.
* @param commit SHA1 of commit.
* @param commitMessage the commit message of the commit.
* @param branchName branch of the commit.
- * @return Links for resolving comflicts.
*/
public ImmutableList<WebLinkInfo> getResolveConflictsLinks(
Project.NameKey project, String commit, String commitMessage, String branchName) {
@@ -121,11 +123,12 @@
}
/**
+ * Returns links for patch sets
+ *
* @param project Project name.
* @param revision SHA1 of the parent revision.
* @param commitMessage the commit message of the parent revision.
* @param branchName branch of the revision (and parent revision).
- * @return Links for patch sets.
*/
public ImmutableList<WebLinkInfo> getParentLinks(
Project.NameKey project, String revision, String commitMessage, String branchName) {
@@ -135,10 +138,11 @@
}
/**
+ * Returns links for editing
+ *
* @param project Project name.
* @param revision SHA1 of revision.
* @param file File name.
- * @return Links for editing.
*/
public ImmutableList<WebLinkInfo> getEditLinks(String project, String revision, String file) {
return Patch.isMagic(file)
@@ -147,10 +151,11 @@
}
/**
+ * Returns links for files
+ *
* @param project Project name.
* @param revision SHA1 of revision.
* @param file File name.
- * @return Links for files.
*/
public ImmutableList<WebLinkInfo> getFileLinks(String project, String revision, String file) {
return Patch.isMagic(file)
@@ -159,10 +164,11 @@
}
/**
+ * Returns links for file history
+ *
* @param project Project name.
* @param revision SHA1 of revision.
* @param file File name.
- * @return Links for file history
*/
public ImmutableList<WebLinkInfo> getFileHistoryLinks(
String project, String revision, String file) {
@@ -176,6 +182,8 @@
}
/**
+ * Returns links for file diffs
+ *
* @param project Project name.
* @param patchSetIdA Patch set ID of side A, <code>null</code> if no base patch set was selected.
* @param revisionA SHA1 of revision of side A.
@@ -183,7 +191,6 @@
* @param patchSetIdB Patch set ID of side B.
* @param revisionB SHA1 of revision of side B.
* @param fileB File name of side B.
- * @return Links for file diffs.
*/
public ImmutableList<DiffWebLinkInfo> getDiffLinks(
String project,
@@ -214,26 +221,29 @@
}
/**
+ * Returns links for projects
+ *
* @param project Project name.
- * @return Links for projects.
*/
public ImmutableList<WebLinkInfo> getProjectLinks(String project) {
return filterLinks(projectLinks, webLink -> webLink.getProjectWeblink(project));
}
/**
+ * Returns links for branches
+ *
* @param project Project name
* @param branch Branch name
- * @return Links for branches.
*/
public ImmutableList<WebLinkInfo> getBranchLinks(String project, String branch) {
return filterLinks(branchLinks, webLink -> webLink.getBranchWebLink(project, branch));
}
/**
+ * Returns links for the tag
+ *
* @param project Project name
* @param tag Tag name
- * @return Links for tags.
*/
public ImmutableList<WebLinkInfo> getTagLinks(String project, String tag) {
return filterLinks(tagLinks, webLink -> webLink.getTagWebLink(project, tag));
diff --git a/java/com/google/gerrit/server/account/AccountLimits.java b/java/com/google/gerrit/server/account/AccountLimits.java
index 1845f5b..5549d28 100644
--- a/java/com/google/gerrit/server/account/AccountLimits.java
+++ b/java/com/google/gerrit/server/account/AccountLimits.java
@@ -51,7 +51,7 @@
user = currentUser;
}
- /** @return which priority queue the user's tasks should be submitted to. */
+ /** Returns which priority queue the user's tasks should be submitted to. */
public QueueProvider.QueueType getQueueType() {
// If a non-generic group (that is not Anonymous Users or Registered Users)
// grants us INTERACTIVE permission, use the INTERACTIVE queue even if
@@ -99,7 +99,7 @@
return getRange(GlobalCapability.QUERY_LIMIT).getMax();
}
- /** @return true if the user has a permission rule specifying the range. */
+ /** Returns true if the user has a permission rule specifying the range. */
public boolean hasExplicitRange(String permission) {
return GlobalCapability.hasRange(permission) && !getRules(permission).isEmpty();
}
diff --git a/java/com/google/gerrit/server/account/AccountManager.java b/java/com/google/gerrit/server/account/AccountManager.java
index 987e7e3..407d2f7 100644
--- a/java/com/google/gerrit/server/account/AccountManager.java
+++ b/java/com/google/gerrit/server/account/AccountManager.java
@@ -118,7 +118,7 @@
this.externalIdKeyFactory = externalIdKeyFactory;
}
- /** @return user identified by this external identity string */
+ /** Returns a user identified by this external identity string */
public Optional<Account.Id> lookup(String externalId) throws AccountException {
try {
return externalIds.get(externalIdKeyFactory.parse(externalId)).map(ExternalId::accountId);
diff --git a/java/com/google/gerrit/server/account/GroupBackend.java b/java/com/google/gerrit/server/account/GroupBackend.java
index d6360c5..91edaf2 100644
--- a/java/com/google/gerrit/server/account/GroupBackend.java
+++ b/java/com/google/gerrit/server/account/GroupBackend.java
@@ -26,7 +26,7 @@
/** Implementations of GroupBackend provide lookup and membership accessors to a group system. */
@ExtensionPoint
public interface GroupBackend {
- /** @return {@code true} if the backend can operate on the UUID. */
+ /** Returns {@code true} if the backend can operate on the UUID. */
boolean handles(AccountGroup.UUID uuid);
/**
@@ -38,12 +38,12 @@
@Nullable
GroupDescription.Basic get(AccountGroup.UUID uuid);
- /** @return suggestions for the group name sorted by name. */
+ /** Returns suggestions for the group name sorted by name. */
Collection<GroupReference> suggest(String name, @Nullable ProjectState project);
- /** @return the group membership checker for the backend. */
+ /** Returns the group membership checker for the backend. */
GroupMembership membershipsOf(CurrentUser user);
- /** @return {@code true} if the group with the given UUID is visible to all registered users. */
+ /** Returns {@code true} if the group with the given UUID is visible to all registered users. */
boolean isVisibleToAll(AccountGroup.UUID uuid);
}
diff --git a/java/com/google/gerrit/server/account/GroupCache.java b/java/com/google/gerrit/server/account/GroupCache.java
index d8cac71..1e28d7d 100644
--- a/java/com/google/gerrit/server/account/GroupCache.java
+++ b/java/com/google/gerrit/server/account/GroupCache.java
@@ -103,6 +103,10 @@
*/
void evict(AccountGroup.UUID groupUuid);
- /** @see #evict(AccountGroup.UUID) */
+ /**
+ * Removes the association of the given UUIDs with groups
+ *
+ * <p>See {@link #evict(AccountGroup.UUID)}
+ */
void evict(Collection<AccountGroup.UUID> groupUuid);
}
diff --git a/java/com/google/gerrit/server/account/GroupIncludeCache.java b/java/com/google/gerrit/server/account/GroupIncludeCache.java
index 6547619..d92d9fc 100644
--- a/java/com/google/gerrit/server/account/GroupIncludeCache.java
+++ b/java/com/google/gerrit/server/account/GroupIncludeCache.java
@@ -37,7 +37,7 @@
*/
Collection<AccountGroup.UUID> parentGroupsOf(AccountGroup.UUID groupId);
- /** @return set of any UUIDs that are not internal groups. */
+ /** Returns set of any UUIDs that are not internal groups. */
Collection<AccountGroup.UUID> allExternalMembers();
void evictGroupsWithMember(Account.Id memberId);
diff --git a/java/com/google/gerrit/server/account/Realm.java b/java/com/google/gerrit/server/account/Realm.java
index d56ed07..3f642f7 100644
--- a/java/com/google/gerrit/server/account/Realm.java
+++ b/java/com/google/gerrit/server/account/Realm.java
@@ -41,10 +41,10 @@
void onCreateAccount(AuthRequest who, Account account);
- /** @return true if the user has the given email address. */
+ /** Returns true if the user has the given email address. */
boolean hasEmailAddress(IdentifiedUser who, String email);
- /** @return all known email addresses for the identified user. */
+ /** Returns all known email addresses for the identified user. */
Set<String> getEmailAddresses(IdentifiedUser who);
/**
@@ -56,19 +56,13 @@
*/
Account.Id lookup(String accountName) throws IOException;
- /**
- * @return true if the account is active.
- * @throws NamingException
- * @throws LoginException
- * @throws AccountException
- * @throws IOException
- */
+ /** Returns true if the account is active. */
default boolean isActive(@SuppressWarnings("unused") String username)
throws LoginException, NamingException, AccountException, IOException {
return true;
}
- /** @return true if the account is backed by the realm, false otherwise. */
+ /** Returns true if the account is backed by the realm, false otherwise. */
default boolean accountBelongsToRealm(
@SuppressWarnings("unused") Collection<ExternalId> externalIds) {
return false;
diff --git a/java/com/google/gerrit/server/account/ServiceUserClassifierImpl.java b/java/com/google/gerrit/server/account/ServiceUserClassifierImpl.java
index 27ac9f4..db030f9 100644
--- a/java/com/google/gerrit/server/account/ServiceUserClassifierImpl.java
+++ b/java/com/google/gerrit/server/account/ServiceUserClassifierImpl.java
@@ -76,7 +76,7 @@
.get(toTraverse.remove(0))
.orElseThrow(() -> new IllegalStateException("invalid subgroup"));
if (seen.contains(currentGroup.getGroupUUID())) {
- logger.atWarning().log(
+ logger.atFine().log(
"Skipping %s because it's a cyclic subgroup", currentGroup.getGroupUUID());
continue;
}
diff --git a/java/com/google/gerrit/server/account/VersionedAuthorizedKeys.java b/java/com/google/gerrit/server/account/VersionedAuthorizedKeys.java
index 30021e6..555a2c1 100644
--- a/java/com/google/gerrit/server/account/VersionedAuthorizedKeys.java
+++ b/java/com/google/gerrit/server/account/VersionedAuthorizedKeys.java
@@ -206,7 +206,6 @@
*
* @param pub the public SSH key to be added
* @return the new SSH key
- * @throws InvalidSshKeyException
*/
private AccountSshKey addKey(String pub) throws InvalidSshKeyException {
checkLoaded();
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalId.java b/java/com/google/gerrit/server/account/externalids/ExternalId.java
index 8bf095c..30f4094 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalId.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalId.java
@@ -191,6 +191,7 @@
* notes branch.
*/
@SuppressWarnings("deprecation") // Use Hashing.sha1 for compatibility.
+ @Memoized
public ObjectId sha1() {
String keyString = isCaseInsensitive() ? get().toLowerCase(Locale.US) : get();
return ObjectId.fromRaw(Hashing.sha1().hashString(keyString, UTF_8).asBytes());
@@ -226,7 +227,8 @@
}
@Override
- public final int hashCode() {
+ @Memoized
+ public int hashCode() {
return Objects.hash(sha1());
}
@@ -322,7 +324,8 @@
* </pre>
*/
@Override
- public final String toString() {
+ @Memoized
+ public String toString() {
Config c = new Config();
writeToConfig(c);
return c.toText();
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java b/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
index 5d81a25..72d703b 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalIdCacheLoader.java
@@ -95,7 +95,9 @@
new Description("Total number of external ID cache reloads from Git.")
.setRate()
.setUnit("updates"),
- Field.ofBoolean("partial", Metadata.Builder::partial).build());
+ Field.ofBoolean("partial", Metadata.Builder::partial)
+ .description("Whether the reload was partial.")
+ .build());
this.reloadDifferential =
metricMaker.newTimer(
"notedb/external_id_partial_read_latency",
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalIdFactory.java b/java/com/google/gerrit/server/account/externalids/ExternalIdFactory.java
index 0c96f58..ee42d67 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalIdFactory.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalIdFactory.java
@@ -24,9 +24,9 @@
import com.google.gerrit.entities.Account;
import com.google.gerrit.server.account.HashedPassword;
import com.google.gerrit.server.account.externalids.ExternalId.Key;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
import java.util.Set;
+import javax.inject.Inject;
+import javax.inject.Singleton;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.ObjectId;
diff --git a/java/com/google/gerrit/server/account/externalids/ExternalIdKeyFactory.java b/java/com/google/gerrit/server/account/externalids/ExternalIdKeyFactory.java
index 37c2604..95df4a9 100644
--- a/java/com/google/gerrit/server/account/externalids/ExternalIdKeyFactory.java
+++ b/java/com/google/gerrit/server/account/externalids/ExternalIdKeyFactory.java
@@ -14,18 +14,46 @@
package com.google.gerrit.server.account.externalids;
+import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.server.config.AuthConfig;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
+import com.google.inject.ImplementedBy;
+import javax.inject.Inject;
+import javax.inject.Singleton;
@Singleton
public class ExternalIdKeyFactory {
+ @ImplementedBy(ConfigImpl.class)
+ public interface Config {
+ boolean isUserNameCaseInsensitive();
+ }
+
+ /**
+ * Default implementation {@link Config}
+ *
+ * <p>Internally in google we are using different implementation.
+ */
+ @Singleton
+ public static class ConfigImpl implements Config {
+ private final boolean isUserNameCaseInsensitive;
+
+ @VisibleForTesting
+ @Inject
+ public ConfigImpl(AuthConfig authConfig) {
+ this.isUserNameCaseInsensitive = authConfig.isUserNameCaseInsensitive();
+ }
+
+ @Override
+ public boolean isUserNameCaseInsensitive() {
+ return isUserNameCaseInsensitive;
+ }
+ }
+
private final boolean isUserNameCaseInsensitive;
@Inject
- public ExternalIdKeyFactory(AuthConfig authConfig) {
- this.isUserNameCaseInsensitive = authConfig.isUserNameCaseInsensitive();
+ public ExternalIdKeyFactory(Config config) {
+ this.isUserNameCaseInsensitive = config.isUserNameCaseInsensitive();
}
/**
diff --git a/java/com/google/gerrit/server/approval/ApprovalCacheImpl.java b/java/com/google/gerrit/server/approval/ApprovalCacheImpl.java
index a01931c..fd31da9 100644
--- a/java/com/google/gerrit/server/approval/ApprovalCacheImpl.java
+++ b/java/com/google/gerrit/server/approval/ApprovalCacheImpl.java
@@ -36,7 +36,7 @@
import com.google.protobuf.ByteString;
import java.util.concurrent.ExecutionException;
-/** @see ApprovalCache */
+/** Implementation of the {@link ApprovalCache} interface */
public class ApprovalCacheImpl implements ApprovalCache {
private static final String CACHE_NAME = "approvals";
diff --git a/java/com/google/gerrit/server/approval/ApprovalInference.java b/java/com/google/gerrit/server/approval/ApprovalInference.java
index dfc5bdb..4cb080a 100644
--- a/java/com/google/gerrit/server/approval/ApprovalInference.java
+++ b/java/com/google/gerrit/server/approval/ApprovalInference.java
@@ -101,20 +101,29 @@
*/
Iterable<PatchSetApproval> forPatchSet(
ChangeNotes notes, PatchSet.Id psId, @Nullable RevWalk rw, @Nullable Config repoConfig) {
+ PatchSet patchset = notes.getPatchSets().get(psId);
+ if (patchset == null) {
+ return Collections.emptyList();
+ }
+ return forPatchSet(notes, patchset, rw, repoConfig);
+ }
+
+ Iterable<PatchSetApproval> forPatchSet(
+ ChangeNotes notes, PatchSet ps, @Nullable RevWalk rw, @Nullable Config repoConfig) {
ProjectState project;
try (TraceTimer traceTimer =
TraceContext.newTimer(
"Computing labels for patch set",
Metadata.builder()
.changeId(notes.load().getChangeId().get())
- .patchSetId(psId.get())
+ .patchSetId(ps.id().get())
.build())) {
project =
projectCache
.get(notes.getProjectName())
.orElseThrow(illegalState(notes.getProjectName()));
Collection<PatchSetApproval> approvals =
- getForPatchSetWithoutNormalization(notes, project, psId, rw, repoConfig);
+ getForPatchSetWithoutNormalization(notes, project, ps, rw, repoConfig);
return labelNormalizer.normalize(notes, approvals).getNormalized();
}
}
@@ -311,13 +320,13 @@
private boolean canCopyBasedOnCopyCondition(
ChangeNotes changeNotes,
PatchSetApproval psa,
- PatchSet.Id psId,
+ PatchSet patchSet,
LabelType type,
ChangeKind changeKind) {
if (!type.getCopyCondition().isPresent()) {
return false;
}
- ApprovalContext ctx = ApprovalContext.create(changeNotes, psa, psId, changeKind);
+ ApprovalContext ctx = ApprovalContext.create(changeNotes, psa, patchSet, changeKind);
try {
// Use a request context to run checks as an internal user with expanded visibility. This is
// so that the output of the copy condition does not depend on who is running the current
@@ -336,7 +345,7 @@
private Collection<PatchSetApproval> getForPatchSetWithoutNormalization(
ChangeNotes notes,
ProjectState project,
- PatchSet.Id psId,
+ PatchSet patchSet,
@Nullable RevWalk rw,
@Nullable Config repoConfig) {
checkState(
@@ -345,15 +354,11 @@
project.getNameKey(),
notes.getProjectName());
- PatchSet ps = notes.load().getPatchSets().get(psId);
- if (ps == null) {
- return Collections.emptyList();
- }
-
+ PatchSet.Id psId = patchSet.id();
// Add approvals on the given patch set to the result
Table<String, Account.Id, PatchSetApproval> resultByUser = HashBasedTable.create();
ImmutableList<PatchSetApproval> approvalsForGivenPatchSet =
- notes.load().getApprovals().get(ps.id());
+ notes.load().getApprovals().get(patchSet.id());
approvalsForGivenPatchSet.forEach(psa -> resultByUser.put(psa.label(), psa.accountId(), psa));
// Bail out immediately if this is the first patch set. Return only approvals granted on the
@@ -376,23 +381,27 @@
Iterable<PatchSetApproval> priorApprovals =
getForPatchSetWithoutNormalization(
- notes, project, priorPatchSet.getValue().id(), rw, repoConfig);
+ notes, project, priorPatchSet.getValue(), rw, repoConfig);
if (!priorApprovals.iterator().hasNext()) {
return resultByUser.values();
}
// Add labels from the previous patch set to the result in case the label isn't already there
// and settings as well as change kind allow copying.
- ChangeKind kind =
+ ChangeKind changeKind =
changeKindCache.getChangeKind(
project.getNameKey(),
rw,
repoConfig,
priorPatchSet.getValue().commitId(),
- ps.commitId());
+ patchSet.commitId());
logger.atFine().log(
"change kind for patch set %d of change %d against prior patch set %s is %s",
- ps.id().get(), ps.id().changeId().get(), priorPatchSet.getValue().id().changeId(), kind);
+ patchSet.id().get(),
+ patchSet.id().changeId().get(),
+ priorPatchSet.getValue().id().changeId(),
+ changeKind);
+
Map<String, FileDiffOutput> modifiedFiles = null;
Map<String, FileDiffOutput> modifiedFilesLastPatchSet = null;
LabelTypes labelTypes = project.getLabelTypes();
@@ -405,7 +414,7 @@
if (modifiedFiles == null
&& type.isPresent()
&& type.get().isCopyAllScoresIfListOfFilesDidNotChange()) {
- modifiedFiles = listModifiedFiles(project, ps);
+ modifiedFiles = listModifiedFiles(project, patchSet);
modifiedFilesLastPatchSet = listModifiedFiles(project, priorPatchSet.getValue());
}
if (!type.isPresent()) {
@@ -421,11 +430,17 @@
continue;
}
if (!canCopyBasedOnBooleanLabelConfigs(
- project, psa, ps.id(), kind, type.get(), modifiedFiles, modifiedFilesLastPatchSet)
- && !canCopyBasedOnCopyCondition(notes, psa, ps.id(), type.get(), kind)) {
+ project,
+ psa,
+ patchSet.id(),
+ changeKind,
+ type.get(),
+ modifiedFiles,
+ modifiedFilesLastPatchSet)
+ && !canCopyBasedOnCopyCondition(notes, psa, patchSet, type.get(), changeKind)) {
continue;
}
- resultByUser.put(psa.label(), psa.accountId(), psa.copyWithPatchSet(ps.id()));
+ resultByUser.put(psa.label(), psa.accountId(), psa.copyWithPatchSet(patchSet.id()));
}
return resultByUser.values();
}
diff --git a/java/com/google/gerrit/server/approval/ApprovalsUtil.java b/java/com/google/gerrit/server/approval/ApprovalsUtil.java
index a1cdd99..c2e35d2 100644
--- a/java/com/google/gerrit/server/approval/ApprovalsUtil.java
+++ b/java/com/google/gerrit/server/approval/ApprovalsUtil.java
@@ -278,7 +278,6 @@
* @param ps patch set being approved.
* @param user user adding approvals.
* @param approvals approvals to add.
- * @throws RestApiException
*/
public Iterable<PatchSetApproval> addApprovalsForNewPatchSet(
ChangeUpdate update,
@@ -349,6 +348,10 @@
return approvalInference.forPatchSet(notes, psId, rw, repoConfig);
}
+ public Iterable<PatchSetApproval> byPatchSet(ChangeNotes notes, PatchSet patchSet) {
+ return approvalInference.forPatchSet(notes, patchSet, /* rw= */ null, /* repoConfig= */ null);
+ }
+
public Iterable<PatchSetApproval> byPatchSet(ChangeNotes notes, PatchSet.Id psId) {
return approvalCache.get(notes, psId);
}
diff --git a/java/com/google/gerrit/server/auth/AuthBackend.java b/java/com/google/gerrit/server/auth/AuthBackend.java
index 9ec3366..424ee43 100644
--- a/java/com/google/gerrit/server/auth/AuthBackend.java
+++ b/java/com/google/gerrit/server/auth/AuthBackend.java
@@ -20,7 +20,7 @@
@ExtensionPoint
public interface AuthBackend {
- /** @return an identifier that uniquely describes the backend. */
+ /** Returns an identifier that uniquely describes the backend. */
String getDomain();
/**
diff --git a/java/com/google/gerrit/server/auth/AuthUser.java b/java/com/google/gerrit/server/auth/AuthUser.java
index 987f086..9e1c5ec 100644
--- a/java/com/google/gerrit/server/auth/AuthUser.java
+++ b/java/com/google/gerrit/server/auth/AuthUser.java
@@ -52,18 +52,18 @@
this.username = username;
}
- /** @return the globally unique identifier. */
+ /** Returns the globally unique identifier. */
public final UUID getUUID() {
return uuid;
}
- /** @return the backend specific user name, or null if one does not exist. */
+ /** Returns the backend specific user name, or null if one does not exist. */
@Nullable
public final String getUsername() {
return username;
}
- /** @return {@code true} if {@link #getUsername()} is not null. */
+ /** Returns {@code true} if {@link #getUsername()} is not null. */
public final boolean hasUsername() {
return getUsername() != null;
}
diff --git a/java/com/google/gerrit/server/cache/CacheMetrics.java b/java/com/google/gerrit/server/cache/CacheMetrics.java
index 12194e7..f1fd4a8 100644
--- a/java/com/google/gerrit/server/cache/CacheMetrics.java
+++ b/java/com/google/gerrit/server/cache/CacheMetrics.java
@@ -35,7 +35,9 @@
@Singleton
public class CacheMetrics {
private static final Field<String> F_NAME =
- Field.ofString("cache_name", Metadata.Builder::cacheName).build();
+ Field.ofString("cache_name", Metadata.Builder::cacheName)
+ .description("The name of the cache.")
+ .build();
@Inject
public CacheMetrics(
diff --git a/java/com/google/gerrit/server/cache/ForwardingRemovalListener.java b/java/com/google/gerrit/server/cache/ForwardingRemovalListener.java
index ee672cd..28d57e6 100644
--- a/java/com/google/gerrit/server/cache/ForwardingRemovalListener.java
+++ b/java/com/google/gerrit/server/cache/ForwardingRemovalListener.java
@@ -25,9 +25,6 @@
/**
* This listener dispatches removal events to all other RemovalListeners attached via the DynamicSet
* API.
- *
- * @param <K>
- * @param <V>
*/
@SuppressWarnings("rawtypes")
public class ForwardingRemovalListener<K, V> implements RemovalListener<K, V> {
diff --git a/java/com/google/gerrit/server/change/ChangeFinder.java b/java/com/google/gerrit/server/change/ChangeFinder.java
index ba104d8..9f253de 100644
--- a/java/com/google/gerrit/server/change/ChangeFinder.java
+++ b/java/com/google/gerrit/server/change/ChangeFinder.java
@@ -96,6 +96,7 @@
.setRate()
.setUnit("requests"),
Field.ofEnum(ChangeIdType.class, "change_id_type", Metadata.Builder::changeIdType)
+ .description("The type of the change identifier.")
.build());
}
diff --git a/java/com/google/gerrit/server/change/ChangeResource.java b/java/com/google/gerrit/server/change/ChangeResource.java
index 0d0df0d..970f1b5 100644
--- a/java/com/google/gerrit/server/change/ChangeResource.java
+++ b/java/com/google/gerrit/server/change/ChangeResource.java
@@ -140,7 +140,7 @@
return changeData.getId();
}
- /** @return true if {@link #getUser()} is the change's owner. */
+ /** Returns true if {@link #getUser()} is the change's owner. */
public boolean isUserOwner() {
Account.Id owner = getChange().getOwner();
return user.isIdentifiedUser() && user.asIdentifiedUser().getAccountId().equals(owner);
diff --git a/java/com/google/gerrit/server/change/EmailReviewComments.java b/java/com/google/gerrit/server/change/EmailReviewComments.java
index d433c4e..3c7ea44 100644
--- a/java/com/google/gerrit/server/change/EmailReviewComments.java
+++ b/java/com/google/gerrit/server/change/EmailReviewComments.java
@@ -45,6 +45,8 @@
// TODO(dborowitz/wyatta): Rationalize these arguments so HTML and text templates are operating
// on the same set of inputs.
/**
+ * Creates handle for sending email
+ *
* @param notify setting for handling notification.
* @param notes change notes.
* @param patchSet patch set corresponding to the top-level op
@@ -57,7 +59,6 @@
* contents should *not* include a "Patch set N" header or "(M comments)" footer, as these
* will be added automatically in soy in a structured way.
* @param labels labels applied as part of this review operation.
- * @return handle for sending email.
*/
EmailReviewComments create(
NotifyResolver.Result notify,
diff --git a/java/com/google/gerrit/server/change/FileContentUtil.java b/java/com/google/gerrit/server/change/FileContentUtil.java
index 49c1fe2..c54b902 100644
--- a/java/com/google/gerrit/server/change/FileContentUtil.java
+++ b/java/com/google/gerrit/server/change/FileContentUtil.java
@@ -76,8 +76,6 @@
* @param parent A 1-based parent index to get the content from instead. Null if the content
* should be obtained from {@code revstr} instead.
* @return Content of the file as {@code BinaryResult}.
- * @throws ResourceNotFoundException
- * @throws IOException
*/
public BinaryResult getContent(
ProjectState project, ObjectId revstr, String path, @Nullable Integer parent)
diff --git a/java/com/google/gerrit/server/change/FileInfoJsonComparingImpl.java b/java/com/google/gerrit/server/change/FileInfoJsonComparingImpl.java
deleted file mode 100644
index a926147..0000000
--- a/java/com/google/gerrit/server/change/FileInfoJsonComparingImpl.java
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright (C) 2021 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.change;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.PatchSet;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.common.FileInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.metrics.Counter1;
-import com.google.gerrit.metrics.Description;
-import com.google.gerrit.metrics.Field;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.server.logging.Metadata;
-import com.google.gerrit.server.patch.DiffExecutor;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.util.Map;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Future;
-import org.eclipse.jgit.lib.ObjectId;
-
-/**
- * Implementation of FileInfoJson which uses {@link FileInfoJsonOldImpl}, but also runs {@link
- * FileInfoJsonNewImpl} asynchronously and compares the results. This implementation is temporary
- * and will be used to verify that the results are the same.
- */
-public class FileInfoJsonComparingImpl implements FileInfoJson {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final FileInfoJsonOldImpl oldImpl;
- private final FileInfoJsonNewImpl newImpl;
- private final ExecutorService executor;
- private final Metrics metrics;
-
- /**
- * TODO(ghareeb): These metrics are temporary for launching the new diff cache redesign and are
- * not documented. These will be removed soon.
- */
- @VisibleForTesting
- @Singleton
- static class Metrics {
- private enum Status {
- MATCH,
- MISMATCH,
- ERROR
- }
-
- final Counter1<Status> diffs;
-
- @Inject
- Metrics(MetricMaker metricMaker) {
- diffs =
- metricMaker.newCounter(
- "diff/list_files/dark_launch",
- new Description(
- "Total number of matching, non-matching, or error in list-files diffs in the old and new diff cache implementations.")
- .setRate()
- .setUnit("count"),
- Field.ofEnum(Status.class, "type", Metadata.Builder::eventType).build());
- }
- }
-
- @Inject
- public FileInfoJsonComparingImpl(
- FileInfoJsonOldImpl oldImpl,
- FileInfoJsonNewImpl newImpl,
- @DiffExecutor ExecutorService executor,
- Metrics metrics) {
- this.oldImpl = oldImpl;
- this.newImpl = newImpl;
- this.executor = executor;
- this.metrics = metrics;
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Change change, ObjectId objectId, @Nullable PatchSet base)
- throws ResourceConflictException, PatchListNotAvailableException {
- Map<String, FileInfo> result = oldImpl.getFileInfoMap(change, objectId, base);
- @SuppressWarnings("unused")
- Future<?> ignored =
- executor.submit(
- () -> {
- try {
- Map<String, FileInfo> fileInfoNew = newImpl.getFileInfoMap(change, objectId, base);
- compareAndLogMetrics(
- result,
- fileInfoNew,
- String.format(
- "Mismatch comparing old and new diff implementations for change: %s, objectId: %s and base: %s",
- change, objectId, base == null ? "none" : base.id()));
- } catch (ResourceConflictException | PatchListNotAvailableException e) {
- // If an exception happens while evaluating the new diff, increment the non-matching
- // counter
- metrics.diffs.increment(Metrics.Status.ERROR);
- logger.atWarning().withCause(e).log(
- "Error comparing old and new diff implementations.");
- }
- });
- return result;
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Project.NameKey project, ObjectId objectId, int parentNum)
- throws ResourceConflictException, PatchListNotAvailableException {
- Map<String, FileInfo> result = oldImpl.getFileInfoMap(project, objectId, parentNum);
- @SuppressWarnings("unused")
- Future<?> ignored =
- executor.submit(
- () -> {
- try {
- Map<String, FileInfo> resultNew =
- newImpl.getFileInfoMap(project, objectId, parentNum);
- compareAndLogMetrics(
- result,
- resultNew,
- String.format(
- "Mismatch comparing old and new diff implementations for project: %s, objectId: %s and parentNum: %d",
- project, objectId, parentNum));
- } catch (ResourceConflictException | PatchListNotAvailableException e) {
- // If an exception happens while evaluating the new diff, increment the non-matching
- // ctr
- metrics.diffs.increment(Metrics.Status.ERROR);
- logger.atWarning().withCause(e).log(
- "Error comparing old and new diff implementations.");
- }
- });
- return result;
- }
-
- private void compareAndLogMetrics(
- Map<String, FileInfo> fileInfoMapOld,
- Map<String, FileInfo> fileInfoMapNew,
- String warningMessage) {
- if (fileInfoMapOld.equals(fileInfoMapNew)) {
- metrics.diffs.increment(Metrics.Status.MATCH);
- return;
- }
- metrics.diffs.increment(Metrics.Status.MISMATCH);
- logger.atWarning().log(
- warningMessage
- + "\n"
- + "Result using old impl: "
- + fileInfoMapOld
- + "\n"
- + "Result using new impl: "
- + fileInfoMapNew);
- }
-}
diff --git a/java/com/google/gerrit/server/change/FileInfoJsonExperimentImpl.java b/java/com/google/gerrit/server/change/FileInfoJsonExperimentImpl.java
deleted file mode 100644
index 81f014d..0000000
--- a/java/com/google/gerrit/server/change/FileInfoJsonExperimentImpl.java
+++ /dev/null
@@ -1,72 +0,0 @@
-// Copyright (C) 2021 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.change;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.PatchSet;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.common.FileInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.server.experiments.ExperimentFeatures;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import java.util.Map;
-import javax.inject.Inject;
-import org.eclipse.jgit.lib.ObjectId;
-
-/**
- * An experimental implementation of FileInfoJson that uses {@link FileInfoJsonNewImpl} if the
- * experiment flag "GerritBackendRequestFeature__use_new_diff_cache" is enabled, or {@link
- * FileInfoJsonOldImpl} otherwise. This would enable a gradual rollout of {@link
- * FileInfoJsonNewImpl}.
- */
-public class FileInfoJsonExperimentImpl implements FileInfoJson {
- @VisibleForTesting
- public static final String NEW_DIFF_CACHE_FEATURE =
- "GerritBackendRequestFeature__use_new_diff_cache";
-
- private final FileInfoJsonOldImpl oldImpl;
- private final FileInfoJsonNewImpl newImpl;
- private final ExperimentFeatures experimentFeatures;
-
- @Inject
- public FileInfoJsonExperimentImpl(
- FileInfoJsonOldImpl oldImpl,
- FileInfoJsonNewImpl newImpl,
- ExperimentFeatures experimentFeatures) {
- this.oldImpl = oldImpl;
- this.newImpl = newImpl;
- this.experimentFeatures = experimentFeatures;
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Change change, ObjectId objectId, @Nullable PatchSet base)
- throws ResourceConflictException, PatchListNotAvailableException {
- return experimentFeatures.isFeatureEnabled(NEW_DIFF_CACHE_FEATURE)
- ? newImpl.getFileInfoMap(change, objectId, base)
- : oldImpl.getFileInfoMap(change, objectId, base);
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Project.NameKey project, ObjectId objectId, int parentNum)
- throws ResourceConflictException, PatchListNotAvailableException {
- return experimentFeatures.isFeatureEnabled(NEW_DIFF_CACHE_FEATURE)
- ? newImpl.getFileInfoMap(project, objectId, parentNum)
- : oldImpl.getFileInfoMap(project, objectId, parentNum);
- }
-}
diff --git a/java/com/google/gerrit/server/change/FileInfoJsonNewImpl.java b/java/com/google/gerrit/server/change/FileInfoJsonImpl.java
similarity index 95%
rename from java/com/google/gerrit/server/change/FileInfoJsonNewImpl.java
rename to java/com/google/gerrit/server/change/FileInfoJsonImpl.java
index 7277404..b729c11 100644
--- a/java/com/google/gerrit/server/change/FileInfoJsonNewImpl.java
+++ b/java/com/google/gerrit/server/change/FileInfoJsonImpl.java
@@ -32,12 +32,12 @@
import org.eclipse.jgit.errors.NoMergeBaseException;
import org.eclipse.jgit.lib.ObjectId;
-/** Implementation of {@link FileInfoJson} using the new diff cache {@link DiffOperations}. */
-public class FileInfoJsonNewImpl implements FileInfoJson {
+/** Implementation of {@link FileInfoJson} using {@link DiffOperations}. */
+public class FileInfoJsonImpl implements FileInfoJson {
private final DiffOperations diffs;
@Inject
- FileInfoJsonNewImpl(DiffOperations diffOperations) {
+ FileInfoJsonImpl(DiffOperations diffOperations) {
this.diffs = diffOperations;
}
diff --git a/java/com/google/gerrit/server/change/FileInfoJsonModule.java b/java/com/google/gerrit/server/change/FileInfoJsonModule.java
index 952b503..b8e05f0 100644
--- a/java/com/google/gerrit/server/change/FileInfoJsonModule.java
+++ b/java/com/google/gerrit/server/change/FileInfoJsonModule.java
@@ -20,7 +20,6 @@
@Override
public void configure() {
- // Binding to the experimental implementation to enable gradual rollout of the new diff cache.
- bind(FileInfoJson.class).to(FileInfoJsonExperimentImpl.class);
+ bind(FileInfoJson.class).to(FileInfoJsonImpl.class);
}
}
diff --git a/java/com/google/gerrit/server/change/FileInfoJsonOldImpl.java b/java/com/google/gerrit/server/change/FileInfoJsonOldImpl.java
deleted file mode 100644
index 0570296..0000000
--- a/java/com/google/gerrit/server/change/FileInfoJsonOldImpl.java
+++ /dev/null
@@ -1,128 +0,0 @@
-// Copyright (C) 2021 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.change;
-
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.entities.Change;
-import com.google.gerrit.entities.Patch;
-import com.google.gerrit.entities.PatchSet;
-import com.google.gerrit.entities.Project;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
-import com.google.gerrit.extensions.common.FileInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListEntry;
-import com.google.gerrit.server.patch.PatchListKey;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.util.Map;
-import java.util.TreeMap;
-import java.util.concurrent.ExecutionException;
-import org.eclipse.jgit.errors.NoMergeBaseException;
-import org.eclipse.jgit.lib.ObjectId;
-
-/** Implementation of {@link FileInfoJson} using the old diff cache {@link PatchListCache}. */
-@Deprecated
-@Singleton
-class FileInfoJsonOldImpl implements FileInfoJson {
- private final PatchListCache patchListCache;
-
- @Inject
- FileInfoJsonOldImpl(PatchListCache patchListCache) {
- this.patchListCache = patchListCache;
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Change change, ObjectId objectId, @Nullable PatchSet base)
- throws ResourceConflictException, PatchListNotAvailableException {
- ObjectId a = base != null ? base.commitId() : null;
- return toFileInfoMap(change, PatchListKey.againstCommit(a, objectId, Whitespace.IGNORE_NONE));
- }
-
- @Override
- public Map<String, FileInfo> getFileInfoMap(
- Project.NameKey project, ObjectId objectId, int parentNum)
- throws ResourceConflictException, PatchListNotAvailableException {
- PatchListKey key =
- parentNum == 0
- ? PatchListKey.againstDefaultBase(objectId, Whitespace.IGNORE_NONE)
- : PatchListKey.againstParentNum(
- parentNum, objectId, DiffPreferencesInfo.Whitespace.IGNORE_NONE);
- return toFileInfoMap(project, key);
- }
-
- private Map<String, FileInfo> toFileInfoMap(Change change, PatchListKey key)
- throws ResourceConflictException, PatchListNotAvailableException {
- return toFileInfoMap(change.getProject(), key);
- }
-
- Map<String, FileInfo> toFileInfoMap(Project.NameKey project, PatchListKey key)
- throws ResourceConflictException, PatchListNotAvailableException {
- PatchList list;
- try {
- list = patchListCache.get(key, project);
- } catch (PatchListNotAvailableException e) {
- Throwable cause = e.getCause();
- if (cause instanceof ExecutionException) {
- cause = cause.getCause();
- }
- if (cause instanceof NoMergeBaseException) {
- throw new ResourceConflictException(
- String.format("Cannot create auto merge commit: %s", e.getMessage()), e);
- }
- throw e;
- }
-
- Map<String, FileInfo> files = new TreeMap<>();
- for (PatchListEntry e : list.getPatches()) {
- FileInfo fileInfo = new FileInfo();
- fileInfo.status =
- e.getChangeType() != Patch.ChangeType.MODIFIED ? e.getChangeType().getCode() : null;
- fileInfo.oldPath = e.getOldName();
- fileInfo.sizeDelta = e.getSizeDelta();
- fileInfo.size = e.getSize();
- if (e.getPatchType() == Patch.PatchType.BINARY) {
- fileInfo.binary = true;
- } else {
- fileInfo.linesInserted = e.getInsertions() > 0 ? e.getInsertions() : null;
- fileInfo.linesDeleted = e.getDeletions() > 0 ? e.getDeletions() : null;
- }
-
- FileInfo o = files.put(e.getNewName(), fileInfo);
- if (o != null) {
- // This should only happen on a delete-add break created by JGit
- // when the file was rewritten and too little content survived. Write
- // a single record with data from both sides.
- fileInfo.status = Patch.ChangeType.REWRITE.getCode();
- fileInfo.sizeDelta = o.sizeDelta;
- fileInfo.size = o.size;
- if (o.binary != null && o.binary) {
- fileInfo.binary = true;
- }
- if (o.linesInserted != null) {
- fileInfo.linesInserted = o.linesInserted;
- }
- if (o.linesDeleted != null) {
- fileInfo.linesDeleted = o.linesDeleted;
- }
- }
- }
- return files;
- }
-}
diff --git a/java/com/google/gerrit/server/change/LabelNormalizer.java b/java/com/google/gerrit/server/change/LabelNormalizer.java
index b5527d7..aeb9db0 100644
--- a/java/com/google/gerrit/server/change/LabelNormalizer.java
+++ b/java/com/google/gerrit/server/change/LabelNormalizer.java
@@ -77,10 +77,11 @@
}
/**
+ * Returns copies of approvals normalized to the defined ranges for the label type. Approvals for
+ * unknown labels are not included in the output
+ *
* @param notes change notes containing the given approvals.
* @param approvals list of approvals.
- * @return copies of approvals normalized to the defined ranges for the label type. Approvals for
- * unknown labels are not included in the output.
*/
public Result normalize(ChangeNotes notes, Collection<PatchSetApproval> approvals) {
List<PatchSetApproval> unchanged = Lists.newArrayListWithCapacity(approvals.size());
diff --git a/java/com/google/gerrit/server/change/PatchSetInserter.java b/java/com/google/gerrit/server/change/PatchSetInserter.java
index d25dba0..f093958 100644
--- a/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -285,6 +285,11 @@
throw new BadRequestException(ex.getMessage());
}
}
+
+ // Approvals that are being set in the new patch-set during this operation are not available yet
+ // outside of the scope of this method. Only copied approvals are set here.
+ approvalsUtil.byPatchSet(ctx.getNotes(), patchSet).forEach(a -> update.putCopiedApproval(a));
+
return true;
}
diff --git a/java/com/google/gerrit/server/change/ReviewerModifier.java b/java/com/google/gerrit/server/change/ReviewerModifier.java
index f3c5193..fffb107 100644
--- a/java/com/google/gerrit/server/change/ReviewerModifier.java
+++ b/java/com/google/gerrit/server/change/ReviewerModifier.java
@@ -201,9 +201,6 @@
* @return handle describing the addition operation. If the {@code op} field is present, this
* operation may be added to a {@code BatchUpdate}. Otherwise, the {@code error} field
* contains information about an error that occurred
- * @throws IOException
- * @throws PermissionBackendException
- * @throws ConfigInvalidException
*/
public ReviewerModification prepare(
ChangeNotes notes, CurrentUser user, ReviewerInput input, boolean allowGroup)
diff --git a/java/com/google/gerrit/server/config/AuthConfig.java b/java/com/google/gerrit/server/config/AuthConfig.java
index 2ac551d..1760378 100644
--- a/java/com/google/gerrit/server/config/AuthConfig.java
+++ b/java/com/google/gerrit/server/config/AuthConfig.java
@@ -229,7 +229,7 @@
return trustContainerAuth;
}
- /** @return true if users with Run As capability can impersonate others. */
+ /** Returns true if users with Run As capability can impersonate others. */
public boolean isRunAsEnabled() {
return enableRunAs;
}
diff --git a/java/com/google/gerrit/server/config/ConfigUtil.java b/java/com/google/gerrit/server/config/ConfigUtil.java
index 27ded63..c44b0fd 100644
--- a/java/com/google/gerrit/server/config/ConfigUtil.java
+++ b/java/com/google/gerrit/server/config/ConfigUtil.java
@@ -282,7 +282,6 @@
* @param sub subsection
* @param s instance of class with config values
* @param defaults instance of class with default values
- * @throws ConfigInvalidException
*/
public static <T> void storeSection(Config cfg, String section, String sub, T s, T defaults)
throws ConfigInvalidException {
@@ -341,7 +340,6 @@
* @param i instance to merge during the load. When present, the boolean fields are not nullified
* when their values are false
* @return loaded instance
- * @throws ConfigInvalidException
*/
public static <T> T loadSection(Config cfg, String section, String sub, T s, T defaults, T i)
throws ConfigInvalidException {
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index ef1c0ae..35b16b4 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -85,6 +85,7 @@
import com.google.gerrit.server.ExceptionHookImpl;
import com.google.gerrit.server.ExternalUser;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.PerformanceMetrics;
import com.google.gerrit.server.RequestListener;
import com.google.gerrit.server.TraceRequestListener;
import com.google.gerrit.server.account.AccountCacheImpl;
@@ -431,6 +432,7 @@
DynamicSet.setOf(binder(), SubmitRule.class);
DynamicSet.setOf(binder(), QuotaEnforcer.class);
DynamicSet.setOf(binder(), PerformanceLogger.class);
+ DynamicSet.bind(binder(), PerformanceLogger.class).to(PerformanceMetrics.class);
DynamicSet.setOf(binder(), RequestListener.class);
DynamicSet.bind(binder(), RequestListener.class).to(TraceRequestListener.class);
DynamicSet.setOf(binder(), ChangeETagComputation.class);
diff --git a/java/com/google/gerrit/server/config/GerritIsReplica.java b/java/com/google/gerrit/server/config/GerritIsReplica.java
index 154fdcd..ab6aa8b 100644
--- a/java/com/google/gerrit/server/config/GerritIsReplica.java
+++ b/java/com/google/gerrit/server/config/GerritIsReplica.java
@@ -19,7 +19,7 @@
import com.google.inject.BindingAnnotation;
import java.lang.annotation.Retention;
-/* Marker on {@link Boolean} indicating whether Gerrit is run as a read-only replica. */
+/** Marker on {@link Boolean} indicating whether Gerrit is run as a read-only replica. */
@Retention(RUNTIME)
@BindingAnnotation
public @interface GerritIsReplica {}
diff --git a/java/com/google/gerrit/server/config/GitwebCgiConfig.java b/java/com/google/gerrit/server/config/GitwebCgiConfig.java
index d7fb83c..1ed0f16 100644
--- a/java/com/google/gerrit/server/config/GitwebCgiConfig.java
+++ b/java/com/google/gerrit/server/config/GitwebCgiConfig.java
@@ -118,22 +118,22 @@
this.logoPng = null;
}
- /** @return local path to the CGI executable; null if we shouldn't execute. */
+ /** Returns local path to the CGI executable; null if we shouldn't execute. */
public Path getGitwebCgi() {
return cgi;
}
- /** @return local path of the {@code gitweb.css} matching the CGI. */
+ /** Returns local path of the {@code gitweb.css} matching the CGI. */
public Path getGitwebCss() {
return css;
}
- /** @return local path of the {@code gitweb.js} for the CGI. */
+ /** Returns local path of the {@code gitweb.js} for the CGI. */
public Path getGitwebJs() {
return js;
}
- /** @return local path of the {@code git-logo.png} for the CGI. */
+ /** Returns local path of the {@code git-logo.png} for the CGI. */
public Path getGitLogoPng() {
return logoPng;
}
diff --git a/java/com/google/gerrit/server/config/GitwebConfig.java b/java/com/google/gerrit/server/config/GitwebConfig.java
index f90a72e..5632978 100644
--- a/java/com/google/gerrit/server/config/GitwebConfig.java
+++ b/java/com/google/gerrit/server/config/GitwebConfig.java
@@ -213,16 +213,16 @@
}
}
- /** @return GitwebType for gitweb viewer. */
+ /** Returns GitwebType for gitweb viewer. */
@Nullable
public GitwebType getGitwebType() {
return type;
}
/**
- * @return URL of the entry point into gitweb. This URL may be relative to our context if gitweb
- * is hosted by ourselves; or absolute if its hosted elsewhere; or null if gitweb has not been
- * configured.
+ * Returns URL of the entry point into gitweb. This URL may be relative to our context if gitweb
+ * is hosted by ourselves; or absolute if its hosted elsewhere; or null if gitweb has not been
+ * configured.
*/
public String getUrl() {
return url;
diff --git a/java/com/google/gerrit/server/config/ProjectConfigEntry.java b/java/com/google/gerrit/server/config/ProjectConfigEntry.java
index fcfa5e9..c09988e3 100644
--- a/java/com/google/gerrit/server/config/ProjectConfigEntry.java
+++ b/java/com/google/gerrit/server/config/ProjectConfigEntry.java
@@ -206,16 +206,18 @@
}
/**
+ * Returns whether the project is editable
+ *
* @param project project state.
- * @return whether the project is editable.
*/
public boolean isEditable(ProjectState project) {
return true;
}
/**
+ * Returns any warning associated with the project
+ *
* @param project project state.
- * @return any warning associated with the project.
*/
public String getWarning(ProjectState project) {
return null;
diff --git a/java/com/google/gerrit/server/edit/ChangeEditUtil.java b/java/com/google/gerrit/server/edit/ChangeEditUtil.java
index 710916e..6b018ce 100644
--- a/java/com/google/gerrit/server/edit/ChangeEditUtil.java
+++ b/java/com/google/gerrit/server/edit/ChangeEditUtil.java
@@ -146,9 +146,6 @@
* @param edit change edit to publish
* @param notify Notify handling that defines to whom email notifications should be sent after the
* change edit is published.
- * @throws IOException
- * @throws UpdateException
- * @throws RestApiException
*/
public void publish(
BatchUpdate.Factory updateFactory,
@@ -209,7 +206,6 @@
* Delete change edit.
*
* @param edit change edit to delete
- * @throws IOException
*/
public void delete(ChangeEdit edit) throws IOException {
Change change = edit.getChange();
diff --git a/java/com/google/gerrit/server/events/EventsMetrics.java b/java/com/google/gerrit/server/events/EventsMetrics.java
index 3c87cca..6d48c37 100644
--- a/java/com/google/gerrit/server/events/EventsMetrics.java
+++ b/java/com/google/gerrit/server/events/EventsMetrics.java
@@ -32,7 +32,9 @@
metricMaker.newCounter(
"events",
new Description("Triggered events").setRate().setUnit("triggered events"),
- Field.ofString("type", Metadata.Builder::eventType).build());
+ Field.ofString("type", Metadata.Builder::eventType)
+ .description("The type of the event.")
+ .build());
}
@Override
diff --git a/java/com/google/gerrit/server/extensions/webui/UiActions.java b/java/com/google/gerrit/server/extensions/webui/UiActions.java
index a7f6b48..34c3c20 100644
--- a/java/com/google/gerrit/server/extensions/webui/UiActions.java
+++ b/java/com/google/gerrit/server/extensions/webui/UiActions.java
@@ -72,7 +72,9 @@
new com.google.gerrit.metrics.Description("Latency for RestView#getDescription calls")
.setCumulative()
.setUnit(Units.MILLISECONDS),
- Field.ofString("view", Metadata.Builder::restViewName).build());
+ Field.ofString("view", Metadata.Builder::restViewName)
+ .description("view implementation class")
+ .build());
}
public <R extends RestResource> Iterable<UiAction.Description> from(
diff --git a/java/com/google/gerrit/server/git/GitRepositoryManager.java b/java/com/google/gerrit/server/git/GitRepositoryManager.java
index 8142089a..8dba3e1 100644
--- a/java/com/google/gerrit/server/git/GitRepositoryManager.java
+++ b/java/com/google/gerrit/server/git/GitRepositoryManager.java
@@ -73,7 +73,7 @@
Repository createRepository(Project.NameKey name)
throws RepositoryNotFoundException, RepositoryExistsException, IOException;
- /** @return set of all known projects, sorted by natural NameKey order. */
+ /** Returns set of all known projects, sorted by natural NameKey order. */
SortedSet<Project.NameKey> list();
/**
diff --git a/java/com/google/gerrit/server/git/MergeTip.java b/java/com/google/gerrit/server/git/MergeTip.java
index 204f453..4ffa1a8 100644
--- a/java/com/google/gerrit/server/git/MergeTip.java
+++ b/java/com/google/gerrit/server/git/MergeTip.java
@@ -52,8 +52,8 @@
}
/**
- * @return the initial tip of the branch before the merge operation started; may be null,
- * indicating a previously unborn branch.
+ * Returns the initial tip of the branch before the merge operation started; may be null,
+ * indicating a previously unborn branch.
*/
public CodeReviewCommit getInitialTip() {
return initialTip;
@@ -82,8 +82,8 @@
}
/**
- * @return The current tip of the current merge operation; may be null, indicating an unborn
- * branch.
+ * Returns The current tip of the current merge operation; may be null, indicating an unborn
+ * branch.
*/
@Nullable
public CodeReviewCommit getCurrentTip() {
diff --git a/java/com/google/gerrit/server/git/MergeUtil.java b/java/com/google/gerrit/server/git/MergeUtil.java
index 3385969..3a4d407 100644
--- a/java/com/google/gerrit/server/git/MergeUtil.java
+++ b/java/com/google/gerrit/server/git/MergeUtil.java
@@ -512,9 +512,6 @@
* <li>Change-Id
* </ul>
*
- * @param n
- * @param notes
- * @param psId
* @return new message
*/
private String createDetailedCommitMessage(RevCommit n, ChangeNotes notes, PatchSet.Id psId) {
@@ -630,10 +627,6 @@
* Plugins implementing {@link ChangeMessageModifier} can modify the resulting commit message
* arbitrarily.
*
- * @param n
- * @param mergeTip
- * @param notes
- * @param id
* @return new message
*/
public String createCommitMessageOnSubmit(
diff --git a/java/com/google/gerrit/server/git/RepoRefCache.java b/java/com/google/gerrit/server/git/RepoRefCache.java
index 6b2493a..c69f9a6 100644
--- a/java/com/google/gerrit/server/git/RepoRefCache.java
+++ b/java/com/google/gerrit/server/git/RepoRefCache.java
@@ -46,7 +46,7 @@
return id;
}
- /** @return an unmodifiable view of the refs that have been cached by this instance. */
+ /** Returns an unmodifiable view of the refs that have been cached by this instance. */
public Map<String, Optional<ObjectId>> getCachedRefs() {
return Collections.unmodifiableMap(ids);
}
diff --git a/java/com/google/gerrit/server/git/TransferConfig.java b/java/com/google/gerrit/server/git/TransferConfig.java
index 55b9448..728e4ed 100644
--- a/java/com/google/gerrit/server/git/TransferConfig.java
+++ b/java/com/google/gerrit/server/git/TransferConfig.java
@@ -52,7 +52,7 @@
packConfig.fromConfig(cfg);
}
- /** @return configured timeout, in seconds. 0 if the timeout is infinite. */
+ /** Returns configured timeout, in seconds. 0 if the timeout is infinite. */
public int getTimeout() {
return timeout;
}
diff --git a/java/com/google/gerrit/server/git/UploadPackMetricsHook.java b/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
index 4afff2b..1619add 100644
--- a/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
+++ b/java/com/google/gerrit/server/git/UploadPackMetricsHook.java
@@ -45,7 +45,9 @@
@Inject
UploadPackMetricsHook(MetricMaker metricMaker) {
Field<Operation> operationField =
- Field.ofEnum(Operation.class, "operation", Metadata.Builder::gitOperation).build();
+ Field.ofEnum(Operation.class, "operation", Metadata.Builder::gitOperation)
+ .description("The name of the operation (CLONE, FETCH).")
+ .build();
requestCount =
metricMaker.newCounter(
"git/upload-pack/request_count",
diff --git a/java/com/google/gerrit/server/git/meta/MetaDataUpdate.java b/java/com/google/gerrit/server/git/meta/MetaDataUpdate.java
index e90f58b..27d5da9 100644
--- a/java/com/google/gerrit/server/git/meta/MetaDataUpdate.java
+++ b/java/com/google/gerrit/server/git/meta/MetaDataUpdate.java
@@ -160,7 +160,7 @@
return create(name, null);
}
- /** @see User#create(Project.NameKey, IdentifiedUser, BatchRefUpdate) */
+ /** See {@link User#create(Project.NameKey, IdentifiedUser, BatchRefUpdate)} */
public MetaDataUpdate create(Project.NameKey name, BatchRefUpdate batch)
throws RepositoryNotFoundException, IOException {
Repository repo = mgr.openRepository(name);
@@ -234,7 +234,7 @@
this.closeRepository = closeRepository;
}
- /** @return batch in which to run the update, or {@code null} for no batch. */
+ /** Returns batch in which to run the update, or {@code null} for no batch. */
BatchRefUpdate getBatch() {
return batch;
}
diff --git a/java/com/google/gerrit/server/git/meta/VersionedMetaData.java b/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
index 999ed4e..a42ab8f 100644
--- a/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
+++ b/java/com/google/gerrit/server/git/meta/VersionedMetaData.java
@@ -100,7 +100,7 @@
protected ObjectInserter inserter;
protected DirCache newTree;
- /** @return name of the reference storing this configuration. */
+ /** Returns name of the reference storing this configuration. */
protected abstract String getRefName();
/** Set up the metadata, parsing any state from the loaded revision. */
@@ -110,13 +110,11 @@
* Save any changes to the metadata in a commit.
*
* @return true if the commit should proceed, false to abort.
- * @throws IOException
- * @throws ConfigInvalidException
*/
protected abstract boolean onSave(CommitBuilder commit)
throws IOException, ConfigInvalidException;
- /** @return revision of the metadata that was loaded. */
+ /** Returns revision of the metadata that was loaded. */
@Nullable
public ObjectId getRevision() {
return ObjectIds.copyOrNull(revision);
@@ -130,8 +128,6 @@
*
* @param projectName the name of the project
* @param db repository to access.
- * @throws IOException
- * @throws ConfigInvalidException
*/
public void load(Project.NameKey projectName, Repository db)
throws IOException, ConfigInvalidException {
@@ -152,8 +148,6 @@
* @param projectName the name of the project
* @param db repository to access.
* @param id revision to load.
- * @throws IOException
- * @throws ConfigInvalidException
*/
public void load(Project.NameKey projectName, Repository db, @Nullable ObjectId id)
throws IOException, ConfigInvalidException {
@@ -176,8 +170,6 @@
* @param projectName the name of the project
* @param walk open walk to access to access.
* @param id revision to load.
- * @throws IOException
- * @throws ConfigInvalidException
*/
public void load(Project.NameKey projectName, RevWalk walk, ObjectId id)
throws IOException, ConfigInvalidException {
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index f7f58fc..ca2a5d3 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -102,7 +102,9 @@
import com.google.gerrit.extensions.validators.CommentValidationFailure;
import com.google.gerrit.extensions.validators.CommentValidator;
import com.google.gerrit.metrics.Counter0;
+import com.google.gerrit.metrics.Counter3;
import com.google.gerrit.metrics.Description;
+import com.google.gerrit.metrics.Field;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.CancellationMetrics;
import com.google.gerrit.server.ChangeUtil;
@@ -323,6 +325,7 @@
@Singleton
private static class Metrics {
private final Counter0 psRevisionMissing;
+ private final Counter3<String, String, String> pushCount;
@Inject
Metrics(MetricMaker metricMaker) {
@@ -330,6 +333,23 @@
metricMaker.newCounter(
"receivecommits/ps_revision_missing",
new Description("errors due to patch set revision missing"));
+ pushCount =
+ metricMaker.newCounter(
+ "receivecommits/push_count",
+ new Description("number of pushes"),
+ Field.ofString("kind", (metadataBuilder, fieldValue) -> {})
+ .description("The push kind (direct vs. magic).")
+ .build(),
+ Field.ofString(
+ "project",
+ (metadataBuilder, fieldValue) -> metadataBuilder.projectName(fieldValue))
+ .description("The name of the project for which the push is done.")
+ .build(),
+ Field.ofString("type", (metadataBuilder, fieldValue) -> {})
+ .description(
+ "The type of the update (CREATE, UPDATE, CREATE/UPDATE,"
+ + " UPDATE_NONFASTFORWARD, DELETE).")
+ .build());
}
}
@@ -727,6 +747,13 @@
return;
}
+ if (!magicCommands.isEmpty()) {
+ metrics.pushCount.increment("magic", project.getName(), getUpdateType(magicCommands));
+ }
+ if (!regularCommands.isEmpty()) {
+ metrics.pushCount.increment("direct", project.getName(), getUpdateType(regularCommands));
+ }
+
try {
if (!regularCommands.isEmpty()) {
handleRegularCommands(regularCommands, progress);
@@ -777,6 +804,15 @@
lazy(() -> commands.stream().map(ReceiveCommits::commandToString).collect(joining(","))));
}
+ private String getUpdateType(List<ReceiveCommand> commands) {
+ return commands.stream()
+ .map(ReceiveCommand::getType)
+ .map(ReceiveCommand.Type::name)
+ .distinct()
+ .sorted()
+ .collect(joining("/"));
+ }
+
private void sendErrorMessages() {
if (!errors.isEmpty()) {
logger.atFine().log("Handling error conditions: %s", errors.keySet());
@@ -2882,8 +2918,6 @@
* </ul>
*
* @return whether the new commit is valid
- * @throws IOException
- * @throws PermissionBackendException
*/
boolean validateNewPatchSet() throws IOException, PermissionBackendException {
try (TraceTimer traceTimer = newTimer("validateNewPatchSet")) {
diff --git a/java/com/google/gerrit/server/git/receive/ReplaceOp.java b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
index b2a31b9..a9ef70e 100644
--- a/java/com/google/gerrit/server/git/receive/ReplaceOp.java
+++ b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
@@ -345,8 +345,11 @@
update.putReviewer(ctx.getAccountId(), REVIEWER);
}
- mailMessage = insertChangeMessage(update, ctx, reviewMessage);
+ // Approvals that are being set in the new patch-set during this operation are not available yet
+ // outside of the scope of this method. Only copied approvals are set here.
+ approvalsUtil.byPatchSet(ctx.getNotes(), newPatchSet).forEach(a -> update.putCopiedApproval(a));
+ mailMessage = insertChangeMessage(update, ctx, reviewMessage);
if (mergedByPushOp == null) {
resetChange(ctx);
} else {
diff --git a/java/com/google/gerrit/server/git/validators/OnSubmitValidationListener.java b/java/com/google/gerrit/server/git/validators/OnSubmitValidationListener.java
index 432dda3..98f2aa2 100644
--- a/java/com/google/gerrit/server/git/validators/OnSubmitValidationListener.java
+++ b/java/com/google/gerrit/server/git/validators/OnSubmitValidationListener.java
@@ -76,8 +76,8 @@
}
/**
- * @return a map from ref to commands covering all ref operations to be performed on this
- * repository as part of the ongoing submit operation.
+ * Returns a map from ref to commands covering all ref operations to be performed on this
+ * repository as part of the ongoing submit operation.
*/
public ImmutableMap<String, ReceiveCommand> getCommands() {
return commands;
diff --git a/java/com/google/gerrit/server/group/db/GroupDelta.java b/java/com/google/gerrit/server/group/db/GroupDelta.java
index 4ef2450..69cb936 100644
--- a/java/com/google/gerrit/server/group/db/GroupDelta.java
+++ b/java/com/google/gerrit/server/group/db/GroupDelta.java
@@ -121,19 +121,39 @@
@AutoValue.Builder
public abstract static class Builder {
- /** @see #getName() */
+ /**
+ * Defines the new name of the group
+ *
+ * <p>See {@link #getName}.
+ */
public abstract Builder setName(AccountGroup.NameKey name);
- /** @see #getDescription() */
+ /**
+ * Defines the new description of the group
+ *
+ * <p>See {@link #getDescription()}}
+ */
public abstract Builder setDescription(String description);
- /** @see #getOwnerGroupUUID() */
+ /**
+ * Defines the new owner of the group
+ *
+ * <p>See {@link #getOwnerGroupUUID()}
+ */
public abstract Builder setOwnerGroupUUID(AccountGroup.UUID ownerGroupUUID);
- /** @see #getVisibleToAll() */
+ /**
+ * Defines the new state of the 'visibleToAll' flag of the group
+ *
+ * <p>See {@link #getVisibleToAll()}
+ */
public abstract Builder setVisibleToAll(boolean visibleToAll);
- /** @see #getMemberModification() */
+ /**
+ * Set {@link MemberModification} for the prospective {@link GroupDelta}
+ *
+ * <p>See {@link #getMemberModification()}
+ */
public abstract Builder setMemberModification(MemberModification memberModification);
/**
@@ -146,7 +166,11 @@
*/
public abstract MemberModification getMemberModification();
- /** @see #getSubgroupModification() */
+ /**
+ * Set {@link SubgroupModification} for the prospective {@link GroupDelta}
+ *
+ * <p>See {@link #getSubgroupModification()}
+ */
public abstract Builder setSubgroupModification(SubgroupModification subgroupModification);
/**
@@ -159,7 +183,12 @@
*/
public abstract SubgroupModification getSubgroupModification();
- /** @see #getUpdatedOn() */
+ /**
+ * Defines the {@code Timestamp} to be used for the NoteDb commits of the update. If not
+ * specified, the current {@code Timestamp} when creating the commit will be used.
+ *
+ * <p>See {@link #getUpdatedOn()}
+ */
public abstract Builder setUpdatedOn(Timestamp timestamp);
public abstract GroupDelta build();
diff --git a/java/com/google/gerrit/server/group/db/GroupsNoteDbConsistencyChecker.java b/java/com/google/gerrit/server/group/db/GroupsNoteDbConsistencyChecker.java
index 01ee811..24bcaf0 100644
--- a/java/com/google/gerrit/server/group/db/GroupsNoteDbConsistencyChecker.java
+++ b/java/com/google/gerrit/server/group/db/GroupsNoteDbConsistencyChecker.java
@@ -22,6 +22,7 @@
import com.google.common.collect.HashBiMap;
import com.google.common.collect.ImmutableList;
import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.FormatMethod;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.AccountGroup;
import com.google.gerrit.entities.GroupReference;
@@ -138,8 +139,7 @@
Optional<Ref> maybeRef =
refs.stream().filter(r -> r.getName().equals(RefNames.REFS_GROUPNAMES)).findFirst();
if (!maybeRef.isPresent()) {
- String msg = String.format("ref %s does not exist", RefNames.REFS_GROUPNAMES);
- result.problems.add(error(msg));
+ result.problems.add(error("ref %s does not exist", RefNames.REFS_GROUPNAMES));
return;
}
Ref ref = maybeRef.get();
@@ -280,6 +280,7 @@
}
}
+ @FormatMethod
public static void logConsistencyProblemAsWarning(String fmt, Object... args) {
logConsistencyProblem(warning(fmt, args));
}
diff --git a/java/com/google/gerrit/server/group/db/InternalGroupCreation.java b/java/com/google/gerrit/server/group/db/InternalGroupCreation.java
index f4bf6e6..291c354 100644
--- a/java/com/google/gerrit/server/group/db/InternalGroupCreation.java
+++ b/java/com/google/gerrit/server/group/db/InternalGroupCreation.java
@@ -26,13 +26,13 @@
@AutoValue
public abstract class InternalGroupCreation {
- /** Defines the numeric ID the group should have. */
+ /** Defines the numeric ID the group should have */
public abstract AccountGroup.Id getId();
- /** Defines the name the group should have. */
+ /** Defines the name the group should have */
public abstract AccountGroup.NameKey getNameKey();
- /** Defines the UUID the group should have. */
+ /** Defines the UUID the group should have */
public abstract AccountGroup.UUID getGroupUUID();
public static Builder builder() {
@@ -41,13 +41,13 @@
@AutoValue.Builder
public abstract static class Builder {
- /** @see #getId() */
+ /** Defines the name the group should have */
public abstract InternalGroupCreation.Builder setId(AccountGroup.Id id);
- /** @see #getNameKey() */
+ /** Defines the name the group should have */
public abstract InternalGroupCreation.Builder setNameKey(AccountGroup.NameKey name);
- /** @see #getGroupUUID() */
+ /** Defines the UUID the group should have */
public abstract InternalGroupCreation.Builder setGroupUUID(AccountGroup.UUID groupUuid);
public abstract InternalGroupCreation build();
diff --git a/java/com/google/gerrit/server/index/VersionManager.java b/java/com/google/gerrit/server/index/VersionManager.java
index 56ce604..cdb69c6 100644
--- a/java/com/google/gerrit/server/index/VersionManager.java
+++ b/java/com/google/gerrit/server/index/VersionManager.java
@@ -107,7 +107,6 @@
* @param name index name
* @param force start re-index
* @return true if started, otherwise false.
- * @throws ReindexerAlreadyRunningException
*/
public synchronized boolean startReindexer(String name, boolean force)
throws ReindexerAlreadyRunningException {
@@ -125,7 +124,6 @@
*
* @param name index name
* @return true if index was activated, otherwise false.
- * @throws ReindexerAlreadyRunningException
*/
public synchronized boolean activateLatestIndex(String name)
throws ReindexerAlreadyRunningException {
diff --git a/java/com/google/gerrit/server/ioutil/HostPlatform.java b/java/com/google/gerrit/server/ioutil/HostPlatform.java
index 39e9c07..e27d17c 100644
--- a/java/com/google/gerrit/server/ioutil/HostPlatform.java
+++ b/java/com/google/gerrit/server/ioutil/HostPlatform.java
@@ -21,7 +21,7 @@
private static final boolean win32 = compute("windows");
private static final boolean mac = compute("mac");
- /** @return true if this JVM is running on a Windows platform. */
+ /** Returns true if this JVM is running on a Windows platform. */
public static boolean isWin32() {
return win32;
}
diff --git a/java/com/google/gerrit/server/ioutil/LimitedByteArrayOutputStream.java b/java/com/google/gerrit/server/ioutil/LimitedByteArrayOutputStream.java
index 015887b..a58d9ae 100644
--- a/java/com/google/gerrit/server/ioutil/LimitedByteArrayOutputStream.java
+++ b/java/com/google/gerrit/server/ioutil/LimitedByteArrayOutputStream.java
@@ -57,7 +57,7 @@
buffer.write(b, off, len);
}
- /** @return a newly allocated byte array with contents of the buffer. */
+ /** Returns a newly allocated byte array with contents of the buffer. */
public byte[] toByteArray() {
return buffer.toByteArray();
}
diff --git a/java/com/google/gerrit/server/logging/TraceContext.java b/java/com/google/gerrit/server/logging/TraceContext.java
index 681dfbc..487e0af 100644
--- a/java/com/google/gerrit/server/logging/TraceContext.java
+++ b/java/com/google/gerrit/server/logging/TraceContext.java
@@ -268,15 +268,23 @@
return this;
}
- public boolean isTracing() {
+ public static boolean isTracing() {
return LoggingContext.getInstance().isLoggingForced();
}
- public Optional<String> getTraceId() {
+ public static Optional<String> getTraceId() {
return LoggingContext.getInstance().getTagsAsMap().get(RequestId.Type.TRACE_ID.name()).stream()
.findFirst();
}
+ public static Optional<String> getPluginTag() {
+ return getTag(PLUGIN_TAG);
+ }
+
+ public static Optional<String> getTag(String tagName) {
+ return LoggingContext.getInstance().getTagsAsMap().get(tagName).stream().findFirst();
+ }
+
public TraceContext enableAclLogging() {
if (stopAclLoggingOnClose) {
return this;
@@ -286,11 +294,7 @@
return this;
}
- public boolean isAclLoggingEnabled() {
- return LoggingContext.getInstance().isAclLogging();
- }
-
- public ImmutableList<String> getAclLogRecords() {
+ public static ImmutableList<String> getAclLogRecords() {
return LoggingContext.getInstance().getAclLogRecords();
}
diff --git a/java/com/google/gerrit/server/mail/receive/MailReceiver.java b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
index dc99b46..e383207 100644
--- a/java/com/google/gerrit/server/mail/receive/MailReceiver.java
+++ b/java/com/google/gerrit/server/mail/receive/MailReceiver.java
@@ -110,8 +110,6 @@
* requestDeletion will enqueue an email for deletion and delete it the next time we connect to
* the email server. This does not guarantee deletion as the Gerrit instance might fail before we
* connect to the email server.
- *
- * @param messageId
*/
public void requestDeletion(String messageId) {
pendingDeletion.add(messageId);
diff --git a/java/com/google/gerrit/server/mail/send/CommentSender.java b/java/com/google/gerrit/server/mail/send/CommentSender.java
index 4593584..b7a7d12 100644
--- a/java/com/google/gerrit/server/mail/send/CommentSender.java
+++ b/java/com/google/gerrit/server/mail/send/CommentSender.java
@@ -71,23 +71,23 @@
public PatchFile fileData;
public List<Comment> comments = new ArrayList<>();
- /** @return a web link to a comment for a change. */
+ /** Returns a web link to a comment for a change. */
public String getCommentLink(String uuid) {
return args.urlFormatter.get().getInlineCommentView(change, uuid).orElse(null);
}
- /** @return a web link to the comment tab view of a change. */
+ /** Returns a web link to the comment tab view of a change. */
public String getCommentsTabLink() {
return args.urlFormatter.get().getCommentsTabView(change).orElse(null);
}
- /** @return a web link to the findings tab view of a change. */
+ /** Returns a web link to the findings tab view of a change. */
public String getFindingsTabLink() {
return args.urlFormatter.get().getFindingsTabView(change).orElse(null);
}
/**
- * @return A title for the group, i.e. "Commit Message", "Merge List", or "File [[filename]]".
+ * Returns a title for the group, i.e. "Commit Message", "Merge List", or "File [[filename]]".
*/
public String getTitle() {
if (Patch.COMMIT_MSG.equals(filename)) {
@@ -180,8 +180,8 @@
}
/**
- * @return a list of FileCommentGroup objects representing the inline comments grouped by the
- * file.
+ * Returns a list of FileCommentGroup objects representing the inline comments grouped by the
+ * file.
*/
private List<CommentSender.FileCommentGroup> getGroupedInlineComments(Repository repo) {
List<CommentSender.FileCommentGroup> groups = new ArrayList<>();
@@ -267,7 +267,7 @@
}
/**
- * @return the lines of file content in fileData that are encompassed by range on the given side.
+ * Returns the lines of file content in fileData that are encompassed by range on the given side.
*/
private List<String> getLinesByRange(Comment.Range range, PatchFile fileData, short side) {
List<String> lines = new ArrayList<>();
@@ -330,9 +330,9 @@
}
/**
- * @return a shortened version of the given comment's message. Will be shortened to 100 characters
- * or the first line, or following the last period within the first 100 characters, whichever
- * is shorter. If the message is shortened, an ellipsis is appended.
+ * Returns a shortened version of the given comment's message. Will be shortened to 100 characters
+ * or the first line, or following the last period within the first 100 characters, whichever is
+ * shorter. If the message is shortened, an ellipsis is appended.
*/
protected static String getShortenedCommentMessage(String message) {
int threshold = 100;
@@ -368,8 +368,8 @@
}
/**
- * @return grouped inline comment data mapped to data structures that are suitable for passing
- * into Soy.
+ * Returns grouped inline comment data mapped to data structures that are suitable for passing
+ * into Soy.
*/
private List<Map<String, Object>> getCommentGroupsTemplateData(Repository repo) {
List<Map<String, Object>> commentGroups = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java b/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
index aa683f6..b32c43a 100644
--- a/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
+++ b/java/com/google/gerrit/server/mail/send/MessageIdGenerator.java
@@ -58,8 +58,6 @@
/**
* Create a {@link MessageId} as a result of a change update.
*
- * @param repoView
- * @param patchsetId
* @return MessageId that depends on the patchset.
*/
public MessageId fromChangeUpdate(RepoView repoView, PatchSet.Id patchsetId) {
@@ -89,8 +87,9 @@
}
/**
- * @param accountId Create a {@link MessageId} as a result of an account update.
- * @return MessageId that depends on the account id.
+ * Create a {@link MessageId} as a result of an account update
+ *
+ * @return {@link MessageId} that depends on the account id.
*/
public MessageId fromAccountUpdate(Account.Id accountId) {
String userRef = RefNames.refsUsers(accountId);
@@ -113,8 +112,6 @@
* Create a {@link MessageId} from a reason, Account.Id, and timestamp.
*
* @param reason for performing this account update
- * @param accountId
- * @param timestamp
* @return MessageId that depends on the reason, accountId, and timestamp.
*/
public MessageId fromReasonAccountIdAndTimestamp(
diff --git a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
index 8547336..8824cbd 100644
--- a/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
+++ b/java/com/google/gerrit/server/mail/send/OutgoingEmail.java
@@ -95,11 +95,7 @@
this.messageId = messageId;
}
- /**
- * Format and enqueue the message for delivery.
- *
- * @throws EmailException
- */
+ /** Format and enqueue the message for delivery. */
public void send() throws EmailException {
try {
args.retryHelper
@@ -185,7 +181,8 @@
// drop them from the recipient lists, but only if the user is not being impersonated.
//
logger.atFine().log(
- "Not CCing email sender %s because the email strategy of this user is not %s but %s",
+ "Not CCing email sender %s because the email strategy of this user is not %s but"
+ + " %s",
fromUser.get().account().id(),
CC_ON_OWN_COMMENTS,
senderPrefs != null ? senderPrefs.getEmailStrategy() : null);
@@ -543,9 +540,9 @@
}
/**
+ * Returns whether this email is visible to the given account
+ *
* @param to account.
- * @throws PermissionBackendException
- * @return whether this email is visible to the given account.
*/
protected boolean isVisibleTo(Account.Id to) throws PermissionBackendException {
return true;
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index a7c7757..d71f9ff 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -134,7 +134,7 @@
return changeId;
}
- /** @return revision of the metadata that was loaded. */
+ /** Returns revision of the metadata that was loaded. */
public ObjectId getRevision() {
return revision;
}
@@ -210,12 +210,12 @@
protected abstract void loadDefaults();
/**
- * @return the NameKey for the project where the notes should be stored, which is not necessarily
- * the same as the change's project.
+ * Returns the NameKey for the project where the notes should be stored, which is not necessarily
+ * the same as the change's project.
*/
public abstract Project.NameKey getProjectName();
- /** @return name of the reference storing this configuration. */
+ /** Returns name of the reference storing this configuration. */
protected abstract String getRefName();
/** Set up the metadata, parsing any state from the loaded revision. */
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
index 8e6606e..6677490 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeUpdate.java
@@ -122,12 +122,11 @@
}
/**
- * @return notes for the state of this change prior to this update. If this update is part of a
- * series managed by a {@link NoteDbUpdateManager}, then this reflects the state prior to the
- * first update in the series. A null return value can only happen when the change is being
- * rebuilt from NoteDb. A change that is in the process of being created will result in a
- * non-null return value from this method, but a null return value from {@link
- * ChangeNotes#getRevision()}.
+ * Returns notes for the state of this change prior to this update. If this update is part of a
+ * series managed by a {@link NoteDbUpdateManager}, then this reflects the state prior to the
+ * first update in the series. A null return value can only happen when the change is being
+ * rebuilt from NoteDb. A change that is in the process of being created will result in a non-null
+ * return value from this method, but a null return value from {@link ChangeNotes#getRevision()}.
*/
@Nullable
public ChangeNotes getNotes() {
@@ -173,8 +172,8 @@
}
/**
- * @return the NameKey for the project where the update will be stored, which is not necessarily
- * the same as the change's project.
+ * Returns the NameKey for the project where the update will be stored, which is not necessarily
+ * the same as the change's project.
*/
protected abstract Project.NameKey getProjectName();
diff --git a/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java b/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
index afd8316..28ab711 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
@@ -40,6 +40,7 @@
static final FooterKey FOOTER_GROUPS = new FooterKey("Groups");
static final FooterKey FOOTER_HASHTAGS = new FooterKey("Hashtags");
static final FooterKey FOOTER_LABEL = new FooterKey("Label");
+ static final FooterKey FOOTER_COPIED_LABEL = new FooterKey("Copied-Label");
static final FooterKey FOOTER_PATCH_SET = new FooterKey("Patch-set");
static final FooterKey FOOTER_PATCH_SET_DESCRIPTION = new FooterKey("Patch-set-description");
static final FooterKey FOOTER_PRIVATE = new FooterKey("Private");
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index 6684493..2d9b014 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -16,6 +16,7 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
+import static com.google.common.collect.ImmutableListMultimap.toImmutableListMultimap;
import static com.google.common.collect.ImmutableSet.toImmutableSet;
import static com.google.gerrit.entities.RefNames.changeMetaRef;
import static java.util.Comparator.comparing;
@@ -36,6 +37,7 @@
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
import com.google.common.flogger.FluentLogger;
+import com.google.errorprone.annotations.FormatMethod;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.AttentionSetUpdate;
@@ -90,6 +92,7 @@
public static final Ordering<ChangeMessage> MESSAGE_BY_TIME =
Ordering.from(comparing(ChangeMessage::getWrittenOn));
+ @FormatMethod
public static ConfigInvalidException parseException(
Change.Id changeId, String fmt, Object... args) {
return new ConfigInvalidException("Change " + changeId + ": " + String.format(fmt, args));
@@ -336,6 +339,7 @@
// ChangeNotesCache from handlers.
private ImmutableSortedMap<PatchSet.Id, PatchSet> patchSets;
private ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvals;
+ private ImmutableListMultimap<PatchSet.Id, PatchSetApproval> approvalsWithCopied;
private ImmutableSet<Comment.Key> commentKeys;
public ChangeNotes(
@@ -373,28 +377,49 @@
return patchSets;
}
+ /**
+ * Gets the approvals, not including the copied approvals. To get copied approvals as well, use
+ * {@link #getApprovalsWithCopied}, or use {@code ApprovalInference}.
+ */
public ImmutableListMultimap<PatchSet.Id, PatchSetApproval> getApprovals() {
if (approvals == null) {
- approvals = ImmutableListMultimap.copyOf(state.approvals());
+ approvals =
+ state.approvals().stream()
+ .filter(e -> !e.getValue().copied())
+ .collect(toImmutableListMultimap(e -> e.getKey(), e -> e.getValue()));
}
return approvals;
}
+ /**
+ * This method is currently used only in tests. TODO(paiking): Use this method to fetch approvals
+ * (including copied approvals) instead of computing copied approvals on demand. This will be used
+ * by {@code ApprovalCache}.
+ *
+ * @return all approvals, including copied approvals.
+ */
+ public ImmutableListMultimap<PatchSet.Id, PatchSetApproval> getApprovalsWithCopied() {
+ if (approvalsWithCopied == null) {
+ approvalsWithCopied = ImmutableListMultimap.copyOf(state.approvals());
+ }
+ return approvalsWithCopied;
+ }
+
public ReviewerSet getReviewers() {
return state.reviewers();
}
- /** @return reviewers that do not currently have a Gerrit account and were added by email. */
+ /** Returns reviewers that do not currently have a Gerrit account and were added by email. */
public ReviewerByEmailSet getReviewersByEmail() {
return state.reviewersByEmail();
}
- /** @return reviewers that were modified during this change's current WIP phase. */
+ /** Returns reviewers that were modified during this change's current WIP phase. */
public ReviewerSet getPendingReviewers() {
return state.pendingReviewers();
}
- /** @return reviewers by email that were modified during this change's current WIP phase. */
+ /** Returns reviewers by email that were modified during this change's current WIP phase. */
public ReviewerByEmailSet getPendingReviewersByEmail() {
return state.pendingReviewersByEmail();
}
@@ -424,8 +449,8 @@
}
/**
- * @return an ImmutableSet of Account.Ids of all users that have been assigned to this change. The
- * order of the set is the order in which they were assigned.
+ * Returns an ImmutableSet of Account.Ids of all users that have been assigned to this change. The
+ * order of the set is the order in which they were assigned.
*/
public ImmutableSet<Account.Id> getPastAssignees() {
return Lists.reverse(state.assigneeUpdates()).stream()
@@ -436,37 +461,37 @@
}
/**
- * @return an ImmutableList of AssigneeStatusUpdate of all the updates to the assignee field to
- * this change. The order of the list is from most recent updates to least recent.
+ * Returns an ImmutableList of AssigneeStatusUpdate of all the updates to the assignee field to
+ * this change. The order of the list is from most recent updates to least recent.
*/
public ImmutableList<AssigneeStatusUpdate> getAssigneeUpdates() {
return state.assigneeUpdates();
}
- /** @return a ImmutableSet of all hashtags for this change sorted in alphabetical order. */
+ /** Returns an ImmutableSet of all hashtags for this change sorted in alphabetical order. */
public ImmutableSet<String> getHashtags() {
return ImmutableSortedSet.copyOf(state.hashtags());
}
- /** @return a list of all users who have ever been a reviewer on this change. */
+ /** Returns a list of all users who have ever been a reviewer on this change. */
public ImmutableList<Account.Id> getAllPastReviewers() {
return state.allPastReviewers();
}
/**
- * @return submit records stored during the most recent submit; only for changes that were
- * actually submitted.
+ * Returns submit records stored during the most recent submit; only for changes that were
+ * actually submitted.
*/
public ImmutableList<SubmitRecord> getSubmitRecords() {
return state.submitRecords();
}
- /** @return all change messages, in chronological order, oldest first. */
+ /** Returns all change messages, in chronological order, oldest first. */
public ImmutableList<ChangeMessage> getChangeMessages() {
return state.changeMessages();
}
- /** @return inline comments on each revision. */
+ /** Returns inline comments on each revision. */
public ImmutableListMultimap<ObjectId, HumanComment> getHumanComments() {
return state.publishedComments();
}
@@ -486,7 +511,7 @@
return state.updateCount();
}
- /** @return {@link Optional} value of time when the change was merged. */
+ /** Returns {@link Optional} value of time when the change was merged. */
public Optional<Timestamp> getMergedOn() {
return Optional.ofNullable(state.mergedOn());
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
index f82349a..5cf3a64 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotesParser.java
@@ -21,6 +21,7 @@
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CHANGE_ID;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CHERRY_PICK_OF;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_COMMIT;
+import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_COPIED_LABEL;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CURRENT;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_GROUPS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_HASHTAGS;
@@ -55,6 +56,7 @@
import com.google.common.collect.Tables;
import com.google.common.flogger.FluentLogger;
import com.google.common.primitives.Ints;
+import com.google.errorprone.annotations.FormatMethod;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
@@ -413,6 +415,9 @@
for (String line : commit.getFooterLineValues(FOOTER_LABEL)) {
parseApproval(psId, accountId, realAccountId, commitTimestamp, line);
}
+ for (String line : commit.getFooterLineValues(FOOTER_COPIED_LABEL)) {
+ parseCopiedApproval(psId, commitTimestamp, line);
+ }
for (ReviewerStateInternal state : ReviewerStateInternal.values()) {
for (String line : commit.getFooterLineValues(state.getFooterKey())) {
@@ -796,6 +801,69 @@
}
}
+ // Footer example: Copied-Label: <LABEL>=VOTE <Gerrit Account>,<Gerrit Real Account> :"<TAG>"
+ // ":<"TAG>"" is optional. <Gerrit Real Account> is also optional, if it was not set.
+ // The label, vote, and the Gerrit account are mandatory (unlike FOOTER_LABEL where Gerrit
+ // Account is also optional since by default it's the committer).
+ private void parseCopiedApproval(PatchSet.Id psId, Timestamp ts, String line)
+ throws ConfigInvalidException {
+ // Copied approvals can't be explicitly removed. They are removed the same way as non-copied
+ // approvals.
+ checkFooter(!line.startsWith("-"), FOOTER_COPIED_LABEL, line);
+
+ Account.Id accountId, realAccountId = null;
+ String labelVoteStr;
+ String tag = null;
+ int s = line.indexOf(' ');
+ int tagStart = line.indexOf(":\"");
+
+ // The first account is the accountId, and second (if applicable) is the realAccountId.
+ try {
+ labelVoteStr = line.substring(0, s);
+ } catch (StringIndexOutOfBoundsException ex) {
+ throw new ConfigInvalidException(ex.getMessage(), ex);
+ }
+ String[] identities =
+ line.substring(s + 1, tagStart == -1 ? line.length() : tagStart).split(",");
+ PersonIdent ident = RawParseUtils.parsePersonIdent(identities[0]);
+ checkFooter(ident != null, FOOTER_COPIED_LABEL, line);
+ accountId = parseIdent(ident);
+
+ if (identities.length > 1) {
+ PersonIdent realIdent = RawParseUtils.parsePersonIdent(identities[1]);
+ checkFooter(realIdent != null, FOOTER_COPIED_LABEL, line);
+ realAccountId = parseIdent(realIdent);
+ }
+
+ LabelVote l;
+ try {
+ l = LabelVote.parseWithEquals(labelVoteStr);
+ } catch (IllegalArgumentException e) {
+ ConfigInvalidException pe = parseException("invalid %s: %s", FOOTER_COPIED_LABEL, line);
+ pe.initCause(e);
+ throw pe;
+ }
+
+ if (tagStart != -1) {
+ // tagStart+2 skips ":\"" to parse the actual tag. Tags are in brackets.
+ // line.length()-1 skips the last ".
+ tag = line.substring(tagStart + 2, line.length() - 1);
+ }
+
+ PatchSetApproval.Builder psa =
+ PatchSetApproval.builder()
+ .key(PatchSetApproval.key(psId, accountId, LabelId.create(l.label())))
+ .value(l.value())
+ .granted(ts)
+ .tag(Optional.ofNullable(tag))
+ .copied(true);
+ if (realAccountId != null) {
+ psa.realAccountId(realAccountId);
+ }
+ approvals.putIfAbsent(psa.key(), psa);
+ bufferedApprovals.add(psa);
+ }
+
private void parseApproval(
PatchSet.Id psId, Account.Id accountId, Account.Id realAccountId, Timestamp ts, String line)
throws ConfigInvalidException {
@@ -1172,6 +1240,7 @@
}
if (!missing.isEmpty()) {
throw parseException(
+ "%s",
"Missing footers: " + missing.stream().map(FooterKey::getName).collect(joining(", ")));
}
}
@@ -1205,6 +1274,7 @@
return pending != null && pending.commitId().isPresent();
}
+ @FormatMethod
private ConfigInvalidException parseException(String fmt, Object... args) {
return ChangeNotes.parseException(id, fmt, args);
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeUpdate.java b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
index 004ad40..5acea1b 100644
--- a/java/com/google/gerrit/server/notedb/ChangeUpdate.java
+++ b/java/com/google/gerrit/server/notedb/ChangeUpdate.java
@@ -24,6 +24,7 @@
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CHANGE_ID;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CHERRY_PICK_OF;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_COMMIT;
+import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_COPIED_LABEL;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_CURRENT;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_GROUPS;
import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_HASHTAGS;
@@ -52,6 +53,7 @@
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Table;
+import com.google.common.collect.Table.Cell;
import com.google.common.collect.TreeBasedTable;
import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Address;
@@ -61,6 +63,7 @@
import com.google.gerrit.entities.Comment;
import com.google.gerrit.entities.HumanComment;
import com.google.gerrit.entities.LabelId;
+import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.Project;
import com.google.gerrit.entities.RobotComment;
import com.google.gerrit.entities.SubmissionId;
@@ -128,6 +131,7 @@
private final ServiceUserClassifier serviceUserClassifier;
private final Table<String, Account.Id, Optional<Short>> approvals;
+ private final List<PatchSetApproval> copiedApprovals = new ArrayList<>();
private final Map<Account.Id, ReviewerStateInternal> reviewers = new LinkedHashMap<>();
private final Map<Address, ReviewerStateInternal> reviewersByEmail = new LinkedHashMap<>();
private final List<HumanComment> comments = new ArrayList<>();
@@ -273,6 +277,15 @@
approvals.put(label, reviewer, Optional.empty());
}
+ /**
+ * We expect the {@code copied} flag of {@code copiedPatchSetApproval} to be set, since this
+ * method is only meant for copied approvals.
+ */
+ public void putCopiedApproval(PatchSetApproval copiedPatchSetApproval) {
+ checkArgument(copiedPatchSetApproval.copied(), "Approval that should be copied is not copied.");
+ copiedApprovals.add(copiedPatchSetApproval);
+ }
+
public void merge(SubmissionId submissionId, Iterable<SubmitRecord> submitRecords) {
this.status = Change.Status.MERGED;
this.submissionId = submissionId.toString();
@@ -492,7 +505,7 @@
this.cherryPickOf = Optional.empty();
}
- /** @return the tree id for the updated tree */
+ /** Returns the tree id for the updated tree */
private ObjectId storeRevisionNotes(RevWalk rw, ObjectInserter inserter, ObjectId curr)
throws ConfigInvalidException, IOException {
if (submitRequirementResults.isEmpty() && comments.isEmpty() && pushCert == null) {
@@ -705,18 +718,10 @@
}
for (Table.Cell<String, Account.Id, Optional<Short>> c : approvals.cellSet()) {
- addFooter(msg, FOOTER_LABEL);
- // Label names/values are safe to append without sanitizing.
- if (!c.getValue().isPresent()) {
- msg.append('-').append(c.getRowKey());
- } else {
- msg.append(LabelVote.create(c.getRowKey(), c.getValue().get()).formatWithEquals());
- }
- Account.Id id = c.getColumnKey();
- if (!id.equals(getAccountId())) {
- noteUtil.appendAccountIdIdentString(msg.append(' '), id);
- }
- msg.append('\n');
+ addLabelFooter(msg, c);
+ }
+ for (PatchSetApproval patchSetApproval : copiedApprovals) {
+ addCopiedLabelFooter(msg, patchSetApproval);
}
if (submissionId != null) {
@@ -797,6 +802,47 @@
return cb;
}
+ private void addLabelFooter(StringBuilder msg, Cell<String, Account.Id, Optional<Short>> c) {
+ addFooter(msg, FOOTER_LABEL);
+ // Label names/values are safe to append without sanitizing.
+ if (!c.getValue().isPresent()) {
+ msg.append('-').append(c.getRowKey());
+ } else {
+ msg.append(LabelVote.create(c.getRowKey(), c.getValue().get()).formatWithEquals());
+ }
+ Account.Id id = c.getColumnKey();
+ if (!id.equals(getAccountId())) {
+ noteUtil.appendAccountIdIdentString(msg.append(' '), id);
+ }
+ msg.append('\n');
+ }
+
+ private void addCopiedLabelFooter(StringBuilder msg, PatchSetApproval patchSetApproval) {
+ if (patchSetApproval.value() == 0) {
+ // Can only happen if we removed a vote. There is no need to persist removed votes.
+ return;
+ }
+ addFooter(msg, FOOTER_COPIED_LABEL);
+ // Label names/values are safe to append without sanitizing.
+ msg.append(
+ LabelVote.create(patchSetApproval.label(), patchSetApproval.value()).formatWithEquals());
+ Account.Id id = patchSetApproval.accountId();
+ noteUtil.appendAccountIdIdentString(msg.append(' '), id);
+
+ // In the non-copied labels, we don't need to pass the real account id since it's already
+ // in FOOTER_REAL_USER. Here, we want to retain the original real account id.
+ if (patchSetApproval.realAccountId() != null) {
+ noteUtil.appendAccountIdIdentString(msg.append(","), patchSetApproval.realAccountId());
+ }
+
+ // In the non-copied labels, we don't need to pass the tag since it's already in
+ // FOOTER_TAG, but in this chase we want to retain the original tag, and not the current tag.
+ if (patchSetApproval.tag().isPresent()) {
+ msg.append(":\"" + sanitizeFooter(patchSetApproval.tag().get()) + "\"");
+ }
+ msg.append('\n');
+ }
+
private void clearAttentionSet(String reason) {
if (getNotes().getAttentionSet() == null) {
return;
@@ -992,6 +1038,7 @@
public boolean isEmpty() {
return commitSubject == null
&& approvals.isEmpty()
+ && copiedApprovals.isEmpty()
&& changeMessage == null
&& comments.isEmpty()
&& reviewers.isEmpty()
diff --git a/java/com/google/gerrit/server/notedb/DeleteChangeMessageRewriter.java b/java/com/google/gerrit/server/notedb/DeleteChangeMessageRewriter.java
index e07c793..6d6d53d 100644
--- a/java/com/google/gerrit/server/notedb/DeleteChangeMessageRewriter.java
+++ b/java/com/google/gerrit/server/notedb/DeleteChangeMessageRewriter.java
@@ -110,7 +110,6 @@
* @param commitMessage the full commit message of the new commit.
* @param inserter the {@code ObjectInserter} for the rewrite process.
* @return the {@code objectId} of the new commit.
- * @throws IOException
*/
private ObjectId rewriteOneCommit(
RevCommit originalCommit,
diff --git a/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java b/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
index d0b6247..e8c0fda 100644
--- a/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
+++ b/java/com/google/gerrit/server/notedb/DeleteCommentRewriter.java
@@ -191,8 +191,6 @@
* @param putInComments the comments put in by this commit.
* @param deletedComments the comments deleted by this commit.
* @return the {@code objectId} of the new commit.
- * @throws IOException
- * @throws ConfigInvalidException
*/
private ObjectId rewriteCommit(
RevCommit originalCommit,
diff --git a/java/com/google/gerrit/server/notedb/Sequences.java b/java/com/google/gerrit/server/notedb/Sequences.java
index 7a8e28f..7ae98778 100644
--- a/java/com/google/gerrit/server/notedb/Sequences.java
+++ b/java/com/google/gerrit/server/notedb/Sequences.java
@@ -112,8 +112,11 @@
.setCumulative()
.setUnit(Units.MILLISECONDS),
Field.ofEnum(SequenceType.class, "sequence", Metadata.Builder::noteDbSequenceType)
+ .description("The sequence from which IDs were retrieved.")
.build(),
- Field.ofBoolean("multiple", Metadata.Builder::multiple).build());
+ Field.ofBoolean("multiple", Metadata.Builder::multiple)
+ .description("Whether more than one ID was retrieved.")
+ .build());
}
public int nextAccountId() {
diff --git a/java/com/google/gerrit/server/patch/AutoMerger.java b/java/com/google/gerrit/server/patch/AutoMerger.java
index 97910400..2529c04 100644
--- a/java/com/google/gerrit/server/patch/AutoMerger.java
+++ b/java/com/google/gerrit/server/patch/AutoMerger.java
@@ -100,18 +100,22 @@
MetricMaker metricMaker,
@GerritServerConfig Config cfg,
@GerritPersonIdent Provider<PersonIdent> gerritIdentProvider) {
+ Field<OperationType> operationTypeField =
+ Field.ofEnum(OperationType.class, "type", Metadata.Builder::operationName)
+ .description("The type of the operation (CACHE_LOAD, IN_MEMORY_WRITE, ON_DISK_WRITE).")
+ .build();
this.counter =
metricMaker.newCounter(
"git/auto-merge/num_operations",
new Description("AutoMerge computations").setRate().setUnit("auto merge computations"),
- Field.ofEnum(OperationType.class, "type", Metadata.Builder::operationName).build());
+ operationTypeField);
this.latency =
metricMaker.newTimer(
"git/auto-merge/latency",
new Description("AutoMerge computation latency")
.setCumulative()
.setUnit("milliseconds"),
- Field.ofEnum(OperationType.class, "type", Metadata.Builder::operationName).build());
+ operationTypeField);
this.save = cacheAutomerge(cfg);
this.gerritIdentProvider = gerritIdentProvider;
this.configuredMergeStrategy = MergeUtil.getMergeStrategy(cfg);
diff --git a/java/com/google/gerrit/server/patch/PatchFile.java b/java/com/google/gerrit/server/patch/PatchFile.java
index 3cc89f85..ab92367 100644
--- a/java/com/google/gerrit/server/patch/PatchFile.java
+++ b/java/com/google/gerrit/server/patch/PatchFile.java
@@ -117,7 +117,6 @@
* @param line the line number to extract (1 based; 1 is the first line).
* @return the string version of the file line.
* @throws IOException the patch or complete file content cannot be read.
- * @throws NoSuchEntityException
*/
public String getLine(int file, int line) throws IOException, NoSuchEntityException {
switch (file) {
diff --git a/java/com/google/gerrit/server/patch/PatchList.java b/java/com/google/gerrit/server/patch/PatchList.java
index cb95553..b983fb8 100644
--- a/java/com/google/gerrit/server/patch/PatchList.java
+++ b/java/com/google/gerrit/server/patch/PatchList.java
@@ -140,17 +140,17 @@
return Collections.unmodifiableList(Arrays.asList(patches));
}
- /** @return the comparison type */
+ /** Returns the comparison type */
public ComparisonType getComparisonType() {
return comparisonType;
}
- /** @return total number of new lines added. */
+ /** Returns total number of new lines added. */
public int getInsertions() {
return insertions;
}
- /** @return total number of lines removed. */
+ /** Returns total number of lines removed. */
public int getDeletions() {
return deletions;
}
diff --git a/java/com/google/gerrit/server/patch/PatchScriptFactory.java b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
index 6fa14e1..96b23c8 100644
--- a/java/com/google/gerrit/server/patch/PatchScriptFactory.java
+++ b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
@@ -26,21 +26,13 @@
import com.google.gerrit.entities.Project;
import com.google.gerrit.exceptions.StorageException;
import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.metrics.Counter1;
-import com.google.gerrit.metrics.Description;
-import com.google.gerrit.metrics.Field;
-import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.PatchSetUtil;
-import com.google.gerrit.server.change.FileInfoJsonExperimentImpl;
import com.google.gerrit.server.edit.ChangeEdit;
import com.google.gerrit.server.edit.ChangeEditUtil;
-import com.google.gerrit.server.experiments.ExperimentFeatures;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.LargeObjectException;
-import com.google.gerrit.server.logging.Metadata;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.patch.PatchScriptBuilder.IntraLineDiffCalculatorResult;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
@@ -51,9 +43,7 @@
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectState;
-import com.google.inject.Inject;
import com.google.inject.Provider;
-import com.google.inject.Singleton;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
@@ -88,27 +78,6 @@
CurrentUser currentUser);
}
- /** These metrics are temporary for launching the new redesigned diff cache. */
- @Singleton
- static class Metrics {
- final Counter1<String> diffs;
- static final String MATCH = "match";
- static final String MISMATCH = "mismatch";
- static final String ERROR = "error";
-
- @Inject
- Metrics(MetricMaker metricMaker) {
- diffs =
- metricMaker.newCounter(
- "diff/get_diff/dark_launch",
- new Description(
- "Total number of matching, non-matching, or error in diffs in the old and new diff cache implementations.")
- .setRate()
- .setUnit("count"),
- Field.ofString("type", Metadata.Builder::eventType).build());
- }
- }
-
private final GitRepositoryManager repoManager;
private final PatchSetUtil psUtil;
private final Provider<PatchScriptBuilder> builderFactory;
@@ -130,8 +99,6 @@
private ChangeNotes notes;
- private final boolean runNewDiffCache;
-
@AssistedInject
PatchScriptFactory(
GitRepositoryManager grm,
@@ -139,7 +106,6 @@
Provider<PatchScriptBuilder> builderFactory,
PatchListCache patchListCache,
ChangeEditUtil editReader,
- ExperimentFeatures experimentFeatures,
PermissionBackend permissionBackend,
ProjectCache projectCache,
DiffOperations diffOperations,
@@ -165,10 +131,6 @@
this.psb = patchSetB;
this.diffPrefs = diffPrefs;
this.currentUser = currentUser;
-
- this.runNewDiffCache =
- experimentFeatures.isFeatureEnabled(FileInfoJsonExperimentImpl.NEW_DIFF_CACHE_FEATURE);
-
changeId = patchSetB.changeId();
}
@@ -179,7 +141,6 @@
Provider<PatchScriptBuilder> builderFactory,
PatchListCache patchListCache,
ChangeEditUtil editReader,
- ExperimentFeatures experimentFeatures,
PermissionBackend permissionBackend,
ProjectCache projectCache,
DiffOperations diffOperations,
@@ -205,10 +166,6 @@
this.psb = patchSetB;
this.diffPrefs = diffPrefs;
this.currentUser = currentUser;
-
- this.runNewDiffCache =
- experimentFeatures.isFeatureEnabled(FileInfoJsonExperimentImpl.NEW_DIFF_CACHE_FEATURE);
-
changeId = patchSetB.changeId();
checkArgument(parentNum > 0, "parentNum must be > 0");
}
@@ -246,11 +203,7 @@
}
bId = edit.get().getEditCommit();
}
- return runNewDiffCache
- ? getPatchScriptWithNewDiffCache(git, aId, bId)
- : getPatchScriptWithOldDiffCache(git, aId, bId);
- } catch (PatchListNotAvailableException e) {
- throw new NoSuchChangeException(changeId, e);
+ return getPatchScript(git, aId, bId);
} catch (DiffNotAvailableException e) {
throw new StorageException(e);
} catch (IOException e) {
@@ -268,15 +221,7 @@
}
}
- private PatchScript getPatchScriptWithOldDiffCache(Repository git, ObjectId aId, ObjectId bId)
- throws IOException, PatchListNotAvailableException {
- PatchScriptBuilder patchScriptBuilder = newBuilder();
- PatchList list = listFor(keyFor(aId, bId, diffPrefs.ignoreWhitespace));
- PatchListEntry content = list.get(fileName);
- return patchScriptBuilder.toPatchScriptOld(git, list, content);
- }
-
- private PatchScript getPatchScriptWithNewDiffCache(Repository git, ObjectId aId, ObjectId bId)
+ private PatchScript getPatchScript(Repository git, ObjectId aId, ObjectId bId)
throws IOException, DiffNotAvailableException {
FileDiffOutput fileDiffOutput =
aId == null
@@ -304,17 +249,6 @@
return Optional.of(getCommitId(psb));
}
- private PatchListKey keyFor(ObjectId aId, ObjectId bId, Whitespace whitespace) {
- if (parentNum == 0) {
- return PatchListKey.againstCommit(aId, bId, whitespace);
- }
- return PatchListKey.againstParentNum(parentNum, bId, whitespace);
- }
-
- private PatchList listFor(PatchListKey key) throws PatchListNotAvailableException {
- return patchListCache.get(key, notes.getProjectName());
- }
-
private PatchScriptBuilder newBuilder() {
final PatchScriptBuilder b = builderFactory.get();
b.setDiffPrefs(diffPrefs);
diff --git a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCache.java b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCache.java
index 56f49c9..76d1710 100644
--- a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCache.java
+++ b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCache.java
@@ -35,9 +35,10 @@
public interface ModifiedFilesCache {
/**
+ * Returns the list of {@link ModifiedFile}s between the 2 git commits identified by the key
+ *
* @param key used to identify two git commits and contains other attributes to control the diff
* calculation.
- * @return the list of {@link ModifiedFile}s between the 2 git commits identified by the key.
* @throws DiffNotAvailableException the supplied commits IDs of the key do no exist, are not IDs
* of a commit, or an exception occurred while reading a pack file.
*/
diff --git a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
index 2ac3f5e..4a406c8 100644
--- a/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
+++ b/java/com/google/gerrit/server/patch/diff/ModifiedFilesCacheKey.java
@@ -32,10 +32,10 @@
/** A specific git project / repository. */
public abstract Project.NameKey project();
- /** @return the old commit ID used in the git tree diff */
+ /** Returns the old commit ID used in the git tree diff */
public abstract ObjectId aCommit();
- /** @return the new commit ID used in the git tree diff */
+ /** Returns the new commit ID used in the git tree diff */
public abstract ObjectId bCommit();
/**
diff --git a/java/com/google/gerrit/server/permissions/LabelPermission.java b/java/com/google/gerrit/server/permissions/LabelPermission.java
index 268570c..c266caa 100644
--- a/java/com/google/gerrit/server/permissions/LabelPermission.java
+++ b/java/com/google/gerrit/server/permissions/LabelPermission.java
@@ -71,12 +71,12 @@
this.name = LabelType.checkName(name);
}
- /** @return {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
+ /** Returns {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
public ForUser forUser() {
return forUser;
}
- /** @return name of the label, e.g. {@code "Code-Review"}. */
+ /** Returns name of the label, e.g. {@code "Code-Review"}. */
public String label() {
return name;
}
@@ -199,17 +199,17 @@
this.label = requireNonNull(label, "LabelVote");
}
- /** @return {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
+ /** Returns {@code SELF} or {@code ON_BEHALF_OF} (or labelAs). */
public ForUser forUser() {
return forUser;
}
- /** @return name of the label, e.g. {@code "Code-Review"}. */
+ /** Returns name of the label, e.g. {@code "Code-Review"}. */
public String label() {
return label.label();
}
- /** @return specific value of the label, e.g. 1 or 2. */
+ /** Returns specific value of the label, e.g. 1 or 2. */
public short value() {
return label.value();
}
diff --git a/java/com/google/gerrit/server/permissions/PermissionCollection.java b/java/com/google/gerrit/server/permissions/PermissionCollection.java
index ddba52b..4b8db1c 100644
--- a/java/com/google/gerrit/server/permissions/PermissionCollection.java
+++ b/java/com/google/gerrit/server/permissions/PermissionCollection.java
@@ -277,8 +277,8 @@
}
/**
- * @return true if a "${username}" pattern might need to be expanded to build this collection,
- * making the results user specific.
+ * Returns true if a "${username}" pattern might need to be expanded to build this collection,
+ * making the results user specific.
*/
public boolean isUserSpecific() {
return perUser;
diff --git a/java/com/google/gerrit/server/permissions/ProjectControl.java b/java/com/google/gerrit/server/permissions/ProjectControl.java
index a92fde0..1203049 100644
--- a/java/com/google/gerrit/server/permissions/ProjectControl.java
+++ b/java/com/google/gerrit/server/permissions/ProjectControl.java
@@ -154,8 +154,8 @@
}
/**
- * @return {@code Capable.OK} if the user can upload to at least one reference. Does not check
- * Contributor Agreements.
+ * Returns {@code Capable.OK} if the user can upload to at least one reference. Does not check
+ * Contributor Agreements.
*/
boolean canPushToAtLeastOneRef() {
return canPerformOnAnyRef(Permission.PUSH)
diff --git a/java/com/google/gerrit/server/permissions/RefControl.java b/java/com/google/gerrit/server/permissions/RefControl.java
index f800207..6b51335 100644
--- a/java/com/google/gerrit/server/permissions/RefControl.java
+++ b/java/com/google/gerrit/server/permissions/RefControl.java
@@ -135,19 +135,19 @@
return hasReadPermissionOnRef;
}
- /** @return true if this user can add a new patch set to this ref */
+ /** Returns true if this user can add a new patch set to this ref */
boolean canAddPatchSet() {
return projectControl
.controlForRef(MagicBranch.NEW_CHANGE + refName)
.canPerform(Permission.ADD_PATCH_SET);
}
- /** @return true if this user can rebase changes on this ref */
+ /** Returns true if this user can rebase changes on this ref */
boolean canRebase() {
return canPerform(Permission.REBASE);
}
- /** @return true if this user can submit patch sets to this ref */
+ /** Returns true if this user can submit patch sets to this ref */
boolean canSubmit(boolean isChangeOwner) {
if (RefNames.REFS_CONFIG.equals(refName)) {
// Always allow project owners to submit configuration changes.
@@ -160,12 +160,12 @@
return canPerform(Permission.SUBMIT, isChangeOwner, false);
}
- /** @return true if this user can force edit topic names. */
+ /** Returns true if this user can force edit topic names. */
boolean canForceEditTopicName() {
return canPerform(Permission.EDIT_TOPIC_NAME, false, true);
}
- /** @return true if this user can delete changes. */
+ /** Returns true if this user can delete changes. */
boolean canDeleteChanges(boolean isChangeOwner) {
return canPerform(Permission.DELETE_CHANGES)
|| (isChangeOwner && canPerform(Permission.DELETE_OWN_CHANGES, isChangeOwner, false));
@@ -201,12 +201,12 @@
return canPerform(Permission.REVERT);
}
- /** @return true if this user can submit merge patch sets to this ref */
+ /** Returns true if this user can submit merge patch sets to this ref */
private boolean canUploadMerges() {
return projectControl.controlForRef("refs/for/" + refName).canPerform(Permission.PUSH_MERGE);
}
- /** @return true if the user can update the reference as a fast-forward. */
+ /** Returns true if the user can update the reference as a fast-forward. */
private boolean canUpdate() {
if (RefNames.REFS_CONFIG.equals(refName) && !projectControl.isOwner()) {
// Pushing requires being at least project owner, in addition to push.
@@ -225,7 +225,7 @@
return canPerform(Permission.PUSH);
}
- /** @return true if the user can rewind (force push) the reference. */
+ /** Returns true if the user can rewind (force push) the reference. */
private boolean canForceUpdate() {
if (canPushWithForce()) {
return true;
@@ -281,7 +281,7 @@
}
}
- /** @return true if this user can forge the author line in a commit. */
+ /** Returns true if this user can forge the author line in a commit. */
private boolean canForgeAuthor() {
if (canForgeAuthor == null) {
canForgeAuthor = canPerform(Permission.FORGE_AUTHOR);
@@ -289,7 +289,7 @@
return canForgeAuthor;
}
- /** @return true if this user can forge the committer line in a commit. */
+ /** Returns true if this user can forge the committer line in a commit. */
private boolean canForgeCommitter() {
if (canForgeCommitter == null) {
canForgeCommitter = canPerform(Permission.FORGE_COMMITTER);
@@ -297,7 +297,7 @@
return canForgeCommitter;
}
- /** @return true if this user can forge the server on the committer line. */
+ /** Returns true if this user can forge the server on the committer line. */
private boolean canForgeGerritServerIdentity() {
return canPerform(Permission.FORGE_SERVER);
}
@@ -364,7 +364,9 @@
}
return new PermissionRange(
- permissionName, Math.max(voteMin, blockAllowMin), Math.min(voteMax, blockAllowMax));
+ permissionName,
+ /* min= */ Math.max(voteMin, blockAllowMin),
+ /* max= */ Math.min(voteMax, blockAllowMax));
}
private boolean isBlocked(String permissionName, boolean isChangeOwner, boolean withForce) {
@@ -560,7 +562,8 @@
break;
case FORGE_COMMITTER:
pde.setAdvice(
- "You need 'Forge Committer' rights to push commits with another user as committer.");
+ "You need 'Forge Committer' rights to push commits with another user as"
+ + " committer.");
break;
case FORGE_SERVER:
pde.setAdvice(
diff --git a/java/com/google/gerrit/server/plugincontext/PluginContext.java b/java/com/google/gerrit/server/plugincontext/PluginContext.java
index 3c30745..ef2e181 100644
--- a/java/com/google/gerrit/server/plugincontext/PluginContext.java
+++ b/java/com/google/gerrit/server/plugincontext/PluginContext.java
@@ -121,11 +121,17 @@
@Inject
PluginMetrics(MetricMaker metricMaker) {
Field<String> pluginNameField =
- Field.ofString("plugin_name", Metadata.Builder::pluginName).build();
+ Field.ofString("plugin_name", Metadata.Builder::pluginName)
+ .description("The name of the plugin.")
+ .build();
Field<String> classNameField =
- Field.ofString("class_name", Metadata.Builder::className).build();
+ Field.ofString("class_name", Metadata.Builder::className)
+ .description("The class of the plugin that was invoked.")
+ .build();
Field<String> exportValueField =
- Field.ofString("export_value", Metadata.Builder::exportValue).build();
+ Field.ofString("export_value", Metadata.Builder::exportValue)
+ .description("The export name under which the invoked class is registered.")
+ .build();
this.latency =
metricMaker.newTimer(
diff --git a/java/com/google/gerrit/server/project/ProjectCache.java b/java/com/google/gerrit/server/project/ProjectCache.java
index cd41ce5..fee7105 100644
--- a/java/com/google/gerrit/server/project/ProjectCache.java
+++ b/java/com/google/gerrit/server/project/ProjectCache.java
@@ -42,10 +42,10 @@
return () -> new NoSuchProjectException(nameKey);
}
- /** @return the parent state for all projects on this server. */
+ /** Returns the parent state for all projects on this server. */
ProjectState getAllProjects();
- /** @return the project state of the project storing meta data for all users. */
+ /** Returns the project state of the project storing meta data for all users. */
ProjectState getAllUsers();
/**
@@ -84,12 +84,12 @@
*/
void remove(Project.NameKey name);
- /** @return sorted iteration of projects. */
+ /** Returns sorted iteration of projects. */
ImmutableSortedSet<Project.NameKey> all();
/**
- * @return estimated set of relevant groups extracted from hot project access rules. If the cache
- * is cold or too small for the entire project set of the server, this set may be incomplete.
+ * Returns estimated set of relevant groups extracted from hot project access rules. If the cache
+ * is cold or too small for the entire project set of the server, this set may be incomplete.
*/
Set<AccountGroup.UUID> guessRelevantGroupUUIDs();
diff --git a/java/com/google/gerrit/server/project/ProjectCacheImpl.java b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
index 2874a34..de27afa 100644
--- a/java/com/google/gerrit/server/project/ProjectCacheImpl.java
+++ b/java/com/google/gerrit/server/project/ProjectCacheImpl.java
@@ -345,9 +345,16 @@
refreshCounter =
metricMaker.newCounter(
"caches/refresh_count",
- new Description("count").setRate(),
- Field.ofString("cache", Metadata.Builder::className).build(),
- Field.ofBoolean("outdated", Metadata.Builder::outdated).build());
+ new Description(
+ "The number of refreshes per cache with an indicator if a reload was"
+ + " necessary.")
+ .setRate(),
+ Field.ofString("cache", Metadata.Builder::className)
+ .description("The name of the cache.")
+ .build(),
+ Field.ofBoolean("outdated", Metadata.Builder::outdated)
+ .description("Whether the cache entry was outdated on reload.")
+ .build());
this.allProjectsName = allProjectsName;
this.allProjectsConfigProvider = allProjectsConfigProvider;
}
diff --git a/java/com/google/gerrit/server/project/ProjectConfig.java b/java/com/google/gerrit/server/project/ProjectConfig.java
index a23bb39..513aeed 100644
--- a/java/com/google/gerrit/server/project/ProjectConfig.java
+++ b/java/com/google/gerrit/server/project/ProjectConfig.java
@@ -560,32 +560,32 @@
groupList.renameGroup(uuid, newName);
}
- /** @return the group reference, if the group is used by at least one rule. */
+ /** Returns the group reference, if the group is used by at least one rule. */
public GroupReference getGroup(AccountGroup.UUID uuid) {
return groupList.byUUID(uuid);
}
/**
- * @return the group reference corresponding to the specified group name if the group is used by
- * at least one rule or plugin value.
+ * Returns the group reference corresponding to the specified group name if the group is used by
+ * at least one rule or plugin value.
*/
public GroupReference getGroup(String groupName) {
return groupList.byName(groupName);
}
/**
- * @return the project's rules.pl ObjectId, if present in the branch. Null if it doesn't exist.
+ * Returns the project's rules.pl ObjectId, if present in the branch. Null if it doesn't exist.
*/
public ObjectId getRulesId() {
return rulesId;
}
- /** @return the maxObjectSizeLimit configured on this project, or zero if not configured. */
+ /** Returns the maxObjectSizeLimit configured on this project, or zero if not configured. */
public long getMaxObjectSizeLimit() {
return maxObjectSizeLimit;
}
- /** @return the checkReceivedObjects for this project, default is true. */
+ /** Returns the checkReceivedObjects for this project, default is true. */
public boolean getCheckReceivedObjects() {
return checkReceivedObjects;
}
diff --git a/java/com/google/gerrit/server/project/ProjectState.java b/java/com/google/gerrit/server/project/ProjectState.java
index 4569027..69e6036 100644
--- a/java/com/google/gerrit/server/project/ProjectState.java
+++ b/java/com/google/gerrit/server/project/ProjectState.java
@@ -138,8 +138,8 @@
}
/**
- * @return cached computation of all global capabilities. This should only be invoked on the state
- * from {@link ProjectCache#getAllProjects()}. Null on any other project.
+ * Returns cached computation of all global capabilities. This should only be invoked on the state
+ * from {@link ProjectCache#getAllProjects()}. Null on any other project.
*/
public CapabilityCollection getCapabilityCollection() {
return capabilities;
@@ -316,9 +316,9 @@
}
/**
- * @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
+ * Returns 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.UUID> getOwners() {
for (ProjectState p : tree()) {
@@ -330,10 +330,10 @@
}
/**
- * @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).
+ * Returns 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.UUID> getAllOwners() {
Set<AccountGroup.UUID> result = new HashSet<>();
@@ -346,16 +346,16 @@
}
/**
- * @return an iterable that walks through this project and then the parents of this project.
- * Starts from this project and progresses up the hierarchy to All-Projects.
+ * Returns an iterable that walks through this project and then the parents of this project.
+ * Starts from this project and progresses up the hierarchy to All-Projects.
*/
public Iterable<ProjectState> tree() {
return () -> new ProjectHierarchyIterator(projectCache, allProjectsName, ProjectState.this);
}
/**
- * @return an iterable that walks in-order from All-Projects through the project hierarchy to this
- * project.
+ * Returns an iterable that walks in-order from All-Projects through the project hierarchy to this
+ * project.
*/
public Iterable<ProjectState> treeInOrder() {
List<ProjectState> projects = Lists.newArrayList(tree());
@@ -364,8 +364,8 @@
}
/**
- * @return an iterable that walks through the parents of this project. Starts from the immediate
- * parent of this project and progresses up the hierarchy to All-Projects.
+ * Returns an iterable that walks through the parents of this project. Starts from the immediate
+ * parent of this project and progresses up the hierarchy to All-Projects.
*/
public FluentIterable<ProjectState> parents() {
return FluentIterable.from(tree()).skip(1);
diff --git a/java/com/google/gerrit/server/project/Reachable.java b/java/com/google/gerrit/server/project/Reachable.java
index 2adebe7..342c2bc 100644
--- a/java/com/google/gerrit/server/project/Reachable.java
+++ b/java/com/google/gerrit/server/project/Reachable.java
@@ -55,9 +55,9 @@
}
/**
- * @return true if a commit is reachable from a given set of refs. This method enforces
- * permissions on the given set of refs and performs a reachability check. Tags are not
- * filtered separately and will only be returned if reachable by a provided ref.
+ * Returns true if a commit is reachable from a given set of refs. This method enforces
+ * permissions on the given set of refs and performs a reachability check. Tags are not filtered
+ * separately and will only be returned if reachable by a provided ref.
*/
public boolean fromRefs(
Project.NameKey project, Repository repo, RevCommit commit, List<Ref> refs) {
diff --git a/java/com/google/gerrit/server/project/RefResource.java b/java/com/google/gerrit/server/project/RefResource.java
index ac2735d..fcf6048 100644
--- a/java/com/google/gerrit/server/project/RefResource.java
+++ b/java/com/google/gerrit/server/project/RefResource.java
@@ -22,9 +22,9 @@
super(projectState, user);
}
- /** @return the ref's name */
+ /** Returns the ref's name */
public abstract String getRef();
- /** @return the ref's revision */
+ /** Returns the ref's revision */
public abstract String getRevision();
}
diff --git a/java/com/google/gerrit/server/project/RemoveReviewerControl.java b/java/com/google/gerrit/server/project/RemoveReviewerControl.java
index 652c49f..0336e8e 100644
--- a/java/com/google/gerrit/server/project/RemoveReviewerControl.java
+++ b/java/com/google/gerrit/server/project/RemoveReviewerControl.java
@@ -62,7 +62,7 @@
checkRemoveReviewer(notes, currentUser, reviewer, 0);
}
- /** @return true if the user is allowed to remove this reviewer. */
+ /** Returns true if the user is allowed to remove this reviewer. */
public boolean testRemoveReviewer(
ChangeData cd, CurrentUser currentUser, Account.Id reviewer, int value)
throws PermissionBackendException {
diff --git a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
index 90c3847..f028def 100644
--- a/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
+++ b/java/com/google/gerrit/server/project/SubmitRequirementsAdapter.java
@@ -25,6 +25,7 @@
import com.google.gerrit.entities.SubmitRequirementExpressionResult;
import com.google.gerrit.entities.SubmitRequirementExpressionResult.Status;
import com.google.gerrit.entities.SubmitRequirementResult;
+import com.google.gerrit.server.query.change.ChangeQueryBuilder;
import java.util.List;
import org.eclipse.jgit.lib.ObjectId;
@@ -130,15 +131,18 @@
}
private static ImmutableList<String> toExpressionAtomList(LabelType lt) {
+ String ignoreSelfApproval =
+ lt.isIgnoreSelfApproval() ? ",user=" + ChangeQueryBuilder.ARG_ID_NON_UPLOADER : "";
switch (lt.getFunction()) {
case MAX_WITH_BLOCK:
return ImmutableList.of(
- String.format("label:%s=MAX", lt.getName()),
+ String.format("label:%s=MAX", lt.getName()) + ignoreSelfApproval,
String.format("-label:%s=MIN", lt.getName()));
case ANY_WITH_BLOCK:
return ImmutableList.of(String.format(String.format("-label:%s=MIN", lt.getName())));
case MAX_NO_BLOCK:
- return ImmutableList.of(String.format(String.format("label:%s=MAX", lt.getName())));
+ return ImmutableList.of(
+ String.format(String.format("label:%s=MAX", lt.getName())) + ignoreSelfApproval);
case NO_BLOCK:
case NO_OP:
case PATCH_SET_LOCK:
diff --git a/java/com/google/gerrit/server/project/SubmitRuleEvaluator.java b/java/com/google/gerrit/server/project/SubmitRuleEvaluator.java
index cb8b686..6c5559c 100644
--- a/java/com/google/gerrit/server/project/SubmitRuleEvaluator.java
+++ b/java/com/google/gerrit/server/project/SubmitRuleEvaluator.java
@@ -18,15 +18,19 @@
import static com.google.gerrit.server.project.ProjectCache.noSuchProject;
import com.google.common.collect.Streams;
+import com.google.common.flogger.FluentLogger;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.SubmitRecord;
import com.google.gerrit.entities.SubmitTypeRecord;
import com.google.gerrit.exceptions.StorageException;
+import com.google.gerrit.extensions.api.changes.ChangeApi;
import com.google.gerrit.metrics.Description;
import com.google.gerrit.metrics.Description.Units;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.Timer0;
+import com.google.gerrit.server.change.ChangeJson;
import com.google.gerrit.server.index.OnlineReindexMode;
+import com.google.gerrit.server.logging.CallerFinder;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.rules.DefaultSubmitRule;
@@ -42,12 +46,15 @@
* the results through rules found in the parent projects, all the way up to All-Projects.
*/
public class SubmitRuleEvaluator {
+ private static final FluentLogger logger = FluentLogger.forEnclosingClass();
+
private final ProjectCache projectCache;
private final PrologRule prologRule;
private final PluginSetContext<SubmitRule> submitRules;
private final Timer0 submitRuleEvaluationLatency;
private final Timer0 submitTypeEvaluationLatency;
private final SubmitRuleOptions opts;
+ private final CallerFinder callerFinder;
public interface Factory {
/** Returns a new {@link SubmitRuleEvaluator} with the specified options */
@@ -78,6 +85,14 @@
.setUnit(Units.MILLISECONDS));
this.opts = options;
+
+ this.callerFinder =
+ CallerFinder.builder()
+ .addTarget(ChangeApi.class)
+ .addTarget(ChangeJson.class)
+ .addTarget(ChangeData.class)
+ .addTarget(SubmitRequirementsEvaluatorImpl.class)
+ .build();
}
/**
@@ -88,6 +103,9 @@
* @param cd ChangeData to evaluate
*/
public List<SubmitRecord> evaluate(ChangeData cd) {
+ logger.atFine().log(
+ "Evaluate submit rules for change %d (caller: %s)",
+ cd.change().getId().get(), callerFinder.findCallerLazy());
try (Timer0.Context ignored = submitRuleEvaluationLatency.start()) {
Change change;
ProjectState projectState;
@@ -146,7 +164,6 @@
* Evaluate the submit type rules to get the submit type.
*
* @return record from the evaluated rules.
- * @param cd
*/
public SubmitTypeRecord getSubmitType(ChangeData cd) {
try (Timer0.Context ignored = submitTypeEvaluationLatency.start()) {
diff --git a/java/com/google/gerrit/server/query/approval/ApprovalContext.java b/java/com/google/gerrit/server/query/approval/ApprovalContext.java
index 3bf072a..4dedbb5 100644
--- a/java/com/google/gerrit/server/query/approval/ApprovalContext.java
+++ b/java/com/google/gerrit/server/query/approval/ApprovalContext.java
@@ -28,8 +28,12 @@
/** Approval on the source patch set to be copied. */
public abstract PatchSetApproval patchSetApproval();
- /** Target change and patch set for the approval. */
- public abstract PatchSet.Id target();
+ /**
+ * Target change and patch set for the approval. This must be used instead of getting the PatchSet
+ * from {@link #changeNotes()} because it is possible we are now creating the patch-set, so it
+ * doesn't exist in changeNotes yet.
+ */
+ public abstract PatchSet target();
/** {@link ChangeNotes} of the change in question. */
public abstract ChangeNotes changeNotes();
@@ -38,18 +42,18 @@
public abstract ChangeKind changeKind();
public static ApprovalContext create(
- ChangeNotes changeNotes, PatchSetApproval psa, PatchSet.Id id, ChangeKind changeKind) {
+ ChangeNotes changeNotes, PatchSetApproval psa, PatchSet patchSet, ChangeKind changeKind) {
checkState(
- psa.patchSetId().changeId().equals(id.changeId()),
+ psa.patchSetId().changeId().equals(patchSet.id().changeId()),
"approval and target must be the same change. got: %s, %s",
psa.patchSetId(),
- id);
+ patchSet.id());
// TODO(ekempin): Use checkState to verify that psa.patchSetId().get() + 1 == id.get() so that
// it's ensured that approvals are only copied to the next consecutive patch set. To add back
// this verification https://gerrit-review.googlesource.com/c/gerrit/+/312633 can be reverted.
// As explained in the commit message of this change doing this check is only possible if there
// are no changes with gaps in patch set numbers. Since it's planned to fix-up old changes with
// gaps in patch set numbers, this todo is a reminder to add back the check once this is done.
- return new AutoValue_ApprovalContext(psa, id, changeNotes, changeKind);
+ return new AutoValue_ApprovalContext(psa, patchSet, changeNotes, changeKind);
}
}
diff --git a/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java b/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
index ec658ac..55c27be 100644
--- a/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
+++ b/java/com/google/gerrit/server/query/approval/ListOfFilesUnchangedPredicate.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.approval;
+import com.google.gerrit.entities.Patch;
import com.google.gerrit.entities.Patch.ChangeType;
import com.google.gerrit.entities.PatchSet;
import com.google.gerrit.entities.Project;
@@ -27,8 +28,10 @@
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
+import java.util.HashSet;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevWalk;
@@ -48,7 +51,7 @@
@Override
public boolean match(ApprovalContext ctx) {
- PatchSet targetPatchSet = ctx.changeNotes().getPatchSets().get(ctx.target());
+ PatchSet targetPatchSet = ctx.target();
PatchSet sourcePatchSet =
ctx.changeNotes().getPatchSets().get(ctx.patchSetApproval().patchSetId());
@@ -77,13 +80,16 @@
*/
public boolean match(
Map<String, FileDiffOutput> modifiedFiles1, Map<String, FileDiffOutput> modifiedFiles2) {
- if (modifiedFiles1.size() != modifiedFiles2.size()) {
- return false;
- }
- for (String file : modifiedFiles1.keySet()) {
+ Set<String> allFiles = new HashSet<>();
+ allFiles.addAll(modifiedFiles1.keySet());
+ allFiles.addAll(modifiedFiles2.keySet());
+ for (String file : allFiles) {
+ if (Patch.isMagic(file)) {
+ continue;
+ }
FileDiffOutput fileDiffOutput1 = modifiedFiles1.get(file);
FileDiffOutput fileDiffOutput2 = modifiedFiles2.get(file);
- if (fileDiffOutput2 == null) {
+ if (fileDiffOutput1 == null || fileDiffOutput2 == null) {
return false;
}
if (!fileDiffOutput2.changeType().equals(fileDiffOutput1.changeType())) {
diff --git a/java/com/google/gerrit/server/query/approval/UserInPredicate.java b/java/com/google/gerrit/server/query/approval/UserInPredicate.java
index 7e16fcb..ac6720d 100644
--- a/java/com/google/gerrit/server/query/approval/UserInPredicate.java
+++ b/java/com/google/gerrit/server/query/approval/UserInPredicate.java
@@ -39,7 +39,7 @@
public boolean match(ApprovalContext ctx) {
Account.Id accountId;
if (field == Field.UPLOADER) {
- PatchSet patchSet = ctx.changeNotes().getPatchSets().get(ctx.target());
+ PatchSet patchSet = ctx.target();
accountId = patchSet.uploader();
} else if (field == Field.APPROVER) {
accountId = ctx.patchSetApproval().accountId();
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 5b83dd5..6c74301 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -728,7 +728,7 @@
this.attentionSet = attentionSet;
}
- /** @return patches for the change, in patch set ID order. */
+ /** Returns patches for the change, in patch set ID order. */
public Collection<PatchSet> patchSets() {
if (patchSets == null) {
patchSets = psUtil.byChange(notes());
@@ -741,7 +741,7 @@
this.patchSets = patchSets;
}
- /** @return patch with the given ID, or null if it does not exist. */
+ /** Returns patch with the given ID, or null if it does not exist. */
public PatchSet patchSet(PatchSet.Id psId) {
if (currentPatchSet != null && currentPatchSet.id().equals(psId)) {
return currentPatchSet;
@@ -755,8 +755,8 @@
}
/**
- * @return all patch set approvals for the change, keyed by ID, ordered by timestamp within each
- * patch set.
+ * Returns all patch set approvals for the change, keyed by ID, ordered by timestamp within each
+ * patch set.
*/
public ListMultimap<PatchSet.Id, PatchSetApproval> approvals() {
if (allApprovals == null) {
@@ -1199,8 +1199,8 @@
}
/**
- * @return {@code null} if {@code revertOf} is {@code null}; true if the change is a pure revert;
- * false otherwise.
+ * Returns {@code null} if {@code revertOf} is {@code null}; true if the change is a pure revert;
+ * false otherwise.
*/
@Nullable
public Boolean isPureRevert() {
diff --git a/java/com/google/gerrit/server/query/change/ChangeDataSource.java b/java/com/google/gerrit/server/query/change/ChangeDataSource.java
index 34579a9..26ce46c 100644
--- a/java/com/google/gerrit/server/query/change/ChangeDataSource.java
+++ b/java/com/google/gerrit/server/query/change/ChangeDataSource.java
@@ -17,6 +17,6 @@
import com.google.gerrit.index.query.DataSource;
public interface ChangeDataSource extends DataSource<ChangeData> {
- /** @return true if all returned ChangeData.hasChange() will be true. */
+ /** Returns true if all returned ChangeData.hasChange() will be true. */
boolean hasChange();
}
diff --git a/java/com/google/gerrit/server/query/change/LabelPredicate.java b/java/com/google/gerrit/server/query/change/LabelPredicate.java
index 989b4bb..5f017fb 100644
--- a/java/com/google/gerrit/server/query/change/LabelPredicate.java
+++ b/java/com/google/gerrit/server/query/change/LabelPredicate.java
@@ -87,7 +87,7 @@
try {
MagicLabelVote mlv = MagicLabelVote.parseWithEquals(v);
- return ImmutableList.of(new MagicLabelPredicate(args, mlv));
+ return ImmutableList.of(magicLabelPredicate(args, mlv));
} catch (IllegalArgumentException e) {
// Try next format.
}
@@ -157,6 +157,17 @@
return or(r);
}
+ protected static Predicate<ChangeData> magicLabelPredicate(Args args, MagicLabelVote mlv) {
+ if (args.accounts == null || args.accounts.isEmpty()) {
+ return new MagicLabelPredicate(args, mlv, /* account= */ null);
+ }
+ List<Predicate<ChangeData>> r = new ArrayList<>();
+ for (Account.Id a : args.accounts) {
+ r.add(new MagicLabelPredicate(args, mlv, a));
+ }
+ return or(r);
+ }
+
@Override
public String toString() {
return ChangeQueryBuilder.FIELD_LABEL + ":" + value;
diff --git a/java/com/google/gerrit/server/query/change/MagicLabelPredicate.java b/java/com/google/gerrit/server/query/change/MagicLabelPredicate.java
index 2c56322..3917c79 100644
--- a/java/com/google/gerrit/server/query/change/MagicLabelPredicate.java
+++ b/java/com/google/gerrit/server/query/change/MagicLabelPredicate.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.query.change;
+import com.google.gerrit.entities.Account;
import com.google.gerrit.entities.Change;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.LabelTypes;
@@ -28,9 +29,12 @@
public class MagicLabelPredicate extends ChangeIndexPredicate {
protected final LabelPredicate.Args args;
private final MagicLabelVote magicLabelVote;
+ private final Account.Id account;
- public MagicLabelPredicate(LabelPredicate.Args args, MagicLabelVote magicLabelVote) {
+ public MagicLabelPredicate(
+ LabelPredicate.Args args, MagicLabelVote magicLabelVote, Account.Id account) {
super(ChangeField.LABEL, magicLabelVote.formatLabel());
+ this.account = account;
this.args = args;
this.magicLabelVote = magicLabelVote;
}
@@ -83,7 +87,7 @@
}
private EqualsLabelPredicate numericPredicate(String label, short value) {
- return new EqualsLabelPredicate(args, label, value, /* account= */ null);
+ return new EqualsLabelPredicate(args, label, value, account);
}
protected static LabelType type(LabelTypes types, String toFind) {
diff --git a/java/com/google/gerrit/server/query/change/PredicateArgs.java b/java/com/google/gerrit/server/query/change/PredicateArgs.java
index ad7917e..d82b9bc 100644
--- a/java/com/google/gerrit/server/query/change/PredicateArgs.java
+++ b/java/com/google/gerrit/server/query/change/PredicateArgs.java
@@ -40,7 +40,6 @@
* name]}.
*
* @param args arguments to be parsed
- * @throws QueryParseException
*/
PredicateArgs(String args) throws QueryParseException {
positional = new ArrayList<>();
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index 94dc21f..5002a82 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -170,7 +170,11 @@
+ "selected by users while posting a review.")
.setRate()
.setUnit("count"),
- Field.ofString("type", Metadata.Builder::eventType).build());
+ Field.ofString("type", Metadata.Builder::eventType)
+ .description(
+ "The type of the draft handling option"
+ + " (KEEP, PUBLISH, PUBLISH_ALL_REVISIONS).")
+ .build());
}
}
diff --git a/java/com/google/gerrit/server/restapi/project/CheckAccess.java b/java/com/google/gerrit/server/restapi/project/CheckAccess.java
index 37616cd..5c2f932 100644
--- a/java/com/google/gerrit/server/restapi/project/CheckAccess.java
+++ b/java/com/google/gerrit/server/restapi/project/CheckAccess.java
@@ -95,7 +95,6 @@
} catch (AuthException e) {
return Response.ok(
createInfo(
- traceContext,
HttpServletResponse.SC_FORBIDDEN,
String.format("user %s cannot see project %s", match, rsrc.getName())));
}
@@ -126,7 +125,6 @@
} catch (AuthException e) {
return Response.ok(
createInfo(
- traceContext,
HttpServletResponse.SC_FORBIDDEN,
String.format(
"user %s lacks permission %s for %s in project %s",
@@ -141,15 +139,15 @@
}
}
}
- return Response.ok(createInfo(traceContext, HttpServletResponse.SC_OK, message));
+ return Response.ok(createInfo(HttpServletResponse.SC_OK, message));
}
}
- private AccessCheckInfo createInfo(TraceContext traceContext, int statusCode, String message) {
+ private AccessCheckInfo createInfo(int statusCode, String message) {
AccessCheckInfo info = new AccessCheckInfo();
info.status = statusCode;
info.message = message;
- info.debugLogs = traceContext.getAclLogRecords();
+ info.debugLogs = TraceContext.getAclLogRecords();
if (info.debugLogs.isEmpty()) {
info.debugLogs =
ImmutableList.of("Found no rules that apply, so defaulting to no permission");
diff --git a/java/com/google/gerrit/server/restapi/project/CommitsCollection.java b/java/com/google/gerrit/server/restapi/project/CommitsCollection.java
index ae7f540..09951b2 100644
--- a/java/com/google/gerrit/server/restapi/project/CommitsCollection.java
+++ b/java/com/google/gerrit/server/restapi/project/CommitsCollection.java
@@ -116,14 +116,14 @@
}
/**
- * @return true if {@code commit} is visible to the caller and {@code commit} is reachable from
- * the given branch.
+ * Returns true if {@code commit} is visible to the caller and {@code commit} is reachable from
+ * the given branch.
*/
public boolean canRead(ProjectState state, Repository repo, RevCommit commit, Ref ref) {
return reachable.fromRefs(state.getNameKey(), repo, commit, ImmutableList.of(ref));
}
- /** @return true if {@code commit} is visible to the caller. */
+ /** Returns true if {@code commit} is visible to the caller. */
public boolean canRead(ProjectState state, Repository repo, RevCommit commit) throws IOException {
Project.NameKey project = state.getNameKey();
if (indexes.getSearchIndex() == null) {
diff --git a/java/com/google/gerrit/server/restapi/project/DeleteRef.java b/java/com/google/gerrit/server/restapi/project/DeleteRef.java
index 4e13ba9..60405a6 100644
--- a/java/com/google/gerrit/server/restapi/project/DeleteRef.java
+++ b/java/com/google/gerrit/server/restapi/project/DeleteRef.java
@@ -86,8 +86,6 @@
*
* @param projectState the {@code ProjectState} of the project containing the target ref.
* @param ref the ref to be deleted.
- * @throws IOException
- * @throws ResourceConflictException
*/
public void deleteSingleRef(ProjectState projectState, String ref)
throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
@@ -100,8 +98,6 @@
* @param projectState the {@code ProjectState} of the project containing the target ref.
* @param ref the ref to be deleted.
* @param prefix the prefix of the ref.
- * @throws IOException
- * @throws ResourceConflictException
*/
public void deleteSingleRef(ProjectState projectState, String ref, @Nullable String prefix)
throws IOException, ResourceConflictException, AuthException, PermissionBackendException {
@@ -161,9 +157,6 @@
* @param projectState the {@code ProjectState} of the project whose refs are to be deleted.
* @param refsToDelete the refs to be deleted.
* @param prefix the prefix to add to abbreviated refs, eg. "refs/heads/".
- * @throws IOException
- * @throws ResourceConflictException
- * @throws PermissionBackendException
*/
public void deleteMultipleRefs(
ProjectState projectState, ImmutableSet<String> refsToDelete, String prefix)
diff --git a/java/com/google/gerrit/server/restapi/project/ProjectsCollection.java b/java/com/google/gerrit/server/restapi/project/ProjectsCollection.java
index efc739c..6174798 100644
--- a/java/com/google/gerrit/server/restapi/project/ProjectsCollection.java
+++ b/java/com/google/gerrit/server/restapi/project/ProjectsCollection.java
@@ -105,7 +105,6 @@
* @throws RestApiException thrown if the project ID cannot be resolved or if the project is not
* visible to the calling user
* @throws IOException thrown when there is an error.
- * @throws PermissionBackendException
*/
public ProjectResource parse(String id)
throws RestApiException, IOException, PermissionBackendException {
@@ -121,7 +120,6 @@
* @throws RestApiException thrown if the project ID cannot be resolved or if the project is not
* visible to the calling user and checkVisibility is true.
* @throws IOException thrown when there is an error.
- * @throws PermissionBackendException
*/
public ProjectResource parse(String id, boolean checkAccess)
throws RestApiException, IOException, PermissionBackendException {
diff --git a/java/com/google/gerrit/server/securestore/SecureStore.java b/java/com/google/gerrit/server/securestore/SecureStore.java
index b5aebee..b53e38c 100644
--- a/java/com/google/gerrit/server/securestore/SecureStore.java
+++ b/java/com/google/gerrit/server/securestore/SecureStore.java
@@ -39,13 +39,7 @@
public final String section;
public final String subsection;
- /**
- * Creates EntryKey.
- *
- * @param section
- * @param subsection
- * @param name
- */
+ /** Creates EntryKey */
public EntryKey(String section, String subsection, String name) {
this.name = name;
this.section = section;
@@ -57,9 +51,6 @@
* Extract decrypted value of stored property from SecureStore or {@code null} when property was
* not found.
*
- * @param section
- * @param subsection
- * @param name
* @return decrypted String value or {@code null} if not found
*/
public final String get(String section, String subsection, String name) {
@@ -74,10 +65,6 @@
* Extract decrypted value of stored plugin config property from SecureStore or {@code null} when
* property was not found.
*
- * @param pluginName
- * @param section
- * @param subsection
- * @param name
* @return decrypted String value or {@code null} if not found
*/
public final String getForPlugin(
@@ -93,10 +80,6 @@
* Extract list of plugin config values from SecureStore and decrypt every value in that list, or
* {@code null} when property was not found.
*
- * @param pluginName
- * @param section
- * @param subsection
- * @param name
* @return decrypted list of string values or {@code null}
*/
public abstract String[] getListForPlugin(
@@ -106,9 +89,6 @@
* Extract list of values from SecureStore and decrypt every value in that list or {@code null}
* when property was not found.
*
- * @param section
- * @param subsection
- * @param name
* @return decrypted list of string values or {@code null}
*/
public abstract String[] getList(String section, String subsection, String name);
@@ -118,9 +98,6 @@
*
* <p>This method is responsible for encrypting value and storing it.
*
- * @param section
- * @param subsection
- * @param name
* @param value plain text value
*/
public final void set(String section, String subsection, String name, String value) {
@@ -132,26 +109,19 @@
*
* <p>This method is responsible for encrypting all values in the list and storing them.
*
- * @param section
- * @param subsection
- * @param name
* @param values list of plain text values
*/
public abstract void setList(String section, String subsection, String name, List<String> values);
/**
* Remove value for given {@code section}, {@code subsection} and {@code name} from SecureStore.
- *
- * @param section
- * @param subsection
- * @param name
*/
public abstract void unset(String section, String subsection, String name);
- /** @return list of stored entries. */
+ /** Returns list of stored entries. */
public abstract Iterable<EntryKey> list();
- /** @return <code>true</code> if currently loaded values are outdated */
+ /** Returns <code>true</code> if currently loaded values are outdated */
public abstract boolean isOutdated();
/** Reload the values */
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
index f181c36..7d428eb 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
@@ -521,32 +521,22 @@
}
}
- /**
- * @see #updateRepo(RepoContext)
- * @param ctx
- */
+ /** See {@link #updateRepo(RepoContext)} */
protected void updateRepoImpl(RepoContext ctx) throws Exception {}
/**
- * @see #updateChange(ChangeContext)
- * @param ctx
- * @return a new patch set if one was created by the submit strategy, or null if not.
+ * Returns a new patch set if one was created by the submit strategy, or null if not
+ *
+ * <p>See {@link #updateChange(ChangeContext)}
*/
protected PatchSet updateChangeImpl(ChangeContext ctx) throws Exception {
return null;
}
- /**
- * @see #postUpdate(PostUpdateContext)
- * @param ctx
- */
+ /** See {@link #postUpdate(PostUpdateContext)} */
protected void postUpdateImpl(PostUpdateContext ctx) throws Exception {}
- /**
- * Amend the commit with gitlink update
- *
- * @param commit
- */
+ /** Amend the commit with gitlink update */
protected CodeReviewCommit amendGitlink(CodeReviewCommit commit)
throws IntegrationConflictException {
if (!args.subscriptionGraph.hasSubscription(args.destBranch)) {
diff --git a/java/com/google/gerrit/server/tools/ToolsCatalog.java b/java/com/google/gerrit/server/tools/ToolsCatalog.java
index aaa366c..9c1483f 100644
--- a/java/com/google/gerrit/server/tools/ToolsCatalog.java
+++ b/java/com/google/gerrit/server/tools/ToolsCatalog.java
@@ -175,28 +175,28 @@
return type;
}
- /** @return the preferred UNIX file mode, e.g. {@code 0755}. */
+ /** Returns the preferred UNIX file mode, e.g. {@code 0755}. */
public int getMode() {
return mode;
}
- /** @return path of the entry, relative to the catalog root. */
+ /** Returns path of the entry, relative to the catalog root. */
public String getPath() {
return path;
}
- /** @return name of the entry, within its parent directory. */
+ /** Returns the name of the entry, within its parent directory. */
public String getName() {
final int s = path.lastIndexOf('/');
return s < 0 ? path : path.substring(s + 1);
}
- /** @return collection of entries below this one, if this is a directory. */
+ /** Returns collection of entries below this one, if this is a directory. */
public List<Entry> getChildren() {
return Collections.unmodifiableList(children);
}
- /** @return a copy of the file's contents. */
+ /** Returns a copy of the file's contents. */
public byte[] getBytes() {
byte[] data = read(getPath());
diff --git a/java/com/google/gerrit/server/update/ChainedReceiveCommands.java b/java/com/google/gerrit/server/update/ChainedReceiveCommands.java
index c223aec..99c72f2 100644
--- a/java/com/google/gerrit/server/update/ChainedReceiveCommands.java
+++ b/java/com/google/gerrit/server/update/ChainedReceiveCommands.java
@@ -118,7 +118,7 @@
}
}
- /** @return an unmodifiable view of commands. */
+ /** Returns an unmodifiable view of commands. */
public Map<String, ReceiveCommand> getCommands() {
return Collections.unmodifiableMap(commands);
}
diff --git a/java/com/google/gerrit/server/update/ChangeContext.java b/java/com/google/gerrit/server/update/ChangeContext.java
index 5a53e2a..aeabde4 100644
--- a/java/com/google/gerrit/server/update/ChangeContext.java
+++ b/java/com/google/gerrit/server/update/ChangeContext.java
@@ -69,7 +69,7 @@
*/
void deleteChange();
- /** @return change corresponding to {@link #getNotes()}. */
+ /** Returns change corresponding to {@link #getNotes()}. */
default Change getChange() {
return requireNonNull(getNotes().getChange());
}
diff --git a/java/com/google/gerrit/server/update/RepoContext.java b/java/com/google/gerrit/server/update/RepoContext.java
index 9faf628..66831cd 100644
--- a/java/com/google/gerrit/server/update/RepoContext.java
+++ b/java/com/google/gerrit/server/update/RepoContext.java
@@ -22,9 +22,9 @@
/** Context for performing the {@link BatchUpdateOp#updateRepo} phase. */
public interface RepoContext extends Context {
/**
- * @return inserter for writing to the repo. Callers should not flush; the walk returned by {@link
- * #getRevWalk()} is able to read back objects inserted by this inserter without flushing
- * first.
+ * Returns inserter for writing to the repo. Callers should not flush; the walk returned by {@link
+ * #getRevWalk()} is able to read back objects inserted by this inserter without flushing first.
+ *
* @throws IOException if an error occurred opening the repo.
*/
ObjectInserter getInserter() throws IOException;
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index 2249b0e..7e6974c 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -121,7 +121,9 @@
@Inject
Metrics(MetricMaker metricMaker) {
Field<String> actionTypeField =
- Field.ofString("action_type", Metadata.Builder::actionType).build();
+ Field.ofString("action_type", Metadata.Builder::actionType)
+ .description("The type of the action that was retried.")
+ .build();
Field<String> operationNameField =
Field.ofString("operation_name", Metadata.Builder::operationName)
.description("The name of the operation that was retried.")
@@ -479,7 +481,7 @@
}
String cause = formatCause(t);
- if (!traceContext.isTracing()) {
+ if (!TraceContext.isTracing()) {
String traceId = "retry-on-failure-" + new RequestId();
traceContext.addTag(RequestId.Type.TRACE_ID, traceId).forceLogging();
logger.atWarning().withCause(t).log(
diff --git a/java/com/google/gerrit/server/util/RequestScopePropagator.java b/java/com/google/gerrit/server/util/RequestScopePropagator.java
index dc8a136..10c46fc 100644
--- a/java/com/google/gerrit/server/util/RequestScopePropagator.java
+++ b/java/com/google/gerrit/server/util/RequestScopePropagator.java
@@ -160,7 +160,11 @@
};
}
- /** @see #wrap(Callable) */
+ /**
+ * Ensures that the current request state is available when the passed in Callable is invoked
+ *
+ * <p>See {@link #wrap(Callable)}
+ */
protected abstract <T> Callable<T> wrapImpl(Callable<T> callable);
protected <T> Callable<T> context(RequestContext context, Callable<T> callable) {
diff --git a/java/com/google/gerrit/sshd/SshLog.java b/java/com/google/gerrit/sshd/SshLog.java
index 616f7d1..7c96342 100644
--- a/java/com/google/gerrit/sshd/SshLog.java
+++ b/java/com/google/gerrit/sshd/SshLog.java
@@ -92,7 +92,7 @@
}
}
- /** @return true if a change in state has occurred */
+ /** Returns true if a change in state has occurred */
public boolean enableLogging() {
synchronized (lock) {
if (async == null) {
@@ -112,7 +112,7 @@
}
}
- /** @return true if a change in state has occurred */
+ /** Returns true if a change in state has occurred */
public boolean disableLogging() {
synchronized (lock) {
if (async != null) {
diff --git a/java/com/google/gerrit/sshd/SshSession.java b/java/com/google/gerrit/sshd/SshSession.java
index b39eaed..d545844 100644
--- a/java/com/google/gerrit/sshd/SshSession.java
+++ b/java/com/google/gerrit/sshd/SshSession.java
@@ -114,7 +114,7 @@
identity.setAccessPath(path);
}
- /** @return {@code true} if the authentication did not succeed. */
+ /** Returns {@code true} if the authentication did not succeed. */
boolean isAuthenticationError() {
return authError != null;
}
diff --git a/java/com/google/gerrit/util/http/RequestUtil.java b/java/com/google/gerrit/util/http/RequestUtil.java
index 92d9967..f64ce5a 100644
--- a/java/com/google/gerrit/util/http/RequestUtil.java
+++ b/java/com/google/gerrit/util/http/RequestUtil.java
@@ -31,8 +31,8 @@
}
/**
- * @return the same value as {@link HttpServletRequest#getPathInfo()}, but without decoding
- * URL-encoded characters.
+ * Returns the same value as {@link HttpServletRequest#getPathInfo()}, but without decoding
+ * URL-encoded characters.
*/
public static String getEncodedPathInfo(HttpServletRequest req) {
// CS IGNORE LineLength FOR NEXT 3 LINES. REASON: URL.
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 95a8950..ac67444 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -4059,6 +4059,46 @@
}
@Test
+ public void submitRequirement_withLabelEqualsMax_fromNonUploader() throws Exception {
+ configLabel("my-label", LabelFunction.NO_OP); // label function has no effect
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(allowLabel("my-label").ref("refs/heads/master").group(REGISTERED_USERS).range(-1, 1))
+ .update();
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("my-label")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create("label:my-label=MAX,user=non_uploader"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ PushOneCommit.Result r = createChange();
+ String changeId = r.getChangeId();
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Voting with a max vote as the uploader will not satisfy the submit requirement.
+ voteLabel(changeId, "my-label", 1);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Voting as a non-uploader will satisfy the submit requirement.
+ requestScopeOperations.setApiUser(user.id());
+ voteLabel(changeId, "my-label", 1);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.SATISFIED, /* isLegacy= */ false);
+ }
+
+ @Test
public void submitRequirement_withLabelEqualsMinBlockingSubmission() throws Exception {
configSubmitRequirement(
project,
@@ -4094,6 +4134,54 @@
}
@Test
+ public void submitRequirement_withMaxWithBlock_ignoringSelfApproval() throws Exception {
+ configLabel("my-label", LabelFunction.MAX_WITH_BLOCK);
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(allowLabel("my-label").ref("refs/heads/master").group(REGISTERED_USERS).range(-1, 1))
+ .update();
+
+ configSubmitRequirement(
+ project,
+ SubmitRequirement.builder()
+ .setName("my-label")
+ .setSubmittabilityExpression(
+ SubmitRequirementExpression.create(
+ "label:my-label=MAX,user=non_uploader -label:my-label=MIN"))
+ .setAllowOverrideInChildProjects(false)
+ .build());
+
+ // Create the change as admin
+ requestScopeOperations.setApiUser(admin.id());
+ PushOneCommit.Result r = createChange();
+ String changeId = r.getChangeId();
+
+ // Admin (a.k.a uploader) adds a -1 min vote. This is going to block submission.
+ voteLabel(changeId, "my-label", -1);
+ ChangeInfo change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // user (i.e. non_uploader) votes 1. Requirement is still blocking because of -1 of uploader.
+ requestScopeOperations.setApiUser(user.id());
+ voteLabel(changeId, "my-label", 1);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.UNSATISFIED, /* isLegacy= */ false);
+
+ // Admin (a.k.a uploader) removes -1. Now requirement is fulfilled.
+ requestScopeOperations.setApiUser(admin.id());
+ voteLabel(changeId, "my-label", 0);
+ change = gApi.changes().id(changeId).get();
+ assertThat(change.submitRequirements).hasSize(1);
+ assertSubmitRequirementStatus(
+ change.submitRequirements, "my-label", Status.SATISFIED, /* isLegacy= */ false);
+ }
+
+ @Test
public void submitRequirement_withLabelEqualsAny() throws Exception {
configSubmitRequirement(
project,
diff --git a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
index f966fc8..cd9e876 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/StickyApprovalsIT.java
@@ -14,6 +14,7 @@
package com.google.gerrit.acceptance.api.change;
+import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
import static com.google.gerrit.acceptance.testsuite.project.TestProjectUpdate.allowLabel;
@@ -28,9 +29,11 @@
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static com.google.gerrit.server.project.testing.TestLabels.labelBuilder;
import static com.google.gerrit.server.project.testing.TestLabels.value;
+import static java.util.Comparator.comparing;
import com.google.common.cache.Cache;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.AbstractDaemonTest;
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
@@ -44,17 +47,21 @@
import com.google.gerrit.entities.LabelId;
import com.google.gerrit.entities.LabelType;
import com.google.gerrit.entities.PatchSet;
+import com.google.gerrit.entities.PatchSetApproval;
import com.google.gerrit.entities.RefNames;
import com.google.gerrit.extensions.api.changes.ReviewInput;
+import com.google.gerrit.extensions.api.changes.RevisionApi;
import com.google.gerrit.extensions.client.ChangeKind;
import com.google.gerrit.extensions.common.ApprovalInfo;
import com.google.gerrit.extensions.common.ChangeInfo;
+import com.google.gerrit.extensions.common.FileInfo;
import com.google.gerrit.server.change.ChangeKindCacheImpl;
import com.google.gerrit.server.project.testing.TestLabels;
import com.google.inject.Inject;
import com.google.inject.name.Named;
import java.util.EnumSet;
import java.util.HashMap;
+import java.util.List;
import java.util.Map;
import java.util.Set;
import org.eclipse.jgit.lib.ObjectId;
@@ -902,6 +909,52 @@
}
@Test
+ public void copyWithListOfFilesUnchangedButAddedMergeList() throws Exception {
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig()
+ .updateLabelType(LabelId.CODE_REVIEW, b -> b.setCopyCondition("has:unchanged-files"));
+ u.save();
+ }
+ Change.Id parent1ChangeId = changeOperations.newChange().create();
+ Change.Id parent2ChangeId = changeOperations.newChange().create();
+ Change.Id dummyParentChangeId = changeOperations.newChange().create();
+ Change.Id changeId =
+ changeOperations
+ .newChange()
+ .mergeOf()
+ .change(parent1ChangeId)
+ .and()
+ .change(parent2ChangeId)
+ .create();
+
+ Map<String, FileInfo> changedFilesFirstPatchset =
+ gApi.changes().id(changeId.get()).current().files();
+
+ assertThat(changedFilesFirstPatchset.keySet()).containsExactly("/COMMIT_MSG", "/MERGE_LIST");
+
+ // Make a Code-Review vote that should be sticky.
+ gApi.changes().id(changeId.get()).current().review(ReviewInput.approve());
+
+ changeOperations
+ .change(changeId)
+ .newPatchset()
+ .parent()
+ .patchset(PatchSet.id(dummyParentChangeId, 1))
+ .create();
+
+ Map<String, FileInfo> changedFilesSecondPatchset =
+ gApi.changes().id(changeId.get()).current().files();
+
+ // Only "/MERGE_LIST" was removed.
+ assertThat(changedFilesSecondPatchset.keySet()).containsExactly("/COMMIT_MSG");
+ ApprovalInfo approvalInfo =
+ Iterables.getOnlyElement(
+ gApi.changes().id(changeId.get()).current().votes().get(LabelId.CODE_REVIEW));
+ assertThat(approvalInfo._accountId).isEqualTo(admin.id().get());
+ assertThat(approvalInfo.value).isEqualTo(2);
+ }
+
+ @Test
public void deleteStickyVote() throws Exception {
String label = LabelId.CODE_REVIEW;
try (ProjectConfigUpdate u = updateProject(project)) {
@@ -948,6 +1001,237 @@
assertThat(r.getChange().approvals().get(PatchSet.id(r.getChange().getId(), 2))).hasSize(1);
}
+ @Test
+ public void stickyVoteStoredOnUpload() throws Exception {
+ // Code-Review will be sticky.
+ String label = LabelId.CODE_REVIEW;
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().updateLabelType(label, b -> b.setCopyAnyScore(true));
+ u.save();
+ }
+
+ PushOneCommit.Result r = createChange();
+ // Add a new vote.
+ ReviewInput input = new ReviewInput().label(LabelId.CODE_REVIEW, 2);
+ input.tag = "tag";
+ gApi.changes().id(r.getChangeId()).current().review(input);
+
+ // Make new patchsets, keeping the Code-Review +2 vote.
+ for (int i = 0; i < 9; i++) {
+ amendChange(r.getChangeId());
+ }
+
+ List<PatchSetApproval> patchSetApprovals =
+ r.getChange().notes().getApprovalsWithCopied().values().stream()
+ .sorted(comparing(a -> a.patchSetId().get()))
+ .collect(toImmutableList());
+
+ for (int i = 0; i < 10; i++) {
+ int patchSet = i + 1;
+ assertThat(patchSetApprovals.get(i).patchSetId().get()).isEqualTo(patchSet);
+ assertThat(patchSetApprovals.get(i).accountId().get()).isEqualTo(admin.id().get());
+ assertThat(patchSetApprovals.get(i).realAccountId().get()).isEqualTo(admin.id().get());
+ assertThat(patchSetApprovals.get(i).label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(patchSetApprovals.get(i).value()).isEqualTo((short) 2);
+ assertThat(patchSetApprovals.get(i).tag().get()).isEqualTo("tag");
+ if (patchSet == 1) {
+ assertThat(patchSetApprovals.get(i).copied()).isFalse();
+ } else {
+ assertThat(patchSetApprovals.get(i).copied()).isTrue();
+ }
+ }
+ }
+
+ @Test
+ public void stickyVoteStoredOnRebase() throws Exception {
+ // Code-Review will be sticky.
+ String label = LabelId.CODE_REVIEW;
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().updateLabelType(label, b -> b.setCopyAnyScore(true));
+ u.save();
+ }
+
+ // Create two changes both with the same parent
+ PushOneCommit.Result r = createChange();
+ testRepo.reset("HEAD~1");
+ PushOneCommit.Result r2 = createChange();
+
+ // Approve and submit the first change
+ RevisionApi revision = gApi.changes().id(r.getChangeId()).current();
+ revision.review(ReviewInput.approve().label(LabelId.VERIFIED, 1));
+ revision.submit();
+
+ // Add an approval whose score should be copied.
+ gApi.changes().id(r2.getChangeId()).current().review(ReviewInput.recommend());
+
+ // Rebase the second change
+ gApi.changes().id(r2.getChangeId()).rebase();
+
+ List<PatchSetApproval> patchSetApprovals =
+ r2.getChange().notes().getApprovalsWithCopied().values().stream()
+ .sorted(comparing(a -> a.patchSetId().get()))
+ .collect(toImmutableList());
+ PatchSetApproval nonCopied = patchSetApprovals.get(0);
+
+ assertThat(nonCopied.patchSetId().get()).isEqualTo(1);
+ assertThat(nonCopied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(nonCopied.value()).isEqualTo((short) 1);
+ assertThat(nonCopied.copied()).isFalse();
+
+ PatchSetApproval copied = patchSetApprovals.get(1);
+ assertThat(copied.patchSetId().get()).isEqualTo(2);
+ assertThat(copied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(copied.value()).isEqualTo((short) 1);
+ assertThat(copied.copied()).isTrue();
+ }
+
+ @Test
+ public void stickyVoteStoredOnUploadWithRealAccount() throws Exception {
+ // Give "user" permission to vote on behalf of other users.
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ allowLabel(TestLabels.codeReview().getName())
+ .impersonation(true)
+ .ref("refs/heads/*")
+ .group(REGISTERED_USERS)
+ .range(-1, 1))
+ .update();
+
+ // Code-Review will be sticky.
+ String label = LabelId.CODE_REVIEW;
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().updateLabelType(label, b -> b.setCopyAnyScore(true));
+ u.save();
+ }
+
+ PushOneCommit.Result r = createChange();
+
+ // Add a new vote as user
+ requestScopeOperations.setApiUser(user.id());
+ ReviewInput input = new ReviewInput().label(LabelId.CODE_REVIEW, 1);
+ input.onBehalfOf = admin.email();
+ gApi.changes().id(r.getChangeId()).current().review(input);
+
+ // Make a new patchset, keeping the Code-Review +1 vote.
+ amendChange(r.getChangeId());
+
+ List<PatchSetApproval> patchSetApprovals =
+ r.getChange().notes().getApprovalsWithCopied().values().stream()
+ .sorted(comparing(a -> a.patchSetId().get()))
+ .collect(toImmutableList());
+
+ PatchSetApproval nonCopied = patchSetApprovals.get(0);
+ assertThat(nonCopied.patchSetId().get()).isEqualTo(1);
+ assertThat(nonCopied.accountId().get()).isEqualTo(admin.id().get());
+ assertThat(nonCopied.realAccountId().get()).isEqualTo(user.id().get());
+ assertThat(nonCopied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(nonCopied.value()).isEqualTo((short) 1);
+ assertThat(nonCopied.copied()).isFalse();
+
+ PatchSetApproval copied = patchSetApprovals.get(1);
+ assertThat(copied.patchSetId().get()).isEqualTo(2);
+ assertThat(copied.accountId().get()).isEqualTo(admin.id().get());
+ assertThat(copied.realAccountId().get()).isEqualTo(user.id().get());
+ assertThat(copied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(copied.value()).isEqualTo((short) 1);
+ assertThat(copied.copied()).isTrue();
+ }
+
+ @Test
+ public void stickyVoteStoredOnUploadWithRealAccountAndTag() throws Exception {
+ // Give "user" permission to vote on behalf of other users.
+ projectOperations
+ .project(project)
+ .forUpdate()
+ .add(
+ allowLabel(TestLabels.codeReview().getName())
+ .impersonation(true)
+ .ref("refs/heads/*")
+ .group(REGISTERED_USERS)
+ .range(-1, 1))
+ .update();
+
+ // Code-Review will be sticky.
+ String label = LabelId.CODE_REVIEW;
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().updateLabelType(label, b -> b.setCopyAnyScore(true));
+ u.save();
+ }
+
+ PushOneCommit.Result r = createChange();
+
+ // Add a new vote as user
+ requestScopeOperations.setApiUser(user.id());
+ ReviewInput input = new ReviewInput().label(LabelId.CODE_REVIEW, 1);
+ input.onBehalfOf = admin.email();
+ input.tag = "tag";
+ gApi.changes().id(r.getChangeId()).current().review(input);
+
+ // Make a new patchset, keeping the Code-Review +1 vote.
+ amendChange(r.getChangeId());
+
+ List<PatchSetApproval> patchSetApprovals =
+ r.getChange().notes().getApprovalsWithCopied().values().stream()
+ .sorted(comparing(a -> a.patchSetId().get()))
+ .collect(toImmutableList());
+
+ PatchSetApproval nonCopied = patchSetApprovals.get(0);
+ assertThat(nonCopied.patchSetId().get()).isEqualTo(1);
+ assertThat(nonCopied.accountId().get()).isEqualTo(admin.id().get());
+ assertThat(nonCopied.realAccountId().get()).isEqualTo(user.id().get());
+ assertThat(nonCopied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(nonCopied.value()).isEqualTo((short) 1);
+ assertThat(nonCopied.tag().get()).isEqualTo("tag");
+ assertThat(nonCopied.copied()).isFalse();
+
+ PatchSetApproval copied = patchSetApprovals.get(1);
+ assertThat(copied.patchSetId().get()).isEqualTo(2);
+ assertThat(copied.accountId().get()).isEqualTo(admin.id().get());
+ assertThat(copied.realAccountId().get()).isEqualTo(user.id().get());
+ assertThat(copied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(copied.value()).isEqualTo((short) 1);
+ assertThat(nonCopied.tag().get()).isEqualTo("tag");
+ assertThat(copied.copied()).isTrue();
+ }
+
+ @Test
+ public void stickyVoteStoredCanBeRemoved() throws Exception {
+ // Code-Review will be sticky.
+ String label = LabelId.CODE_REVIEW;
+ try (ProjectConfigUpdate u = updateProject(project)) {
+ u.getConfig().updateLabelType(label, b -> b.setCopyAnyScore(true));
+ u.save();
+ }
+
+ PushOneCommit.Result r = createChange();
+
+ // Add a new vote
+ ReviewInput input = new ReviewInput().label(LabelId.CODE_REVIEW, 2);
+ gApi.changes().id(r.getChangeId()).current().review(input);
+
+ // Make a new patchset, keeping the Code-Review +2 vote.
+ amendChange(r.getChangeId());
+ assertVotes(detailedChange(r.getChangeId()), admin, label, 2, null);
+
+ gApi.changes().id(r.getChangeId()).current().review(ReviewInput.noScore());
+
+ PatchSetApproval nonCopiedSecondPatchsetRemovedVote =
+ Iterables.getOnlyElement(
+ r.getChange()
+ .notes()
+ .getApprovalsWithCopied()
+ .get(r.getChange().change().currentPatchSetId()));
+
+ assertThat(nonCopiedSecondPatchsetRemovedVote.patchSetId().get()).isEqualTo(2);
+ assertThat(nonCopiedSecondPatchsetRemovedVote.accountId().get()).isEqualTo(admin.id().get());
+ assertThat(nonCopiedSecondPatchsetRemovedVote.label()).isEqualTo(LabelId.CODE_REVIEW);
+ // The vote got removed since the latest patch-set only has one vote and it's "0".
+ assertThat(nonCopiedSecondPatchsetRemovedVote.value()).isEqualTo((short) 0);
+ assertThat(nonCopiedSecondPatchsetRemovedVote.copied()).isFalse();
+ }
+
private void assertChangeKindCacheContains(ObjectId prior, ObjectId next) {
ChangeKind kind =
changeKindCache.getIfPresent(ChangeKindCacheImpl.Key.create(prior, next, "recursive"));
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
index eadd259..58dc0b0 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionDiffIT.java
@@ -50,7 +50,6 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.extensions.webui.EditWebLink;
-import com.google.gerrit.server.change.FileInfoJsonExperimentImpl;
import com.google.gerrit.server.patch.DiffOperations;
import com.google.gerrit.server.patch.filediff.FileDiffOutput;
import com.google.inject.Inject;
@@ -93,7 +92,6 @@
@Inject private ProjectOperations projectOperations;
private boolean intraline;
- private boolean useNewDiffCache;
private ObjectId initialCommit;
private ObjectId commit1;
@@ -108,9 +106,6 @@
baseConfig.setString("cache", "diff_intraline", "timeout", "1 minute");
intraline = baseConfig.getBoolean(TEST_PARAMETER_MARKER, "intraline", false);
- useNewDiffCache =
- Arrays.asList(baseConfig.getStringList("experiments", null, "enabled"))
- .contains(FileInfoJsonExperimentImpl.NEW_DIFF_CACHE_FEATURE);
ObjectId headCommit = testRepo.getRepository().resolve("HEAD");
initialCommit = headCommit;
@@ -1358,10 +1353,10 @@
}
@Test
+ @Ignore
public void renamedUnrelatedFileIsIgnored_forPatchSetDiffWithRebase_whenEquallyModifiedInBoth()
throws Exception {
// TODO(ghareeb): fix this test for the new diff cache implementation
- assume().that(useNewDiffCache).isFalse();
Function<String, String> contentModification =
fileContent -> fileContent.replace("1st line\n", "First line\n");
@@ -1452,9 +1447,9 @@
}
@Test
+ @Ignore
public void filesTouchedByPatchSetsAndContainingOnlyRebaseHunksAreIgnored() throws Exception {
// TODO(ghareeb): fix this test for the new diff cache implementation
- assume().that(useNewDiffCache).isFalse();
addModifiedPatchSet(
changeId, FILE_NAME, fileContent -> fileContent.replace("Line 50\n", "Line fifty\n"));
@@ -2865,13 +2860,11 @@
DiffInfo diffInfo = gApi.changes().id(cId).current().file(symlink).diff(initialRev);
assertThat(diffInfo.content).hasSize(1);
assertThat(diffInfo).content().element(0).linesOfB().containsExactly("new content");
- // TODO(ghareeb): remove conditional assertion when new diff cache is fully rolled out.
- assertThat(diffInfo.changeType)
- .isEqualTo(useNewDiffCache ? ChangeType.REWRITE : ChangeType.ADDED);
+ assertThat(diffInfo.changeType).isEqualTo(ChangeType.REWRITE);
}
@Test
- public void renameDeleteByJgit_isIdentifiedAsRewritten6() throws Exception {
+ public void renameDeleteByJgit_isIdentifiedAsRewritten() throws Exception {
String target = "file.txt";
String symlink = "link.lnk";
PushOneCommit push =
@@ -2908,9 +2901,7 @@
"rename to link.lnk");
assertThat(diffInfo.content).hasSize(1);
assertThat(diffInfo).content().element(0).commonLines().containsExactly("content");
- // TODO(ghareeb): remove conditional assertion when new diff cache is fully rolled out.
- assertThat(diffInfo.changeType)
- .isEqualTo(useNewDiffCache ? ChangeType.REWRITE : ChangeType.RENAMED);
+ assertThat(diffInfo.changeType).isEqualTo(ChangeType.REWRITE);
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 3d2026b..d3fe83f 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -47,6 +47,7 @@
import com.google.gerrit.acceptance.RestResponse;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
+import com.google.gerrit.acceptance.UseClockStep;
import com.google.gerrit.acceptance.config.GerritConfig;
import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
import com.google.gerrit.acceptance.testsuite.request.RequestScopeOperations;
@@ -1199,6 +1200,7 @@
}
@Test
+ @UseClockStep
public void cherryPickSetsReadyChangeOnNewPatchset() throws Exception {
PushOneCommit.Result result = pushTo("refs/for/master");
CherryPickInput input = new CherryPickInput();
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionNewDiffCacheIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionNewDiffCacheIT.java
deleted file mode 100644
index 714bd78..0000000
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionNewDiffCacheIT.java
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (C) 2021 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.acceptance.api.revision;
-
-import com.google.gerrit.server.change.FileInfoJsonExperimentImpl;
-import com.google.gerrit.testing.ConfigSuite;
-import org.eclipse.jgit.lib.Config;
-
-/**
- * Runs the {@link RevisionDiffIT} with the list files endpoint using the new diff cache. This is
- * temporary until the new diff cache is fully deployed. The new diff cache will become the default
- * in the future.
- */
-public class RevisionNewDiffCacheIT extends RevisionDiffIT {
- @ConfigSuite.Default
- public static Config newDiffCacheConfig() {
- Config config = new Config();
- config.setString(
- "experiments", null, "enabled", FileInfoJsonExperimentImpl.NEW_DIFF_CACHE_FEATURE);
- return config;
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractForcePush.java b/javatests/com/google/gerrit/acceptance/git/AbstractForcePush.java
index 943d990..f4918b6 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractForcePush.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractForcePush.java
@@ -35,7 +35,7 @@
import org.junit.Test;
public abstract class AbstractForcePush extends AbstractDaemonTest {
- @Inject private ProjectOperations projectOperations;
+ @Inject protected ProjectOperations projectOperations;
@Test
public void forcePushNotAllowed() throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index 92770ba..194f5f9 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -1434,7 +1434,6 @@
* Assert that refs seen by a non-admin user match the expected refs.
*
* @param expectedRefs expected refs.
- * @throws Exception
*/
private void assertUploadPackRefs(String... expectedRefs) throws Exception {
assertRefs(project, user, true, expectedRefs);
diff --git a/javatests/com/google/gerrit/acceptance/rest/CancellationIT.java b/javatests/com/google/gerrit/acceptance/rest/CancellationIT.java
index 9f294b3..c5ceea0 100644
--- a/javatests/com/google/gerrit/acceptance/rest/CancellationIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/CancellationIT.java
@@ -232,6 +232,32 @@
@Test
@GerritConfig(name = "deadline.default.timeout", value = "1ms")
+ @GerritConfig(
+ name = "deadline.default.excludedRequestUriPattern",
+ value = "/projects/non-matching")
+ public void abortIfServerDeadlineExceeded_excludedRequestUriPattern() throws Exception {
+ RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
+ assertThat(response.getStatusCode()).isEqualTo(SC_REQUEST_TIMEOUT);
+ assertThat(response.getEntityContent())
+ .isEqualTo("Server Deadline Exceeded\n\ndefault.timeout=1ms");
+ }
+
+ @Test
+ @GerritConfig(name = "deadline.default.timeout", value = "1ms")
+ @GerritConfig(name = "deadline.default.requestUriPattern", value = "/projects/.*")
+ @GerritConfig(
+ name = "deadline.default.excludedRequestUriPattern",
+ value = "/projects/non-matching")
+ public void abortIfServerDeadlineExceeded_requestUriPatternAndExcludedRequestUriPattern()
+ throws Exception {
+ RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
+ assertThat(response.getStatusCode()).isEqualTo(SC_REQUEST_TIMEOUT);
+ assertThat(response.getEntityContent())
+ .isEqualTo("Server Deadline Exceeded\n\ndefault.timeout=1ms");
+ }
+
+ @Test
+ @GerritConfig(name = "deadline.default.timeout", value = "1ms")
@GerritConfig(name = "deadline.default.projectPattern", value = ".*new.*")
public void abortIfServerDeadlineExceeded_projectPattern() throws Exception {
RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
@@ -268,6 +294,24 @@
@Test
@GerritConfig(name = "deadline.default.timeout", value = "1ms")
+ @GerritConfig(name = "deadline.default.excludedRequestUriPattern", value = "/projects/.*")
+ public void nonMatchingServerDeadlineIsIgnored_excludedRequestUriPattern() throws Exception {
+ RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
+ response.assertCreated();
+ }
+
+ @Test
+ @GerritConfig(name = "deadline.default.timeout", value = "1ms")
+ @GerritConfig(name = "deadline.default.requestUriPattern", value = "/projects/.*")
+ @GerritConfig(name = "deadline.default.excludedRequestUriPattern", value = "/projects/.*new")
+ public void nonMatchingServerDeadlineIsIgnored_requestUriPatternAndExcludedRequestUriPattern()
+ throws Exception {
+ RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
+ response.assertCreated();
+ }
+
+ @Test
+ @GerritConfig(name = "deadline.default.timeout", value = "1ms")
@GerritConfig(name = "deadline.default.projectPattern", value = ".*foo.*")
public void nonMatchingServerDeadlineIsIgnored_projectPattern() throws Exception {
RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
@@ -340,6 +384,14 @@
@Test
@GerritConfig(name = "deadline.default.timeout", value = "1ms")
+ @GerritConfig(name = "deadline.default.excludedRequestUriPattern", value = "][")
+ public void invalidServerDeadlineIsIgnored_invalidExcludedRequestUriPattern() throws Exception {
+ RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
+ response.assertCreated();
+ }
+
+ @Test
+ @GerritConfig(name = "deadline.default.timeout", value = "1ms")
@GerritConfig(name = "deadline.default.projectPattern", value = "][")
public void invalidServerDeadlineIsIgnored_invalidProjectPattern() throws Exception {
RestResponse response = adminRestSession.putWithHeaders("/projects/" + name("new"));
diff --git a/javatests/com/google/gerrit/acceptance/rest/TraceIT.java b/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
index 530f2ec..7e40b2b 100644
--- a/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/TraceIT.java
@@ -711,6 +711,94 @@
}
@Test
+ @GerritConfig(name = "tracing.issue123.excludedRequestUriPattern", value = "/projects/.*")
+ public void traceExcludedRequestUriPattern() throws Exception {
+ TraceValidatingProjectCreationValidationListener projectCreationListener =
+ new TraceValidatingProjectCreationValidationListener();
+ try (Registration registration =
+ extensionRegistry.newRegistration().add(projectCreationListener)) {
+ RestResponse response = adminRestSession.put("/projects/xyz1");
+ assertThat(response.getStatusCode()).isEqualTo(SC_CREATED);
+ assertThat(response.getHeader(RestApiServlet.X_GERRIT_TRACE)).isNull();
+ assertThat(projectCreationListener.traceId).isNull();
+ assertThat(projectCreationListener.isLoggingForced).isFalse();
+
+ // The logging tag with the project name is also set if tracing is off.
+ assertThat(projectCreationListener.tags.get("project")).containsExactly("xyz1");
+ }
+ }
+
+ @Test
+ @GerritConfig(name = "tracing.issue123.excludedRequestUriPattern", value = "/projects/no-match")
+ public void traceExcludedRequestUriPatternNoMatch() throws Exception {
+ TraceValidatingProjectCreationValidationListener projectCreationListener =
+ new TraceValidatingProjectCreationValidationListener();
+ try (Registration registration =
+ extensionRegistry.newRegistration().add(projectCreationListener)) {
+ RestResponse response = adminRestSession.put("/projects/xyz3");
+ assertThat(response.getStatusCode()).isEqualTo(SC_CREATED);
+ assertThat(response.getHeader(RestApiServlet.X_GERRIT_TRACE)).isNull();
+ assertThat(projectCreationListener.traceId).isEqualTo("issue123");
+ assertThat(projectCreationListener.isLoggingForced).isTrue();
+ assertThat(projectCreationListener.tags.get("project")).containsExactly("xyz3");
+ }
+ }
+
+ @Test
+ @GerritConfig(name = "tracing.issue123.requestUriPattern", value = "/projects/.*")
+ @GerritConfig(name = "tracing.issue123.excludedRequestUriPattern", value = "/projects/xyz2")
+ public void traceRequestUriPatternAndExcludedRequestUriPattern() throws Exception {
+ TraceValidatingProjectCreationValidationListener projectCreationListener =
+ new TraceValidatingProjectCreationValidationListener();
+ try (Registration registration =
+ extensionRegistry.newRegistration().add(projectCreationListener)) {
+ RestResponse response = adminRestSession.put("/projects/xyz2");
+ assertThat(response.getStatusCode()).isEqualTo(SC_CREATED);
+ assertThat(response.getHeader(RestApiServlet.X_GERRIT_TRACE)).isNull();
+ assertThat(projectCreationListener.traceId).isNull();
+ assertThat(projectCreationListener.isLoggingForced).isFalse();
+
+ // The logging tag with the project name is also set if tracing is off.
+ assertThat(projectCreationListener.tags.get("project")).containsExactly("xyz2");
+ }
+ }
+
+ @Test
+ @GerritConfig(name = "tracing.issue123.requestUriPattern", value = "/projects/.*")
+ @GerritConfig(name = "tracing.issue123.excludedRequestUriPattern", value = "/projects/no-match")
+ public void traceRequestUriPatternAndExcludedRequestUriPatternNoMatch() throws Exception {
+ TraceValidatingProjectCreationValidationListener projectCreationListener =
+ new TraceValidatingProjectCreationValidationListener();
+ try (Registration registration =
+ extensionRegistry.newRegistration().add(projectCreationListener)) {
+ RestResponse response = adminRestSession.put("/projects/xyz3");
+ assertThat(response.getStatusCode()).isEqualTo(SC_CREATED);
+ assertThat(response.getHeader(RestApiServlet.X_GERRIT_TRACE)).isNull();
+ assertThat(projectCreationListener.traceId).isEqualTo("issue123");
+ assertThat(projectCreationListener.isLoggingForced).isTrue();
+ assertThat(projectCreationListener.tags.get("project")).containsExactly("xyz3");
+ }
+ }
+
+ @Test
+ @GerritConfig(name = "tracing.issue123.excludedRequestUriPattern", value = "][")
+ public void traceExcludedRequestUriInvalidRegEx() throws Exception {
+ TraceValidatingProjectCreationValidationListener projectCreationListener =
+ new TraceValidatingProjectCreationValidationListener();
+ try (Registration registration =
+ extensionRegistry.newRegistration().add(projectCreationListener)) {
+ RestResponse response = adminRestSession.put("/projects/xyz4");
+ assertThat(response.getStatusCode()).isEqualTo(SC_CREATED);
+ assertThat(response.getHeader(RestApiServlet.X_GERRIT_TRACE)).isNull();
+ assertThat(projectCreationListener.traceId).isNull();
+ assertThat(projectCreationListener.isLoggingForced).isFalse();
+
+ // The logging tag with the project name is also set if tracing is off.
+ assertThat(projectCreationListener.tags.get("project")).containsExactly("xyz4");
+ }
+ }
+
+ @Test
@GerritConfig(name = "retry.retryWithTraceOnFailure", value = "true")
public void noAutoRetryIfExceptionCausesNormalRetrying() throws Exception {
String changeId = createChange().getChangeId();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
index 92a4028..b0a14cf 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
@@ -1181,7 +1181,6 @@
* @param branchB name of second branch to create
* @param fileB name of file to commit to branchB
* @return A {@code Map} of branchName => commit result.
- * @throws Exception
*/
private Map<String, Result> changeInTwoBranches(
String branchA, String fileA, String branchB, String fileB) throws Exception {
@@ -1201,7 +1200,6 @@
* @param fileB name of file to commit to branchB
* @param contentB file content to commit to branchB
* @return A {@code Map} of branchName => commit result.
- * @throws Exception
*/
private Map<String, Result> changeInTwoBranches(
String branchA,
diff --git a/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
index f98fb45..55735fc 100644
--- a/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
+++ b/javatests/com/google/gerrit/acceptance/rest/util/RestApiCallHelper.java
@@ -29,13 +29,13 @@
/** Helper to execute REST API calls using the HTTP client. */
@Ignore
public class RestApiCallHelper {
- /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+ /** See {@link #execute(RestSession, List, BeforeRestCall, String...)} */
public static void execute(RestSession restSession, List<RestCall> restCalls, String... args)
throws Exception {
execute(restSession, restCalls, () -> {}, args);
}
- /** @see #execute(RestSession, List, BeforeRestCall, String...) */
+ /** See {@link #execute(RestSession, RestCall, String...)} */
public static void execute(
RestSession restSession,
List<RestCall> restCalls,
diff --git a/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java b/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
deleted file mode 100644
index b23f9a3..0000000
--- a/javatests/com/google/gerrit/acceptance/server/change/PatchListCacheIT.java
+++ /dev/null
@@ -1,326 +0,0 @@
-// Copyright (C) 2014 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.acceptance.server.change;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.acceptance.GitUtil.getChangeId;
-import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.cache.Cache;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.entities.Patch;
-import com.google.gerrit.entities.Patch.ChangeType;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
-import com.google.gerrit.server.patch.IntraLineDiff;
-import com.google.gerrit.server.patch.IntraLineDiffArgs;
-import com.google.gerrit.server.patch.IntraLineDiffKey;
-import com.google.gerrit.server.patch.PatchList;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListCacheImpl;
-import com.google.gerrit.server.patch.PatchListEntry;
-import com.google.gerrit.server.patch.PatchListKey;
-import com.google.gerrit.server.patch.Text;
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Optional;
-import java.util.Set;
-import org.eclipse.jgit.diff.Edit;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.junit.Test;
-
-@NoHttpd
-public class PatchListCacheIT extends AbstractDaemonTest {
- private static String SUBJECT_1 = "subject 1";
- private static String SUBJECT_2 = "subject 2";
- private static String SUBJECT_3 = "subject 3";
- private static String FILE_A = "a.txt";
- private static String FILE_B = "b.txt";
- private static String FILE_C = "c.txt";
- private static String FILE_D = "d.txt";
-
- @Inject private PatchListCache patchListCache;
-
- @Inject
- @Named("diff")
- private Cache<PatchListKey, PatchList> abstractPatchListCache;
-
- @Test
- public void ensureLegacyBackendIsUsedForFileCacheBackend() throws Exception {
- Field fileCacheField = patchListCache.getClass().getDeclaredField("fileCache");
- fileCacheField.setAccessible(true);
- // Use the reflection to access "localCache" field that is only present in Guava backend.
- assertThat(
- Arrays.stream(fileCacheField.get(patchListCache).getClass().getDeclaredFields())
- .anyMatch(f -> f.getName().equals("localCache")))
- .isTrue();
-
- // intraCache (and all other cache backends) should use Caffeine backend.
- Field intraCacheField = patchListCache.getClass().getDeclaredField("intraCache");
- intraCacheField.setAccessible(true);
- assertThat(
- Arrays.stream(intraCacheField.get(patchListCache).getClass().getDeclaredFields())
- .noneMatch(f -> f.getName().equals("localCache")))
- .isTrue();
- }
-
- @Test
- public void listPatchesAgainstBase() throws Exception {
- commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();
- pushHead(testRepo, "refs/heads/master", false);
-
- // Change 1, 1 (+FILE_A, -FILE_D)
- RevCommit c =
- commitBuilder().add(FILE_A, "1").rm(FILE_D).message(SUBJECT_2).insertChangeId().create();
- String id = getChangeId(testRepo, c).get();
- pushHead(testRepo, "refs/for/master", false);
-
- // Compare Change 1,1 with Base (+FILE_A, -FILE_D)
- List<PatchListEntry> entries = getCurrentPatches(id);
- assertThat(entries).hasSize(3);
- assertAdded(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_A, entries.get(1));
- assertDeleted(FILE_D, entries.get(2));
-
- // Change 1,2 (+FILE_A, +FILE_B, -FILE_D)
- amendBuilder().add(FILE_B, "2").create();
- pushHead(testRepo, "refs/for/master", false);
- entries = getCurrentPatches(id);
-
- // Compare Change 1,2 with Base (+FILE_A, +FILE_B, -FILE_D)
- assertThat(entries).hasSize(4);
- assertAdded(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_A, entries.get(1));
- assertAdded(FILE_B, entries.get(2));
- assertDeleted(FILE_D, entries.get(3));
- }
-
- @Test
- public void listPatchesAgainstBaseWithRebase() throws Exception {
- commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();
- pushHead(testRepo, "refs/heads/master", false);
-
- // Change 1,1 (+FILE_A, -FILE_D)
- RevCommit c = commitBuilder().add(FILE_A, "1").rm(FILE_D).message(SUBJECT_2).create();
- String id = getChangeId(testRepo, c).get();
- pushHead(testRepo, "refs/for/master", false);
- List<PatchListEntry> entries = getCurrentPatches(id);
- assertThat(entries).hasSize(3);
- assertAdded(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_A, entries.get(1));
- assertDeleted(FILE_D, entries.get(2));
-
- // Change 2,1 (+FILE_B)
- testRepo.reset("HEAD~1");
- commitBuilder().add(FILE_B, "2").message(SUBJECT_3).create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Change 1,2 (+FILE_A, -FILE_D))
- testRepo.cherryPick(c);
- pushHead(testRepo, "refs/for/master", false);
-
- // Compare Change 1,2 with Base (+FILE_A, -FILE_D))
- entries = getCurrentPatches(id);
- assertThat(entries).hasSize(3);
- assertAdded(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_A, entries.get(1));
- assertDeleted(FILE_D, entries.get(2));
- }
-
- @Test
- public void listPatchesAgainstOtherPatchSet() throws Exception {
- commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();
- pushHead(testRepo, "refs/heads/master", false);
-
- // Change 1,1 (+FILE_A, +FILE_C, -FILE_D)
- RevCommit a =
- commitBuilder().add(FILE_A, "1").add(FILE_C, "3").rm(FILE_D).message(SUBJECT_2).create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Change 1,2 (+FILE_A, +FILE_B, -FILE_D)
- RevCommit b = amendBuilder().add(FILE_B, "2").rm(FILE_C).create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Compare Change 1,1 with Change 1,2 (+FILE_B, -FILE_C)
- List<PatchListEntry> entries = getPatches(a, b);
- assertThat(entries).hasSize(3);
- assertModified(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_B, entries.get(1));
- assertDeleted(FILE_C, entries.get(2));
-
- // Compare Change 1,2 with Change 1,1 (-FILE_B, +FILE_C)
- List<PatchListEntry> entriesReverse = getPatches(b, a);
- assertThat(entriesReverse).hasSize(3);
- assertModified(Patch.COMMIT_MSG, entriesReverse.get(0));
- assertDeleted(FILE_B, entriesReverse.get(1));
- assertAdded(FILE_C, entriesReverse.get(2));
- }
-
- @Test
- public void listPatchesAgainstOtherPatchSetWithRebase() throws Exception {
- commitBuilder().add(FILE_D, "4").message(SUBJECT_1).create();
- pushHead(testRepo, "refs/heads/master", false);
-
- // Change 1,1 (+FILE_A, -FILE_D)
- RevCommit a = commitBuilder().add(FILE_A, "1").rm(FILE_D).message(SUBJECT_2).create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Change 2,1 (+FILE_B)
- testRepo.reset("HEAD~1");
- commitBuilder().add(FILE_B, "2").message(SUBJECT_3).create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Change 1,2 (+FILE_A, +FILE_C, -FILE_D)
- testRepo.cherryPick(a);
- RevCommit b = amendBuilder().add(FILE_C, "2").create();
- pushHead(testRepo, "refs/for/master", false);
-
- // Compare Change 1,1 with Change 1,2 (+FILE_C)
- List<PatchListEntry> entries = getPatches(a, b);
- assertThat(entries).hasSize(2);
- assertModified(Patch.COMMIT_MSG, entries.get(0));
- assertAdded(FILE_C, entries.get(1));
-
- // Compare Change 1,2 with Change 1,1 (-FILE_C)
- List<PatchListEntry> entriesReverse = getPatches(b, a);
- assertThat(entriesReverse).hasSize(2);
- assertModified(Patch.COMMIT_MSG, entriesReverse.get(0));
- assertDeleted(FILE_C, entriesReverse.get(1));
- }
-
- @Test
- public void harmfulMutationsOfEditsAreNotPossibleForPatchListEntry() throws Exception {
- RevCommit commit =
- commitBuilder().add("a.txt", "First line\nSecond line\n").message(SUBJECT_1).create();
- pushHead(testRepo, "refs/heads/master", false);
-
- PatchListKey diffKey = PatchListKey.againstDefaultBase(commit.copy(), Whitespace.IGNORE_NONE);
- PatchList patchList = patchListCache.get(diffKey, project);
-
- PatchListEntry patchListEntry = getEntryFor(patchList, "a.txt");
- Edit outputEdit = Iterables.getOnlyElement(patchListEntry.getEdits());
- Edit originalEdit =
- new Edit(
- outputEdit.getBeginA(),
- outputEdit.getEndA(),
- outputEdit.getBeginB(),
- outputEdit.getEndB());
-
- outputEdit.shift(5);
-
- assertThat(patchListEntry.getEdits()).containsExactly(originalEdit);
- }
-
- @Test
- public void harmfulMutationsOfEditsAreNotPossibleForIntraLineDiffArgsAndCachedValue() {
- String a = "First line\nSecond line\n";
- String b = "1st line\n2nd line\n";
- Text aText = new Text(a.getBytes(UTF_8));
- Text bText = new Text(b.getBytes(UTF_8));
- Edit inputEdit = new Edit(0, 2, 0, 2);
- List<Edit> inputEdits = new ArrayList<>(ImmutableList.of(inputEdit));
- Set<Edit> inputEditsDueToRebase = new HashSet<>(ImmutableSet.of(inputEdit));
-
- IntraLineDiffKey diffKey =
- IntraLineDiffKey.create(ObjectId.zeroId(), ObjectId.zeroId(), Whitespace.IGNORE_NONE);
- IntraLineDiffArgs diffArgs =
- IntraLineDiffArgs.create(
- aText,
- bText,
- inputEdits,
- inputEditsDueToRebase,
- project,
- ObjectId.zeroId(),
- "file.txt");
- IntraLineDiff intraLineDiff = patchListCache.getIntraLineDiff(diffKey, diffArgs);
-
- Edit outputEdit = Iterables.getOnlyElement(intraLineDiff.getEdits());
-
- outputEdit.shift(5);
- inputEdit.shift(7);
- inputEdits.add(new Edit(43, 47, 50, 51));
- inputEditsDueToRebase.add(new Edit(53, 57, 60, 61));
-
- Edit originalEdit = new Edit(0, 2, 0, 2);
- assertThat(diffArgs.edits()).containsExactly(originalEdit);
- assertThat(diffArgs.editsDueToRebase()).containsExactly(originalEdit);
- assertThat(intraLineDiff.getEdits()).containsExactly(originalEdit);
- }
-
- @Test
- public void largeObjectTombstoneGetsCached() {
- PatchListKey key = PatchListKey.againstDefaultBase(ObjectId.zeroId(), Whitespace.IGNORE_ALL);
- PatchListCacheImpl.LargeObjectTombstone tombstone =
- new PatchListCacheImpl.LargeObjectTombstone();
- abstractPatchListCache.put(key, tombstone);
- assertThat(abstractPatchListCache.getIfPresent(key)).isSameInstanceAs(tombstone);
- }
-
- private static void assertAdded(String expectedNewName, PatchListEntry e) {
- assertName(expectedNewName, e);
- assertThat(e.getChangeType()).isEqualTo(ChangeType.ADDED);
- }
-
- private static void assertModified(String expectedNewName, PatchListEntry e) {
- assertName(expectedNewName, e);
- assertThat(e.getChangeType()).isEqualTo(ChangeType.MODIFIED);
- }
-
- private static void assertDeleted(String expectedNewName, PatchListEntry e) {
- assertName(expectedNewName, e);
- assertThat(e.getChangeType()).isEqualTo(ChangeType.DELETED);
- }
-
- private static void assertName(String expectedNewName, PatchListEntry e) {
- assertThat(e.getNewName()).isEqualTo(expectedNewName);
- assertThat(e.getOldName()).isNull();
- }
-
- private List<PatchListEntry> getCurrentPatches(String changeId) throws Exception {
- return patchListCache.get(getKey(null, getCurrentRevisionId(changeId)), project).getPatches();
- }
-
- private List<PatchListEntry> getPatches(ObjectId revisionIdA, ObjectId revisionIdB)
- throws Exception {
- return patchListCache.get(getKey(revisionIdA, revisionIdB), project).getPatches();
- }
-
- private PatchListKey getKey(ObjectId revisionIdA, ObjectId revisionIdB) {
- return PatchListKey.againstCommit(revisionIdA, revisionIdB, Whitespace.IGNORE_NONE);
- }
-
- private ObjectId getCurrentRevisionId(String changeId) throws Exception {
- return ObjectId.fromString(gApi.changes().id(changeId).get().currentRevision);
- }
-
- private static PatchListEntry getEntryFor(PatchList patchList, String filePath) {
- Optional<PatchListEntry> patchListEntry =
- patchList.getPatches().stream()
- .filter(entry -> entry.getNewName().equals(filePath))
- .findAny();
- return patchListEntry.orElseThrow(
- () -> new IllegalStateException("No PatchListEntry for " + filePath + " exists"));
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/server/query/ApprovalQueryIT.java b/javatests/com/google/gerrit/acceptance/server/query/ApprovalQueryIT.java
index 9392219..b4d9558 100644
--- a/javatests/com/google/gerrit/acceptance/server/query/ApprovalQueryIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/query/ApprovalQueryIT.java
@@ -269,6 +269,7 @@
.key(PatchSetApproval.key(psId, approver, LabelId.create("Code-Review")))
.value(value)
.build();
- return ApprovalContext.create(changeNotes, approval, newPsId, changeKind);
+ return ApprovalContext.create(
+ changeNotes, approval, changeNotes.getPatchSets().get(newPsId), changeKind);
}
}
diff --git a/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java b/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
index f866fff..3b38bad 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/AbstractIndexTests.java
@@ -38,7 +38,6 @@
public abstract class AbstractIndexTests extends AbstractDaemonTest {
@Inject private ExtensionRegistry extensionRegistry;
- /** @param injector injector */
public void configureIndex(Injector injector) {}
@Test
diff --git a/javatests/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverterTest.java b/javatests/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverterTest.java
index bf39ff8..d332f8a 100644
--- a/javatests/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverterTest.java
+++ b/javatests/com/google/gerrit/entities/converter/PatchSetApprovalProtoConverterTest.java
@@ -49,6 +49,7 @@
.tag("tag-21")
.realAccountId(Account.id(612))
.postSubmit(true)
+ .copied(true)
.build();
Entities.PatchSetApproval proto = protoConverter.toProto(patchSetApproval);
@@ -68,6 +69,7 @@
.setTag("tag-21")
.setRealAccountId(Entities.Account_Id.newBuilder().setId(612))
.setPostSubmit(true)
+ .setCopied(true)
.build();
assertThat(proto).isEqualTo(expectedProto);
}
@@ -99,6 +101,7 @@
.setGranted(987654L)
// This value can't be unset when our entity class is given.
.setPostSubmit(false)
+ .setCopied(false)
.build();
assertThat(proto).isEqualTo(expectedProto);
}
@@ -115,6 +118,7 @@
.tag("tag-21")
.realAccountId(Account.id(612))
.postSubmit(true)
+ .copied(true)
.build();
PatchSetApproval convertedPatchSetApproval =
@@ -162,6 +166,7 @@
assertThat(patchSetApproval.value()).isEqualTo(0);
assertThat(patchSetApproval.granted()).isEqualTo(new Timestamp(0));
assertThat(patchSetApproval.postSubmit()).isEqualTo(false);
+ assertThat(patchSetApproval.copied()).isEqualTo(false);
}
/** See {@link SerializedClassSubject} for background and what to do if this test fails. */
@@ -176,6 +181,7 @@
.put("tag", new TypeLiteral<Optional<String>>() {}.getType())
.put("realAccountId", Account.Id.class)
.put("postSubmit", boolean.class)
+ .put("copied", boolean.class)
.put("toBuilder", PatchSetApproval.Builder.class)
.build());
}
diff --git a/javatests/com/google/gerrit/httpd/ProjectBasicAuthFilterTest.java b/javatests/com/google/gerrit/httpd/ProjectBasicAuthFilterTest.java
index 162a171..da6092b 100644
--- a/javatests/com/google/gerrit/httpd/ProjectBasicAuthFilterTest.java
+++ b/javatests/com/google/gerrit/httpd/ProjectBasicAuthFilterTest.java
@@ -101,7 +101,7 @@
req = new FakeHttpServletRequest("gerrit.example.com", 80, "", "");
res = new FakeHttpServletResponse();
- extIdKeyFactory = new ExternalIdKeyFactory(authConfig);
+ extIdKeyFactory = new ExternalIdKeyFactory(new ExternalIdKeyFactory.ConfigImpl(authConfig));
extIdFactory = new ExternalIdFactory(extIdKeyFactory);
authRequestFactory = new AuthRequest.Factory(extIdKeyFactory);
pwdVerifier = new PasswordVerifier(extIdKeyFactory);
diff --git a/javatests/com/google/gerrit/mail/HtmlParserTest.java b/javatests/com/google/gerrit/mail/HtmlParserTest.java
index a7ff172..bb60fd8 100644
--- a/javatests/com/google/gerrit/mail/HtmlParserTest.java
+++ b/javatests/com/google/gerrit/mail/HtmlParserTest.java
@@ -176,7 +176,6 @@
/**
* Create an html message body with the specified comments.
*
- * @param changeMessage
* @param c1 Comment in reply to first comment.
* @param c2 Comment in reply to second comment.
* @param c3 Comment in reply to third comment.
diff --git a/javatests/com/google/gerrit/mail/TextParserTest.java b/javatests/com/google/gerrit/mail/TextParserTest.java
index caed5f8..d3e7447 100644
--- a/javatests/com/google/gerrit/mail/TextParserTest.java
+++ b/javatests/com/google/gerrit/mail/TextParserTest.java
@@ -181,7 +181,6 @@
/**
* Create a plaintext message body with the specified comments.
*
- * @param changeMessage
* @param c1 Comment in reply to first inline comment.
* @param c2 Comment in reply to second inline comment.
* @param c3 Comment in reply to third inline comment.
diff --git a/javatests/com/google/gerrit/server/CancellationMetricsTest.java b/javatests/com/google/gerrit/server/RequestInfoTest.java
similarity index 96%
rename from javatests/com/google/gerrit/server/CancellationMetricsTest.java
rename to javatests/com/google/gerrit/server/RequestInfoTest.java
index 2343c71..fafe856 100644
--- a/javatests/com/google/gerrit/server/CancellationMetricsTest.java
+++ b/javatests/com/google/gerrit/server/RequestInfoTest.java
@@ -18,7 +18,7 @@
import org.junit.Test;
-public class CancellationMetricsTest {
+public class RequestInfoTest {
@Test
public void redactRequestUri() throws Exception {
// test with valid request URIs
@@ -52,6 +52,6 @@
}
public static String redact(String uri) {
- return CancellationMetrics.redactRequestUri(uri);
+ return RequestInfo.redactRequestUri(uri);
}
}
diff --git a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
index 058384e..7d9db0b 100644
--- a/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
+++ b/javatests/com/google/gerrit/server/account/externalids/AllExternalIdsTest.java
@@ -25,24 +25,27 @@
import com.google.gerrit.server.account.externalids.AllExternalIds.Serializer;
import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto;
import com.google.gerrit.server.cache.proto.Cache.AllExternalIdsProto.ExternalIdProto;
-import com.google.gerrit.server.config.AuthConfig;
import com.google.inject.TypeLiteral;
import java.lang.reflect.Type;
import java.util.Arrays;
import org.eclipse.jgit.lib.ObjectId;
import org.junit.Before;
import org.junit.Test;
-import org.mockito.Mockito;
public class AllExternalIdsTest {
- private AuthConfig authConfig;
private ExternalIdFactory externalIdFactory;
@Before
public void setUp() throws Exception {
- authConfig = Mockito.mock(AuthConfig.class);
- Mockito.when(authConfig.isUserNameCaseInsensitive()).thenReturn(false);
- externalIdFactory = new ExternalIdFactory(new ExternalIdKeyFactory(authConfig));
+ externalIdFactory =
+ new ExternalIdFactory(
+ new ExternalIdKeyFactory(
+ new ExternalIdKeyFactory.Config() {
+ @Override
+ public boolean isUserNameCaseInsensitive() {
+ return false;
+ }
+ }));
}
@Test
diff --git a/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java b/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
index fab90d4..4f8c559 100644
--- a/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
+++ b/javatests/com/google/gerrit/server/account/externalids/ExternalIDCacheLoaderTest.java
@@ -28,7 +28,6 @@
import com.google.gerrit.server.account.externalids.testing.ExternalIdTestUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
-import com.google.gerrit.server.config.AuthConfig;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.meta.MetaDataUpdate;
@@ -57,14 +56,20 @@
private GitRepositoryManager repoManager = new InMemoryRepositoryManager();
private ExternalIdReader externalIdReader;
private ExternalIdReader externalIdReaderSpy;
- private AuthConfig authConfig;
+
private ExternalIdFactory externalIdFactory;
@Before
public void setUp() throws Exception {
- authConfig = Mockito.mock(AuthConfig.class);
- Mockito.when(authConfig.isUserNameCaseInsensitive()).thenReturn(false);
- externalIdFactory = new ExternalIdFactory(new ExternalIdKeyFactory(authConfig));
+ externalIdFactory =
+ new ExternalIdFactory(
+ new ExternalIdKeyFactory(
+ new ExternalIdKeyFactory.Config() {
+ @Override
+ public boolean isUserNameCaseInsensitive() {
+ return false;
+ }
+ }));
externalIdCache = CacheBuilder.newBuilder().build();
repoManager.createRepository(ALL_USERS).close();
externalIdReader =
diff --git a/javatests/com/google/gerrit/server/logging/PerformanceLogContextTest.java b/javatests/com/google/gerrit/server/logging/PerformanceLogContextTest.java
index ed4325d..fefa066 100644
--- a/javatests/com/google/gerrit/server/logging/PerformanceLogContextTest.java
+++ b/javatests/com/google/gerrit/server/logging/PerformanceLogContextTest.java
@@ -34,6 +34,7 @@
import com.google.inject.Injector;
import java.util.ArrayList;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
import org.eclipse.jgit.lib.Config;
import org.junit.After;
import org.junit.Before;
@@ -110,9 +111,10 @@
@Test
public void
- traceTimersInsidePerformanceLogContextDoNotCreatePerformanceLogIfNoPerformanceLoggers() {
+ traceTimersInsidePerformanceLogContextDoNotCreatePerformanceLogIfNoPerformanceLoggers()
+ throws Exception {
// Remove test performance logger so that there are no registered performance loggers.
- performanceLoggerRegistrationHandle.remove();
+ removeAllPerformanceLoggers();
assertThat(LoggingContext.getInstance().isPerformanceLogging()).isFalse();
assertThat(LoggingContext.getInstance().getPerformanceLogRecords()).isEmpty();
@@ -277,9 +279,10 @@
@Test
public void
- timerMetricssInsidePerformanceLogContextDoNotCreatePerformanceLogIfNoPerformanceLoggers() {
- // Remove test performance logger so that there are no registered performance loggers.
- performanceLoggerRegistrationHandle.remove();
+ timerMetricssInsidePerformanceLogContextDoNotCreatePerformanceLogIfNoPerformanceLoggers()
+ throws Exception {
+ // Remove all performance loggers so that there are no registered performance loggers.
+ removeAllPerformanceLoggers();
assertThat(LoggingContext.getInstance().isPerformanceLogging()).isFalse();
assertThat(LoggingContext.getInstance().getPerformanceLogRecords()).isEmpty();
@@ -369,6 +372,12 @@
}
}
+ private void removeAllPerformanceLoggers() throws Exception {
+ java.lang.reflect.Field itemsField = DynamicSet.class.getDeclaredField("items");
+ itemsField.setAccessible(true);
+ ((CopyOnWriteArrayList<?>) itemsField.get(performanceLoggers)).clear();
+ }
+
@AutoValue
abstract static class PerformanceLogEntry {
static PerformanceLogEntry create(String operation, Metadata metadata) {
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesParserTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
index 6a32fa1..dc9b9cd 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesParserTest.java
@@ -153,6 +153,43 @@
}
@Test
+ public void parseCopiedApproval() throws Exception {
+ assertParseSucceeds(
+ "Update change\n"
+ + "\n"
+ + "Branch: refs/heads/master\n"
+ + "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ + "Patch-set: 1\n"
+ + "Copied-Label: Label1=+1 Account <1@gerrit>,Other Account <2@Gerrit>\n"
+ + "Copied-Label: Label2=+1 Account <1@gerrit>\n"
+ + "Copied-Label: Label3=+1 Account <1@gerrit>,Other Account <2@Gerrit> :\"tag\"\n"
+ + "Copied-Label: Label4=+1 Account <1@Gerrit> :\"tag with characters %^#@^( *::!\"\n"
+ + "Subject: This is a test change\n");
+ assertParseSucceeds(
+ "Update change\n"
+ + "\n"
+ + "Branch: refs/heads/master\n"
+ + "Change-id: I577fb248e474018276351785930358ec0450e9f7\n"
+ + "Patch-set: 1\n"
+ + "Label: -Label1\n"
+ + "Label: -Label4 Account <1@gerrit>\n"
+ + "Subject: This is a test change\n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: Label1=X\n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: Label1 = 1\n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: X+Y\n");
+ assertParseFails(
+ "Update change\n\nPatch-set: 1\nCopied-Label: Label1 Other Account <2@gerrit>\n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: -Label!1\n");
+ assertParseFails(
+ "Update change\n\nPatch-set: 1\nCopied-Label: -Label!1 Other Account <2@gerrit>\n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: -Label1\n");
+ assertParseFails(
+ "Update change\n\nPatch-set: 1\nCopied-Label: Label1 Other Account <2@gerrit>,Other "
+ + "Account <2@gerrit>,Other Account <2@gerrit> \n");
+ assertParseFails("Update change\n\nPatch-set: 1\nCopied-Label: Label1 non-user\n");
+ }
+
+ @Test
public void parseSubmitRecords() throws Exception {
assertParseSucceeds(
"Update change\n"
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
index 048e3fd..52eaf11 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesStateTest.java
@@ -375,6 +375,7 @@
PatchSetApproval.key(
PatchSet.id(ID, 1), Account.id(2001), LabelId.create(LabelId.CODE_REVIEW)))
.value(1)
+ .tag("tag")
.granted(new Timestamp(1212L))
.build();
Entities.PatchSetApproval psa1 = PatchSetApprovalProtoConverter.INSTANCE.toProto(a1);
@@ -386,11 +387,13 @@
PatchSetApproval.key(
PatchSet.id(ID, 1), Account.id(2002), LabelId.create(LabelId.VERIFIED)))
.value(-1)
+ .tag("tag")
+ .copied(true)
.granted(new Timestamp(3434L))
.build();
Entities.PatchSetApproval psa2 = PatchSetApprovalProtoConverter.INSTANCE.toProto(a2);
ByteString a2Bytes = Protos.toByteString(psa2);
- assertThat(a2Bytes.size()).isEqualTo(49);
+ assertThat(a2Bytes.size()).isEqualTo(56);
assertThat(a2Bytes).isNotEqualTo(a1Bytes);
assertRoundTrip(
@@ -980,6 +983,7 @@
.put("tag", new TypeLiteral<Optional<String>>() {}.getType())
.put("realAccountId", Account.Id.class)
.put("postSubmit", boolean.class)
+ .put("copied", boolean.class)
.put("toBuilder", PatchSetApproval.Builder.class)
.build());
}
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 9c2e9a9..c524c94 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -514,6 +514,184 @@
}
@Test
+ public void copiedApprovals() throws Exception {
+ Change c = newChange();
+ ChangeUpdate update = newUpdate(c, changeOwner);
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.CODE_REVIEW)))
+ .value(1)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .tag("tag")
+ .realAccountId(otherUserId)
+ .build());
+ update.putApprovalFor(otherUserId, LabelId.CODE_REVIEW, (short) -1);
+ update.commit();
+
+ // Only the non copied approval is reachable by getApprovals.
+ ChangeNotes notes = newNotes(c);
+ PatchSetApproval approval =
+ Iterables.getOnlyElement(notes.getApprovals().get(c.currentPatchSetId()));
+ assertThat(approval.accountId()).isEqualTo(otherUser.getAccountId());
+ assertThat(approval.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(approval.value()).isEqualTo((short) -1);
+ assertThat(approval.copied()).isFalse();
+
+ // Get approvals with copied gets all of the approvals (including copied).
+ ImmutableList<PatchSetApproval> approvals =
+ notes.getApprovalsWithCopied().get(c.currentPatchSetId()).stream()
+ .sorted(comparing(a -> a.accountId().get()))
+ .collect(toImmutableList());
+ assertThat(approvals).hasSize(2);
+
+ PatchSetApproval copied = approvals.get(0);
+ assertThat(copied.accountId()).isEqualTo(changeOwner.getAccountId());
+ assertThat(copied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(copied.value()).isEqualTo((short) 1);
+ assertThat(copied.tag()).hasValue("tag");
+ assertThat(copied.accountId()).isEqualTo(changeOwner.getAccountId());
+ assertThat(copied.realAccountId()).isEqualTo(otherUserId);
+ assertThat(copied.copied()).isTrue();
+
+ PatchSetApproval nonCopied = approvals.get(1);
+ assertThat(nonCopied.accountId()).isEqualTo(otherUserId);
+ assertThat(nonCopied.realAccountId()).isEqualTo(otherUserId);
+ assertThat(nonCopied.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(nonCopied.value()).isEqualTo((short) -1);
+ }
+
+ @Test
+ public void copiedApprovalsCanBeRemoved() throws Exception {
+ Change c = newChange();
+ ChangeUpdate update = newUpdate(c, changeOwner);
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.CODE_REVIEW)))
+ .value(1)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .build());
+ update.commit();
+
+ update.removeApproval(LabelId.CODE_REVIEW);
+ update.commit();
+
+ ChangeNotes notes = newNotes(c);
+ PatchSetApproval approval =
+ Iterables.getOnlyElement(notes.getApprovalsWithCopied().get(c.currentPatchSetId()));
+ assertThat(approval.accountId()).isEqualTo(changeOwner.getAccountId());
+ assertThat(approval.label()).isEqualTo(LabelId.CODE_REVIEW);
+ // The vote got removed since the latest patch-set only has one vote and it's "0". The copied
+ // approval will never have a "0" vote, but it can be overridden by a "0" vote of a
+ // non-copied approval.
+ assertThat(approval.value()).isEqualTo((short) 0);
+ assertThat(approval.copied()).isFalse();
+ }
+
+ @Test
+ public void copiedApprovalsWithStrangeTags() throws Exception {
+ String strangeTag = "!@#$%^\0&*):\" \n: \r\"#$@,. :";
+ Change c = newChange();
+ ChangeUpdate update = newUpdate(c, changeOwner);
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.CODE_REVIEW)))
+ .value(1)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .tag(strangeTag)
+ .build());
+ update.commit();
+
+ ChangeNotes notes = newNotes(c);
+ PatchSetApproval approval =
+ Iterables.getOnlyElement(notes.getApprovalsWithCopied().get(c.currentPatchSetId()));
+ assertThat(approval.accountId()).isEqualTo(changeOwner.getAccountId());
+ assertThat(approval.label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(approval.value()).isEqualTo((short) 1);
+ assertThat(approval.tag()).hasValue(NoteDbUtil.sanitizeFooter(strangeTag));
+ assertThat(approval.copied()).isTrue();
+ }
+
+ @Test
+ public void copiedApprovalsPostSubmit() throws Exception {
+ Change c = newChange();
+ SubmissionId submissionId = new SubmissionId(c);
+ ChangeUpdate update = newUpdate(c, changeOwner);
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.CODE_REVIEW)))
+ .value(1)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .build());
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.VERIFIED)))
+ .value(1)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .build());
+ update.commit();
+
+ update = newUpdate(c, changeOwner);
+ update.merge(
+ submissionId,
+ ImmutableList.of(
+ submitRecord(
+ "NOT_READY",
+ null,
+ submitLabel(LabelId.VERIFIED, "OK", changeOwner.getAccountId()),
+ submitLabel(LabelId.CODE_REVIEW, "NEED", null))));
+ update.commit();
+
+ update = newUpdate(c, changeOwner);
+ update.putCopiedApproval(
+ PatchSetApproval.builder()
+ .key(
+ PatchSetApproval.key(
+ c.currentPatchSetId(),
+ changeOwner.getAccountId(),
+ LabelId.create(LabelId.CODE_REVIEW)))
+ .value(2)
+ .copied(true)
+ .granted(TimeUtil.nowTs())
+ .build());
+ update.commit();
+
+ ChangeNotes notes = newNotes(c);
+ List<PatchSetApproval> approvals = Lists.newArrayList(notes.getApprovalsWithCopied().values());
+ assertThat(approvals).hasSize(2);
+ assertThat(approvals.get(0).label()).isEqualTo(LabelId.VERIFIED);
+ assertThat(approvals.get(0).value()).isEqualTo((short) 1);
+ assertThat(approvals.get(0).postSubmit()).isFalse();
+ assertThat(approvals.get(1).label()).isEqualTo(LabelId.CODE_REVIEW);
+ assertThat(approvals.get(1).value()).isEqualTo((short) 2);
+ assertThat(approvals.get(1).postSubmit()).isTrue();
+ }
+
+ @Test
public void multipleReviewers() throws Exception {
Change c = newChange();
ChangeUpdate update = newUpdate(c, changeOwner);
diff --git a/javatests/com/google/gerrit/server/permissions/SectionSortCacheTest.java b/javatests/com/google/gerrit/server/permissions/SectionSortCacheTest.java
index 9ec1625..0ba3b56 100644
--- a/javatests/com/google/gerrit/server/permissions/SectionSortCacheTest.java
+++ b/javatests/com/google/gerrit/server/permissions/SectionSortCacheTest.java
@@ -78,7 +78,7 @@
// Cache preserves relative order (reference equality) for identical elements
AccessSection[] expected = {sectionBClone, sectionB, sectionA, sectionAClone, sectionA};
for (int i = 0; i < sorted.size(); i++) {
- assert (sorted.get(i) == expected[i]);
+ assertThat(sorted.get(i)).isSameInstanceAs(expected[i]);
}
}
}
diff --git a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
index e85074b..05eb6e0 100644
--- a/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
+++ b/javatests/com/google/gerrit/server/project/SubmitRequirementsAdapterTest.java
@@ -69,7 +69,18 @@
.setFunction(LabelFunction.ANY_WITH_BLOCK)
.build();
- labelTypes = Arrays.asList(codeReview, verified, codeStyle);
+ LabelType ignoreSelfApprovalLabel =
+ LabelType.builder(
+ "ISA-Label",
+ ImmutableList.of(
+ LabelValue.create((short) 1, "Looks good to me"),
+ LabelValue.create((short) 0, "No score"),
+ LabelValue.create((short) -1, "I would prefer this is not merged as is")))
+ .setFunction(LabelFunction.MAX_WITH_BLOCK)
+ .setIgnoreSelfApproval(true)
+ .build();
+
+ labelTypes = Arrays.asList(codeReview, verified, codeStyle, ignoreSelfApprovalLabel);
}
@Test
@@ -129,6 +140,46 @@
}
@Test
+ public void defaultSubmitRule_withLabelStatusNeed_labelHasIgnoreSelfApproval() throws Exception {
+ SubmitRecord submitRecord =
+ createSubmitRecord(
+ "gerrit~DefaultSubmitRule",
+ Status.NOT_READY,
+ Arrays.asList(createLabel("ISA-Label", Label.Status.NEED)));
+
+ List<SubmitRequirementResult> requirements =
+ SubmitRequirementsAdapter.createResult(submitRecord, labelTypes, psCommitId);
+
+ assertThat(requirements).hasSize(1);
+ assertResult(
+ requirements.get(0),
+ /* reqName= */ "ISA-Label",
+ /* submitExpression= */ "label:ISA-Label=MAX,user=non_uploader -label:ISA-Label=MIN",
+ SubmitRequirementResult.Status.UNSATISFIED,
+ SubmitRequirementExpressionResult.Status.FAIL);
+ }
+
+ @Test
+ public void defaultSubmitRule_withLabelStatusOk_labelHasIgnoreSelfApproval() throws Exception {
+ SubmitRecord submitRecord =
+ createSubmitRecord(
+ "gerrit~DefaultSubmitRule",
+ Status.OK,
+ Arrays.asList(createLabel("ISA-Label", Label.Status.OK)));
+
+ List<SubmitRequirementResult> requirements =
+ SubmitRequirementsAdapter.createResult(submitRecord, labelTypes, psCommitId);
+
+ assertThat(requirements).hasSize(1);
+ assertResult(
+ requirements.get(0),
+ /* reqName= */ "ISA-Label",
+ /* submitExpression= */ "label:ISA-Label=MAX,user=non_uploader -label:ISA-Label=MIN",
+ SubmitRequirementResult.Status.SATISFIED,
+ SubmitRequirementExpressionResult.Status.PASS);
+ }
+
+ @Test
public void customSubmitRule_noLabels_withStatusOk() {
SubmitRecord submitRecord =
createSubmitRecord("gerrit~IgnoreSelfApprovalRule", Status.OK, Arrays.asList());
diff --git a/plugins/delete-project b/plugins/delete-project
index 7dce6f7..0b5bcbf 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit 7dce6f70611cd8dbf1d38628698155258ee8ef82
+Subproject commit 0b5bcbfc26d9c0559312ced40bb36a37f517b793
diff --git a/plugins/replication b/plugins/replication
index 46cfb7d..c62dcce 160000
--- a/plugins/replication
+++ b/plugins/replication
@@ -1 +1 @@
-Subproject commit 46cfb7dd5b6891f991cfe66e72c08953487c1c81
+Subproject commit c62dcced96659f717db59185e98d83398df50f46
diff --git a/polygerrit-ui/app/api/checks.ts b/polygerrit-ui/app/api/checks.ts
index 6c11e57..d52a555 100644
--- a/polygerrit-ui/app/api/checks.ts
+++ b/polygerrit-ui/app/api/checks.ts
@@ -144,8 +144,8 @@
* attempt. Every run has its own attempt numbering, so attempt 3 of run A is
* not directly related to attempt 3 of run B.
*
- * RUNNABLE runs must use `undefined` as attempt.
- * COMPLETED and RUNNING runs must use an attempt number >=0.
+ * The attempt number must be >=0. Only if you have just one RUNNABLE attempt,
+ * then you can leave it undefined.
*
* TBD: Optionally providing aggregate information about former attempts will
* probably be a useful feature, but we are deferring the exact data modeling
@@ -184,7 +184,8 @@
/**
* RUNNABLE: Not run (yet). Mostly useful for runs that the user can trigger
- * (see actions). Cannot contain results.
+ * (see actions) and for indicating that a check was not run at a
+ * later attempt. Cannot contain results.
* RUNNING: Subsumes "scheduled".
* COMPLETED: The attempt of the run has finished. Does not indicate at all
* whether the run was successful or not. Outcomes can and should
diff --git a/polygerrit-ui/app/api/diff.ts b/polygerrit-ui/app/api/diff.ts
index 26701e8..1453fd0 100644
--- a/polygerrit-ui/app/api/diff.ts
+++ b/polygerrit-ui/app/api/diff.ts
@@ -209,6 +209,18 @@
line_wrapping?: boolean;
}
+/**
+ * Listens to changes in token highlighting - when a new token starts or stopped being highlighted.
+ * Examples:
+ * - Token highlighted: ('myFunctionName', 12, [Element]).
+ * - Token unhighlighted: (undefined, 0, undefined).
+ */
+export type TokenHighlightedListener = (
+ newHighlight: string | undefined,
+ newLineNumber: number,
+ hoveredElement?: Element
+) => void;
+
export declare interface ImageDiffPreferences {
automatic_blink?: boolean;
}
diff --git a/polygerrit-ui/app/api/embed.ts b/polygerrit-ui/app/api/embed.ts
index ba378e2..fed724e 100644
--- a/polygerrit-ui/app/api/embed.ts
+++ b/polygerrit-ui/app/api/embed.ts
@@ -20,14 +20,24 @@
* limitations under the License.
*/
-import {DiffLayer, GrAnnotation, GrDiffCursor} from './diff';
+import {
+ DiffLayer,
+ GrAnnotation,
+ GrDiffCursor,
+ TokenHighlightedListener,
+} from './diff';
declare global {
interface Window {
grdiff: {
GrAnnotation: GrAnnotation;
GrDiffCursor: {new (): GrDiffCursor};
- TokenHighlightLayer: {new (container?: HTMLElement): DiffLayer};
+ TokenHighlightLayer: {
+ new (
+ container?: HTMLElement,
+ listener?: TokenHighlightedListener
+ ): DiffLayer;
+ };
};
}
}
diff --git a/polygerrit-ui/app/constants/constants.ts b/polygerrit-ui/app/constants/constants.ts
index 2acad49..8f94b38 100644
--- a/polygerrit-ui/app/constants/constants.ts
+++ b/polygerrit-ui/app/constants/constants.ts
@@ -304,3 +304,5 @@
theme: 'DEFAULT',
};
}
+
+export const RELOAD_DASHBOARD_INTERVAL_MS = 10 * 1000;
diff --git a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
index 9970dd5..2360312 100644
--- a/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-change-list-view/gr-change-list-view.ts
@@ -39,6 +39,7 @@
import {fireTitleChange} from '../../../utils/event-util';
import {appContext} from '../../../services/app-context';
import {GerritView} from '../../../services/router/router-model';
+import {RELOAD_DASHBOARD_INTERVAL_MS} from '../../../constants/constants';
const LOOKUP_QUERY_PATTERNS: RegExp[] = [
/^\s*i?[0-9a-f]{7,40}\s*$/i, // CHANGE_ID
@@ -112,10 +113,26 @@
private reporting = appContext.reportingService;
+ private lastVisibleTimestampMs = 0;
+
constructor() {
super();
this.addEventListener('next-page', () => this._handleNextPage());
this.addEventListener('previous-page', () => this._handlePreviousPage());
+ this.addEventListener('reload', () => this.reload());
+ // We are not currently verifying if the view is actually visible. We rely
+ // on gr-app-element to restamp the component if view changes
+ document.addEventListener('visibilitychange', () => {
+ if (document.visibilityState === 'visible') {
+ if (
+ Date.now() - this.lastVisibleTimestampMs >
+ RELOAD_DASHBOARD_INTERVAL_MS
+ )
+ this.reload();
+ } else {
+ this.lastVisibleTimestampMs = Date.now();
+ }
+ });
}
override connectedCallback() {
@@ -123,6 +140,15 @@
this._loadPreferences();
}
+ reload() {
+ if (this._loading) return;
+ this._loading = true;
+ this._getChanges().then(changes => {
+ this._changes = changes || [];
+ this._loading = false;
+ });
+ }
+
_paramsChanged(value: AppElementParams) {
if (value.view !== GerritView.SEARCH) return;
diff --git a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
index c341dea..456b7cf 100644
--- a/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
+++ b/polygerrit-ui/app/elements/change-list/gr-dashboard-view/gr-dashboard-view.ts
@@ -54,9 +54,9 @@
import {DashboardViewState} from '../../../types/types';
import {firePageError, fireTitleChange} from '../../../utils/event-util';
import {GerritView} from '../../../services/router/router-model';
+import {RELOAD_DASHBOARD_INTERVAL_MS} from '../../../constants/constants';
const PROJECT_PLACEHOLDER_PATTERN = /\${project}/g;
-const RELOAD_DASHBOARD_INTERVAL_MS = 10 * 1000;
export interface GrDashboardView {
$: {
@@ -122,12 +122,9 @@
constructor() {
super();
- }
-
- override connectedCallback() {
- super.connectedCallback();
- this._loadPreferences();
this.addEventListener('reload', () => this._reload(this.params));
+ // We are not currently verifying if the view is actually visible. We rely
+ // on gr-app-element to restamp the component if view changes
document.addEventListener('visibilitychange', () => {
if (document.visibilityState === 'visible') {
if (
@@ -141,6 +138,11 @@
});
}
+ override connectedCallback() {
+ super.connectedCallback();
+ this._loadPreferences();
+ }
+
_loadPreferences() {
return this.restApiService.getLoggedIn().then(loggedIn => {
if (loggedIn) {
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
index a090aee..fbf57f3 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog.ts
@@ -298,6 +298,9 @@
let newMessage = commitMessage;
if (changeStatus === 'MERGED') {
+ if (!newMessage.endsWith('\n')) {
+ newMessage += '\n';
+ }
newMessage += '(cherry picked from commit ' + commitNum.toString() + ')';
}
this.message = newMessage;
diff --git a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
index 90fddaa..ff078f0 100644
--- a/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
+++ b/polygerrit-ui/app/elements/change/gr-confirm-cherrypick-dialog/gr-confirm-cherrypick-dialog_test.js
@@ -46,6 +46,16 @@
element.project = 'test-project';
});
+ test('with message missing newline', () => {
+ element.changeStatus = 'MERGED';
+ element.commitMessage = 'message';
+ element.commitNum = '123';
+ element.branch = 'master';
+ flush();
+ const expectedMessage = 'message\n(cherry picked from commit 123)';
+ assert.equal(element.message, expectedMessage);
+ });
+
test('with merged change', () => {
element.changeStatus = 'MERGED';
element.commitMessage = 'message\n';
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts
index 4147cc0..a496be5 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores.ts
@@ -16,9 +16,8 @@
*/
import '../gr-label-score-row/gr-label-score-row';
import '../../../styles/shared-styles';
-import {PolymerElement} from '@polymer/polymer/polymer-element';
-import {htmlTemplate} from './gr-label-scores_html';
-import {customElement, property} from '@polymer/decorators';
+import {LitElement, css, html} from 'lit';
+import {customElement, property} from 'lit/decorators';
import {hasOwnProperty} from '../../../utils/common-util';
import {
LabelNameToValueMap,
@@ -33,21 +32,14 @@
Label,
LabelValuesMap,
} from '../gr-label-score-row/gr-label-score-row';
-import {PolymerDeepPropertyChange} from '@polymer/polymer/interfaces';
import {appContext} from '../../../services/app-context';
import {labelCompare} from '../../../utils/label-util';
import {Execution} from '../../../constants/reporting';
+import {ChangeStatus} from '../../../constants/constants';
@customElement('gr-label-scores')
-export class GrLabelScores extends PolymerElement {
- static get template() {
- return htmlTemplate;
- }
-
- @property({type: Array, computed: '_computeLabels(change.labels.*, account)'})
- _labels: Label[] = [];
-
- @property({type: Object, observer: '_computeColumns'})
+export class GrLabelScores extends LitElement {
+ @property({type: Object})
permittedLabels?: LabelNameToValueMap;
@property({type: Object})
@@ -56,11 +48,63 @@
@property({type: Object})
account?: AccountInfo;
- @property({type: Object})
- _labelValues?: LabelValuesMap;
-
private readonly reporting = appContext.reportingService;
+ static override get styles() {
+ return [
+ css`
+ .scoresTable {
+ display: table;
+ width: 100%;
+ }
+ .mergedMessage,
+ .abandonedMessage {
+ font-style: italic;
+ text-align: center;
+ width: 100%;
+ }
+ gr-label-score-row:hover {
+ background-color: var(--hover-background-color);
+ }
+ gr-label-score-row {
+ display: table-row;
+ }
+ gr-label-score-row.no-access {
+ display: none;
+ }
+ `,
+ ];
+ }
+
+ override render() {
+ const labels = this._computeLabels();
+ const labelValues = this._computeColumns();
+ return html`<div class="scoresTable">
+ ${labels.map(
+ label => html`<gr-label-score-row
+ class="${this.computeLabelAccessClass(label.name)}"
+ .label="${label}"
+ .name="${label.name}"
+ .labels="${this.change?.labels}"
+ .permittedLabels="${this.permittedLabels}"
+ .labelValues="${labelValues}"
+ ></gr-label-score-row>`
+ )}
+ </div>
+ <div
+ class="mergedMessage"
+ ?hidden=${this.change?.status !== ChangeStatus.MERGED}
+ >
+ Because this change has been merged, votes may not be decreased.
+ </div>
+ <div
+ class="abandonedMessage"
+ ?hidden=${this.change?.status !== ChangeStatus.ABANDONED}
+ >
+ Because this change has been abandoned, you cannot vote.
+ </div>`;
+ }
+
getLabelValues(includeDefaults = true): LabelNameToValuesMap {
const labels: LabelNameToValuesMap = {};
if (this.shadowRoot === null || !this.change) {
@@ -79,7 +123,7 @@
if (selectedVal === undefined) continue;
- const defValNum = this._getDefaultValue(this.change.labels, label);
+ const defValNum = this.getDefaultValue(label);
if (includeDefaults || selectedVal !== defValNum) {
labels[label] = selectedVal;
}
@@ -87,7 +131,7 @@
return labels;
}
- _getStringLabelValue(
+ private getStringLabelValue(
labels: LabelNameToInfoMap,
labelName: string,
numberValue?: number
@@ -108,25 +152,26 @@
return stringVal;
}
- _getDefaultValue(labels?: LabelNameToInfoMap, labelName?: string) {
+ private getDefaultValue(labelName?: string) {
+ const labels = this.change?.labels;
if (!labelName || !labels?.[labelName]) return undefined;
const labelInfo = labels[labelName] as DetailedLabelInfo;
return labelInfo.default_value;
}
- _getVoteForAccount(
- labels: LabelNameToInfoMap | undefined,
- labelName: string,
- account?: AccountInfo
- ): string | null {
+ _getVoteForAccount(labelName: string): string | null {
+ const labels = this.change?.labels;
if (!labels) return null;
const votes = labels[labelName] as DetailedLabelInfo;
if (votes.all && votes.all.length > 0) {
for (let i = 0; i < votes.all.length; i++) {
- // TODO(TS): Replace == with === and check code can assign string to _account_id instead of number
- // eslint-disable-next-line eqeqeq
- if (account && votes.all[i]._account_id == account._account_id) {
- return this._getStringLabelValue(
+ if (
+ this.account &&
+ // TODO(TS): Replace == with === and check code can assign string to _account_id instead of number
+ // eslint-disable-next-line eqeqeq
+ votes.all[i]._account_id == this.account._account_id
+ ) {
+ return this.getStringLabelValue(
labels,
labelName,
votes.all[i].value
@@ -137,32 +182,26 @@
return null;
}
- _computeLabels(
- labelRecord: PolymerDeepPropertyChange<
- LabelNameToInfoMap,
- LabelNameToInfoMap
- >,
- account?: AccountInfo
- ): Label[] {
- if (!account) return [];
- if (!labelRecord?.base) return [];
- const labelsObj = labelRecord.base;
+ _computeLabels(): Label[] {
+ if (!this.account) return [];
+ const labelsObj = this.change?.labels;
+ if (!labelsObj) return [];
return Object.keys(labelsObj)
.sort(labelCompare)
.map(key => {
return {
name: key,
- value: this._getVoteForAccount(labelsObj, key, this.account),
+ value: this._getVoteForAccount(key),
};
});
}
- _computeColumns(permittedLabels?: LabelNameToValueMap) {
- if (!permittedLabels) return;
- const labels = Object.keys(permittedLabels);
+ _computeColumns() {
+ if (!this.permittedLabels) return;
+ const labels = Object.keys(this.permittedLabels);
const values: Set<number> = new Set();
for (const label of labels) {
- for (const value of permittedLabels[label]) {
+ for (const value of this.permittedLabels[label]) {
values.add(Number(value));
}
}
@@ -173,23 +212,14 @@
for (let i = 0; i < orderedValues.length; i++) {
labelValues[orderedValues[i]] = i;
}
- this._labelValues = labelValues;
+ return labelValues;
}
- _changeIsMerged(changeStatus: string) {
- return changeStatus === 'MERGED';
- }
+ private computeLabelAccessClass(label?: string) {
+ if (!this.permittedLabels || !label) return '';
- _computeLabelAccessClass(
- label?: string,
- permittedLabels?: LabelNameToValueMap
- ) {
- if (!permittedLabels || !label) {
- return '';
- }
-
- return hasOwnProperty(permittedLabels, label) &&
- permittedLabels[label].length
+ return hasOwnProperty(this.permittedLabels, label) &&
+ this.permittedLabels[label].length
? 'access'
: 'no-access';
}
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_html.ts b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_html.ts
deleted file mode 100644
index 7b1fb7f..0000000
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_html.ts
+++ /dev/null
@@ -1,55 +0,0 @@
-/**
- * @license
- * Copyright (C) 2020 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.
- */
-import {html} from '@polymer/polymer/lib/utils/html-tag';
-
-export const htmlTemplate = html`
- <style include="shared-styles">
- .scoresTable {
- display: table;
- width: 100%;
- }
- .mergedMessage {
- font-style: italic;
- text-align: center;
- width: 100%;
- }
- gr-label-score-row:hover {
- background-color: var(--hover-background-color);
- }
- gr-label-score-row {
- display: table-row;
- }
- gr-label-score-row.no-access {
- display: none;
- }
- </style>
- <div class="scoresTable">
- <template is="dom-repeat" items="[[_labels]]" as="label">
- <gr-label-score-row
- class$="[[_computeLabelAccessClass(label.name, permittedLabels)]]"
- label="[[label]]"
- name="[[label.name]]"
- labels="[[change.labels]]"
- permitted-labels="[[permittedLabels]]"
- label-values="[[_labelValues]]"
- ></gr-label-score-row>
- </template>
- </div>
- <div class="mergedMessage" hidden$="[[!_changeIsMerged(change.status)]]">
- Because this change has been merged, votes may not be decreased.
- </div>
-`;
diff --git a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.ts b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.ts
index 58fe189..cfecf91 100644
--- a/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.ts
+++ b/polygerrit-ui/app/elements/change/gr-label-scores/gr-label-scores_test.ts
@@ -17,7 +17,7 @@
import '../../../test/common-test-setup-karma';
import './gr-label-scores';
-import {queryAndAssert, stubRestApi} from '../../../test/test-utils';
+import {isHidden, queryAndAssert, stubRestApi} from '../../../test/test-utils';
import {GrLabelScores} from './gr-label-scores';
import {AccountId} from '../../../types/common';
import {GrLabelScoreRow} from '../gr-label-score-row/gr-label-score-row';
@@ -25,6 +25,7 @@
createAccountWithId,
createChange,
} from '../../../test/test-data-generators';
+import {ChangeStatus} from '../../../constants/constants';
const basicFixture = fixtureFromElement('gr-label-scores');
@@ -116,19 +117,12 @@
test('_getVoteForAccount', () => {
const labelName = 'Code-Review';
- assert.strictEqual(
- element._getVoteForAccount(
- element.change!.labels,
- labelName,
- element.account
- ),
- '+1'
- );
+ assert.strictEqual(element._getVoteForAccount(labelName), '+1');
});
test('_computeColumns', () => {
- element._computeColumns(element.permittedLabels);
- assert.deepEqual(element._labelValues, {
+ const labelValues = element._computeColumns();
+ assert.deepEqual(labelValues, {
'-2': 0,
'-1': 1,
'0': 2,
@@ -137,31 +131,8 @@
});
});
- test('_computeLabelAccessClass undefined case', () => {
- assert.strictEqual(
- element._computeLabelAccessClass(undefined, undefined),
- ''
- );
- assert.strictEqual(element._computeLabelAccessClass('', undefined), '');
- assert.strictEqual(element._computeLabelAccessClass(undefined, {}), '');
- });
-
- test('_computeLabelAccessClass has access', () => {
- assert.strictEqual(
- element._computeLabelAccessClass('foo', {foo: ['']}),
- 'access'
- );
- });
-
- test('_computeLabelAccessClass no access', () => {
- assert.strictEqual(
- element._computeLabelAccessClass('zap', {foo: ['']}),
- 'no-access'
- );
- });
-
- test('changes in label score are reflected in _labels', () => {
- element.change = {
+ test('changes in label score are reflected in _labels', async () => {
+ const change = {
...createChange(),
labels: {
'Code-Review': {
@@ -186,17 +157,62 @@
},
},
};
- assert.deepEqual(element._labels, [
+ element.change = change;
+ await flush();
+ let labels = element._computeLabels();
+ assert.deepEqual(labels, [
{name: 'Code-Review', value: null},
{name: 'Verified', value: null},
]);
- element.set(
- ['change', 'labels', 'Verified', 'all'],
- [{_account_id: accountId, value: 1}]
- );
- assert.deepEqual(element._labels, [
+ element.change = {
+ ...change,
+ labels: {
+ ...change.labels,
+ Verified: {
+ ...change.labels.Verified,
+ all: [
+ {
+ _account_id: accountId,
+ value: 1,
+ },
+ ],
+ },
+ },
+ };
+ await flush();
+ labels = element._computeLabels();
+ assert.deepEqual(labels, [
{name: 'Code-Review', value: null},
{name: 'Verified', value: '+1'},
]);
});
+ suite('message', () => {
+ test('shown when change is abandoned', async () => {
+ element.change = {
+ ...createChange(),
+ status: ChangeStatus.ABANDONED,
+ };
+ await flush();
+ assert.isFalse(isHidden(queryAndAssert(element, '.abandonedMessage')));
+ assert.isTrue(isHidden(queryAndAssert(element, '.mergedMessage')));
+ });
+ test('shown when change is merged', async () => {
+ element.change = {
+ ...createChange(),
+ status: ChangeStatus.MERGED,
+ };
+ await flush();
+ assert.isFalse(isHidden(queryAndAssert(element, '.mergedMessage')));
+ assert.isTrue(isHidden(queryAndAssert(element, '.abandonedMessage')));
+ });
+ test('do not show for new', async () => {
+ element.change = {
+ ...createChange(),
+ status: ChangeStatus.NEW,
+ };
+ await flush();
+ assert.isTrue(isHidden(queryAndAssert(element, '.mergedMessage')));
+ assert.isTrue(isHidden(queryAndAssert(element, '.abandonedMessage')));
+ });
+ });
});
diff --git a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
index 058007b..b081be7 100644
--- a/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-reviewer-list/gr-reviewer-list_html.ts
@@ -58,8 +58,8 @@
display: inline-block;
}
gr-vote-chip {
- --gr-vote-chip-width: 16px;
- --gr-vote-chip-height: 16px;
+ --gr-vote-chip-width: 14px;
+ --gr-vote-chip-height: 14px;
}
</style>
<div class="container">
diff --git a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
index 286f24a..724d803 100644
--- a/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
+++ b/polygerrit-ui/app/elements/change/gr-submit-requirements/gr-submit-requirements.ts
@@ -30,6 +30,7 @@
extractAssociatedLabels,
iconForStatus,
} from '../../../utils/label-util';
+import {fontStyles} from '../../../styles/gr-font-styles';
@customElement('gr-submit-requirements')
export class GrSubmitRequirements extends LitElement {
@@ -44,43 +45,19 @@
static override get styles() {
return [
+ fontStyles,
css`
- :host {
- display: table;
- width: 100%;
- }
.metadata-title {
- font-size: 100%;
font-weight: var(--font-weight-bold);
color: var(--deemphasized-text-color);
padding-left: var(--metadata-horizontal-padding);
- }
- section {
- display: table-row;
- }
- .title {
- min-width: 10em;
- padding: var(--spacing-s) 0 0 0;
- }
- .value {
- padding: var(--spacing-s) 0 0 0;
- }
- .title,
- .status {
- display: table-cell;
- vertical-align: top;
- }
- .value {
- display: inline-flex;
- }
- .status {
- width: var(--line-height-small);
- padding: var(--spacing-s) var(--spacing-m) 0
- var(--requirements-horizontal-padding);
+ margin: 0 0 var(--spacing-s);
+ border-top: 1px solid var(--border-color);
+ padding-top: var(--spacing-s);
}
iron-icon {
- width: var(--line-height-small);
- height: var(--line-height-small);
+ width: var(--line-height-normal, 20px);
+ height: var(--line-height-normal, 20px);
}
iron-icon.check {
color: var(--success-foreground);
@@ -102,6 +79,20 @@
.testing:hover * {
visibility: visible;
}
+ .requirements,
+ section.votes {
+ margin-left: var(--spacing-l);
+ }
+ gr-limited-text.name {
+ font-weight: var(--font-weight-bold);
+ }
+ table {
+ border-collapse: collapse;
+ border-spacing: 0;
+ }
+ td {
+ padding: var(--spacing-s);
+ }
`,
];
}
@@ -110,25 +101,46 @@
const submit_requirements = (this.change?.submit_requirements ?? []).filter(
req => req.status !== SubmitRequirementStatus.NOT_APPLICABLE
);
- return html`<h3 class="metadata-title">Submit Requirements</h3>
+ return html` <h2
+ class="metadata-title heading-3"
+ id="submit-requirements-caption"
+ >
+ Submit Requirements
+ </h2>
+ <table class="requirements" aria-labelledby="submit-requirements-caption">
+ <thead hidden>
+ <tr>
+ <th>Status</th>
+ <th>Name</th>
+ <th>Votes</th>
+ </tr>
+ </thead>
+ <tbody>
+ ${submit_requirements.map(
+ requirement => html`<tr id="requirement-${requirement.name}">
+ <td>${this.renderStatus(requirement.status)}</td>
+ <td class="name">
+ <gr-limited-text
+ class="name"
+ limit="25"
+ .text="${requirement.name}"
+ ></gr-limited-text>
+ </td>
+ <td>${this.renderVotes(requirement)}</td>
+ </tr>`
+ )}
+ </tbody>
+ </table>
${submit_requirements.map(
- requirement => html`<section>
+ requirement => html`
<gr-submit-requirement-hovercard
+ for="requirement-${requirement.name}"
.requirement="${requirement}"
.change="${this.change}"
.account="${this.account}"
.mutable="${this.mutable}"
></gr-submit-requirement-hovercard>
- <div class="status">${this.renderStatus(requirement.status)}</div>
- <div class="title">
- <gr-limited-text
- class="name"
- limit="25"
- text="${requirement.name}"
- ></gr-limited-text>
- </div>
- <div class="value">${this.renderVotes(requirement)}</div>
- </section>`
+ `
)}
${this.renderTriggerVotes(
submit_requirements
@@ -140,6 +152,8 @@
return html`<iron-icon
class="${icon}"
icon="gr-icons:${icon}"
+ role="img"
+ aria-label="${status.toLowerCase()}"
></iron-icon>`;
}
@@ -183,17 +197,19 @@
label => !labelAssociatedWithSubmitReqs.includes(label)
);
if (!triggerVotes.length) return;
- return html`<h3 class="metadata-title">Trigger Votes</h3>
- ${triggerVotes.map(
- label => html`${label}:
- <gr-label-info
- .change="${this.change}"
- .account="${this.account}"
- .mutable="${this.mutable}"
- label="${label}"
- .labelInfo="${labels[label]}"
- ></gr-label-info>`
- )}`;
+ return html`<h3 class="metadata-title heading-3">Trigger Votes</h3>
+ <section class="votes">
+ ${triggerVotes.map(
+ label => html`${label}:
+ <gr-label-info
+ .change="${this.change}"
+ .account="${this.account}"
+ .mutable="${this.mutable}"
+ label="${label}"
+ .labelInfo="${labels[label]}"
+ ></gr-label-info>`
+ )}
+ </section>`;
}
renderFakeControls() {
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
index 4d97fec..6ed5a2c 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_html.ts
@@ -102,9 +102,9 @@
items="[[getCommentsDropdownEntires(threads, loggedIn)]]"
>
</gr-dropdown-list>
- <template is="dom-if" if="[[threads.length]]">
+ <template is="dom-if" if="[[_displayedThreads.length]]">
<span class="author-text">From:</span>
- <template is="dom-repeat" items="[[getCommentAuthors(threads, account)]]">
+ <template is="dom-repeat" items="[[getCommentAuthors(_displayedThreads, account)]]">
<gr-account-label
account="[[item]]"
on-click="handleAccountClicked"
diff --git a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
index b478ef5..aab5cee 100644
--- a/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
+++ b/polygerrit-ui/app/elements/change/gr-thread-list/gr-thread-list_test.js
@@ -495,15 +495,18 @@
test('tapping single author chips', () => {
element.account = createAccountDetailWithId(1);
flush();
- const chips = queryAll(element, 'gr-account-label');
- const authors = Array.from(chips).map(
+ const chips = Array.from(queryAll(element, 'gr-account-label'));
+ const authors = chips.map(
chip => accountOrGroupKey(chip.account))
.sort();
assert.deepEqual(authors, [1, 1000000, 1000001, 1000002, 1000003]);
assert.equal(element.threads.length, 9);
assert.equal(element._displayedThreads.length, 9);
- tap(chips[0]); // accountId 1000001
+ // accountId 1000001
+ const chip = chips.find(chip => chip.account._account_id === 1000001);
+
+ tap(chip);
flush();
assert.equal(element.threads.length, 9);
@@ -511,7 +514,7 @@
assert.equal(element._displayedThreads[0].comments[0].author._account_id,
1000001);
- tap(chips[0]); // tapping again resets
+ tap(chip); // tapping again resets
flush();
assert.equal(element.threads.length, 9);
assert.equal(element._displayedThreads.length, 9);
@@ -520,10 +523,10 @@
test('tapping multiple author chips', () => {
element.account = createAccountDetailWithId(1);
flush();
- const chips = queryAll(element, 'gr-account-label');
+ const chips = Array.from(queryAll(element, 'gr-account-label'));
- tap(chips[0]); // accountId 1000001
- tap(chips[2]); // accountId 1000002
+ tap(chips.find(chip => chip.account._account_id === 1000001));
+ tap(chips.find(chip => chip.account._account_id === 1000002));
flush();
assert.equal(element.threads.length, 9);
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-results.ts b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
index de334be..90f7215 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-results.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-results.ts
@@ -54,7 +54,7 @@
import {modifierPressed, toggleClass, whenVisible} from '../../utils/dom-util';
import {durationString} from '../../utils/date-util';
import {charsOnly} from '../../utils/string-util';
-import {isAttemptSelected} from './gr-checks-util';
+import {isAttemptSelected, matches} from './gr-checks-util';
import {ChecksTabState} from '../../types/events';
import {
ConfigInfo,
@@ -1185,11 +1185,8 @@
);
const isSelection = this.selectedRuns.length > 0;
const selected = all.filter(result => this.isRunSelected(result));
- const filtered = selected.filter(
- result =>
- this.filterRegExp.test(result.checkName) ||
- this.filterRegExp.test(result.summary) ||
- this.filterRegExp.test(result.message ?? '')
+ const filtered = selected.filter(result =>
+ matches(result, this.filterRegExp)
);
let expanded = this.isSectionExpanded.get(category);
const expandedByUser = this.isSectionExpandedByUser.get(category) ?? false;
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
index d296a46..28354d2 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-runs.ts
@@ -16,7 +16,7 @@
*/
import {classMap} from 'lit/directives/class-map';
import './gr-hovercard-run';
-import {LitElement, css, html, nothing, PropertyValues} from 'lit';
+import {css, html, LitElement, nothing, PropertyValues} from 'lit';
import {customElement, property, query, state} from 'lit/decorators';
import './gr-checks-attempt';
import {Action, Link, RunStatus} from '../../api/checks';
@@ -24,6 +24,7 @@
import {
AttemptDetail,
compareByWorstCategory,
+ headerForStatus,
iconFor,
iconForRun,
PRIMARY_STATUS_ACTIONS,
@@ -276,16 +277,20 @@
const checkNameId = charsOnly(this.run.checkName).toLowerCase();
const id = `attempt-${detail.attempt}`;
const icon = detail.icon;
+ const wasNotRun = icon === iconFor(RunStatus.RUNNABLE);
return html`<div class="attemptDetail">
<input
type="radio"
id="${id}"
name="${`${checkNameId}-attempt-choice`}"
?checked="${this.isSelected(detail)}"
+ ?disabled="${!this.isSelected(detail) && wasNotRun}"
@change="${() => this.handleAttemptChange(detail)}"
/>
<iron-icon class="${icon}" icon="gr-icons:${icon}"></iron-icon>
- <label for="${id}">Attempt ${detail.attempt}</label>
+ <label for="${id}">
+ Attempt ${detail.attempt}${wasNotRun ? ' (not run)' : ''}
+ </label>
</div>`;
}
@@ -698,7 +703,7 @@
@click="${() => this.toggleExpanded(status)}"
>
<iron-icon class="expandIcon" icon="${icon}"></iron-icon>
- <h3 class="heading-3">${status.toLowerCase()}</h3>
+ <h3 class="heading-3">${headerForStatus(status)}</h3>
</div>
<div class="sectionRuns">${runs.map(run => this.renderRun(run))}</div>
</div>
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-util.ts b/polygerrit-ui/app/elements/checks/gr-checks-util.ts
index 05a87a4..e9bbb22 100644
--- a/polygerrit-ui/app/elements/checks/gr-checks-util.ts
+++ b/polygerrit-ui/app/elements/checks/gr-checks-util.ts
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {CheckRun} from '../../services/checks/checks-model';
+import {CheckRun, RunResult} from '../../services/checks/checks-model';
export interface AttemptSelectedEventDetail {
checkName: string;
@@ -85,3 +85,12 @@
(selected === undefined && run.isLatestAttempt) || selected === run.attempt
);
}
+
+export function matches(result: RunResult, regExp: RegExp) {
+ return (
+ regExp.test(result.checkName) ||
+ regExp.test(result.summary) ||
+ (result.tags ?? []).some(tag => regExp.test(tag.name)) ||
+ regExp.test(result.message ?? '')
+ );
+}
diff --git a/polygerrit-ui/app/elements/checks/gr-checks-util_test.ts b/polygerrit-ui/app/elements/checks/gr-checks-util_test.ts
new file mode 100644
index 0000000..698a4a1
--- /dev/null
+++ b/polygerrit-ui/app/elements/checks/gr-checks-util_test.ts
@@ -0,0 +1,34 @@
+/**
+ * @license
+ * Copyright (C) 2021 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.
+ */
+import '../../test/common-test-setup-karma';
+import {createRunResult} from '../../test/test-data-generators';
+import {matches} from './gr-checks-util';
+import {RunResult} from '../../services/checks/checks-model';
+
+suite('gr-checks-util test', () => {
+ test('regexp filter matching results', () => {
+ const result: RunResult = {
+ ...createRunResult(),
+ tags: [{name: 'tag'}],
+ };
+ assert.isTrue(matches(result, new RegExp('message')));
+ assert.isTrue(matches(result, new RegExp('summary')));
+ assert.isTrue(matches(result, new RegExp('name')));
+ assert.isTrue(matches(result, new RegExp('tag')));
+ assert.isFalse(matches(result, new RegExp('qwertyui')));
+ });
+});
diff --git a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
index 6dd67e4..1c25755 100644
--- a/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
+++ b/polygerrit-ui/app/elements/diff/gr-apply-fix-dialog/gr-apply-fix-dialog.ts
@@ -38,7 +38,7 @@
import {OpenFixPreviewEvent} from '../../../types/events';
import {appContext} from '../../../services/app-context';
import {fireCloseFixPreview, fireEvent} from '../../../utils/event-util';
-import {ParsedChangeInfo} from '../../../types/types';
+import {DiffLayer, ParsedChangeInfo} from '../../../types/types';
import {GrButton} from '../../shared/gr-button/gr-button';
import {TokenHighlightLayer} from '../gr-diff-builder/token-highlight-layer';
import {KnownExperimentId} from '../../../services/flags/flags';
@@ -99,16 +99,25 @@
})
_disableApplyFixButton = false;
- layers = appContext.flagsService.isEnabled(
- KnownExperimentId.TOKEN_HIGHLIGHTING
- )
- ? [new TokenHighlightLayer(this)]
- : [];
+ @property({type: Array})
+ layers: DiffLayer[] = [];
private refitOverlay?: () => void;
private readonly restApiService = appContext.restApiService;
+ constructor() {
+ super();
+ this.restApiService.getPreferences().then(prefs => {
+ if (
+ !prefs?.disable_token_highlighting &&
+ appContext.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING)
+ ) {
+ this.layers = [new TokenHighlightLayer(this)];
+ }
+ });
+ }
+
/**
* Given robot comment CustomEvent object, fetch diffs associated
* with first robot comment suggested fix and open dialog.
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer.ts
index 4cc98d0a..480e26c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer.ts
@@ -15,7 +15,7 @@
* limitations under the License.
*/
import {DiffLayer, DiffLayerListener} from '../../../types/types';
-import {GrDiffLine, Side} from '../../../api/diff';
+import {GrDiffLine, Side, TokenHighlightedListener} from '../../../api/diff';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation';
import {debounce, DelayedTask} from '../../../utils/async-util';
import {
@@ -65,6 +65,9 @@
/** The currently highlighted token. */
private currentHighlight?: string;
+ /** Trigger when a new token starts or stoped being highlighted.*/
+ private readonly tokenHighlightedListener?: TokenHighlightedListener;
+
/**
* The line of the currently highlighted token. We store this in order to
* re-render only relevant lines of the diff. Only lines visible on the screen
@@ -95,7 +98,11 @@
private updateTokenTask?: DelayedTask;
- constructor(container: HTMLElement = document.documentElement) {
+ constructor(
+ container: HTMLElement = document.documentElement,
+ tokenHighlightedListener?: TokenHighlightedListener
+ ) {
+ this.tokenHighlightedListener = tokenHighlightedListener;
container.addEventListener('click', e => {
this.handleContainerClick(e);
});
@@ -188,7 +195,7 @@
this.updateTokenTask = debounce(
this.updateTokenTask,
() => {
- this.updateTokenHighlight(newHighlight, line);
+ this.updateTokenHighlight(newHighlight, line, element);
},
HOVER_DELAY_MS
);
@@ -203,11 +210,11 @@
if (element) return;
this.hoveredElement = undefined;
this.updateTokenTask?.cancel();
- this.updateTokenHighlight(undefined, 0);
+ this.updateTokenHighlight(undefined, 0, undefined);
}
private interferesWithSelection() {
- return window.getSelection()?.type === 'Range';
+ return document.getSelection()?.type === 'Range';
}
findTokenAncestor(el?: EventTarget | Element | null): {
@@ -241,7 +248,8 @@
private updateTokenHighlight(
newHighlight: string | undefined,
- newLineNumber: number
+ newLineNumber: number,
+ newHoveredElement: Element | undefined
) {
if (
this.currentHighlight === newHighlight &&
@@ -253,6 +261,13 @@
this.currentHighlight = newHighlight;
this.currentHighlightLineNumber = newLineNumber;
+ if (this.tokenHighlightedListener) {
+ this.tokenHighlightedListener(
+ newHighlight,
+ newLineNumber,
+ newHoveredElement
+ );
+ }
this.notifyForToken(oldHighlight, oldLineNumber);
this.notifyForToken(newHighlight, newLineNumber);
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer_test.ts b/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer_test.ts
index 9fc69b5..4f44665 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer_test.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-builder/token-highlight-layer_test.ts
@@ -21,7 +21,7 @@
import {GrDiffLine, GrDiffLineType} from '../gr-diff/gr-diff-line.js';
import {HOVER_DELAY_MS, TokenHighlightLayer} from './token-highlight-layer';
import {GrAnnotation} from '../gr-diff-highlight/gr-annotation';
-import {html, render} from 'lit-html';
+import {html, render} from 'lit';
import {_testOnly_allTasks} from '../../../utils/async-util';
import {queryAndAssert} from '../../../test/test-utils';
@@ -66,12 +66,22 @@
let container: HTMLElement;
let listener: MockListener;
let highlighter: TokenHighlightLayer;
+ let tokenHighlightingCalls: any[] = [];
+
+ function tokenHighlightedListener(
+ newHighlight: string | undefined,
+ newLineNumber: number,
+ hoveredElement?: Element
+ ) {
+ tokenHighlightingCalls.push({newHighlight, newLineNumber, hoveredElement});
+ }
setup(async () => {
listener = new MockListener();
+ tokenHighlightingCalls = [];
container = document.createElement('div');
document.body.appendChild(container);
- highlighter = new TokenHighlightLayer(container);
+ highlighter = new TokenHighlightLayer(container, tokenHighlightedListener);
highlighter.addListener((...args) => listener.notify(...args));
});
@@ -251,6 +261,37 @@
assert.equal(_testOnly_allTasks.size, 0);
});
+ test('triggers listener for applying and clearing highlighting', async () => {
+ const clock = sinon.useFakeTimers();
+ const line1 = createLine('two words');
+ annotate(line1);
+ const line2 = createLine('three words', 2);
+ annotate(line2, Side.RIGHT, 2);
+ const words1 = queryAndAssert(line1, '.tk-words');
+ assert.isTrue(words1.classList.contains('token'));
+ dispatchMouseEvent(
+ 'mouseover',
+ MockInteractions.middleOfNode(words1),
+ words1
+ );
+ assert.equal(tokenHighlightingCalls.length, 0);
+ clock.tick(HOVER_DELAY_MS);
+ assert.equal(tokenHighlightingCalls.length, 1);
+ assert.deepEqual(tokenHighlightingCalls[0], {
+ newHighlight: 'words',
+ newLineNumber: 1,
+ hoveredElement: words1,
+ });
+
+ MockInteractions.click(container);
+ assert.equal(tokenHighlightingCalls.length, 2);
+ assert.deepEqual(tokenHighlightingCalls[1], {
+ newHighlight: undefined,
+ newLineNumber: 0,
+ hoveredElement: undefined,
+ });
+ });
+
test('clicking clears highlight', async () => {
const clock = sinon.useFakeTimers();
const line1 = createLine('two words');
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
index 18fbe9a..4c1295f 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-highlight/gr-diff-highlight_test.js
@@ -251,7 +251,7 @@
};
const emulateSelection = (startNode, startOffset, endNode, endOffset) => {
- const selection = window.getSelection();
+ const selection = document.getSelection();
const range = document.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
@@ -281,7 +281,7 @@
teardown(() => {
contentStubs = null;
- window.getSelection().removeAllRanges();
+ document.getSelection().removeAllRanges();
});
test('single first line', () => {
@@ -389,7 +389,7 @@
test('collapsed', () => {
const content = stubContent(138, 'left');
emulateSelection(content.firstChild, 5, content.firstChild, 5);
- assert.isOk(window.getSelection().getRangeAt(0).startContainer);
+ assert.isOk(document.getSelection().getRangeAt(0).startContainer);
assert.isFalse(!!element.selectedRange);
});
@@ -556,7 +556,7 @@
content.querySelectorAll('hl')[3], 0,
content.querySelectorAll('span')[1], 0);
const spyCall = spy.getCall(0);
- const range = window.getSelection().getRangeAt(0);
+ const range = document.getSelection().getRangeAt(0);
assert.notDeepEqual(spyCall.returnValue, range);
});
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
index c4fed53..463163c 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-host/gr-diff-host.ts
@@ -223,6 +223,9 @@
@property({type: Boolean})
_loggedIn = false;
+ @property({type: Boolean})
+ disableTokenHighlighting = false;
+
@property({type: String})
_errorMessage: string | null = null;
@@ -300,6 +303,11 @@
this.addEventListener('diff-context-expanded', event =>
this._handleDiffContextExpanded(event)
);
+ appContext.restApiService.getPreferences().then(prefs => {
+ if (prefs?.disable_token_highlighting) {
+ this.disableTokenHighlighting = prefs.disable_token_highlighting;
+ }
+ });
}
override ready() {
@@ -413,7 +421,8 @@
private _getLayers(path: string): DiffLayer[] {
const layers = [];
if (
- appContext.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING)
+ appContext.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING) &&
+ !this.disableTokenHighlighting
) {
layers.push(new TokenHighlightLayer(this));
}
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.ts b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.ts
index 0051b8b..2665ef0 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.ts
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection.ts
@@ -195,7 +195,7 @@
_getSelection() {
const diffHosts = querySelectorAll(document.body, 'gr-diff');
- if (!diffHosts.length) return window.getSelection();
+ if (!diffHosts.length) return document.getSelection();
const curDiffHost = diffHosts.find(diffHost => {
if (!diffHost?.shadowRoot?.getSelection) return false;
@@ -205,9 +205,9 @@
return selection && selection.type !== 'None';
});
- return curDiffHost
- ? curDiffHost.shadowRoot!.getSelection()
- : window.getSelection();
+ return curDiffHost?.shadowRoot?.getSelection
+ ? curDiffHost.shadowRoot.getSelection()
+ : document.getSelection();
}
/**
diff --git a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
index 8d7264c..15454f9 100644
--- a/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
+++ b/polygerrit-ui/app/elements/diff/gr-diff-selection/gr-diff-selection_test.js
@@ -247,7 +247,7 @@
element.classList.add('selected-left');
element.classList.remove('selected-right');
- const selection = window.getSelection();
+ const selection = document.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.setStart(element.querySelector('div.contentText').firstChild, 3);
@@ -261,7 +261,7 @@
element.classList.add('selected-left');
element.classList.add('selected-comment');
element.classList.remove('selected-right');
- const selection = window.getSelection();
+ const selection = document.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.setStart(
@@ -277,7 +277,7 @@
element.classList.add('selected-left');
element.classList.add('selected-comment');
element.classList.remove('selected-right');
- const selection = window.getSelection();
+ const selection = document.getSelection();
selection.removeAllRanges();
const range = document.createRange();
const nodes = element.querySelectorAll('.gr-formatted-text *');
@@ -307,7 +307,7 @@
element.classList.add('selected-right');
element.classList.remove('selected-left');
- const selection = window.getSelection();
+ const selection = document.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.setStart(
@@ -329,7 +329,7 @@
};
element.classList.add('selected-left');
element.classList.remove('selected-right');
- const selection = window.getSelection();
+ const selection = document.getSelection();
selection.removeAllRanges();
const range = document.createRange();
range.setStart(element.querySelector('div.contentText').firstChild, 3);
@@ -348,7 +348,7 @@
element.classList.add('selected-left');
element.classList.add('selected-comment');
element.classList.remove('selected-right');
- selection = window.getSelection();
+ selection = document.getSelection();
selection.removeAllRanges();
range = document.createRange();
nodes = element.querySelectorAll('.gr-formatted-text *');
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
index 453bc3f..da4bb0a 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view.ts
@@ -85,6 +85,7 @@
'diff_view',
'publish_comments_on_push',
'disable_keyboard_shortcuts',
+ 'disable_token_highlighting',
'work_in_progress_by_default',
'default_base_for_merges',
'signed_off_by',
@@ -124,6 +125,7 @@
showSizeBarsInFileList: HTMLInputElement;
publishCommentsOnPush: HTMLInputElement;
disableKeyboardShortcuts: HTMLInputElement;
+ disableTokenHighlighting: HTMLInputElement;
relativeDateInChangeTable: HTMLInputElement;
changesPerPageSelect: HTMLInputElement;
dateTimeFormatSelect: HTMLInputElement;
@@ -408,6 +410,13 @@
);
}
+ _handleDisableTokenHighlightingChanged() {
+ this.set(
+ '_localPrefs.disable_token_highlighting',
+ this.$.disableTokenHighlighting.checked
+ );
+ }
+
_handleWorkInProgressByDefault() {
this.set(
'_localPrefs.work_in_progress_by_default',
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
index 1ed0d57..78c4a62 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_html.ts
@@ -309,6 +309,19 @@
</span>
</section>
<section>
+ <label for="disableTokenHighlighting" class="title"
+ >Disable token highlighting on hover</label
+ >
+ <span class="value">
+ <input
+ id="disableTokenHighlighting"
+ type="checkbox"
+ checked$="[[_localPrefs.disable_token_highlighting]]"
+ on-change="_handleDisableTokenHighlightingChanged"
+ />
+ </span>
+ </section>
+ <section>
<label for="insertSignedOff" class="title">
Insert Signed-off-by Footer For Inline Edit Changes
</label>
diff --git a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
index 26705ee..8194d5b 100644
--- a/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
+++ b/polygerrit-ui/app/elements/settings/gr-settings-view/gr-settings-view_test.ts
@@ -244,6 +244,13 @@
);
assert.equal(
(
+ valueOf('Disable token highlighting on hover', 'preferences')!
+ .firstElementChild as HTMLInputElement
+ ).checked,
+ false
+ );
+ assert.equal(
+ (
valueOf(
'Insert Signed-off-by Footer For Inline Edit Changes',
'preferences'
diff --git a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
index d6aae5c..82f6b46 100644
--- a/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
+++ b/polygerrit-ui/app/elements/shared/gr-comment-thread/gr-comment-thread.ts
@@ -204,6 +204,9 @@
@property({type: Object})
_selfAccount?: AccountDetailInfo;
+ @property({type: Boolean})
+ disableTokenHighlighting = false;
+
get keyBindings() {
return {
'e shift+e': '_handleEKey',
@@ -227,6 +230,11 @@
this.addEventListener('comment-update', e =>
this._handleCommentUpdate(e as CustomEvent)
);
+ appContext.restApiService.getPreferences().then(prefs => {
+ if (prefs?.disable_token_highlighting) {
+ this.disableTokenHighlighting = prefs.disable_token_highlighting;
+ }
+ });
}
override connectedCallback() {
@@ -360,7 +368,10 @@
_getLayers(diff?: DiffInfo) {
if (!diff) return [];
const layers = [];
- if (this.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING)) {
+ if (
+ this.flagsService.isEnabled(KnownExperimentId.TOKEN_HIGHLIGHTING) &&
+ !this.disableTokenHighlighting
+ ) {
layers.push(new TokenHighlightLayer(this));
}
layers.push(this.syntaxLayer);
diff --git a/polygerrit-ui/app/elements/shared/gr-vote-chip/gr-vote-chip.ts b/polygerrit-ui/app/elements/shared/gr-vote-chip/gr-vote-chip.ts
index 5b9ad5c..73ca99d 100644
--- a/polygerrit-ui/app/elements/shared/gr-vote-chip/gr-vote-chip.ts
+++ b/polygerrit-ui/app/elements/shared/gr-vote-chip/gr-vote-chip.ts
@@ -81,13 +81,13 @@
.vote-chip,
.chip-angle {
display: flex;
- width: var(--gr-vote-chip-width, 18px);
- height: var(--gr-vote-chip-height, 18px);
+ width: var(--gr-vote-chip-width, 16px);
+ height: var(--gr-vote-chip-height, 16px);
justify-content: center;
margin-right: var(--spacing-s);
padding: 1px;
border-radius: var(--border-radius);
- line-height: var(--gr-vote-chip-width, 18px);
+ line-height: var(--gr-vote-chip-width, 16px);
}
.vote-chip {
position: relative;
diff --git a/polygerrit-ui/app/services/checks/checks-model.ts b/polygerrit-ui/app/services/checks/checks-model.ts
index 0a5eeca..75c24b6d 100644
--- a/polygerrit-ui/app/services/checks/checks-model.ts
+++ b/polygerrit-ui/app/services/checks/checks-model.ts
@@ -546,7 +546,7 @@
pluginName: 'f4',
internalRunId: 'f4',
checkName: 'FAKE Elimination Long Long Long Long Long',
- status: RunStatus.COMPLETED,
+ status: RunStatus.RUNNABLE,
attempt: 1,
isSingleAttempt: false,
isLatestAttempt: false,
diff --git a/polygerrit-ui/app/services/checks/checks-util.ts b/polygerrit-ui/app/services/checks/checks-util.ts
index 37ebe9d..18cc076 100644
--- a/polygerrit-ui/app/services/checks/checks-util.ts
+++ b/polygerrit-ui/app/services/checks/checks-util.ts
@@ -167,6 +167,19 @@
return {...action, name};
}
+export function headerForStatus(status: RunStatus) {
+ switch (status) {
+ case RunStatus.COMPLETED:
+ return 'Completed';
+ case RunStatus.RUNNABLE:
+ return 'Not run';
+ case RunStatus.RUNNING:
+ return 'Running';
+ default:
+ assertNever(status, `Unsupported status: ${status}`);
+ }
+}
+
function primaryActionName(status: RunStatus) {
switch (status) {
case RunStatus.COMPLETED:
diff --git a/polygerrit-ui/app/services/flags/flags.ts b/polygerrit-ui/app/services/flags/flags.ts
index ef5fde2..2839874 100644
--- a/polygerrit-ui/app/services/flags/flags.ts
+++ b/polygerrit-ui/app/services/flags/flags.ts
@@ -27,6 +27,5 @@
NEW_IMAGE_DIFF_UI = 'UiFeature__new_image_diff_ui',
TOKEN_HIGHLIGHTING = 'UiFeature__token_highlighting',
CHECKS_DEVELOPER = 'UiFeature__checks_developer',
- NEW_REPLY_DIALOG = 'UiFeature__new_reply_dialog',
SUBMIT_REQUIREMENTS_UI = 'UiFeature__submit_requirements_ui',
}
diff --git a/polygerrit-ui/app/styles/gr-menu-page-styles.ts b/polygerrit-ui/app/styles/gr-menu-page-styles.ts
index 0471a4e..5f58571 100644
--- a/polygerrit-ui/app/styles/gr-menu-page-styles.ts
+++ b/polygerrit-ui/app/styles/gr-menu-page-styles.ts
@@ -14,7 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
-import {css} from 'lit-element';
+import {css} from 'lit';
export const menuPageStyles = css`
:host {
diff --git a/polygerrit-ui/app/test/test-data-generators.ts b/polygerrit-ui/app/test/test-data-generators.ts
index c82c15b..db84043 100644
--- a/polygerrit-ui/app/test/test-data-generators.ts
+++ b/polygerrit-ui/app/test/test-data-generators.ts
@@ -106,6 +106,8 @@
SubmitRequirementResultInfo,
SubmitRequirementStatus,
} from '../api/rest-api';
+import {RunResult} from '../services/checks/checks-model';
+import {Category, RunStatus} from '../api/checks';
export function dateToTimestamp(date: Date): Timestamp {
const nanosecondSuffix = '.000000000';
@@ -688,3 +690,19 @@
submittability_expression_result: createSubmitRequirementExpressionInfo(),
};
}
+
+export function createRunResult(): RunResult {
+ return {
+ attemptDetails: [],
+ category: Category.INFO,
+ checkName: 'test-name',
+ internalResultId: 'test-internal-result-id',
+ internalRunId: 'test-internal-run-id',
+ isLatestAttempt: true,
+ isSingleAttempt: true,
+ pluginName: 'test-plugin-name',
+ status: RunStatus.COMPLETED,
+ summary: 'This is the test summary.',
+ message: 'This is the test message.',
+ };
+}
diff --git a/polygerrit-ui/app/types/common.ts b/polygerrit-ui/app/types/common.ts
index 98c60d2..1617aa3 100644
--- a/polygerrit-ui/app/types/common.ts
+++ b/polygerrit-ui/app/types/common.ts
@@ -1143,6 +1143,7 @@
default_base_for_merges: DefaultBase;
publish_comments_on_push?: boolean;
disable_keyboard_shortcuts?: boolean;
+ disable_token_highlighting?: boolean;
work_in_progress_by_default?: boolean;
// The email_format doesn't mentioned in doc, but exists in Java class GeneralPreferencesInfo
email_format?: EmailFormat;
diff --git a/polygerrit-ui/app/types/globals.ts b/polygerrit-ui/app/types/globals.ts
index a06c2c4..b5bd2aa 100644
--- a/polygerrit-ui/app/types/globals.ts
+++ b/polygerrit-ui/app/types/globals.ts
@@ -75,4 +75,8 @@
lineNumber?: number; // non-standard property
columnNumber?: number; // non-standard property
}
+
+ interface ShadowRoot {
+ getSelection?: () => Selection | null;
+ }
}
diff --git a/polygerrit-ui/app/utils/dom-util.ts b/polygerrit-ui/app/utils/dom-util.ts
index e7cc956..16129af 100644
--- a/polygerrit-ui/app/utils/dom-util.ts
+++ b/polygerrit-ui/app/utils/dom-util.ts
@@ -227,7 +227,7 @@
// document.activeElement is not enough, because it's not getting activeElement
// without looking inside of shadow roots. This will find best activeElement.
export function findActiveElement(
- root: DocumentOrShadowRoot | null,
+ root: Document | ShadowRoot | null,
ignoreDialogs?: boolean
): HTMLElement | null {
if (root === null) {
@@ -257,7 +257,7 @@
export function isSafari() {
return (
/^((?!chrome|android).)*safari/i.test(navigator.userAgent) ||
- (/iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream)
+ /iPad|iPhone|iPod/.test(navigator.userAgent)
);
}
diff --git a/proto/entities.proto b/proto/entities.proto
index d4ff736..de8f647 100644
--- a/proto/entities.proto
+++ b/proto/entities.proto
@@ -133,6 +133,7 @@
optional string tag = 6;
optional Account_Id real_account_id = 7;
optional bool post_submit = 8;
+ optional bool copied = 9;
// Deleted fields, should not be reused:
reserved 4; // changeOpen
diff --git a/tools/BUILD b/tools/BUILD
index 545a206..6cc108b 100644
--- a/tools/BUILD
+++ b/tools/BUILD
@@ -68,77 +68,398 @@
# Error Prone errors enabled by default; see ../.bazelrc for how this is
# enabled. This warnings list is originally based on:
# https://github.com/bazelbuild/BUILD_file_generator/blob/master/tools/bazel_defs/java.bzl
+# Additionally, items used internally in google is added. Such items have
+# the same or higher verbosity level than in google.
# However, feel free to add any additional errors. Thus far they have all been pretty useful.
-# TODO(davido): Enable ImmutableAnnotationChecker again when these issues are fixed:
-# https://github.com/google/error-prone/issues/1348
-# https://github.com/bazelbuild/bazel/issues/9378
+# All warnings are commented to avoid noise in the output.
+# Newer versions of error-prone have XepDisableAllWarnings flag which could
+# be used instead of commenting. Bazel should be updated to use a new version
+# of error-prone.
java_package_configuration(
name = "error_prone",
javacopts = [
"-XepDisableWarningsInGeneratedCode",
+ # The XepDisableWarningsInGeneratedCode disables only warnings, but
+ # not errors. We should manually exclude all files generated by
+ # AutoValue; such files always start $AutoValue_.....
+ # XepExcludedPaths is a regexp. If you need more paths - use | as
+ # separator.
+ "-XepExcludedPaths:.*/\\\\$$AutoValue_.*\\.java",
+ "-Xep:AlmostJavadoc:ERROR",
+ "-Xep:AlwaysThrows:ERROR",
"-Xep:AmbiguousMethodReference:ERROR",
+ "-Xep:AnnotateFormatMethod:ERROR",
+ "-Xep:ArgumentSelectionDefectChecker:ERROR",
+ "-Xep:ArrayAsKeyOfSetOrMap:ERROR",
+ "-Xep:ArrayEquals:ERROR",
+ "-Xep:ArrayFillIncompatibleType:ERROR",
+ "-Xep:ArrayHashCode:ERROR",
+ "-Xep:ArrayToString:ERROR",
+ "-Xep:ArraysAsListPrimitiveArray:ERROR",
+ "-Xep:AssertEqualsArgumentOrderChecker:ERROR",
+ "-Xep:AssertionFailureIgnored:ERROR",
+ "-Xep:AsyncCallableReturnsNull:ERROR",
+ "-Xep:AsyncFunctionReturnsNull:ERROR",
+ "-Xep:AutoValueConstructorOrderChecker:ERROR",
"-Xep:AutoValueFinalMethods:ERROR",
+ # "-Xep:AutoValueImmutableFields:WARN",
+ # "-Xep:AutoValueSubclassLeaked:WARN",
"-Xep:BadAnnotationImplementation:ERROR",
"-Xep:BadComparable:ERROR",
+ # "-Xep:BadImport:WARN",
+ "-Xep:BadInstanceof:ERROR",
+ "-Xep:BadShiftAmount:ERROR",
+ "-Xep:BanSerializableRead:ERROR",
+ "-Xep:BigDecimalEquals:ERROR",
+ "-Xep:BigDecimalLiteralDouble:ERROR",
"-Xep:BoxedPrimitiveConstructor:ERROR",
+ "-Xep:BoxedPrimitiveEquality:ERROR",
+ "-Xep:BundleDeserializationCast:ERROR",
+ "-Xep:ByteBufferBackingArray:ERROR",
+ "-Xep:CacheLoaderNull:ERROR",
"-Xep:CannotMockFinalClass:ERROR",
+ "-Xep:CanonicalDuration:ERROR",
+ # "-Xep:CatchAndPrintStackTrace:WARN",
+ "-Xep:CatchFail:ERROR",
+ "-Xep:ChainedAssertionLosesContext:ERROR",
+ "-Xep:ChainingConstructorIgnoresParameter:ERROR",
+ "-Xep:CharacterGetNumericValue:ERROR",
+ "-Xep:CheckNotNullMultipleTimes:ERROR",
+ "-Xep:CheckReturnValue:ERROR",
"-Xep:ClassCanBeStatic:ERROR",
+ "-Xep:ClassName:ERROR",
"-Xep:ClassNewInstance:ERROR",
+ "-Xep:CollectionIncompatibleType:ERROR",
+ "-Xep:CollectionToArraySafeParameter:ERROR",
+ "-Xep:CollectionUndefinedEquality:ERROR",
+ "-Xep:CollectorShouldNotUseState:ERROR",
+ "-Xep:ComparableAndComparator:ERROR",
+ "-Xep:ComparableType:ERROR",
+ "-Xep:CompareToZero:ERROR",
+ "-Xep:ComparingThisWithNull:ERROR",
+ "-Xep:ComparisonOutOfRange:ERROR",
+ "-Xep:CompatibleWithAnnotationMisuse:ERROR",
+ "-Xep:CompileTimeConstant:ERROR",
+ "-Xep:ComplexBooleanConstant:ERROR",
+ "-Xep:ComputeIfAbsentAmbiguousReference:ERROR",
+ "-Xep:ConditionalExpressionNumericPromotion:ERROR",
+ "-Xep:ConstantOverflow:ERROR",
+ "-Xep:DaggerProvidesNull:ERROR",
+ "-Xep:DangerousLiteralNull:ERROR",
+ "-Xep:DateChecker:ERROR",
"-Xep:DateFormatConstant:ERROR",
+ "-Xep:DeadException:ERROR",
+ "-Xep:DeadThread:ERROR",
"-Xep:DefaultCharset:ERROR",
+ # "-Xep:DefaultPackage:WARN",
+ "-Xep:DepAnn:ERROR",
+ "-Xep:DeprecatedVariable:ERROR",
+ "-Xep:DiscardedPostfixExpression:ERROR",
+ "-Xep:DoNotCall:ERROR",
+ "-Xep:DoNotCallSuggester:ERROR",
+ "-Xep:DoNotClaimAnnotations:ERROR",
+ "-Xep:DoNotMock:ERROR",
+ "-Xep:DoNotMockAutoValue:ERROR",
+ "-Xep:DoubleBraceInitialization:ERROR",
"-Xep:DoubleCheckedLocking:ERROR",
- "-Xep:ElementsCountedInLoop:ERROR",
+ "-Xep:DuplicateMapKeys:ERROR",
+ "-Xep:DurationFrom:ERROR",
+ "-Xep:DurationGetTemporalUnit:ERROR",
+ "-Xep:DurationTemporalUnit:ERROR",
+ "-Xep:DurationToLongTimeUnit:ERROR",
+ "-Xep:EmptyBlockTag:ERROR",
+ # "-Xep:EmptyCatch:WARN",
+ "-Xep:EmptySetMultibindingContributions:ERROR",
+ # "-Xep:EqualsGetClass:WARN",
"-Xep:EqualsHashCode:ERROR",
"-Xep:EqualsIncompatibleType:ERROR",
+ "-Xep:EqualsNaN:ERROR",
+ "-Xep:EqualsNull:ERROR",
+ "-Xep:EqualsReference:ERROR",
+ "-Xep:EqualsUnsafeCast:ERROR",
+ "-Xep:EqualsUsingHashCode:ERROR",
+ "-Xep:EqualsWrongThing:ERROR",
+ "-Xep:ErroneousThreadPoolConstructorChecker:ERROR",
+ # "-Xep:EscapedEntity:WARN",
"-Xep:ExpectedExceptionChecker:ERROR",
+ "-Xep:ExtendingJUnitAssert:ERROR",
+ "-Xep:ExtendsAutoValue:ERROR",
+ "-Xep:FallThrough:ERROR",
"-Xep:Finally:ERROR",
+ "-Xep:FloatCast:ERROR",
+ "-Xep:FloatingPointAssertionWithinEpsilon:ERROR",
"-Xep:FloatingPointLiteralPrecision:ERROR",
+ "-Xep:FloggerArgumentToString:ERROR",
+ "-Xep:FloggerFormatString:ERROR",
+ "-Xep:FloggerLogVarargs:ERROR",
+ "-Xep:FloggerSplitLogStatement:ERROR",
+ "-Xep:FloggerStringConcatenation:ERROR",
+ "-Xep:ForOverride:ERROR",
+ "-Xep:FormatString:ERROR",
"-Xep:FormatStringAnnotation:ERROR",
"-Xep:FragmentInjection:ERROR",
"-Xep:FragmentNotInstantiable:ERROR",
+ "-Xep:FromTemporalAccessor:ERROR",
"-Xep:FunctionalInterfaceClash:ERROR",
+ "-Xep:FunctionalInterfaceMethodChanged:ERROR",
"-Xep:FutureReturnValueIgnored:ERROR",
+ "-Xep:FuturesGetCheckedIllegalExceptionType:ERROR",
+ "-Xep:GetClassOnAnnotation:ERROR",
+ "-Xep:GetClassOnClass:ERROR",
"-Xep:GetClassOnEnum:ERROR",
- "-Xep:ImmutableAnnotationChecker:OFF",
+ "-Xep:GuardedBy:ERROR",
+ "-Xep:GuiceAssistedInjectScoping:ERROR",
+ "-Xep:GuiceAssistedParameters:ERROR",
+ "-Xep:HashtableContains:ERROR",
+ "-Xep:HidingField:ERROR",
+ "-Xep:IdentityBinaryExpression:ERROR",
+ "-Xep:IdentityHashMapBoxing:ERROR",
+ "-Xep:IdentityHashMapUsage:ERROR",
+ "-Xep:IgnoredPureGetter:ERROR",
+ "-Xep:Immutable:ERROR",
+ "-Xep:ImmutableAnnotationChecker:ERROR",
"-Xep:ImmutableEnumChecker:ERROR",
+ "-Xep:ImmutableModification:ERROR",
+ "-Xep:Incomparable:ERROR",
+ "-Xep:IncompatibleArgumentType:ERROR",
"-Xep:IncompatibleModifiers:ERROR",
+ # "-Xep:InconsistentCapitalization:WARN",
+ "-Xep:InconsistentHashCode:ERROR",
+ "-Xep:IncrementInForLoopAndHeader:ERROR",
+ "-Xep:IndexOfChar:ERROR",
+ "-Xep:InexactVarargsConditional:ERROR",
+ "-Xep:InfiniteRecursion:ERROR",
"-Xep:InjectOnConstructorOfAbstractClass:ERROR",
+ "-Xep:InheritDoc:ERROR",
+ # "-Xep:InlineFormatString:WARN",
+ "-Xep:InlineMeInliner:ERROR",
+ "-Xep:InlineMeSuggester:ERROR",
+ "-Xep:InlineMeValidator:ERROR",
"-Xep:InputStreamSlowMultibyteRead:ERROR",
+ "-Xep:InsecureCryptoUsage:ERROR",
+ "-Xep:InstanceOfAndCastMatchWrongType:ERROR",
+ "-Xep:InstantTemporalUnit:ERROR",
+ "-Xep:IntLongMath:ERROR",
+ # "-Xep:InvalidBlockTag:WARN",
+ # "-Xep:InvalidInlineTag:WARN",
+ "-Xep:InvalidJavaTimeConstant:ERROR",
+ "-Xep:InvalidLink:ERROR",
+ # "-Xep:InvalidParam:WARN",
+ "-Xep:InvalidPatternSyntax:ERROR",
+ "-Xep:InvalidThrows:ERROR",
+ "-Xep:InvalidThrowsLink:ERROR",
+ "-Xep:InvalidTimeZoneID:ERROR",
+ "-Xep:InvalidZoneId:ERROR",
+ "-Xep:IsInstanceIncompatibleType:ERROR",
+ "-Xep:IsInstanceOfClass:ERROR",
+ "-Xep:IsLoggableTagLength:ERROR",
"-Xep:IterableAndIterator:ERROR",
+ "-Xep:IterablePathParameter:ERROR",
"-Xep:JUnit3FloatingPointComparisonWithoutDelta:ERROR",
+ "-Xep:JUnit3TestNotRun:ERROR",
+ "-Xep:JUnit4ClassAnnotationNonStatic:ERROR",
+ "-Xep:JUnit4ClassUsedInJUnit3:ERROR",
+ "-Xep:JUnit4SetUpNotRun:ERROR",
+ "-Xep:JUnit4TearDownNotRun:ERROR",
+ "-Xep:JUnit4TestNotRun:ERROR",
+ "-Xep:JUnit4TestsNotRunWithinEnclosed:ERROR",
"-Xep:JUnitAmbiguousTestClass:ERROR",
- "-Xep:LiteralClassName:ERROR",
+ "-Xep:JUnitAssertSameCheck:ERROR",
+ "-Xep:JUnitParameterMethodNotFound:ERROR",
+ "-Xep:JavaDurationGetSecondsGetNano:ERROR",
+ "-Xep:JavaDurationWithNanos:ERROR",
+ "-Xep:JavaDurationWithSeconds:ERROR",
+ "-Xep:JavaInstantGetSecondsGetNano:ERROR",
+ # "-Xep:JavaLangClash:WARN",
+ "-Xep:JavaLocalDateTimeGetNano:ERROR",
+ "-Xep:JavaLocalTimeGetNano:ERROR",
+ "-Xep:JavaPeriodGetDays:ERROR",
+ "-Xep:JavaTimeDefaultTimeZone:ERROR",
+ "-Xep:JavaUtilDate:ERROR",
+ # "-Xep:JdkObsolete:WARN",
+ "-Xep:JodaConstructors:ERROR",
+ "-Xep:JodaDateTimeConstants:ERROR",
+ "-Xep:JodaDurationWithMillis:ERROR",
+ "-Xep:JodaInstantWithMillis:ERROR",
+ "-Xep:JodaNewPeriod:ERROR",
+ "-Xep:JodaPlusMinusLong:ERROR",
+ "-Xep:JodaTimeConverterManager:ERROR",
+ "-Xep:JodaToSelf:ERROR",
+ "-Xep:JodaWithDurationAddedLong:ERROR",
+ "-Xep:LiteByteStringUtf8:ERROR",
+ "-Xep:LiteEnumValueOf:ERROR",
+ "-Xep:LiteProtoToString:ERROR",
+ "-Xep:LocalDateTemporalAmount:ERROR",
+ "-Xep:LockNotBeforeTry:ERROR",
+ "-Xep:LockOnBoxedPrimitive:ERROR",
+ "-Xep:LogicalAssignment:ERROR",
+ "-Xep:LongFloatConversion:ERROR",
+ "-Xep:LongLiteralLowerCaseSuffix:ERROR",
+ "-Xep:LoopConditionChecker:ERROR",
+ "-Xep:LoopOverCharArray:ERROR",
+ "-Xep:LossyPrimitiveCompare:ERROR",
+ "-Xep:MathAbsoluteRandom:ERROR",
+ "-Xep:MathRoundIntLong:ERROR",
+ "-Xep:MemoizeConstantVisitorStateLookups:ERROR",
+ "-Xep:MislabeledAndroidString:ERROR",
"-Xep:MissingCasesInEnumSwitch:ERROR",
"-Xep:MissingFail:ERROR",
"-Xep:MissingOverride:ERROR",
+ "-Xep:MissingSummary:ERROR",
+ "-Xep:MissingSuperCall:ERROR",
+ "-Xep:MissingTestCall:ERROR",
+ "-Xep:MisusedDayOfYear:ERROR",
+ "-Xep:MisusedWeekYear:ERROR",
+ "-Xep:MixedDescriptors:ERROR",
+ # "-Xep:MixedMutabilityReturnType:WARN",
+ "-Xep:MockitoUsage:ERROR",
+ "-Xep:ModifiedButNotUsed:ERROR",
+ "-Xep:ModifyCollectionInEnhancedForLoop:ERROR",
+ "-Xep:ModifySourceCollectionInStream:ERROR",
+ "-Xep:ModifyingCollectionWithItself:ERROR",
+ "-Xep:MultipleParallelOrSequentialCalls:ERROR",
+ "-Xep:MultipleUnaryOperatorsInMethodCall:ERROR",
+ "-Xep:MustBeClosedChecker:ERROR",
"-Xep:MutableConstantField:ERROR",
+ # "-Xep:MutablePublicArray:WARN",
+ "-Xep:NCopiesOfChar:ERROR",
"-Xep:NarrowingCompoundAssignment:ERROR",
+ "-Xep:NestedInstanceOfConditions:ERROR",
"-Xep:NonAtomicVolatileUpdate:ERROR",
+ "-Xep:NonCanonicalStaticImport:ERROR",
+ # "-Xep:NonCanonicalType:WARN",
+ "-Xep:NonFinalCompileTimeConstant:ERROR",
"-Xep:NonOverridingEquals:ERROR",
+ "-Xep:NonRuntimeAnnotation:ERROR",
+ "-Xep:NullOptional:ERROR",
+ "-Xep:NullTernary:ERROR",
"-Xep:NullableConstructor:ERROR",
"-Xep:NullablePrimitive:ERROR",
+ "-Xep:NullablePrimitiveArray:ERROR",
"-Xep:NullableVoid:ERROR",
+ "-Xep:ObjectEqualsForPrimitives:ERROR",
"-Xep:ObjectToString:ERROR",
+ "-Xep:ObjectsHashCodePrimitive:ERROR",
"-Xep:OperatorPrecedence:ERROR",
+ "-Xep:OptionalEquality:ERROR",
+ "-Xep:OptionalMapToOptional:ERROR",
+ "-Xep:OptionalMapUnusedValue:ERROR",
+ "-Xep:OptionalNotPresent:ERROR",
+ "-Xep:OptionalOfRedundantMethod:ERROR",
+ "-Xep:OrphanedFormatString:ERROR",
+ "-Xep:OutlineNone:ERROR",
+ "-Xep:OverlappingQualifierAndScopeAnnotation:ERROR",
+ "-Xep:OverrideThrowableToString:ERROR",
+ "-Xep:Overrides:ERROR",
"-Xep:OverridesGuiceInjectableMethod:ERROR",
+ "-Xep:OverridesJavaxInjectableMethod:ERROR",
+ "-Xep:PackageInfo:ERROR",
+ # "-Xep:ParameterName:WARN",
+ "-Xep:ParametersButNotParameterized:ERROR",
+ "-Xep:ParcelableCreator:ERROR",
+ "-Xep:PeriodFrom:ERROR",
+ "-Xep:PeriodGetTemporalUnit:ERROR",
+ "-Xep:PeriodTimeMath:ERROR",
+ "-Xep:PreconditionsCheckNotNullRepeated:ERROR",
"-Xep:PreconditionsInvalidPlaceholder:ERROR",
- "-Xep:ProtoFieldPreconditionsCheckNotNull:ERROR",
+ "-Xep:PrimitiveAtomicReference:ERROR",
+ "-Xep:PrivateSecurityContractProtoAccess:ERROR",
+ # "-Xep:ProtectedMembersInFinalClass:WARN",
+ "-Xep:ProtoBuilderReturnValueIgnored:ERROR",
+ "-Xep:ProtoDurationGetSecondsGetNano:ERROR",
+ "-Xep:ProtoFieldNullComparison:ERROR",
+ "-Xep:ProtoRedundantSet:ERROR",
+ "-Xep:ProtoStringFieldReferenceEquality:ERROR",
+ "-Xep:ProtoTimestampGetSecondsGetNano:ERROR",
+ "-Xep:ProtoTruthMixedDescriptors:ERROR",
"-Xep:ProtocolBufferOrdinal:ERROR",
+ "-Xep:ProvidesMethodOutsideOfModule:ERROR",
+ "-Xep:RandomCast:ERROR",
+ "-Xep:RandomModInteger:ERROR",
+ "-Xep:ReachabilityFenceUsage:ERROR",
+ "-Xep:RectIntersectReturnValueIgnored:ERROR",
"-Xep:ReferenceEquality:ERROR",
+ "-Xep:RefersToDaggerCodegen:ERROR",
+ "-Xep:RemovedInJDK11:ERROR",
"-Xep:RequiredModifiers:ERROR",
+ "-Xep:RestrictedApiChecker:ERROR",
+ "-Xep:RethrowReflectiveOperationExceptionAsLinkageError:ERROR",
+ "-Xep:ReturnFromVoid:ERROR",
+ "-Xep:ReturnValueIgnored:ERROR",
+ "-Xep:RxReturnValueIgnored:ERROR",
+ # "-Xep:SameNameButDifferent:WARN",
+ "-Xep:SelfAssignment:ERROR",
+ "-Xep:SelfComparison:ERROR",
+ "-Xep:SelfEquals:ERROR",
"-Xep:ShortCircuitBoolean:ERROR",
- "-Xep:SimpleDateFormatConstant:ERROR",
+ "-Xep:ShouldHaveEvenArgs:ERROR",
+ "-Xep:SizeGreaterThanOrEqualsZero:ERROR",
+ "-Xep:StaticAssignmentInConstructor:ERROR",
"-Xep:StaticGuardedByInstance:ERROR",
+ "-Xep:StaticMockMember:ERROR",
+ "-Xep:StaticQualifiedUsingExpression:ERROR",
+ "-Xep:StreamToString:ERROR",
+ "-Xep:StringBuilderInitWithChar:ERROR",
"-Xep:StringEquality:ERROR",
+ # "-Xep:StringSplitter:WARN",
+ "-Xep:SubstringOfZero:ERROR",
+ "-Xep:SuppressWarningsDeprecated:ERROR",
+ "-Xep:SwigMemoryLeak:ERROR",
"-Xep:SynchronizeOnNonFinalField:ERROR",
+ "-Xep:TemporalAccessorGetChronoField:ERROR",
+ "-Xep:TestParametersNotInitialized:ERROR",
+ "-Xep:TheoryButNoTheories:ERROR",
+ # "-Xep:ThreadJoinLoop:WARN",
+ "-Xep:ThreadLocalUsage:ERROR",
+ # "-Xep:ThreadPriorityCheck:WARN",
+ "-Xep:ThreeLetterTimeZoneID:ERROR",
+ "-Xep:ThrowIfUncheckedKnownChecked:ERROR",
+ "-Xep:ThrowNull:ERROR",
+ "-Xep:TimeUnitConversionChecker:ERROR",
+ "-Xep:ToStringReturnsNull:ERROR",
+ "-Xep:TreeToString:ERROR",
+ # "-Xep:TruthAssertExpected:WARN",
"-Xep:TruthConstantAsserts:ERROR",
+ "-Xep:TruthGetOrDefault:ERROR",
+ "-Xep:TruthIncompatibleType:ERROR",
+ "-Xep:TruthSelfEquals:ERROR",
+ "-Xep:TryFailThrowable:ERROR",
+ "-Xep:TypeEquals:ERROR",
+ "-Xep:TypeNameShadowing:ERROR",
+ "-Xep:TypeParameterQualifier:ERROR",
"-Xep:TypeParameterShadowing:ERROR",
"-Xep:TypeParameterUnusedInFormals:ERROR",
"-Xep:URLEqualsHashCode:ERROR",
+ # "-Xep:UndefinedEquals:WARN",
+ # "-Xep:UnescapedEntity:WARN",
+ "-Xep:UnnecessaryAssignment:ERROR",
+ "-Xep:UnnecessaryCheckNotNull:ERROR",
+ # "-Xep:UnnecessaryLambda:WARN",
+ "-Xep:UnnecessaryMethodInvocationMatcher:ERROR",
+ "-Xep:UnnecessaryMethodReference:ERROR",
+ # "-Xep:UnnecessaryParentheses:WARN",
+ "-Xep:UnnecessaryTypeArgument:ERROR",
+ "-Xep:UnrecognisedJavadocTag:ERROR",
+ "-Xep:UnsafeFinalization:ERROR",
+ "-Xep:UnsafeReflectiveConstructionCast:ERROR",
"-Xep:UnsynchronizedOverridesSynchronized:ERROR",
+ "-Xep:UnusedAnonymousClass:ERROR",
+ "-Xep:UnusedCollectionModifiedInPlace:ERROR",
"-Xep:UnusedException:ERROR",
+ # "-Xep:UnusedMethod:WARN",
+ "-Xep:UnusedNestedClass:ERROR",
+ # "-Xep:UnusedVariable:WARN",
+ "-Xep:UseBinds:ERROR",
+ "-Xep:UseCorrectAssertInTests:ERROR",
+ "-Xep:VarTypeName:ERROR",
+ "-Xep:VariableNameSameAsType:ERROR",
"-Xep:WaitNotInLoop:ERROR",
+ "-Xep:WakelockReleasedDangerously:ERROR",
"-Xep:WildcardImport:ERROR",
+ "-Xep:WithSignatureDiscouraged:ERROR",
+ "-Xep:WrongOneof:ERROR",
+ "-Xep:XorPower:ERROR",
+ "-Xep:ZoneIdOfZ:ERROR",
],
packages = ["error_prone_packages"],
)