Merge "Inline AbstractDaemonTest#getRelated"
diff --git a/BUILD b/BUILD
index 5ddf8b1..f0b1954 100644
--- a/BUILD
+++ b/BUILD
@@ -23,7 +23,6 @@
cmd = ("cat bazel-out/volatile-status.txt bazel-out/stable-status.txt | " +
"grep STABLE_BUILD_GERRIT_LABEL | cut -d ' ' -f 2 > $@"),
stamp = 1,
- visibility = ["//visibility:public"],
)
genrule(
@@ -31,7 +30,6 @@
srcs = ["//Documentation:licenses.txt"],
outs = ["LICENSES.txt"],
cmd = "cp $< $@",
- visibility = ["//visibility:public"],
)
pkg_war(
diff --git a/Documentation/BUILD b/Documentation/BUILD
index b322fef..8a7a313 100644
--- a/Documentation/BUILD
+++ b/Documentation/BUILD
@@ -40,7 +40,6 @@
":prettify_files",
"//:LICENSES.txt",
],
- visibility = ["//visibility:public"],
)
license_map(
@@ -50,7 +49,6 @@
"//polygerrit-ui/app:polygerrit_ui",
"//java/com/google/gerrit/pgm",
],
- visibility = ["//visibility:public"],
)
license_map(
@@ -58,7 +56,6 @@
targets = [
"//polygerrit-ui/app:polygerrit_ui",
],
- visibility = ["//visibility:public"],
)
DOC_DIR = "Documentation"
@@ -86,7 +83,6 @@
srcs = SRCS,
attributes = documentation_attributes(),
backend = "html5",
- visibility = ["//visibility:public"],
)
genasciidoc_zip(
@@ -95,7 +91,6 @@
attributes = documentation_attributes(),
backend = "html5",
directory = DOC_DIR,
- visibility = ["//visibility:public"],
)
genasciidoc_zip(
@@ -105,5 +100,4 @@
backend = "html5",
directory = DOC_DIR,
searchbox = False,
- visibility = ["//visibility:public"],
)
diff --git a/Documentation/access-control.txt b/Documentation/access-control.txt
index 516cf13..1d1f17e 100644
--- a/Documentation/access-control.txt
+++ b/Documentation/access-control.txt
@@ -1204,8 +1204,7 @@
[[capability_accessDatabase]]
=== Access Database
-Allow users to access the database using the `gsql` command, and view code
-review metadata refs in repositories.
+Allow users to view code review metadata refs in repositories.
[[capability_administrateServer]]
diff --git a/Documentation/cmd-gsql.txt b/Documentation/cmd-gsql.txt
deleted file mode 100644
index 7f2aaf7..0000000
--- a/Documentation/cmd-gsql.txt
+++ /dev/null
@@ -1,64 +0,0 @@
-= gerrit gsql
-
-== NAME
-gerrit gsql - Administrative interface to active database.
-
-== SYNOPSIS
-[verse]
---
-_ssh_ -p <port> <host> _gerrit gsql_
- [--format {PRETTY | JSON | JSON_SINGLE}]
- [-c QUERY]
---
-
-== DESCRIPTION
-Provides interactive query support directly against the underlying
-SQL database used by the host Gerrit server. All SQL statements
-are supported, including SELECT, UPDATE, INSERT, DELETE and ALTER.
-
-== OPTIONS
---format::
- Set the format records are output in. In PRETTY (the
- default) records are displayed in a tabular output suitable
- for reading by a human on a sufficiently wide terminal.
- In JSON mode records are output as JSON objects using the
- column names as the property names, one object per line.
- In JSON_SINGLE mode the whole result set is output as a
- single JSON object.
-
--c::
- Execute the single query statement supplied, and then exit.
-
-== ACCESS
-Caller must have been granted the
-link:access-control.html#capability_accessDatabase[Access Database]
-global capability.
-
-== SCRIPTING
-Intended for interactive use only, unless format is JSON, or
-JSON_SINGLE.
-
-== EXAMPLES
-To manually correct a user's SSH user name:
-
-----
-$ ssh -p 29418 review.example.com gerrit gsql
-Welcome to Gerrit Code Review v2.0.25
-(PostgreSQL 8.3.8)
-
-Type '\h' for help. Type '\r' to clear the buffer.
-
-gerrit> update accounts set ssh_user_name = 'alice' where account_id=1;
-UPDATE 1; 1 ms
-gerrit> \q
-Bye
-
-$ ssh -p 29418 review.example.com gerrit flush-caches --cache sshkeys --cache accounts
-----
-
-GERRIT
-------
-Part of link:index.html[Gerrit Code Review]
-
-SEARCHBOX
----------
diff --git a/Documentation/cmd-index.txt b/Documentation/cmd-index.txt
index 25099fa..e999218 100644
--- a/Documentation/cmd-index.txt
+++ b/Documentation/cmd-index.txt
@@ -130,9 +130,6 @@
link:cmd-gc.html[gerrit gc]::
Run the Git garbage collection.
-link:cmd-gsql.html[gerrit gsql]::
- Administrative interface to active database.
-
link:cmd-index-activate.html[gerrit index activate]::
Activate the latest index version available.
diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt
index fc9d405..037731d 100644
--- a/Documentation/config-gerrit.txt
+++ b/Documentation/config-gerrit.txt
@@ -693,7 +693,9 @@
allows to limit the memory used by H2 and thus prevent out-of-memory
caused by the H2 database using too much memory.
+
-See <<database.h2.cacheSize,database.h2.cacheSize>> for a detailed discussion.
+Technically the H2 cache size is configured using the CACHE_SIZE parameter in
+the H2 JDBC connection URL, as described
+link:http://www.h2database.com/html/features.html#cache_settings[here]
+
Default is unset, using up to half of the available memory.
+
@@ -1677,215 +1679,6 @@
+
Default is 1 hour.
-[[database]]
-=== Section database
-
-The database section configures ReviewDb, where Gerrit stores its metadata
-records about account groups and change reviews. Starting from 2.15, accounts
-are always stored in NoteDb and, optionally, changes too. See the
-link:note-db.html[NoteDb documentation] for more information.
-
-Note that user file reviewed flags are stored in a separate database. See the
-<<accountPatchReviewDb,accountPatchReviewDb>> section for more information.
-
-----
-[database]
- type = POSTGRESQL
- hostname = localhost
- database = reviewdb
- username = gerrit
- password = s3kr3t
-----
-
-[[database.type]]database.type::
-+
-Type of database server to connect to. If set this value will be
-used to automatically create correct database.driver and database.url
-values to open the connection.
-+
-* `DB2`
-+
-Connect to a DB2 database server.
-+
-* `DERBY`
-+
-Connect to an Apache Derby database server.
-+
-* `H2`
-+
-Connect to a local embedded H2 database.
-+
-* `JDBC`
-+
-Connect using a JDBC driver class name and URL.
-+
-* `MAXDB`
-+
-Connect to an SAP MaxDB database server.
-+
-* `MYSQL`
-+
-Connect to a MySQL database server.
-+
-* `MARIADB`
-+
-Connect to a MariaDB database server.
-+
-* `ORACLE`
-+
-Connect to an Oracle database server.
-+
-* `POSTGRESQL`
-+
-Connect to a PostgreSQL database server.
-
-+
-If not specified, database.driver and database.url are used as-is,
-and if they are also not specified, defaults to H2.
-
-[[database.hostname]]database.hostname::
-+
-Hostname of the database server. Defaults to 'localhost'.
-
-[[database.port]]database.port::
-+
-Port number of the database server. Defaults to the default port
-of the server named by database.type.
-
-[[database.database]]database.database::
-+
-For POSTGRESQL or MYSQL, the name of the database on the server.
-+
-For H2, this is the path to the database, and if not absolute is
-relative to `'$site_path'`.
-
-[[database.username]]database.username::
-+
-Username to connect to the database server as.
-
-[[database.password]]database.password::
-+
-Password to authenticate to the database server with.
-
-[[database.driver]]database.driver::
-+
-Name of the JDBC driver class to connect to the database with.
-Setting this usually isn't necessary as it can be derived from
-database.type or database.url for any supported database.
-
-[[database.url]]database.url::
-+
-'jdbc:' URL for the database. Setting this variable usually
-isn't necessary as it can be constructed from the all of the
-above properties.
-
-[[database.connectionPool]]database.connectionPool::
-+
-If true, use connection pooling for database connections. Otherwise, a
-new database connection is opened for each request.
-+
-Default is false for MySQL, and true for other database backends.
-
-[[database.poolLimit]]database.poolLimit::
-+
-Maximum number of open database connections. If the server needs
-more than this number, request processing threads will wait up
-to <<database.poolMaxWait, poolMaxWait>> seconds for a
-connection to be released before they abort with an exception.
-This limit must be several units higher than the total number of
-httpd and sshd threads as some request processing code paths may
-need multiple connections.
-+
-Default is <<sshd.threads, sshd.threads>>
- + <<httpd.maxThreads, httpd.maxThreads>> + 2.
-+
-This setting only applies if
-<<database.connectionPool,database.connectionPool>> is true.
-
-[[database.poolMinIdle]]database.poolMinIdle::
-+
-Minimum number of connections to keep idle in the pool.
-Default is 4.
-+
-This setting only applies if
-<<database.connectionPool,database.connectionPool>> is true.
-
-[[database.poolMaxIdle]]database.poolMaxIdle::
-+
-Maximum number of connections to keep idle in the pool. If there
-are more idle connections, connections will be closed instead of
-being returned back to the pool.
-Default is min(<<database.poolLimit, database.poolLimit>>, 16).
-+
-This setting only applies if
-<<database.connectionPool,database.connectionPool>> is true.
-
-[[database.poolMaxWait]]database.poolMaxWait::
-+
-Maximum amount of time a request processing thread will wait to
-acquire a database connection from the pool. If no connection is
-released within this time period, the processing thread will abort
-its current operations and return an error to the client.
-Values should use common unit suffixes to express their setting:
-+
-* ms, milliseconds
-* s, sec, second, seconds
-* m, min, minute, minutes
-* h, hr, hour, hours
-
-+
---
-If a unit suffix is not specified, `milliseconds` is assumed.
-
-Default is `30 seconds`.
-
-This setting only applies if
-<<database.connectionPool,database.connectionPool>> is true.
---
-
-[[database.dataSourceInterceptorClass]]database.dataSourceInterceptorClass::
-
-Class that implements DataSourceInterceptor interface to monitor SQL activity.
-This class must have default constructor and be available on Gerrit's bootstrap
-classpath, e. g. in `$gerrit_site/lib` directory. Example implementation of
-SQL monitoring can be found in javamelody-plugin.
-
-[[database.h2]]database.h2::
-+
-The settings in this section are used for the reviewdb if the
-<<database.type,database.type>> is H2.
-+
-Additionally gerrit uses H2 for storing reviewed flags on changes.
-
-[[database.h2.cacheSize]]database.h2.cacheSize::
-+
-The size of the H2 internal database cache, in bytes. The H2 internal cache for
-persistent H2-backed caches is controlled by
-<<cache.h2CacheSize,cache.h2CacheSize>>.
-+
-H2 uses memory to cache its database content. The parameter `cacheSize`
-allows to limit the memory used by H2 and thus prevent out-of-memory
-caused by the H2 database using too much memory.
-+
-Technically the H2 cache size is configured using the CACHE_SIZE parameter in
-the H2 JDBC connection URL, as described
-link:http://www.h2database.com/html/features.html#cache_settings[here]
-+
-Default is unset, using up to half of the available memory.
-+
-H2 will persist this value in the database, so to unset explicitly specify 0.
-+
-Common unit suffixes of 'k', 'm', or 'g' are supported.
-
-[[database.h2.autoServer]]database.h2.autoServer::
-+
-If `true` enable the automatic mixed mode
-(see link:http://www.h2database.com/html/features.html#auto_mixed_mode[Automatic Mixed Mode]).
-This enables concurrent access to the embedded H2 database from command line
-utils (e.g. MigrateToNoteDb).
-+
-Default is `false`.
-
[[download]]
=== Section download
diff --git a/Documentation/config-plugins.txt b/Documentation/config-plugins.txt
index 35f44c0..bda0b67 100644
--- a/Documentation/config-plugins.txt
+++ b/Documentation/config-plugins.txt
@@ -124,16 +124,6 @@
link:https://gerrit.googlesource.com/plugins/reviewnotes/+doc/master/src/main/resources/Documentation/about.md[
Documentation]
-[[review-strategy]]
-=== review-strategy
-
-This plugin allows users to configure different review strategies.
-
-link:https://gerrit-review.googlesource.com/admin/repos/plugins/review-strategy[
-Project] |
-link:https://gerrit.googlesource.com/plugins/review-strategy/+doc/master/src/main/resources/Documentation/about.md[
-Documentation]
-
[[singleusergroup]]
=== singleusergroup
@@ -566,6 +556,16 @@
link:https://gerrit.googlesource.com/plugins/reparent/+doc/master/src/main/resources/Documentation/config.md[
Configuration]
+[[review-strategy]]
+=== review-strategy
+
+This plugin allows users to configure different review strategies.
+
+link:https://gerrit-review.googlesource.com/admin/repos/plugins/review-strategy[
+Project] |
+link:https://gerrit.googlesource.com/plugins/review-strategy/+doc/master/src/main/resources/Documentation/about.md[
+Documentation]
+
[[reviewers]]
=== reviewers
diff --git a/Documentation/database-setup.txt b/Documentation/database-setup.txt
deleted file mode 100644
index 2153751..0000000
--- a/Documentation/database-setup.txt
+++ /dev/null
@@ -1,280 +0,0 @@
-[[createdb]]
-== Database Setup
-
-During the init phase of Gerrit you will need to specify which database to use.
-
-[[createdb_h2]]
-=== H2
-
-If you choose H2, Gerrit will automatically set up the embedded H2 database as
-backend so no set up or configuration is necessary.
-
-Using the embedded H2 database is the easiest way to get a Gerrit
-site up and running, making it ideal for proof of concepts or small team
-servers. On the flip side, H2 is not the recommended option for large
-corporate installations. This is because there is no easy way to interact
-with the database while Gerrit is offline, it's not easy to backup the data,
-and it's not possible to set up H2 in a load balanced/hotswap configuration.
-
-If this option interests you, you might want to consider
-link:linux-quickstart.html[the quick guide].
-
-[[createdb_derby]]
-=== Apache Derby
-
-If Derby is selected, Gerrit will automatically set up the embedded Derby
-database as backend so no set up or configuration is necessary.
-
-Currently only support for embedded mode is added. There are two other
-deployment options for Apache Derby that can be added later:
-
-* link:http://db.apache.org/derby/papers/DerbyTut/ns_intro.html#Network+Server+Options[
-Derby Network Server (standalone mode)]
-
-* link:http://db.apache.org/derby/papers/DerbyTut/ns_intro.html#Embedded+Server[
-Embedded Server (hybrid mode)]
-
-[[createdb_postgres]]
-=== PostgreSQL
-
-This option is more complicated than the H2 option but is recommended
-for larger installations. It's the database backend with the largest userbase
-in the Gerrit community.
-
-Create a user for the web application within PostgreSQL, assign it a
-password, create a database to store the metadata, and grant the user
-full rights on the newly created database:
-
-----
- $ createuser --username=postgres -RDIElPS gerrit
- $ createdb --username=postgres -E UTF-8 -O gerrit reviewdb
-----
-
-Visit PostgreSQL's link:http://www.postgresql.org/docs/9.1/interactive/index.html[documentation] for further information regarding
-using PostgreSQL.
-
-[[createdb_mysql]]
-=== MySQL
-
-Requirements: MySQL version 5.1 or later.
-
-This option is also more complicated than the H2 option. Just as with
-PostgreSQL it's also recommended for larger installations.
-
-Create a user for the web application within the database, assign it a
-password, create a database, and give the newly created user full
-rights on it:
-
-----
- mysql
-
- CREATE USER 'gerrit'@'localhost' IDENTIFIED BY 'secret';
- CREATE DATABASE reviewdb DEFAULT CHARACTER SET 'utf8';
- GRANT ALL ON reviewdb.* TO 'gerrit'@'localhost';
- FLUSH PRIVILEGES;
-----
-
-Visit MySQL's link:http://dev.mysql.com/doc/[documentation] for further
-information regarding using MySQL.
-
-[[createdb_mariadb]]
-=== MariaDB
-
-Requirements: MariaDB version 5.5 or later.
-
-Refer to MySQL section above how to create MariaDB database.
-
-Visit MariaDB's link:https://mariadb.com/kb/en/mariadb/[documentation] for further
-information regarding using MariaDB.
-
-[[createdb_oracle]]
-=== Oracle
-
-PostgreSQL or H2 is the recommended database for Gerrit Code Review.
-Oracle is supported for environments where running on an existing Oracle
-installation simplifies administrative overheads, such as database backups.
-
-Create a user for the web application within sqlplus, assign it a
-password, and grant the user full rights on the newly created database:
-
-----
- SQL> create user gerrit identified by secret_password default tablespace users;
- SQL> grant connect, resources to gerrit;
-----
-
-JDBC driver ojdbc6.jar must be obtained from your Oracle distribution. Gerrit
-initialization process tries to copy it from a known location:
-
-----
-/u01/app/oracle/product/11.2.0/xe/jdbc/lib/ojdbc6.jar
-----
-
-If this file can not be located at this place, then the alternative location
-can be provided.
-
-Instance name is the Oracle SID. Sample database section in
-$site_path/etc/gerrit.config:
-
-----
-[database]
- type = oracle
- instance = xe
- hostname = localhost
- username = gerrit
- port = 1521
-----
-
-Sample database section in $site_path/etc/secure.config:
-
-----
-[database]
- password = secret_password
-----
-
-[[createdb_maxdb]]
-=== SAP MaxDB
-
-SAP MaxDB is a supported database for running Gerrit Code Review. However it is
-recommended only for environments where you intend to run Gerrit on an existing
-MaxDB installation to reduce administrative overhead.
-
-In the MaxDB studio or using the SQLCLI command line interface create a user
-'gerrit' with the user class 'RESOURCE' and a password <secret password>. This
-will also create an associated schema on the database.
-
-To run Gerrit on MaxDB, you need to obtain the MaxDB JDBC driver. It can be
-found in your MaxDB installation at the following location:
-
-- on Windows 64bit at "C:\Program Files\sdb\MaxDB\runtime\jar\sapdbc.jar"
-- on Linux at "/opt/sdb/MaxDB/runtime/jar/sapdbc.jar"
-
-It needs to be stored in the 'lib' folder of the review site.
-
-In the following sample database section it is assumed that the database name is
-'reviewdb' and the database is installed on localhost:
-
-In $site_path/etc/gerrit.config:
-
-----
-[database]
- type = maxdb
- database = reviewdb
- hostname = localhost
- username = gerrit
-
-----
-
-In $site_path/etc/secure.config:
-
-----
-[database]
- password = <secret password>
-----
-
-Visit SAP MaxDB's link:http://maxdb.sap.com/documentation/[documentation] for further
-information regarding using SAP MaxDB.
-
-[[createdb_db2]]
-=== DB2
-
-IBM DB2 is a supported database for running Gerrit Code Review. However it is
-recommended only for environments where you intend to run Gerrit on an existing
-DB2 installation to reduce administrative overhead.
-
-Create a system wide user for the Gerrit application, and grant the user
-full rights on the newly created database:
-
-----
- db2 => create database gerrit
- db2 => connect to gerrit
- db2 => grant connect,accessctrl,dataaccess,dbadm,secadm on database to gerrit;
-----
-
-JDBC driver db2jcc4.jar and db2jcc_license_cu.jar must be obtained
-from your DB2 distribution. Gerrit initialization process tries to copy
-it from a known location:
-
-----
-/opt/ibm/db2/V10.5/java/db2jcc4.jar
-/opt/ibm/db2/V10.5/java/db2jcc_license_cu.jar
-----
-
-If these files cannot be located at this place, then an alternative location
-can be provided during init step execution.
-
-Sample database section in $site_path/etc/gerrit.config:
-
-----
-[database]
- type = db2
- database = gerrit
- hostname = localhost
- username = gerrit
- port = 50001
-----
-
-Sample database section in $site_path/etc/secure.config:
-
-----
-[database]
- password = secret_password
-----
-
-[[createdb_hana]]
-=== SAP HANA
-
-SAP HANA is a supported database for running Gerrit Code Review. However it is
-recommended only for environments where you intend to run Gerrit on an existing
-HANA installation to reduce administrative overhead.
-
-In the HANA studio or the SAP HANA Web-based Development Workbench create a user
-'GERRIT2' with the role 'RESTRICTED_USER_JDBC_ACCESS' and a password
-<secret password>. This will also create an associated schema on the database.
-As this user would be required to change the password upon first login you might
-want to to disable the password lifetime check by executing
-'ALTER USER GERRIT2 DISABLE PASSWORD LIFETIME'.
-
-To run Gerrit on HANA, you need to obtain the HANA JDBC driver. It can be found
-as described
-link:http://help.sap.com/saphelp_hanaplatform/helpdata/en/ff/15928cf5594d78b841fbbe649f04b4/frameset.htm[here].
-It needs to be stored in the 'lib' folder of the review site.
-
-In the following sample database section it is assumed that HANA is running on
-the host 'hana.host' and listening on port '4242' where a schema/user GERRIT2
-was created:
-
-In $site_path/etc/gerrit.config:
-
-----
-[database]
- type = hana
- hostname = hana.host
- port = 4242
- username = GERRIT2
-
-----
-
-In order to configure a specific database in a multi-database environment (MDC)
-the database name has to be specified additionally:
-
-In $site_path/etc/gerrit.config:
-
-----
-[database]
- type = hana
- hostname = hana.host
- database = tdb1
- port = 4242
- username = GERRIT2
-
-----
-
-In $site_path/etc/secure.config:
-
-----
-[database]
- password = <secret password>
-----
-
-Visit SAP HANA's link:http://help.sap.com/hana_appliance/[documentation] for
-further information regarding using SAP HANA.
diff --git a/Documentation/dev-design.txt b/Documentation/dev-design.txt
index 2d6e24c..d2fd958 100644
--- a/Documentation/dev-design.txt
+++ b/Documentation/dev-design.txt
@@ -65,6 +65,9 @@
changing the implementation from Python on Google App Engine, to Java
on a J2EE servlet container and an SQL database.
+Since Gerrit 3.x link:note-db.html[NoteDb] replaced the SQL database
+and all metadata is now stored in Git.
+
* link:http://video.google.com/videoplay?docid=-8502904076440714866[Mondrian Code Review On The Web]
* link:https://github.com/rietveld-codereview/rietveld[Rietveld - Code Review for Subversion]
* link:http://eagain.net/gitweb/?p=gitosis.git;a=blob;f=README.rst;hb=HEAD[Gitosis README]
@@ -83,9 +86,7 @@
Each Git commit created on the client desktop system is converted
into a unique change record which can be reviewed independently.
-Change records are stored in a database: PostgreSQL, MySQL, or the
-built-in H2, where they can be queried to present customized user
-dashboards, enumerating any pending changes.
+Change records are stored in NoteDb.
A summary of each newly uploaded change is automatically emailed
to reviewers, so they receive a direct hyperlink to review the
@@ -167,7 +168,6 @@
online and operating in order to authenticate that user.
* link:http://www.kernel.org/pub/software/scm/git/docs/gitrepository-layout.html[Git Repository Format]
-* link:http://www.postgresql.org/about/[About PostgreSQL]
* link:http://openid.net/developers/specs/[OpenID Specifications]
*1 Although an effort is underway to eliminate the use of the
@@ -363,7 +363,7 @@
project's mailing list archives.
The user's name and email address is stored unencrypted in the
-Gerrit metadata store, typically a PostgreSQL database.
+link:config-accounts.html#all-users[All-Users] repository.
The snail-mail mailing address, country, and phone and fax numbers
are gathered to help project leads contact the user should there
@@ -633,12 +633,6 @@
=== Backups
-PostgreSQL and MySQL can be configured to replicate their data to
-other systems, where they are applied to a warm-standby backup in
-real time. Gerrit instances which care about redundancy will setup
-this feature of PostgreSQL or MySQL to ensure the warm-standby is
-reasonably current should the master go offline.
-
Using the standard replication plugin, Gerrit can be configured
to replicate changes made to the local Git repositories over any
standard Git transports. After the plugin is installed, remote
diff --git a/Documentation/dev-inspector.txt b/Documentation/dev-inspector.txt
index 2134f2f..b1559ca 100644
--- a/Documentation/dev-inspector.txt
+++ b/Documentation/dev-inspector.txt
@@ -54,8 +54,6 @@
----
"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d"
"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248"
-"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c"
-"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd"
Welcome to the Gerrit Inspector
Enter help() to see the above again, EOF to quit and stop Gerrit
@@ -109,71 +107,11 @@
'registerNatives', 'toString', 'wait']
----
-Startup script provides some convenient variables to access some global Gerrit components,
-for example a connection to the review database is kept open:
-
-----
->>> ds
-org.apache.commons.dbcp.BasicDataSource@61db2215
->>> ds.driverClassName
-u'org.postgresql.Driver'
->>> ds.dataSource
-org.apache.commons.dbcp.PoolingDataSource@23226fe1
->>> ds.dataSource.connection
-jdbc:postgresql://localhost/reviewdb, UserName=rv, PostgreSQL Native Driver
-----
-
-It is also possible to interact with the ORM layer:
-
-----
->>> db = schk.schema.open()
->>> db
-com.google.gerrit.reviewdb.server.ReviewDb_Schema_GwtOrm$$28@24cbbdf3
->>> db.getDialect()
-com.google.gwtorm.schema.sql.DialectPostgreSQL@4de07d3e
->>> for x in db.patchSets().iterateAllEntities():
-... print x
-...
-[PatchSet 1,1]
-[PatchSet 2,1]
-[PatchSet 3,1]
-[PatchSet 4,1]
-[PatchSet 5,1]
-[PatchSet 6,1]
-[PatchSet 7,1]
-[PatchSet 8,1]
-[PatchSet 6,2]
->>> for x in db.patchComments().iterateAllEntities():
-... print x
-com.google.gerrit.reviewdb.client.PatchLineComment@5381298a
-com.google.gerrit.reviewdb.client.PatchLineComment@44ce4dda
-com.google.gerrit.reviewdb.client.PatchLineComment@44594680
->>> dir(com.google.gerrit.reviewdb.client.PatchLineComment)
-['Key', 'STATUS_DRAFT', 'STATUS_PUBLISHED', 'Status', '__class__',
-'__copy__', '__deepcopy__', '__delattr__', '__doc__', '__eq__',
-'__getattribute__', '__hash__', '__init__', '__ne__', '__new__',
-'__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__str__',
-'__unicode__', 'author', 'class', 'clone', 'equals', 'finalize',
-'getAuthor', 'getClass', 'getKey', 'getLine', 'getMessage',
-'getParentUuid', 'getSide', 'getStatus', 'getWrittenOn', 'hashCode',
-'key', 'line', 'lineNbr', 'message', 'notify', 'notifyAll',
-'parentUuid', 'registerNatives', 'setMessage', 'setSide', 'setStatus',
-'side', 'status', 'toString', 'updated', 'wait', 'writtenOn']
->>> for x in db.patchComments().iterateAllEntities():
-... print x.status, x.line, x.message
-...
-P 2 I like it!
-P 2 more
-P 1 better
-----
-
A built-in *help()* function provides values of global variables
defined in the interpreter:
----
>>> help()
-"schk" is "com.google.gerrit.server.schema.SchemaVersionCheck@5e8cb9bd"
-"ds" is "com.google.gerrit.server.schema.DataSourceProvider@6b3592c"
"m" is "com.google.gerrit.lifecycle.LifecycleManager@6f03b248"
"Shell" is "com.google.gerrit.pgm.shell.JythonShell@61644f2d"
"d" is "com.google.gerrit.pgm.Daemon@28a3f689"
diff --git a/Documentation/dev-readme.txt b/Documentation/dev-readme.txt
index 92d080b..433e0c1 100644
--- a/Documentation/dev-readme.txt
+++ b/Documentation/dev-readme.txt
@@ -187,27 +187,6 @@
CAUTION: When using the Inspector, be careful not to modify the internal state
of the system.
-=== Querying the database
-
-The embedded H2 database can be queried and updated from the command line. If
-the daemon is not running, run:
-
-----
- $(bazel info output_base)/external/local_jdk/bin/java \
- -jar bazel-bin/gerrit.war gsql -d ../gerrit_testsite -s
-----
-
-NOTE: To learn why using `java -jar` isn't sufficient, see
-<<special_bazel_java_version,this explanation>>.
-
-Alternatively, if the daemon is running and the database is in use, use an
-administrator user account to connect over SSH:
-
-----
- ssh -p 29418 user@localhost gerrit gsql
-----
-
-
== Switching between branches
When using `git checkout` without `--recurse-submodules` to switch between
diff --git a/Documentation/install-j2ee.txt b/Documentation/install-j2ee.txt
index 91d73cc..48751b7 100644
--- a/Documentation/install-j2ee.txt
+++ b/Documentation/install-j2ee.txt
@@ -14,9 +14,8 @@
== Installation
-* Complete the link:install.html#createdb[database setup] and
- link:install.html#init[site initialization] tasks described
- in the standard installation documentation.
+* Complete the link:install.html#init[site initialization] task
+ described in the standard installation documentation.
* Stop the embedded daemon that was automatically started by 'init':
+
@@ -24,13 +23,6 @@
review_site/bin/gerrit.sh stop
----
-* Configure JNDI DataSource 'jdbc/ReviewDb'.
-+
-This DataSource must point to the database you created above.
-Don't forget to ensure your JNDI configuration can load the
-necessary JDBC drivers. You may wish to ensure connection pooling
-is configured and enabled within the DataSource.
-
* Deploy the 'gerrit.war' file to your application server.
+
The deployment process differs between servers, but typically this
@@ -70,20 +62,8 @@
java -jar webapps/gerrit.war cat extra/jetty7/gerrit.xml >contexts/gerrit.xml
----
-Install the required additional libraries by copying them into the
-`'$JETTY_HOME'/lib/ext` directory:
-
-----
- cp ../review_db/lib/* lib/ext/
- java -jar webapps/gerrit.war cat lib/commons-dbcp-1.2.2.jar >lib/ext/commons-dbcp-1.2.2.jar
- java -jar webapps/gerrit.war cat lib/commons-pool-1.5.4.jar >lib/ext/commons-pool-1.5.4.jar
- java -jar webapps/gerrit.war cat lib/h2-1.2.128.jar >lib/ext/h2-1.2.128.jar
- java -jar webapps/gerrit.war cat lib/postgresql-8.4-701.jdbc4.jar >lib/ext/postgresql-8.4-701.jdbc4.jar
-----
-
Edit `'$JETTY_HOME'/contexts/gerrit.xml` to correctly configure
-the database and outgoing SMTP connections, especially the user
-and password fields.
+outgoing SMTP connections.
If OpenID authentication (or certain enterprise single-sign-on
solutions) is being used, you may need to increase the
diff --git a/Documentation/install.txt b/Documentation/install.txt
index dbca368..be55417 100644
--- a/Documentation/install.txt
+++ b/Documentation/install.txt
@@ -9,10 +9,6 @@
+
Gerrit is not yet compatible with Java 9 or newer at this time.
-By default, Gerrit uses link:note-db.html[NoteDB] as the storage backend. (If
-desired, you can _optionally_ use an external database such as MySQL or
-PostgreSQL.)
-
[[cryptography]]
== Configure Java for Strong Cryptography
@@ -60,8 +56,6 @@
If you would prefer to build Gerrit directly from source, review
the notes under link:dev-readme.html[developer setup].
-include::database-setup.txt[]
-
[[init]]
== Initialize the Site
@@ -217,8 +211,7 @@
--StartPath=C:\MY\GERRIT\SITE ^
--StartMode=jvm --StopMode=jvm ^
--StartClass=com.google.gerrit.launcher.GerritLauncher --StartMethod=daemonStart ^
- --StopClass=com.google.gerrit.launcher.GerritLauncher --StopMethod=daemonStop ^
- ++DependsOn=postgresql-x64-9.4
+ --StopClass=com.google.gerrit.launcher.GerritLauncher --StopMethod=daemonStop
====
[[customize]]
@@ -255,8 +248,6 @@
== External Documentation Links
-* http://www.postgresql.org/docs/[PostgreSQL Documentation]
-* http://dev.mysql.com/doc/[MySQL Documentation]
* http://www.kernel.org/pub/software/scm/git/docs/git-daemon.html[git-daemon]
diff --git a/Documentation/pgm-gsql.txt b/Documentation/pgm-gsql.txt
deleted file mode 100644
index 4986522..0000000
--- a/Documentation/pgm-gsql.txt
+++ /dev/null
@@ -1,55 +0,0 @@
-= gsql
-
-== NAME
-gsql - Administrative interface to idle database
-
-== SYNOPSIS
-[verse]
---
-_java_ -jar gerrit.war _gsql_
- -d <SITE_PATH>
---
-
-== DESCRIPTION
-Interactive query support against the configured SQL database.
-All SQL statements are supported, including SELECT, UPDATE, INSERT,
-DELETE and ALTER.
-
-This command is primarily intended to access a local H2 database
-which is not currently open by a Gerrit daemon. To access an open
-database use link:cmd-gsql.html[gerrit gsql] over SSH.
-
-== OPTIONS
-
--d::
---site-path::
- Location of the gerrit.config file, and all other per-site
- configuration data, supporting libraries and log files.
-
-== CONTEXT
-This command can only be run on a server which has direct
-connectivity to the metadata database, and local access to the
-managed Git repositories.
-
-== EXAMPLES
-To manually correct a user's SSH user name:
-
-----
- $ java -jar gerrit.war gsql
- Welcome to Gerrit Code Review v2.0.25
- (PostgreSQL 8.3.8)
-
- Type '\h' for help. Type '\r' to clear the buffer.
-
- gerrit> update accounts set ssh_user_name = 'alice' where account_id=1;
- UPDATE 1; 1 ms
- gerrit> \q
- Bye
-----
-
-GERRIT
-------
-Part of link:index.html[Gerrit Code Review]
-
-SEARCHBOX
----------
diff --git a/Documentation/pgm-index.txt b/Documentation/pgm-index.txt
index d61cc0b..dde0231 100644
--- a/Documentation/pgm-index.txt
+++ b/Documentation/pgm-index.txt
@@ -15,9 +15,6 @@
link:pgm-daemon.html[daemon]::
Gerrit HTTP, SSH network server.
-link:pgm-gsql.html[gsql]::
- Administrative interface to idle database.
-
link:pgm-prolog-shell.html[prolog-shell]::
Simple interactive Prolog interpreter.
diff --git a/WORKSPACE b/WORKSPACE
index 58bde27..9e51fcd 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -568,18 +568,18 @@
sha1 = "18d4d07010c24405129a6dbb0e92057f8779fb9d",
)
-AUTO_VALUE_VERSION = "1.6.2"
+AUTO_VALUE_VERSION = "1.6.3"
maven_jar(
name = "auto-value",
artifact = "com.google.auto.value:auto-value:" + AUTO_VALUE_VERSION,
- sha1 = "e7eae562942315a983eea3e191b72d755c153620",
+ sha1 = "8edb6675b9c09ffdcc19937428e7ef1e3d066e12",
)
maven_jar(
name = "auto-value-annotations",
artifact = "com.google.auto.value:auto-value-annotations:" + AUTO_VALUE_VERSION,
- sha1 = "ed193d86e0af90cc2342aedbe73c5d86b03fa09b",
+ sha1 = "b88c1bb7f149f6d2cc03898359283e57b08f39cc",
)
# Transitive dependency of commons-compress
@@ -995,12 +995,6 @@
)
maven_jar(
- name = "postgresql",
- artifact = "org.postgresql:postgresql:42.2.5",
- sha1 = "951b7eda125f3137538a94e2cbdcf744088ad4c2",
-)
-
-maven_jar(
name = "commons-io",
artifact = "commons-io:commons-io:2.2",
sha1 = "83b5b8a7ba1c08f9e8c8ff2373724e33d3c1e22a",
@@ -1022,8 +1016,8 @@
# and httpasyncclient as necessary.
maven_jar(
name = "elasticsearch-rest-client",
- artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.5.1",
- sha1 = "d87892e24ef361b9fff5435246b0f0b8f4561fe8",
+ artifact = "org.elasticsearch.client:elasticsearch-rest-client:6.5.2",
+ sha1 = "6ad0dd15affe56be7dfe638fe317bc5f7456b730",
)
JACKSON_VERSION = "2.9.7"
diff --git a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
index d43f9ff..ff0013d 100644
--- a/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
+++ b/java/com/google/gerrit/acceptance/AbstractDaemonTest.java
@@ -427,10 +427,10 @@
db = reviewDbProvider.open();
- // All groups which were added during the server start (e.g. in ReviewDbSchemaCreator) aren't
+ // All groups which were added during the server start (e.g. in SchemaCreatorImpl) aren't
// contained in the instance of the group index which is available here and in tests. There are
// two reasons:
- // 1) No group index is available in ReviewDbSchemaCreator when using an in-memory database.
+ // 1) No group index is available in SchemaCreatorImpl when using an in-memory database.
// (This could be fixed by using the IndexManagerOnInit in InMemoryDatabase similar as BaseInit
// uses it.)
// 2) During the on-init part of the server start, we use another instance of the index than
diff --git a/java/com/google/gerrit/acceptance/GerritServer.java b/java/com/google/gerrit/acceptance/GerritServer.java
index 96a9053..4788ab7 100644
--- a/java/com/google/gerrit/acceptance/GerritServer.java
+++ b/java/com/google/gerrit/acceptance/GerritServer.java
@@ -40,15 +40,11 @@
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.git.receive.AsyncReceiveCommits;
import com.google.gerrit.server.ssh.NoSshModule;
-import com.google.gerrit.server.util.ManualRequestContext;
-import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.SocketUtil;
import com.google.gerrit.server.util.SystemLog;
import com.google.gerrit.testing.FakeEmailSender;
import com.google.gerrit.testing.FakeGroupAuditService;
-import com.google.gerrit.testing.InMemoryDatabase;
import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.NoteDbChecker;
import com.google.gerrit.testing.NoteDbMode;
import com.google.gerrit.testing.SshMode;
import com.google.inject.AbstractModule;
@@ -315,7 +311,7 @@
if (!desc.memory()) {
init(desc, baseConfig, site);
}
- return start(desc, baseConfig, site, testSysModule, null, null);
+ return start(desc, baseConfig, site, testSysModule, null);
} catch (Exception e) {
throw e;
}
@@ -333,8 +329,6 @@
* @param testSysModule optional additional module to add to the system injector.
* @param inMemoryRepoManager {@link InMemoryRepositoryManager} that should be used if the site is
* started in memory
- * @param inMemoryDatabaseInstance {@link com.google.gerrit.testing.InMemoryDatabase.Instance}
- * that should be used if the site is started in memory
* @param additionalArgs additional command-line arguments for the daemon program; only allowed if
* the test is not in-memory.
* @return started server.
@@ -346,7 +340,6 @@
Path site,
@Nullable Module testSysModule,
@Nullable InMemoryRepositoryManager inMemoryRepoManager,
- @Nullable InMemoryDatabase.Instance inMemoryDatabaseInstance,
String... additionalArgs)
throws Exception {
checkArgument(site != null, "site is required (even for in-memory server");
@@ -371,8 +364,7 @@
if (desc.memory()) {
checkArgument(additionalArgs.length == 0, "cannot pass args to in-memory server");
- return startInMemory(
- desc, site, baseConfig, daemon, inMemoryRepoManager, inMemoryDatabaseInstance);
+ return startInMemory(desc, site, baseConfig, daemon, inMemoryRepoManager);
}
return startOnDisk(desc, site, daemon, serverStarted, additionalArgs);
}
@@ -382,8 +374,7 @@
Path site,
Config baseConfig,
Daemon daemon,
- @Nullable InMemoryRepositoryManager inMemoryRepoManager,
- @Nullable InMemoryDatabase.Instance inMemoryDatabaseInstance)
+ @Nullable InMemoryRepositoryManager inMemoryRepoManager)
throws Exception {
Config cfg = desc.buildConfig(baseConfig);
mergeTestConfig(cfg);
@@ -398,8 +389,7 @@
daemon.setLuceneModule(LuceneIndexModule.singleVersionAllLatest(0, isSlave(baseConfig)));
daemon.setDatabaseForTesting(
ImmutableList.<Module>of(
- new InMemoryTestingDatabaseModule(
- cfg, site, inMemoryRepoManager, inMemoryDatabaseInstance),
+ new InMemoryTestingDatabaseModule(cfg, site, inMemoryRepoManager),
new AbstractModule() {
@Override
protected void configure() {
@@ -597,21 +587,9 @@
inMemoryRepoManager = server.testInjector.getInstance(InMemoryRepositoryManager.class);
}
- InMemoryDatabase.Instance dbInstance = null;
- if (hasBinding(server.testInjector, InMemoryDatabase.class)) {
- InMemoryDatabase inMemoryDatabase = server.testInjector.getInstance(InMemoryDatabase.class);
- dbInstance = inMemoryDatabase.getDbInstance();
- dbInstance.setKeepOpen(true);
- }
- try {
- server.close();
- server.daemon.stop();
- return start(server.desc, cfg, site, null, inMemoryRepoManager, dbInstance);
- } finally {
- if (dbInstance != null) {
- dbInstance.setKeepOpen(false);
- }
- }
+ server.close();
+ server.daemon.stop();
+ return start(server.desc, cfg, site, null, inMemoryRepoManager);
}
private static boolean hasBinding(Injector injector, Class<?> clazz) {
@@ -620,40 +598,19 @@
@Override
public void close() throws Exception {
- try {
- checkNoteDbState();
- } finally {
- daemon.getLifecycleManager().stop();
- if (daemonService != null) {
- System.out.println("Gerrit Server Shutdown");
- daemonService.shutdownNow();
- daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
- }
- RepositoryCache.clear();
+ daemon.getLifecycleManager().stop();
+ if (daemonService != null) {
+ System.out.println("Gerrit Server Shutdown");
+ daemonService.shutdownNow();
+ daemonService.awaitTermination(Long.MAX_VALUE, TimeUnit.SECONDS);
}
+ RepositoryCache.clear();
}
public Path getSitePath() {
return sitePath;
}
- private void checkNoteDbState() throws Exception {
- NoteDbMode mode = NoteDbMode.get();
- if (mode != NoteDbMode.CHECK && mode != NoteDbMode.PRIMARY) {
- return;
- }
- NoteDbChecker checker = testInjector.getInstance(NoteDbChecker.class);
- OneOffRequestContext oneOffRequestContext =
- testInjector.getInstance(OneOffRequestContext.class);
- try (ManualRequestContext ctx = oneOffRequestContext.open()) {
- if (mode == NoteDbMode.CHECK) {
- checker.rebuildAndCheckAllChanges();
- } else if (mode == NoteDbMode.PRIMARY) {
- checker.assertNoReviewDbChanges(desc.testDescription());
- }
- }
- }
-
@Override
public String toString() {
return MoreObjects.toStringHelper(this).addValue(desc).toString();
diff --git a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
index 0bbf9f1..e15d162 100644
--- a/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
+++ b/java/com/google/gerrit/acceptance/InMemoryTestingDatabaseModule.java
@@ -28,16 +28,11 @@
import com.google.gerrit.server.config.TrackingFooters;
import com.google.gerrit.server.config.TrackingFootersProvider;
import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.GwtormChangeBundleReader;
import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.NotesMigrationSchemaFactory;
import com.google.gerrit.server.schema.ReviewDbFactory;
import com.google.gerrit.server.schema.ReviewDbSchemaModule;
-import com.google.gerrit.server.schema.ReviewDbSchemaVersion;
import com.google.gerrit.testing.InMemoryDatabase;
-import com.google.gerrit.testing.InMemoryH2Type;
import com.google.gerrit.testing.InMemoryRepositoryManager;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.OrmRuntimeException;
@@ -46,7 +41,6 @@
import com.google.inject.Key;
import com.google.inject.ProvisionException;
import com.google.inject.TypeLiteral;
-import com.google.inject.util.Providers;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
@@ -56,17 +50,12 @@
private final Config cfg;
private final Path sitePath;
@Nullable private final InMemoryRepositoryManager repoManager;
- @Nullable private final InMemoryDatabase.Instance inMemoryDatabaseInstance;
InMemoryTestingDatabaseModule(
- Config cfg,
- Path sitePath,
- @Nullable InMemoryRepositoryManager repoManager,
- @Nullable InMemoryDatabase.Instance inMemoryDatabaseInstance) {
+ Config cfg, Path sitePath, @Nullable InMemoryRepositoryManager repoManager) {
this.cfg = cfg;
this.sitePath = sitePath;
this.repoManager = repoManager;
- this.inMemoryDatabaseInstance = inMemoryDatabaseInstance;
makeSiteDirs(sitePath);
}
@@ -85,16 +74,13 @@
}
bind(MetricMaker.class).to(DisabledMetricMaker.class);
- bind(DataSourceType.class).to(InMemoryH2Type.class);
install(new NotesMigration.Module());
TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
new TypeLiteral<SchemaFactory<ReviewDb>>() {};
bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
- bind(InMemoryDatabase.Instance.class).toProvider(Providers.of(inMemoryDatabaseInstance));
bind(Key.get(schemaFactory, ReviewDbFactory.class)).to(InMemoryDatabase.class);
bind(InMemoryDatabase.class).in(SINGLETON);
- bind(ChangeBundleReader.class).to(GwtormChangeBundleReader.class);
listener().to(CreateDatabase.class);
@@ -102,7 +88,6 @@
bind(TrackingFooters.class).toProvider(TrackingFootersProvider.class).in(SINGLETON);
install(new ReviewDbSchemaModule());
- bind(ReviewDbSchemaVersion.class).to(ReviewDbSchemaVersion.C);
install(new SshdModule());
}
@@ -125,9 +110,7 @@
}
@Override
- public void stop() {
- mem.getDbInstance().drop();
- }
+ public void stop() {}
}
private static void makeSiteDirs(Path p) {
diff --git a/java/com/google/gerrit/acceptance/PushOneCommit.java b/java/com/google/gerrit/acceptance/PushOneCommit.java
index 5e45df2..d0735c8 100644
--- a/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import static java.util.stream.Collectors.toList;
import static org.junit.Assert.assertEquals;
import com.google.common.base.Strings;
@@ -31,7 +30,6 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
@@ -43,7 +41,6 @@
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.Stream;
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.PersonIdent;
@@ -144,7 +141,6 @@
private final ChangeNotes.Factory notesFactory;
private final ApprovalsUtil approvalsUtil;
private final Provider<InternalChangeQuery> queryProvider;
- private final NotesMigration notesMigration;
private final ReviewDb db;
private final TestRepository<?> testRepo;
@@ -162,7 +158,6 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
@Assisted ReviewDb db,
@Assisted PersonIdent i,
@Assisted TestRepository<?> testRepo)
@@ -171,7 +166,6 @@
notesFactory,
approvalsUtil,
queryProvider,
- notesMigration,
db,
i,
testRepo,
@@ -185,7 +179,6 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
@Assisted ReviewDb db,
@Assisted PersonIdent i,
@Assisted TestRepository<?> testRepo,
@@ -195,7 +188,6 @@
notesFactory,
approvalsUtil,
queryProvider,
- notesMigration,
db,
i,
testRepo,
@@ -210,7 +202,6 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
@Assisted ReviewDb db,
@Assisted PersonIdent i,
@Assisted TestRepository<?> testRepo,
@@ -222,7 +213,6 @@
notesFactory,
approvalsUtil,
queryProvider,
- notesMigration,
db,
i,
testRepo,
@@ -237,24 +227,13 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
@Assisted ReviewDb db,
@Assisted PersonIdent i,
@Assisted TestRepository<?> testRepo,
@Assisted String subject,
@Assisted Map<String, String> files)
throws Exception {
- this(
- notesFactory,
- approvalsUtil,
- queryProvider,
- notesMigration,
- db,
- i,
- testRepo,
- subject,
- files,
- null);
+ this(notesFactory, approvalsUtil, queryProvider, db, i, testRepo, subject, files, null);
}
@AssistedInject
@@ -262,7 +241,6 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
@Assisted ReviewDb db,
@Assisted PersonIdent i,
@Assisted TestRepository<?> testRepo,
@@ -275,7 +253,6 @@
notesFactory,
approvalsUtil,
queryProvider,
- notesMigration,
db,
i,
testRepo,
@@ -288,7 +265,6 @@
ChangeNotes.Factory notesFactory,
ApprovalsUtil approvalsUtil,
Provider<InternalChangeQuery> queryProvider,
- NotesMigration notesMigration,
ReviewDb db,
PersonIdent i,
TestRepository<?> testRepo,
@@ -301,7 +277,6 @@
this.notesFactory = notesFactory;
this.approvalsUtil = approvalsUtil;
this.queryProvider = queryProvider;
- this.notesMigration = notesMigration;
this.subject = subject;
this.files = files;
this.changeId = changeId;
@@ -436,22 +411,15 @@
assertThat(c.getSubject()).isEqualTo(resSubj);
assertThat(c.getStatus()).isEqualTo(expectedStatus);
assertThat(Strings.emptyToNull(c.getTopic())).isEqualTo(expectedTopic);
- if (notesMigration.readChanges()) {
- assertReviewers(c, ReviewerStateInternal.REVIEWER, expectedReviewers);
- assertReviewers(c, ReviewerStateInternal.CC, expectedCcs);
- } else {
- assertReviewers(
- c,
- ReviewerStateInternal.REVIEWER,
- Stream.concat(expectedReviewers.stream(), expectedCcs.stream()).collect(toList()));
- }
+ assertReviewers(c, ReviewerStateInternal.REVIEWER, expectedReviewers);
+ assertReviewers(c, ReviewerStateInternal.CC, expectedCcs);
}
private void assertReviewers(
Change c, ReviewerStateInternal state, List<TestAccount> expectedReviewers)
throws OrmException {
Iterable<Account.Id> actualIds =
- approvalsUtil.getReviewers(db, notesFactory.createChecked(db, c)).byState(state);
+ approvalsUtil.getReviewers(notesFactory.createChecked(db, c)).byState(state);
assertThat(actualIds)
.containsExactlyElementsIn(Sets.newHashSet(TestAccount.ids(expectedReviewers)));
}
diff --git a/java/com/google/gerrit/acceptance/StandaloneSiteTest.java b/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
index a50de1a..c03c8b6 100644
--- a/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
+++ b/java/com/google/gerrit/acceptance/StandaloneSiteTest.java
@@ -209,7 +209,7 @@
private GerritServer startImpl(@Nullable Module testSysModule, String... additionalArgs)
throws Exception {
return GerritServer.start(
- serverDesc, baseConfig, sitePaths.site_path, testSysModule, null, null, additionalArgs);
+ serverDesc, baseConfig, sitePaths.site_path, testSysModule, null, additionalArgs);
}
protected static void runGerrit(String... args) throws Exception {
diff --git a/java/com/google/gerrit/common/data/GlobalCapability.java b/java/com/google/gerrit/common/data/GlobalCapability.java
index 3e11256..fbe1deb 100644
--- a/java/com/google/gerrit/common/data/GlobalCapability.java
+++ b/java/com/google/gerrit/common/data/GlobalCapability.java
@@ -22,7 +22,7 @@
/** Server wide capabilities. Represented as {@link Permission} objects. */
public class GlobalCapability {
- /** Ability to access the database (with gsql). */
+ /** Ability to view code review metadata refs in repositories. */
public static final String ACCESS_DATABASE = "accessDatabase";
/**
diff --git a/java/com/google/gerrit/httpd/init/SiteInitializer.java b/java/com/google/gerrit/httpd/init/SiteInitializer.java
index 67510cd..04a0ddd 100644
--- a/java/com/google/gerrit/httpd/init/SiteInitializer.java
+++ b/java/com/google/gerrit/httpd/init/SiteInitializer.java
@@ -47,7 +47,7 @@
if (sitePath != null) {
Path site = Paths.get(sitePath);
logger.atInfo().log("Initializing site at %s", site.toRealPath().normalize());
- new BaseInit(site, false, true, pluginsDistribution, pluginsToInstall).run();
+ new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
return;
}
@@ -62,14 +62,7 @@
}
if (site != null) {
logger.atInfo().log("Initializing site at %s", site.toRealPath().normalize());
- new BaseInit(
- site,
- new ReviewDbDataSourceProvider(),
- false,
- false,
- pluginsDistribution,
- pluginsToInstall)
- .run();
+ new BaseInit(site, false, pluginsDistribution, pluginsToInstall).run();
}
} catch (Exception e) {
logger.atSevere().withCause(e).log("Site init failed");
diff --git a/java/com/google/gerrit/httpd/init/WebAppInitializer.java b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
index b73d57e..8b113b2 100644
--- a/java/com/google/gerrit/httpd/init/WebAppInitializer.java
+++ b/java/com/google/gerrit/httpd/init/WebAppInitializer.java
@@ -85,9 +85,6 @@
import com.google.gerrit.server.plugins.PluginModule;
import com.google.gerrit.server.project.DefaultProjectNameLockManager;
import com.google.gerrit.server.restapi.RestApiModule;
-import com.google.gerrit.server.schema.DataSourceModule;
-import com.google.gerrit.server.schema.DataSourceProvider;
-import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
@@ -266,28 +263,6 @@
Module configModule = new GerritServerConfigModule();
modules.add(configModule);
-
- Injector cfgInjector = Guice.createInjector(sitePathModule, configModule, secureStore);
- Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
- String dbType = cfg.getString("database", null, "type");
-
- final DataSourceType dst =
- Guice.createInjector(new DataSourceModule(), configModule, sitePathModule, secureStore)
- .getInstance(Key.get(DataSourceType.class, Names.named(dbType.toLowerCase())));
- modules.add(
- new LifecycleModule() {
- @Override
- protected void configure() {
- bind(DataSourceType.class).toInstance(dst);
- bind(DataSourceProvider.Context.class)
- .toInstance(DataSourceProvider.Context.MULTI_USER);
- bind(Key.get(DataSource.class, Names.named("ReviewDb")))
- .toProvider(DataSourceProvider.class)
- .in(SINGLETON);
- listener().to(DataSourceProvider.class);
- }
- });
-
} else {
modules.add(
new LifecycleModule() {
diff --git a/java/com/google/gerrit/launcher/GerritLauncher.java b/java/com/google/gerrit/launcher/GerritLauncher.java
index 5406d52..868c1d5 100644
--- a/java/com/google/gerrit/launcher/GerritLauncher.java
+++ b/java/com/google/gerrit/launcher/GerritLauncher.java
@@ -94,7 +94,6 @@
System.err.println(" init Initialize a Gerrit installation");
System.err.println(" reindex Rebuild the secondary index");
System.err.println(" daemon Run the Gerrit network daemons");
- System.err.println(" gsql Run the interactive query console");
System.err.println(" version Display the build version number");
System.err.println(" passwd Set or change password in secure.config");
diff --git a/java/com/google/gerrit/pgm/Daemon.java b/java/com/google/gerrit/pgm/Daemon.java
index e480f77..e7e8ea3 100644
--- a/java/com/google/gerrit/pgm/Daemon.java
+++ b/java/com/google/gerrit/pgm/Daemon.java
@@ -14,9 +14,7 @@
package com.google.gerrit.pgm;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.MoreObjects;
@@ -86,15 +84,12 @@
import com.google.gerrit.server.mail.receive.MailReceiver;
import com.google.gerrit.server.mail.send.SmtpEmailSender;
import com.google.gerrit.server.mime.MimeUtil2Module;
-import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
-import com.google.gerrit.server.notedb.rebuild.OnlineNoteDbMigrator;
import com.google.gerrit.server.patch.DiffExecutorModule;
import com.google.gerrit.server.permissions.DefaultPermissionBackendModule;
import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
import com.google.gerrit.server.plugins.PluginModule;
import com.google.gerrit.server.project.DefaultProjectNameLockManager;
import com.google.gerrit.server.restapi.RestApiModule;
-import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.InMemoryAccountPatchReviewStore;
import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
import com.google.gerrit.server.schema.NoteDbSchemaVersionCheck;
@@ -128,7 +123,6 @@
import javax.servlet.http.HttpServletRequest;
import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;
-import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler;
/** Run SSH daemon portions of Gerrit. */
public class Daemon extends SiteProgram {
@@ -177,15 +171,6 @@
@Option(name = "--stop-only", usage = "Stop the daemon", hidden = true)
private boolean stopOnly;
- @Option(
- name = "--migrate-to-note-db",
- usage = "Automatically migrate changes to NoteDb",
- handler = ExplicitBooleanOptionHandler.class)
- private boolean migrateToNoteDb;
-
- @Option(name = "--trial", usage = "(With --migrate-to-note-db) " + MigrateToNoteDb.TRIAL_USAGE)
- private boolean trial;
-
private final LifecycleManager manager = new LifecycleManager();
private Injector dbInjector;
private Injector cfgInjector;
@@ -289,7 +274,6 @@
if (inspector) {
JythonShell shell = new JythonShell();
shell.set("m", manager);
- shell.set("ds", dbInjector.getInstance(DataSourceProvider.class));
shell.set("d", this);
shell.run();
} else {
@@ -338,7 +322,7 @@
@VisibleForTesting
public void start() throws IOException {
if (dbInjector == null) {
- dbInjector = createDbInjector(true /* enableMetrics */, MULTI_USER);
+ dbInjector = createDbInjector(true /* enableMetrics */);
}
cfgInjector = createCfgInjector();
config = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
@@ -495,9 +479,6 @@
modules.add(new AccountDeactivator.Module());
modules.add(new ChangeCleanupRunner.Module());
}
- if (migrateToNoteDb()) {
- modules.add(new OnlineNoteDbMigrator.Module(trial));
- }
if (testSysModule != null) {
modules.add(testSysModule);
}
@@ -507,18 +488,11 @@
ModuleOverloader.override(modules, LibModuleLoader.loadModules(cfgInjector)));
}
- private boolean migrateToNoteDb() {
- return migrateToNoteDb || NoteDbMigrator.getAutoMigrate(requireNonNull(config));
- }
-
private Module createIndexModule() {
if (luceneModule != null) {
return luceneModule;
}
- boolean onlineUpgrade =
- VersionManager.getOnlineUpgrade(config)
- // Schema upgrade is handled by OnlineNoteDbMigrator in this case.
- && !migrateToNoteDb();
+ boolean onlineUpgrade = VersionManager.getOnlineUpgrade(config);
switch (indexType) {
case LUCENE:
return onlineUpgrade
diff --git a/java/com/google/gerrit/pgm/Gsql.java b/java/com/google/gerrit/pgm/Gsql.java
deleted file mode 100644
index 004486b..0000000
--- a/java/com/google/gerrit/pgm/Gsql.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm;
-
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.pgm.util.RuntimeShutdown;
-import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.sshd.commands.QueryShell;
-import com.google.gerrit.sshd.commands.QueryShell.Factory;
-import com.google.inject.Injector;
-import java.io.IOException;
-import org.kohsuke.args4j.Option;
-
-/** Run Gerrit's SQL query tool */
-public class Gsql extends SiteProgram {
- private final LifecycleManager manager = new LifecycleManager();
- private Injector dbInjector;
-
- @Option(name = "--format", usage = "Set output format")
- private QueryShell.OutputFormat format = QueryShell.OutputFormat.PRETTY;
-
- @Option(name = "-c", metaVar = "SQL QUERY", usage = "Query to execute")
- private String query;
-
- @Override
- public int run() throws Exception {
- mustHaveValidSite();
-
- dbInjector = createDbInjector(SINGLE_USER);
- manager.add(dbInjector);
- manager.start();
- RuntimeShutdown.add(
- () -> {
- try {
- System.in.close();
- } catch (IOException e) {
- // Ignored
- }
- manager.stop();
- });
- final QueryShell shell = shellFactory().create(System.in, System.out);
- shell.setOutputFormat(format);
- if (query != null) {
- shell.execute(query);
- } else {
- shell.run();
- }
- return 0;
- }
-
- private Factory shellFactory() {
- return dbInjector
- .createChildInjector(
- new FactoryModule() {
- @Override
- protected void configure() {
- factory(QueryShell.Factory.class);
- }
- })
- .getInstance(QueryShell.Factory.class);
- }
-}
diff --git a/java/com/google/gerrit/pgm/Init.java b/java/com/google/gerrit/pgm/Init.java
index 4ea31da..f31fb2c 100644
--- a/java/com/google/gerrit/pgm/Init.java
+++ b/java/com/google/gerrit/pgm/Init.java
@@ -95,7 +95,7 @@
}
public Init(Path sitePath) {
- super(sitePath, true, true, new WarDistribution(), null);
+ super(sitePath, true, new WarDistribution(), null);
batchMode = true;
noAutoStart = true;
}
diff --git a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
index feeaa27..14a0b5d 100644
--- a/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
+++ b/java/com/google/gerrit/pgm/LocalUsernamesToLowerCase.java
@@ -15,7 +15,6 @@
package com.google.gerrit.pgm;
import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_GERRIT;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleManager;
@@ -54,7 +53,7 @@
@Override
public int run() throws Exception {
- Injector dbInjector = createDbInjector(MULTI_USER);
+ Injector dbInjector = createDbInjector();
manager.add(dbInjector, dbInjector.createChildInjector(NoteDbSchemaVersionCheck.module()));
manager.start();
dbInjector
diff --git a/java/com/google/gerrit/pgm/MigrateAccountPatchReviewDb.java b/java/com/google/gerrit/pgm/MigrateAccountPatchReviewDb.java
index 4ace62b..e12bde2 100644
--- a/java/com/google/gerrit/pgm/MigrateAccountPatchReviewDb.java
+++ b/java/com/google/gerrit/pgm/MigrateAccountPatchReviewDb.java
@@ -21,7 +21,6 @@
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.config.ThreadSettingsConfig;
-import com.google.gerrit.server.schema.DataSourceProvider;
import com.google.gerrit.server.schema.JdbcAccountPatchReviewStore;
import com.google.inject.Injector;
import com.google.inject.Key;
@@ -49,7 +48,7 @@
@Override
public int run() throws Exception {
- Injector dbInjector = createDbInjector(DataSourceProvider.Context.SINGLE_USER);
+ Injector dbInjector = createDbInjector();
SitePaths sitePaths = new SitePaths(getSitePath());
ThreadSettingsConfig threadSettingsConfig = dbInjector.getInstance(ThreadSettingsConfig.class);
Config fakeCfg = new Config();
diff --git a/java/com/google/gerrit/pgm/MigrateToNoteDb.java b/java/com/google/gerrit/pgm/MigrateToNoteDb.java
deleted file mode 100644
index 61d7ed9..0000000
--- a/java/com/google/gerrit/pgm/MigrateToNoteDb.java
+++ /dev/null
@@ -1,222 +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.pgm;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.pgm.util.BatchProgramModule;
-import com.google.gerrit.pgm.util.RuntimeShutdown;
-import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.pgm.util.ThreadLimiter;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.change.ChangeResource;
-import com.google.gerrit.server.git.GarbageCollection;
-import com.google.gerrit.server.index.DummyIndexModule;
-import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
-import com.google.gerrit.server.notedb.rebuild.GcAllUsers;
-import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
-import com.google.gerrit.server.plugins.PluginGuiceEnvironment;
-import com.google.gerrit.server.schema.DataSourceType;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Provider;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import org.kohsuke.args4j.Option;
-import org.kohsuke.args4j.spi.ExplicitBooleanOptionHandler;
-
-public class MigrateToNoteDb extends SiteProgram {
- static final String TRIAL_USAGE =
- "Trial mode: migrate changes and turn on reading from NoteDb, but leave ReviewDb as the"
- + " source of truth";
-
- private static final int ISSUE_8022_THREAD_LIMIT = 4;
-
- @Option(name = "--threads", usage = "Number of threads to use for rebuilding NoteDb")
- private Integer threads;
-
- @Option(
- name = "--project",
- usage =
- "Only rebuild these projects, do no other migration; incompatible with --change;"
- + " recommended for debugging only")
- private List<String> projects = new ArrayList<>();
-
- @Option(
- name = "--change",
- usage =
- "Only rebuild these changes, do no other migration; incompatible with --project;"
- + " recommended for debugging only")
- private List<Integer> changes = new ArrayList<>();
-
- @Option(
- name = "--force",
- usage =
- "Force rebuilding changes where ReviewDb is still the source of truth, even if they"
- + " were previously migrated")
- private boolean force;
-
- @Option(name = "--trial", usage = TRIAL_USAGE)
- private boolean trial;
-
- @Option(
- name = "--sequence-gap",
- usage =
- "gap in change sequence numbers between last ReviewDb number and first NoteDb number;"
- + " negative indicates using the value of noteDb.changes.initialSequenceGap (default"
- + " 1000)")
- private int sequenceGap;
-
- @Option(
- name = "--reindex",
- usage =
- "Reindex all changes after migration; defaults to false in trial mode, true otherwise",
- handler = ExplicitBooleanOptionHandler.class)
- private Boolean reindex;
-
- private Injector dbInjector;
- private Injector sysInjector;
- private LifecycleManager dbManager;
- private LifecycleManager sysManager;
-
- @Inject private GcAllUsers gcAllUsers;
- @Inject private Provider<NoteDbMigrator.Builder> migratorBuilderProvider;
-
- @Override
- public int run() throws Exception {
- RuntimeShutdown.add(this::stop);
- try {
- mustHaveValidSite();
- dbInjector = createDbInjector(MULTI_USER);
-
- dbManager = new LifecycleManager();
- dbManager.add(dbInjector);
- dbManager.start();
-
- threads = limitThreads();
-
- sysInjector = createSysInjector();
- sysInjector.injectMembers(this);
- sysManager = new LifecycleManager();
- sysManager.add(sysInjector);
- sysInjector
- .getInstance(PluginGuiceEnvironment.class)
- .setDbCfgInjector(dbInjector, dbInjector);
- sysManager.start();
-
- try (NoteDbMigrator migrator =
- migratorBuilderProvider
- .get()
- .setThreads(threads)
- .setProgressOut(System.err)
- .setProjects(projects.stream().map(Project.NameKey::new).collect(toList()))
- .setChanges(changes.stream().map(Change.Id::new).collect(toList()))
- .setTrialMode(trial)
- .setForceRebuild(force)
- .setSequenceGap(sequenceGap)
- .build()) {
- if (!projects.isEmpty() || !changes.isEmpty()) {
- migrator.rebuild();
- } else {
- migrator.migrate();
- }
- }
- try (PrintWriter w = new PrintWriter(new OutputStreamWriter(System.out, UTF_8), true)) {
- gcAllUsers.run(w);
- }
- } finally {
- stop();
- }
-
- boolean reindex = firstNonNull(this.reindex, !trial);
- if (!reindex) {
- return 0;
- }
- // Reindex all indices, to save the user from having to run yet another program by hand while
- // their server is offline.
- List<String> reindexArgs =
- ImmutableList.of(
- "--site-path",
- getSitePath().toString(),
- "--threads",
- Integer.toString(threads),
- "--index",
- ChangeSchemaDefinitions.NAME);
- System.out.println("Migration complete, reindexing changes with:");
- System.out.println(" reindex " + reindexArgs.stream().collect(joining(" ")));
- Reindex reindexPgm = new Reindex();
- return reindexPgm.main(reindexArgs.stream().toArray(String[]::new));
- }
-
- private int limitThreads() {
- if (threads != null) {
- return threads;
- }
- int actualThreads;
- int procs = Runtime.getRuntime().availableProcessors();
- DataSourceType dsType = dbInjector.getInstance(DataSourceType.class);
- if (dsType.getDriver().equals("org.h2.Driver") && procs > ISSUE_8022_THREAD_LIMIT) {
- System.out.println(
- "Not using more than "
- + ISSUE_8022_THREAD_LIMIT
- + " threads due to http://crbug.com/gerrit/8022");
- System.out.println("Can be increased by passing --threads, but may cause errors");
- actualThreads = ISSUE_8022_THREAD_LIMIT;
- } else {
- actualThreads = procs;
- }
- actualThreads = ThreadLimiter.limitThreads(dbInjector, actualThreads);
- return actualThreads;
- }
-
- private Injector createSysInjector() {
- return dbInjector.createChildInjector(
- new FactoryModule() {
- @Override
- public void configure() {
- install(dbInjector.getInstance(BatchProgramModule.class));
- install(new DummyIndexModule());
- factory(ChangeResource.Factory.class);
- factory(GarbageCollection.Factory.class);
- }
- });
- }
-
- private void stop() {
- try {
- LifecycleManager m = sysManager;
- sysManager = null;
- if (m != null) {
- m.stop();
- }
- } finally {
- LifecycleManager m = dbManager;
- dbManager = null;
- if (m != null) {
- m.stop();
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/pgm/ProtobufImport.java b/java/com/google/gerrit/pgm/ProtobufImport.java
index 0179b1d..0335cbb 100644
--- a/java/com/google/gerrit/pgm/ProtobufImport.java
+++ b/java/com/google/gerrit/pgm/ProtobufImport.java
@@ -15,7 +15,6 @@
package com.google.gerrit.pgm;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
import static java.util.Objects.requireNonNull;
import com.google.auto.value.AutoValue;
@@ -63,6 +62,7 @@
* <p><strong>Warning</strong>: This method blindly upserts data into the database. It should only
* be used to restore a protobuf-formatted backup into a new, empty site.
*/
+// TODO(dborowitz): Delete this program.
public class ProtobufImport extends SiteProgram {
@Option(
name = "--file",
@@ -81,7 +81,7 @@
public int run() throws Exception {
mustHaveValidSite();
- Injector dbInjector = createDbInjector(SINGLE_USER);
+ Injector dbInjector = createDbInjector();
manager.add(dbInjector);
manager.start();
RuntimeShutdown.add(manager::stop);
diff --git a/java/com/google/gerrit/pgm/Reindex.java b/java/com/google/gerrit/pgm/Reindex.java
index 52d3bd3..cb129a7 100644
--- a/java/com/google/gerrit/pgm/Reindex.java
+++ b/java/com/google/gerrit/pgm/Reindex.java
@@ -14,7 +14,6 @@
package com.google.gerrit.pgm;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.MULTI_USER;
import static java.util.Objects.requireNonNull;
import static java.util.stream.Collectors.toSet;
@@ -29,7 +28,6 @@
import com.google.gerrit.lucene.LuceneIndexModule;
import com.google.gerrit.pgm.util.BatchProgramModule;
import com.google.gerrit.pgm.util.SiteProgram;
-import com.google.gerrit.pgm.util.ThreadLimiter;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.index.IndexModule;
@@ -81,10 +79,9 @@
@Override
public int run() throws Exception {
mustHaveValidSite();
- dbInjector = createDbInjector(MULTI_USER);
+ dbInjector = createDbInjector();
cfgInjector = dbInjector.createChildInjector();
globalConfig = dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
- threads = ThreadLimiter.limitThreads(dbInjector, threads);
overrideConfig();
LifecycleManager dbManager = new LifecycleManager();
dbManager.add(dbInjector);
diff --git a/java/com/google/gerrit/pgm/Rulec.java b/java/com/google/gerrit/pgm/Rulec.java
index add06ef..aa72ae0 100644
--- a/java/com/google/gerrit/pgm/Rulec.java
+++ b/java/com/google/gerrit/pgm/Rulec.java
@@ -14,8 +14,6 @@
package com.google.gerrit.pgm;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
-
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.rules.PrologCompiler;
@@ -60,7 +58,7 @@
@Override
public int run() throws Exception {
- dbInjector = createDbInjector(SINGLE_USER);
+ dbInjector = createDbInjector();
manager.add(dbInjector);
manager.start();
dbInjector
diff --git a/java/com/google/gerrit/pgm/SwitchSecureStore.java b/java/com/google/gerrit/pgm/SwitchSecureStore.java
index 3f10130..733c9d1 100644
--- a/java/com/google/gerrit/pgm/SwitchSecureStore.java
+++ b/java/com/google/gerrit/pgm/SwitchSecureStore.java
@@ -14,8 +14,6 @@
package com.google.gerrit.pgm;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
-
import com.google.common.base.Joiner;
import com.google.common.base.Strings;
import com.google.common.collect.Iterables;
@@ -86,7 +84,7 @@
logger.atInfo().log(
"Current secureStoreClass property (%s) will be replaced with %s",
currentSecureStoreName, newSecureStore);
- Injector dbInjector = createDbInjector(SINGLE_USER);
+ Injector dbInjector = createDbInjector();
SecureStore currentStore = getSecureStore(currentSecureStoreName, dbInjector);
SecureStore newStore = getSecureStore(newSecureStore, dbInjector);
diff --git a/java/com/google/gerrit/pgm/init/BaseInit.java b/java/com/google/gerrit/pgm/init/BaseInit.java
index 9a92408..7d9ac3f 100644
--- a/java/com/google/gerrit/pgm/init/BaseInit.java
+++ b/java/com/google/gerrit/pgm/init/BaseInit.java
@@ -14,8 +14,6 @@
package com.google.gerrit.pgm.init;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.unwrapDb;
-import static com.google.gerrit.server.schema.DataSourceProvider.Context.SINGLE_USER;
import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.Stage.PRODUCTION;
@@ -44,13 +42,10 @@
import com.google.gerrit.server.plugins.JarScanner;
import com.google.gerrit.server.schema.NoteDbSchemaUpdater;
import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.server.schema.ReviewDbSchemaUpdater;
import com.google.gerrit.server.schema.UpdateUI;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gerrit.server.securestore.SecureStoreProvider;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.gwtorm.server.StatementExecutor;
@@ -60,7 +55,6 @@
import com.google.inject.Inject;
import com.google.inject.Injector;
import com.google.inject.Module;
-import com.google.inject.Provider;
import com.google.inject.TypeLiteral;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
@@ -76,14 +70,12 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import javax.sql.DataSource;
/** Initialize a new Gerrit installation. */
public class BaseInit extends SiteProgram {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
private final boolean standalone;
- private final boolean initDb;
protected final PluginsDistribution pluginsDistribution;
private final List<String> pluginsToInstall;
@@ -91,7 +83,6 @@
protected BaseInit(PluginsDistribution pluginsDistribution, List<String> pluginsToInstall) {
this.standalone = true;
- this.initDb = true;
this.pluginsDistribution = pluginsDistribution;
this.pluginsToInstall = pluginsToInstall;
}
@@ -99,22 +90,10 @@
public BaseInit(
Path sitePath,
boolean standalone,
- boolean initDb,
PluginsDistribution pluginsDistribution,
List<String> pluginsToInstall) {
- this(sitePath, null, standalone, initDb, pluginsDistribution, pluginsToInstall);
- }
-
- public BaseInit(
- Path sitePath,
- final Provider<DataSource> dsProvider,
- boolean standalone,
- boolean initDb,
- PluginsDistribution pluginsDistribution,
- List<String> pluginsToInstall) {
- super(sitePath, dsProvider);
+ super(sitePath);
this.standalone = standalone;
- this.initDb = initDb;
this.pluginsDistribution = pluginsDistribution;
this.pluginsToInstall = pluginsToInstall;
}
@@ -257,7 +236,7 @@
}
m.add(new GerritServerConfigModule());
- m.add(new InitModule(standalone, initDb));
+ m.add(new InitModule(standalone));
m.add(
new AbstractModule() {
@Override
@@ -359,7 +338,6 @@
public final ConsoleUI ui;
public final SitePaths site;
public final InitFlags flags;
- final ReviewDbSchemaUpdater reviewDbSchemaUpdater;
final NoteDbSchemaUpdater noteDbSchemaUpdater;
final SchemaFactory<ReviewDb> schema;
final GitRepositoryManager repositoryManager;
@@ -369,58 +347,26 @@
ConsoleUI ui,
SitePaths site,
InitFlags flags,
- ReviewDbSchemaUpdater reviewDbSchemaUpdater,
NoteDbSchemaUpdater noteDbSchemaUpdater,
@ReviewDbFactory SchemaFactory<ReviewDb> schema,
GitRepositoryManager repositoryManager) {
this.ui = ui;
this.site = site;
this.flags = flags;
- this.reviewDbSchemaUpdater = reviewDbSchemaUpdater;
this.noteDbSchemaUpdater = noteDbSchemaUpdater;
this.schema = schema;
this.repositoryManager = repositoryManager;
}
void upgradeSchema() throws OrmException {
- final List<String> pruneList = new ArrayList<>();
- UpdateUI uiImpl = new UpdateUIImpl(ui, pruneList);
- reviewDbSchemaUpdater.update(uiImpl);
-
- if (!pruneList.isEmpty()) {
- StringBuilder msg = new StringBuilder();
- msg.append("Execute the following SQL to drop unused objects:\n");
- msg.append("\n");
- for (String sql : pruneList) {
- msg.append(" ");
- msg.append(sql);
- msg.append(";\n");
- }
-
- if (ui.isBatch()) {
- System.err.print(msg);
- System.err.flush();
-
- } else if (ui.yesno(true, "%s\nExecute now", msg)) {
- try (JdbcSchema db = (JdbcSchema) unwrapDb(schema.open());
- JdbcExecutor e = new JdbcExecutor(db)) {
- for (String sql : pruneList) {
- e.execute(sql);
- }
- }
- }
- }
-
- noteDbSchemaUpdater.update(uiImpl);
+ noteDbSchemaUpdater.update(new UpdateUIImpl(ui));
}
private static class UpdateUIImpl implements UpdateUI {
private final ConsoleUI consoleUi;
- private final List<String> pruneList;
- UpdateUIImpl(ConsoleUI consoleUi, List<String> pruneList) {
+ UpdateUIImpl(ConsoleUI consoleUi) {
this.consoleUi = consoleUi;
- this.pruneList = pruneList;
}
@Override
@@ -451,11 +397,8 @@
@Override
public void pruneSchema(StatementExecutor e, List<String> prune) {
- for (String p : prune) {
- if (!pruneList.contains(p)) {
- pruneList.add(p);
- }
- }
+ // Do nothing in NoteDb.
+ // TODO(dborowitz): Remove this method in the base class.
}
}
}
@@ -475,7 +418,7 @@
bind(InitFlags.class).toInstance(init.flags);
}
});
- Injector dbInjector = createDbInjector(SINGLE_USER);
+ Injector dbInjector = createDbInjector();
switch (IndexModule.getIndexType(dbInjector)) {
case LUCENE:
modules.add(new LuceneIndexModuleOnInit());
diff --git a/java/com/google/gerrit/pgm/init/DB2Initializer.java b/java/com/google/gerrit/pgm/init/DB2Initializer.java
deleted file mode 100644
index 9dc1088..0000000
--- a/java/com/google/gerrit/pgm/init/DB2Initializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2015 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-public class DB2Initializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "50001";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, false);
- databaseSection.string("Database name", "database", "gerrit");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/DatabaseConfigInitializer.java b/java/com/google/gerrit/pgm/init/DatabaseConfigInitializer.java
deleted file mode 100644
index 2701957..0000000
--- a/java/com/google/gerrit/pgm/init/DatabaseConfigInitializer.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-/** Abstraction of initializer for the database section */
-interface DatabaseConfigInitializer {
-
- /**
- * Performs database platform specific configuration steps and writes configuration parameters
- * into the given database section
- */
- void initConfig(Section databaseSection);
-}
diff --git a/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java b/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java
deleted file mode 100644
index 44f883a..0000000
--- a/java/com/google/gerrit/pgm/init/DatabaseConfigModule.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.AbstractModule;
-import com.google.inject.name.Names;
-
-public class DatabaseConfigModule extends AbstractModule {
-
- private final SitePaths site;
-
- public DatabaseConfigModule(SitePaths site) {
- this.site = site;
- }
-
- @Override
- protected void configure() {
- bind(SitePaths.class).toInstance(site);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("db2"))
- .to(DB2Initializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("derby"))
- .to(DerbyInitializer.class);
- bind(DatabaseConfigInitializer.class).annotatedWith(Names.named("h2")).to(H2Initializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("jdbc"))
- .to(JDBCInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("mariadb"))
- .to(MariaDbInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("mysql"))
- .to(MySqlInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("oracle"))
- .to(OracleInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("postgresql"))
- .to(PostgreSQLInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("maxdb"))
- .to(MaxDbInitializer.class);
- bind(DatabaseConfigInitializer.class)
- .annotatedWith(Names.named("hana"))
- .to(HANAInitializer.class);
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/DerbyInitializer.java b/java/com/google/gerrit/pgm/init/DerbyInitializer.java
deleted file mode 100644
index 3aad0f4..0000000
--- a/java/com/google/gerrit/pgm/init/DerbyInitializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2015 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.die;
-
-import com.google.gerrit.common.FileUtil;
-import com.google.gerrit.pgm.init.api.Section;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import java.nio.file.Path;
-
-class DerbyInitializer implements DatabaseConfigInitializer {
-
- private final SitePaths site;
-
- @Inject
- DerbyInitializer(SitePaths site) {
- this.site = site;
- }
-
- @Override
- public void initConfig(Section databaseSection) {
- String path = databaseSection.get("database");
- Path db;
- if (path == null) {
- db = site.resolve("db").resolve("ReviewDB");
- databaseSection.set("database", db.toString());
- } else {
- db = site.resolve(path);
- }
- if (db == null) {
- throw die("database.database must be supplied for Derby");
- }
- db = db.getParent();
- FileUtil.mkdirsOrDie(db, "cannot create database.database");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/H2Initializer.java b/java/com/google/gerrit/pgm/init/H2Initializer.java
deleted file mode 100644
index 63aa6ec..0000000
--- a/java/com/google/gerrit/pgm/init/H2Initializer.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.die;
-
-import com.google.gerrit.common.FileUtil;
-import com.google.gerrit.pgm.init.api.Section;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import java.nio.file.Path;
-
-class H2Initializer implements DatabaseConfigInitializer {
-
- private final SitePaths site;
-
- @Inject
- H2Initializer(SitePaths site) {
- this.site = site;
- }
-
- @Override
- public void initConfig(Section databaseSection) {
- String path = databaseSection.get("database");
- Path db;
- if (path == null) {
- db = site.resolve("db").resolve("ReviewDB");
- databaseSection.set("database", db.toString());
- } else {
- db = site.resolve(path);
- }
- if (db == null) {
- throw die("database.database must be supplied for H2");
- }
- db = db.getParent();
- FileUtil.mkdirsOrDie(db, "cannot create database.database");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/HANAInitializer.java b/java/com/google/gerrit/pgm/init/HANAInitializer.java
deleted file mode 100644
index 713392d..0000000
--- a/java/com/google/gerrit/pgm/init/HANAInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2016 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-public class HANAInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "(hana default)";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, true);
- databaseSection.string("Database name", "database", null);
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/InitDatabase.java b/java/com/google/gerrit/pgm/init/InitDatabase.java
deleted file mode 100644
index 558716c..0000000
--- a/java/com/google/gerrit/pgm/init/InitDatabase.java
+++ /dev/null
@@ -1,140 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm.init;
-
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
-import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
-import static com.google.inject.Stage.PRODUCTION;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.Sets;
-import com.google.gerrit.pgm.init.api.ConsoleUI;
-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.GerritServerIdProvider;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import com.google.inject.Binding;
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Singleton;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Named;
-import com.google.inject.name.Names;
-import java.lang.annotation.Annotation;
-import java.util.List;
-import java.util.Set;
-import org.eclipse.jgit.lib.Config;
-
-/** Initialize the {@code database} configuration section. */
-@Singleton
-class InitDatabase implements InitStep {
- private final ConsoleUI ui;
- private final SitePaths site;
- private final Libraries libraries;
- private final InitFlags flags;
- private final Section database;
- private final Section idSection;
- private final Section noteDbChanges;
-
- @Inject
- InitDatabase(
- ConsoleUI ui,
- SitePaths site,
- Libraries libraries,
- InitFlags flags,
- Section.Factory sections) {
- this.ui = ui;
- this.site = site;
- this.libraries = libraries;
- this.flags = flags; // Don't grab any flags yet; they aren't initialized until BaseInit#run.
- this.database = sections.get("database", null);
- this.idSection = sections.get(GerritServerIdProvider.SECTION, null);
- this.noteDbChanges = sections.get(SECTION_NOTE_DB, CHANGES.key());
- }
-
- @Override
- public void run() {
- initSqlDb();
- if (flags.isNew) {
- initNoteDb();
- }
- }
-
- private void initSqlDb() {
- ui.header("SQL Database");
-
- Set<String> allowedValues = Sets.newTreeSet();
- Injector i = Guice.createInjector(PRODUCTION, new DatabaseConfigModule(site));
- List<Binding<DatabaseConfigInitializer>> dbConfigBindings =
- i.findBindingsByType(new TypeLiteral<DatabaseConfigInitializer>() {});
- for (Binding<DatabaseConfigInitializer> binding : dbConfigBindings) {
- Annotation annotation = binding.getKey().getAnnotation();
- if (annotation instanceof Named) {
- allowedValues.add(((Named) annotation).value());
- }
- }
-
- if (!Strings.isNullOrEmpty(database.get("url"))
- && Strings.isNullOrEmpty(database.get("type"))) {
- database.set("type", "jdbc");
- }
-
- String dbType = database.select("Database server type", "type", "h2", allowedValues);
-
- DatabaseConfigInitializer dci =
- i.getInstance(Key.get(DatabaseConfigInitializer.class, Names.named(dbType.toLowerCase())));
-
- if (dci instanceof MySqlInitializer) {
- libraries.mysqlDriver.downloadRequired();
- } else if (dci instanceof MariaDbInitializer) {
- libraries.mariadbDriver.downloadRequired();
- } else if (dci instanceof OracleInitializer) {
- libraries.oracleDriver.downloadRequired();
- } else if (dci instanceof DB2Initializer) {
- libraries.db2Driver.downloadRequired();
- } else if (dci instanceof HANAInitializer) {
- libraries.hanaDriver.downloadRequired();
- }
-
- dci.initConfig(database);
-
- // Initialize UUID for NoteDb on first init.
- String id = idSection.get(GerritServerIdProvider.KEY);
- if (Strings.isNullOrEmpty(id)) {
- idSection.set(GerritServerIdProvider.KEY, GerritServerIdProvider.generate());
- }
- }
-
- private void initNoteDb() {
- ui.header("NoteDb Database");
- ui.message(
- "Use NoteDb for change metadata?\n"
- + " See documentation:\n"
- + " https://gerrit-review.googlesource.com/Documentation/note-db.html\n");
- if (!ui.yesno(true, "Enable")) {
- return;
- }
-
- Config defaultConfig = new Config();
- NotesMigrationState.FINAL.setConfigValues(defaultConfig);
- for (String name : defaultConfig.getNames(SECTION_NOTE_DB, CHANGES.key())) {
- noteDbChanges.set(name, defaultConfig.getString(SECTION_NOTE_DB, CHANGES.key(), name));
- }
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/InitModule.java b/java/com/google/gerrit/pgm/init/InitModule.java
index f677ceb..75145de 100644
--- a/java/com/google/gerrit/pgm/init/InitModule.java
+++ b/java/com/google/gerrit/pgm/init/InitModule.java
@@ -26,11 +26,9 @@
public class InitModule extends FactoryModule {
private final boolean standalone;
- private final boolean initDb;
- public InitModule(boolean standalone, boolean initDb) {
+ public InitModule(boolean standalone) {
this.standalone = standalone;
- this.initDb = initDb;
}
@Override
@@ -43,12 +41,8 @@
// Steps are executed in the order listed here.
//
- step().to(UpgradeFrom2_0_x.class);
-
step().to(InitGitManager.class);
- if (initDb) {
- step().to(InitDatabase.class);
- }
+ step().to(InitNoteDb.class);
step().to(InitLogging.class);
step().to(InitIndex.class);
step().to(InitAuth.class);
diff --git a/java/com/google/gerrit/pgm/init/InitNoteDb.java b/java/com/google/gerrit/pgm/init/InitNoteDb.java
new file mode 100644
index 0000000..dc52868
--- /dev/null
+++ b/java/com/google/gerrit/pgm/init/InitNoteDb.java
@@ -0,0 +1,50 @@
+// Copyright (C) 2018 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.pgm.init;
+
+import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
+import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
+
+import com.google.gerrit.pgm.init.api.InitStep;
+import com.google.gerrit.pgm.init.api.Section;
+import com.google.gerrit.server.notedb.NotesMigrationState;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import org.eclipse.jgit.lib.Config;
+
+/** Initialize the NoteDb in gerrit site. */
+@Singleton
+class InitNoteDb implements InitStep {
+
+ private final Section noteDbChanges;
+
+ @Inject
+ InitNoteDb(Section.Factory sections) {
+ this.noteDbChanges = sections.get(SECTION_NOTE_DB, CHANGES.key());
+ }
+
+ @Override
+ public void run() {
+ initNoteDb();
+ }
+
+ private void initNoteDb() {
+ Config defaultConfig = new Config();
+ NotesMigrationState.FINAL.setConfigValues(defaultConfig);
+ for (String name : defaultConfig.getNames(SECTION_NOTE_DB, CHANGES.key())) {
+ noteDbChanges.set(name, defaultConfig.getString(SECTION_NOTE_DB, CHANGES.key(), name));
+ }
+ }
+}
diff --git a/java/com/google/gerrit/pgm/init/JDBCInitializer.java b/java/com/google/gerrit/pgm/init/JDBCInitializer.java
deleted file mode 100644
index e3a1d66..0000000
--- a/java/com/google/gerrit/pgm/init/JDBCInitializer.java
+++ /dev/null
@@ -1,49 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.pgm.init.api.Section;
-
-class JDBCInitializer implements DatabaseConfigInitializer {
- @Override
- public void initConfig(Section database) {
- boolean hasUrl = Strings.emptyToNull(database.get("url")) != null;
- database.string("URL", "url", null);
- guessDriver(database);
- database.string("Driver class name", "driver", null);
- database.string("Database username", "username", hasUrl ? null : username());
- database.password("username", "password");
- }
-
- private void guessDriver(Section database) {
- String url = Strings.emptyToNull(database.get("url"));
- if (url != null && Strings.isNullOrEmpty(database.get("driver"))) {
- if (url.startsWith("jdbc:derby:")) {
- database.set("driver", "org.apache.derby.jdbc.EmbeddedDriver");
- } else if (url.startsWith("jdbc:h2:")) {
- database.set("driver", "org.h2.Driver");
- } else if (url.startsWith("jdbc:mariadb:")) {
- database.set("driver", "org.mariadb.jdbc.Driver");
- } else if (url.startsWith("jdbc:mysql:")) {
- database.set("driver", "com.mysql.jdbc.Driver");
- } else if (url.startsWith("jdbc:postgresql:")) {
- database.set("driver", "org.postgresql.Driver");
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/MariaDbInitializer.java b/java/com/google/gerrit/pgm/init/MariaDbInitializer.java
deleted file mode 100644
index db32113..0000000
--- a/java/com/google/gerrit/pgm/init/MariaDbInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2017 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-class MariaDbInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "(mariadb default)";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, true);
- databaseSection.string("Database name", "database", "reviewdb");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/MaxDbInitializer.java b/java/com/google/gerrit/pgm/init/MaxDbInitializer.java
deleted file mode 100644
index 0f696b7..0000000
--- a/java/com/google/gerrit/pgm/init/MaxDbInitializer.java
+++ /dev/null
@@ -1,32 +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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-public class MaxDbInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "(maxdb default)";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, true);
- databaseSection.string("Database name", "database", "reviewdb");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/MySqlInitializer.java b/java/com/google/gerrit/pgm/init/MySqlInitializer.java
deleted file mode 100644
index 037b52b..0000000
--- a/java/com/google/gerrit/pgm/init/MySqlInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-class MySqlInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "(mysql default)";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, true);
- databaseSection.string("Database name", "database", "reviewdb");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/OracleInitializer.java b/java/com/google/gerrit/pgm/init/OracleInitializer.java
deleted file mode 100644
index ffbaf34..0000000
--- a/java/com/google/gerrit/pgm/init/OracleInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2013 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-public class OracleInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "1521";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, false);
- databaseSection.string("Instance name", "instance", "xe");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/PostgreSQLInitializer.java b/java/com/google/gerrit/pgm/init/PostgreSQLInitializer.java
deleted file mode 100644
index 65a66de..0000000
--- a/java/com/google/gerrit/pgm/init/PostgreSQLInitializer.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2012 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.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.username;
-
-import com.google.gerrit.pgm.init.api.Section;
-
-class PostgreSQLInitializer implements DatabaseConfigInitializer {
-
- @Override
- public void initConfig(Section databaseSection) {
- final String defPort = "(postgresql default)";
- databaseSection.string("Server hostname", "hostname", "localhost");
- databaseSection.string("Server port", "port", defPort, true);
- databaseSection.string("Database name", "database", "reviewdb");
- databaseSection.string("Database username", "username", username());
- databaseSection.password("username", "password");
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java b/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
deleted file mode 100644
index 95ff8d7..0000000
--- a/java/com/google/gerrit/pgm/init/UpgradeFrom2_0_x.java
+++ /dev/null
@@ -1,291 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm.init;
-
-import static com.google.gerrit.pgm.init.api.InitUtil.die;
-import static com.google.gerrit.pgm.init.api.InitUtil.savePublic;
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.base.Splitter;
-import com.google.gerrit.pgm.init.api.ConsoleUI;
-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.securestore.SecureStore;
-import com.google.gerrit.server.util.SocketUtil;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.UnsupportedEncodingException;
-import java.net.InetSocketAddress;
-import java.net.URLDecoder;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.Arrays;
-import java.util.Map;
-import java.util.Properties;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-
-/** Upgrade from a 2.0.x site to a 2.1 site. */
-@Singleton
-class UpgradeFrom2_0_x implements InitStep {
- static final String[] etcFiles = {
- "gerrit.config", //
- "secure.config", //
- "replication.config", //
- "ssh_host_rsa_key", //
- "ssh_host_rsa_key.pub", //
- "ssh_host_dsa_key", //
- "ssh_host_dsa_key.pub", //
- "ssh_host_key", //
- "contact_information.pub", //
- "gitweb_config.perl", //
- "keystore", //
- "GerritSite.css", //
- "GerritSiteFooter.html", //
- "GerritSiteHeader.html", //
- };
-
- private final ConsoleUI ui;
-
- private final FileBasedConfig cfg;
- private final SecureStore sec;
- private final Path site_path;
- private final Path etc_dir;
- private final Section.Factory sections;
-
- @Inject
- UpgradeFrom2_0_x(
- final SitePaths site,
- final InitFlags flags,
- final ConsoleUI ui,
- final Section.Factory sections) {
- this.ui = ui;
- this.sections = sections;
-
- this.cfg = flags.cfg;
- this.sec = flags.sec;
- this.site_path = site.site_path;
- this.etc_dir = site.etc_dir;
- }
-
- boolean isNeedUpgrade() {
- for (String name : etcFiles) {
- if (Files.exists(site_path.resolve(name))) {
- return true;
- }
- }
- return false;
- }
-
- @Override
- public void run() throws IOException, ConfigInvalidException {
- if (!isNeedUpgrade()) {
- return;
- }
-
- if (!ui.yesno(true, "Upgrade '%s'", site_path.toAbsolutePath())) {
- throw die("aborted by user");
- }
-
- for (String name : etcFiles) {
- Path src = site_path.resolve(name);
- Path dst = etc_dir.resolve(name);
- if (Files.exists(src)) {
- if (Files.exists(dst)) {
- throw die("File " + src + " would overwrite " + dst);
- }
- try {
- Files.move(src, dst);
- } catch (IOException e) {
- throw die("Cannot rename " + src + " to " + dst, e);
- }
- }
- }
-
- // We have to reload the configuration after the rename as
- // the initial load pulled up an non-existent (and thus
- // believed to be empty) file.
- //
- cfg.load();
-
- final Properties oldprop = readGerritServerProperties();
- if (oldprop != null) {
- final Section database = sections.get("database", null);
-
- String url = oldprop.getProperty("url");
- if (url != null && !convertUrl(database, url)) {
- database.set("type", "jdbc");
- database.set("driver", oldprop.getProperty("driver"));
- database.set("url", url);
- }
-
- String username = oldprop.getProperty("user");
- if (username == null || username.isEmpty()) {
- username = oldprop.getProperty("username");
- }
- if (username != null && !username.isEmpty()) {
- cfg.setString("database", null, "username", username);
- }
-
- String password = oldprop.getProperty("password");
- if (password != null && !password.isEmpty()) {
- sec.set("database", null, "password", password);
- }
- }
-
- String[] values;
-
- values = cfg.getStringList("ldap", null, "password");
- cfg.unset("ldap", null, "password");
- sec.setList("ldap", null, "password", Arrays.asList(values));
-
- values = cfg.getStringList("sendemail", null, "smtpPass");
- cfg.unset("sendemail", null, "smtpPass");
- sec.setList("sendemail", null, "smtpPass", Arrays.asList(values));
-
- savePublic(cfg);
- }
-
- private boolean convertUrl(Section database, String url) throws UnsupportedEncodingException {
- String username = null;
- String password = null;
-
- if (url.contains("?")) {
- final int q = url.indexOf('?');
- for (String pair : Splitter.on('&').split(url.substring(q + 1))) {
- final int eq = pair.indexOf('=');
- if (0 < eq) {
- return false;
- }
-
- String n = URLDecoder.decode(pair.substring(0, eq), UTF_8.name());
- String v = URLDecoder.decode(pair.substring(eq + 1), UTF_8.name());
-
- if ("user".equals(n) || "username".equals(n)) {
- username = v;
-
- } else if ("password".equals(n)) {
- password = v;
-
- } else {
- // There is a parameter setting we don't recognize, use the
- // JDBC URL format instead to preserve the configuration.
- //
- return false;
- }
- }
- url = url.substring(0, q);
- }
-
- if (url.startsWith("jdbc:h2:file:")) {
- url = url.substring("jdbc:h2:file:".length());
- database.set("type", "h2");
- database.set("database", url);
- return true;
- }
-
- if (url.startsWith("jdbc:postgresql://")) {
- url = url.substring("jdbc:postgresql://".length());
- final int sl = url.indexOf('/');
- if (sl < 0) {
- return false;
- }
-
- final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
- database.set("type", "postgresql");
- sethost(database, addr);
- database.set("database", url.substring(sl + 1));
- setuser(database, username, password);
- return true;
- }
-
- if (url.startsWith("jdbc:postgresql:")) {
- url = url.substring("jdbc:postgresql:".length());
- database.set("type", "postgresql");
- database.set("hostname", "localhost");
- database.set("database", url);
- setuser(database, username, password);
- return true;
- }
-
- if (url.startsWith("jdbc:mysql://")) {
- url = url.substring("jdbc:mysql://".length());
- final int sl = url.indexOf('/');
- if (sl < 0) {
- return false;
- }
-
- final InetSocketAddress addr = SocketUtil.parse(url.substring(0, sl), 0);
- database.set("type", "mysql");
- sethost(database, addr);
- database.set("database", url.substring(sl + 1));
- setuser(database, username, password);
- return true;
- }
-
- return false;
- }
-
- private void sethost(Section database, InetSocketAddress addr) {
- database.set("hostname", SocketUtil.hostname(addr));
- if (0 < addr.getPort()) {
- database.set("port", String.valueOf(addr.getPort()));
- }
- }
-
- private void setuser(Section database, String username, String password) {
- if (username != null && !username.isEmpty()) {
- database.set("username", username);
- }
- if (password != null && !password.isEmpty()) {
- sec.set("database", null, "password", password);
- }
- }
-
- private Properties readGerritServerProperties() throws IOException {
- final Properties srvprop = new Properties();
- final String name = System.getProperty("GerritServer");
- Path path;
- if (name != null) {
- path = Paths.get(name);
- } else {
- path = site_path.resolve("GerritServer.properties");
- if (!Files.exists(path)) {
- path = Paths.get("GerritServer.properties");
- }
- }
- if (Files.exists(path)) {
- try (InputStream in = Files.newInputStream(path)) {
- srvprop.load(in);
- } catch (IOException e) {
- throw new IOException("Cannot read " + name, e);
- }
- final Properties dbprop = new Properties();
- for (Map.Entry<Object, Object> e : srvprop.entrySet()) {
- final String key = (String) e.getKey();
- if (key.startsWith("database.")) {
- dbprop.put(key.substring("database.".length()), e.getValue());
- }
- }
- return dbprop;
- }
- return null;
- }
-}
diff --git a/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java b/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
index b417d05..0d73089 100644
--- a/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
+++ b/java/com/google/gerrit/pgm/init/index/IndexModuleOnInit.java
@@ -30,7 +30,6 @@
import com.google.gerrit.server.index.account.AccountSchemaDefinitions;
import com.google.gerrit.server.index.account.AllAccountsIndexer;
import com.google.gerrit.server.index.group.AllGroupsIndexer;
-import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.index.group.GroupIndexDefinition;
import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.inject.AbstractModule;
@@ -75,8 +74,6 @@
// during init, hence we don't need AllGroupsIndexer.
bind(AllGroupsIndexer.class).toProvider(Providers.of(null));
- bind(GroupIndexCollection.class);
-
bind(new TypeLiteral<Map<String, Integer>>() {})
.annotatedWith(Names.named(SingleVersionModule.SINGLE_VERSIONS))
.toInstance(ImmutableMap.<String, Integer>of());
diff --git a/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index 540c5f3..ca4b6f3 100644
--- a/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -50,7 +50,6 @@
import com.google.gerrit.server.config.DefaultUrlFormatter;
import com.google.gerrit.server.config.DisableReverseDnsLookup;
import com.google.gerrit.server.config.DisableReverseDnsLookupProvider;
-import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GitReceivePackGroups;
import com.google.gerrit.server.config.GitUploadPackGroups;
import com.google.gerrit.server.config.SysExecutorModule;
@@ -87,21 +86,13 @@
import java.util.Collections;
import java.util.List;
import java.util.Set;
-import org.eclipse.jgit.lib.Config;
-/**
- * Module for programs that perform batch operations on a site.
- *
- * <p>Any program that requires this module likely also requires using {@link ThreadLimiter} to
- * limit the number of threads accessing the database concurrently.
- */
+/** Module for programs that perform batch operations on a site. */
public class BatchProgramModule extends FactoryModule {
- private final Config cfg;
private final Module reviewDbModule;
@Inject
- BatchProgramModule(@GerritServerConfig Config cfg, PerThreadReviewDbModule reviewDbModule) {
- this.cfg = cfg;
+ BatchProgramModule(PerThreadReviewDbModule reviewDbModule) {
this.reviewDbModule = reviewDbModule;
}
@@ -173,7 +164,7 @@
install(new H2CacheModule());
install(new ExternalIdModule());
install(new GroupModule());
- install(new NoteDbModule(cfg));
+ install(new NoteDbModule());
install(AccountCacheImpl.module());
install(GroupCacheImpl.module());
install(GroupIncludeCacheImpl.module());
diff --git a/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java b/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
deleted file mode 100644
index 1c7dc52..0000000
--- a/java/com/google/gerrit/pgm/util/SiteLibraryBasedDataSourceProvider.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2013 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.pgm.util;
-
-import com.google.gerrit.common.SiteLibraryLoaderUtil;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.config.ThreadSettingsConfig;
-import com.google.gerrit.server.schema.DataSourceProvider;
-import com.google.gerrit.server.schema.DataSourceType;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.nio.file.Path;
-import javax.sql.DataSource;
-import org.eclipse.jgit.lib.Config;
-
-/** Loads the site library if not yet loaded. */
-@Singleton
-public class SiteLibraryBasedDataSourceProvider extends DataSourceProvider {
- private final Path libdir;
- private boolean init;
-
- @Inject
- SiteLibraryBasedDataSourceProvider(
- SitePaths site,
- @GerritServerConfig Config cfg,
- MetricMaker metrics,
- ThreadSettingsConfig tsc,
- DataSourceProvider.Context ctx,
- DataSourceType dst) {
- super(cfg, metrics, tsc, ctx, dst);
- libdir = site.lib_dir;
- }
-
- @Override
- public synchronized DataSource get() {
- if (!init) {
- SiteLibraryLoaderUtil.loadSiteLib(libdir);
- init = true;
- }
- return super.get();
- }
-}
diff --git a/java/com/google/gerrit/pgm/util/SiteProgram.java b/java/com/google/gerrit/pgm/util/SiteProgram.java
index 65feeab..e273c02 100644
--- a/java/com/google/gerrit/pgm/util/SiteProgram.java
+++ b/java/com/google/gerrit/pgm/util/SiteProgram.java
@@ -15,52 +15,34 @@
package com.google.gerrit.pgm.util;
import static com.google.gerrit.server.config.GerritServerConfigModule.getSecureStoreClassName;
-import static com.google.inject.Scopes.SINGLETON;
import static com.google.inject.Stage.PRODUCTION;
import com.google.gerrit.common.Die;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.lifecycle.LifecycleModule;
import com.google.gerrit.metrics.DisabledMetricMaker;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.metrics.dropwizard.DropWizardMetricMaker;
import com.google.gerrit.server.config.GerritRuntime;
-import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.config.GerritServerConfigModule;
import com.google.gerrit.server.config.SitePath;
import com.google.gerrit.server.git.GitRepositoryManagerModule;
import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.schema.DataSourceModule;
-import com.google.gerrit.server.schema.DataSourceProvider;
-import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.DatabaseModule;
import com.google.gerrit.server.schema.ReviewDbSchemaModule;
import com.google.gerrit.server.securestore.SecureStoreClassName;
import com.google.gwtorm.server.OrmException;
import com.google.inject.AbstractModule;
-import com.google.inject.Binding;
import com.google.inject.CreationException;
import com.google.inject.Guice;
import com.google.inject.Injector;
-import com.google.inject.Key;
import com.google.inject.Module;
-import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Named;
-import com.google.inject.name.Names;
import com.google.inject.spi.Message;
import com.google.inject.util.Providers;
-import java.lang.annotation.Annotation;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
-import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
-import javax.sql.DataSource;
-import org.eclipse.jgit.lib.Config;
import org.kohsuke.args4j.Option;
public abstract class SiteProgram extends AbstractProgram {
@@ -74,8 +56,6 @@
sitePath = Paths.get(path);
}
- protected Provider<DataSource> dsProvider;
-
private Path sitePath = Paths.get(".");
protected SiteProgram() {}
@@ -84,11 +64,6 @@
this.sitePath = sitePath;
}
- protected SiteProgram(Path sitePath, Provider<DataSource> dsProvider) {
- this.sitePath = sitePath;
- this.dsProvider = dsProvider;
- }
-
/** @return the site path specified on the command line. */
protected Path getSitePath() {
return sitePath;
@@ -102,12 +77,12 @@
}
/** @return provides database connectivity and site path. */
- protected Injector createDbInjector(DataSourceProvider.Context context) {
- return createDbInjector(false, context);
+ protected Injector createDbInjector() {
+ return createDbInjector(false);
}
/** @return provides database connectivity and site path. */
- protected Injector createDbInjector(boolean enableMetrics, DataSourceProvider.Context context) {
+ protected Injector createDbInjector(boolean enableMetrics) {
List<Module> modules = new ArrayList<>();
Module sitePathModule =
@@ -134,26 +109,6 @@
});
}
- modules.add(
- new LifecycleModule() {
- @Override
- protected void configure() {
- bind(DataSourceProvider.Context.class).toInstance(context);
- if (dsProvider != null) {
- bind(Key.get(DataSource.class, Names.named("ReviewDb")))
- .toProvider(dsProvider)
- .in(SINGLETON);
- if (LifecycleListener.class.isAssignableFrom(dsProvider.getClass())) {
- listener().toInstance((LifecycleListener) dsProvider);
- }
- } else {
- bind(Key.get(DataSource.class, Names.named("ReviewDb")))
- .toProvider(SiteLibraryBasedDataSourceProvider.class)
- .in(SINGLETON);
- listener().to(SiteLibraryBasedDataSourceProvider.class);
- }
- }
- });
Module configModule = new GerritServerConfigModule();
modules.add(configModule);
modules.add(
@@ -164,29 +119,7 @@
}
});
Injector cfgInjector = Guice.createInjector(sitePathModule, configModule);
- Config cfg = cfgInjector.getInstance(Key.get(Config.class, GerritServerConfig.class));
- String dbType;
- if (dsProvider != null) {
- dbType = getDbType(dsProvider);
- } else {
- dbType = cfg.getString("database", null, "type");
- }
- if (dbType == null) {
- throw new ProvisionException("database.type must be defined");
- }
-
- DataSourceType dst =
- Guice.createInjector(new DataSourceModule(), configModule, sitePathModule)
- .getInstance(Key.get(DataSourceType.class, Names.named(dbType.toLowerCase())));
-
- modules.add(
- new AbstractModule() {
- @Override
- protected void configure() {
- bind(DataSourceType.class).toInstance(dst);
- }
- });
modules.add(new DatabaseModule());
modules.add(new ReviewDbSchemaModule());
modules.add(cfgInjector.getInstance(GitRepositoryManagerModule.class));
@@ -236,41 +169,6 @@
return getSecureStoreClassName(sitePath);
}
- private String getDbType(Provider<DataSource> dsProvider) {
- String dbProductName;
- try (Connection conn = dsProvider.get().getConnection()) {
- dbProductName = conn.getMetaData().getDatabaseProductName().toLowerCase();
- } catch (SQLException e) {
- throw new RuntimeException(e);
- }
-
- List<Module> modules = new ArrayList<>();
- modules.add(
- new AbstractModule() {
- @Override
- protected void configure() {
- bind(Path.class).annotatedWith(SitePath.class).toInstance(getSitePath());
- }
- });
- modules.add(new GerritServerConfigModule());
- modules.add(new DataSourceModule());
- Injector i = Guice.createInjector(modules);
- List<Binding<DataSourceType>> dsTypeBindings =
- i.findBindingsByType(new TypeLiteral<DataSourceType>() {});
- for (Binding<DataSourceType> binding : dsTypeBindings) {
- Annotation annotation = binding.getKey().getAnnotation();
- if (annotation instanceof Named) {
- Named named = (Named) annotation;
- if (named.value().toLowerCase().contains(dbProductName)) {
- return named.value();
- }
- }
- }
- throw new IllegalStateException(
- String.format(
- "Cannot guess database type from the database product name '%s'", dbProductName));
- }
-
@SuppressWarnings("deprecation")
private static boolean isCannotCreatePoolException(Throwable why) {
return why instanceof org.apache.commons.dbcp.SQLNestedException
diff --git a/java/com/google/gerrit/pgm/util/ThreadLimiter.java b/java/com/google/gerrit/pgm/util/ThreadLimiter.java
deleted file mode 100644
index 64f703bd..0000000
--- a/java/com/google/gerrit/pgm/util/ThreadLimiter.java
+++ /dev/null
@@ -1,50 +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.pgm.util;
-
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.ThreadSettingsConfig;
-import com.google.gerrit.server.schema.DataSourceType;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import org.eclipse.jgit.lib.Config;
-
-// TODO(dborowitz): Not necessary once we switch to NoteDb.
-/** Utility to limit threads used by a batch program. */
-public class ThreadLimiter {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- public static int limitThreads(Injector dbInjector, int threads) {
- return limitThreads(
- dbInjector.getInstance(Key.get(Config.class, GerritServerConfig.class)),
- dbInjector.getInstance(DataSourceType.class),
- dbInjector.getInstance(ThreadSettingsConfig.class),
- threads);
- }
-
- private static int limitThreads(
- Config cfg, DataSourceType dst, ThreadSettingsConfig threadSettingsConfig, int threads) {
- boolean usePool = cfg.getBoolean("database", "connectionpool", dst.usePool());
- int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
- if (usePool && threads > poolLimit) {
- logger.atWarning().log("Limiting program to %d threads due to database.poolLimit", poolLimit);
- return poolLimit;
- }
- return threads;
- }
-
- private ThreadLimiter() {}
-}
diff --git a/java/com/google/gerrit/reviewdb/BUILD b/java/com/google/gerrit/reviewdb/BUILD
index a4c6601..76e35a1 100644
--- a/java/com/google/gerrit/reviewdb/BUILD
+++ b/java/com/google/gerrit/reviewdb/BUILD
@@ -5,9 +5,8 @@
java_library(
name = "server",
srcs = glob(["**/*.java"]),
- resource_strip_prefix = "resources",
- resources = ["//resources/com/google/gerrit/reviewdb"],
deps = [
+ "//java/com/google/gerrit/common:annotations",
"//java/com/google/gerrit/extensions:api",
"//lib:guava",
"//lib:gwtorm",
diff --git a/java/com/google/gerrit/reviewdb/server/ReviewDb.java b/java/com/google/gerrit/reviewdb/server/ReviewDb.java
index 90cd066..5ff4afa 100644
--- a/java/com/google/gerrit/reviewdb/server/ReviewDb.java
+++ b/java/com/google/gerrit/reviewdb/server/ReviewDb.java
@@ -30,10 +30,7 @@
* </ul>
*/
public interface ReviewDb extends Schema {
- /* If you change anything, update ReviewDbSchemaVersion.C to use a new version. */
-
- @Relation(id = 1)
- SchemaVersionAccess schemaVersion();
+ // Deleted @Relation(id = 1)
// Deleted @Relation(id = 2)
diff --git a/java/com/google/gerrit/reviewdb/server/ReviewDbWrapper.java b/java/com/google/gerrit/reviewdb/server/ReviewDbWrapper.java
index c420254..5a77e01 100644
--- a/java/com/google/gerrit/reviewdb/server/ReviewDbWrapper.java
+++ b/java/com/google/gerrit/reviewdb/server/ReviewDbWrapper.java
@@ -105,11 +105,6 @@
}
@Override
- public SchemaVersionAccess schemaVersion() {
- return delegate.schemaVersion();
- }
-
- @Override
public ChangeAccess changes() {
return delegate.changes();
}
diff --git a/java/com/google/gerrit/server/ApprovalsUtil.java b/java/com/google/gerrit/server/ApprovalsUtil.java
index 3625de6..95b92af 100644
--- a/java/com/google/gerrit/server/ApprovalsUtil.java
+++ b/java/com/google/gerrit/server/ApprovalsUtil.java
@@ -21,7 +21,6 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
import com.google.common.collect.Iterables;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.Lists;
@@ -44,7 +43,6 @@
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.notedb.ReviewerStateInternal;
import com.google.gerrit.server.permissions.ChangePermission;
import com.google.gerrit.server.permissions.LabelPermission;
@@ -106,7 +104,6 @@
return Iterables.filter(psas, a -> Objects.equals(a.getAccountId(), accountId));
}
- private final NotesMigration migration;
private final ApprovalCopier copier;
private final PermissionBackend permissionBackend;
private final ProjectCache projectCache;
@@ -114,11 +111,7 @@
@VisibleForTesting
@Inject
public ApprovalsUtil(
- NotesMigration migration,
- ApprovalCopier copier,
- PermissionBackend permissionBackend,
- ProjectCache projectCache) {
- this.migration = migration;
+ ApprovalCopier copier, PermissionBackend permissionBackend, ProjectCache projectCache) {
this.copier = copier;
this.permissionBackend = permissionBackend;
this.projectCache = projectCache;
@@ -127,15 +120,11 @@
/**
* Get all reviewers for a change.
*
- * @param db review database.
* @param notes change notes.
* @return reviewers for the change.
* @throws OrmException if reviewers for the change could not be read.
*/
- public ReviewerSet getReviewers(ReviewDb db, ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return ReviewerSet.fromApprovals(db.patchSetApprovals().byChange(notes.getChangeId()));
- }
+ public ReviewerSet getReviewers(ChangeNotes notes) throws OrmException {
return notes.load().getReviewers();
}
@@ -148,23 +137,17 @@
*/
public ReviewerSet getReviewers(ChangeNotes notes, Iterable<PatchSetApproval> allApprovals)
throws OrmException {
- if (!migration.readChanges()) {
- return ReviewerSet.fromApprovals(allApprovals);
- }
return notes.load().getReviewers();
}
/**
- * Get updates to reviewer set. Always returns empty list for ReviewDb.
+ * Get updates to reviewer set.
*
* @param notes change notes.
* @return reviewer updates for the change.
* @throws OrmException if reviewer updates for the change could not be read.
*/
public List<ReviewerStatusUpdate> getReviewerUpdates(ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return ImmutableList.of();
- }
return notes.load().getReviewerUpdates();
}
@@ -200,13 +183,7 @@
throws OrmException {
PatchSet.Id psId = change.currentPatchSetId();
Collection<Account.Id> existingReviewers;
- if (migration.readChanges()) {
- // If using NoteDB, we only want reviewers in the REVIEWER state.
- existingReviewers = notes.load().getReviewers().byState(REVIEWER);
- } else {
- // Prior to NoteDB, we gather all reviewers regardless of state.
- existingReviewers = getReviewers(db, notes).all();
- }
+ existingReviewers = notes.load().getReviewers().byState(REVIEWER);
// Existing reviewers should include pending additions in the REVIEWER
// state, taken from ChangeUpdate.
existingReviewers = Lists.newArrayList(existingReviewers);
@@ -308,7 +285,7 @@
}
/**
- * Adds approvals to ChangeUpdate for a new patch set, and writes to ReviewDb.
+ * Adds approvals to ChangeUpdate for a new patch set, and writes to NoteDb.
*
* @param db review database.
* @param update change update.
@@ -346,7 +323,6 @@
for (PatchSetApproval psa : cells) {
update.putApproval(psa.getLabel(), psa.getValue());
}
- db.patchSetApprovals().insert(cells);
return cells;
}
@@ -377,16 +353,8 @@
}
}
- public ListMultimap<PatchSet.Id, PatchSetApproval> byChange(ReviewDb db, ChangeNotes notes)
+ public ListMultimap<PatchSet.Id, PatchSetApproval> byChange(ChangeNotes notes)
throws OrmException {
- if (!migration.readChanges()) {
- ImmutableListMultimap.Builder<PatchSet.Id, PatchSetApproval> result =
- ImmutableListMultimap.builder();
- for (PatchSetApproval psa : db.patchSetApprovals().byChange(notes.getChangeId())) {
- result.put(psa.getPatchSetId(), psa);
- }
- return result.build();
- }
return notes.load().getApprovals();
}
@@ -397,9 +365,6 @@
@Nullable RevWalk rw,
@Nullable Config repoConfig)
throws OrmException {
- if (!migration.readChanges()) {
- return sortApprovals(db.patchSetApprovals().byPatchSet(psId));
- }
return copier.getForPatchSet(db, notes, psId, rw, repoConfig);
}
@@ -411,19 +376,16 @@
@Nullable RevWalk rw,
@Nullable Config repoConfig)
throws OrmException {
- if (!migration.readChanges()) {
- return sortApprovals(db.patchSetApprovals().byPatchSetUser(psId, accountId));
- }
return filterApprovals(byPatchSet(db, notes, psId, rw, repoConfig), accountId);
}
- public PatchSetApproval getSubmitter(ReviewDb db, ChangeNotes notes, PatchSet.Id c) {
+ public PatchSetApproval getSubmitter(ChangeNotes notes, PatchSet.Id c) {
if (c == null) {
return null;
}
try {
// Submit approval is never copied, so bypass expensive byPatchSet call.
- return getSubmitter(c, byChange(db, notes).get(c));
+ return getSubmitter(c, byChange(notes).get(c));
} catch (OrmException e) {
return null;
}
diff --git a/java/com/google/gerrit/server/ChangeMessagesUtil.java b/java/com/google/gerrit/server/ChangeMessagesUtil.java
index 969cf38..c2b6b23 100644
--- a/java/com/google/gerrit/server/ChangeMessagesUtil.java
+++ b/java/com/google/gerrit/server/ChangeMessagesUtil.java
@@ -15,37 +15,24 @@
package com.google.gerrit.server;
import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.unwrapDb;
import static java.util.Objects.requireNonNull;
-import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.ChangeMessage;
import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.update.BatchUpdateReviewDb;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.sql.Timestamp;
-import java.util.Collections;
import java.util.List;
import java.util.Objects;
-/**
- * Utility functions to manipulate ChangeMessages.
- *
- * <p>These methods either query for and update ChangeMessages in the NoteDb or ReviewDb, depending
- * on the state of the NotesMigration.
- */
+/** Utility functions to manipulate ChangeMessages. */
@Singleton
public class ChangeMessagesUtil {
public static final String AUTOGENERATED_TAG_PREFIX = "autogenerated:";
@@ -100,27 +87,11 @@
return workInProgress ? TAG_UPLOADED_WIP_PATCH_SET : TAG_UPLOADED_PATCH_SET;
}
- private static List<ChangeMessage> sortChangeMessages(Iterable<ChangeMessage> changeMessage) {
- return ChangeNotes.MESSAGE_BY_TIME.sortedCopy(changeMessage);
- }
-
- private final NotesMigration migration;
-
- @VisibleForTesting
- @Inject
- public ChangeMessagesUtil(NotesMigration migration) {
- this.migration = migration;
- }
-
- public List<ChangeMessage> byChange(ReviewDb db, ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return sortChangeMessages(db.changeMessages().byChange(notes.getChangeId()));
- }
+ public List<ChangeMessage> byChange(ChangeNotes notes) throws OrmException {
return notes.load().getChangeMessages();
}
- public void addChangeMessage(ReviewDb db, ChangeUpdate update, ChangeMessage changeMessage)
- throws OrmException {
+ public void addChangeMessage(ChangeUpdate update, ChangeMessage changeMessage) {
checkState(
Objects.equals(changeMessage.getAuthor(), update.getNullableAccountId()),
"cannot store change message by %s in update by %s",
@@ -128,7 +99,6 @@
update.getNullableAccountId());
update.setChangeMessage(changeMessage.getMessage());
update.setTag(changeMessage.getTag());
- db.changeMessages().insert(Collections.singleton(changeMessage));
}
/**
@@ -139,63 +109,14 @@
* deleted from both NoteDb and ReviewDb, the index of the change message must be used rather than
* its ID.
*
- * @param db the {@code ReviewDb} instance to update.
* @param update change update.
* @param targetMessageIdx the index of the target change message.
* @param newMessage the new message which is going to replace the old.
- * @throws OrmException
*/
- public void replaceChangeMessage(
- ReviewDb db, ChangeUpdate update, int targetMessageIdx, String newMessage)
- throws OrmException {
- if (PrimaryStorage.of(update.getChange()).equals(PrimaryStorage.REVIEW_DB)) {
- if (db instanceof BatchUpdateReviewDb) {
- db = ((BatchUpdateReviewDb) db).unsafeGetDelegate();
- }
- db = unwrapDb(db);
-
- List<ChangeMessage> messagesInReviewDb =
- sortChangeMessages(db.changeMessages().byChange(update.getId()));
- if (migration.readChanges()) {
- sanityCheckForChangeMessages(messagesInReviewDb, update.getNotes().getChangeMessages());
- }
- ChangeMessage targetMessage = messagesInReviewDb.get(targetMessageIdx);
- targetMessage.setMessage(newMessage);
- db.changeMessages().upsert(Collections.singleton(targetMessage));
- }
-
+ public void replaceChangeMessage(ChangeUpdate update, int targetMessageIdx, String newMessage) {
update.deleteChangeMessageByRewritingHistory(targetMessageIdx, newMessage);
}
- private static void sanityCheckForChangeMessages(
- List<ChangeMessage> messagesInReviewDb, List<ChangeMessage> messagesInNoteDb) {
- String message =
- String.format(
- "Change messages in ReivewDb and NoteDb don't match: NoteDb %s; ReviewDb %s",
- messagesInNoteDb, messagesInReviewDb);
- if (messagesInReviewDb.size() != messagesInNoteDb.size()) {
- throw new IllegalStateException(message);
- }
-
- for (int i = 0; i < messagesInReviewDb.size(); i++) {
- ChangeMessage messageInReviewDb = messagesInReviewDb.get(i);
- ChangeMessage messageInNoteDb = messagesInNoteDb.get(i);
-
- // Don't compare the keys because they are different for the same change message in NoteDb and
- // ReviewDb.
- boolean isEqual =
- Objects.equals(messageInReviewDb.getAuthor(), messageInNoteDb.getAuthor())
- && Objects.equals(messageInReviewDb.getWrittenOn(), messageInNoteDb.getWrittenOn())
- && Objects.equals(messageInReviewDb.getMessage(), messageInNoteDb.getMessage())
- && Objects.equals(messageInReviewDb.getPatchSetId(), messageInNoteDb.getPatchSetId())
- && Objects.equals(messageInReviewDb.getTag(), messageInNoteDb.getTag())
- && Objects.equals(messageInReviewDb.getRealAuthor(), messageInNoteDb.getRealAuthor());
- if (!isEqual) {
- throw new IllegalStateException(message);
- }
- }
- }
-
/**
* @param tag value of a tag, or null.
* @return whether the tag starts with the autogenerated prefix.
diff --git a/java/com/google/gerrit/server/CommentsUtil.java b/java/com/google/gerrit/server/CommentsUtil.java
index 99dfbbb..b3812a0 100644
--- a/java/com/google/gerrit/server/CommentsUtil.java
+++ b/java/com/google/gerrit/server/CommentsUtil.java
@@ -16,16 +16,12 @@
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.gerrit.reviewdb.client.PatchLineComment.Status.PUBLISHED;
import static java.util.stream.Collectors.toList;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Ordering;
-import com.google.common.collect.Streams;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.extensions.client.Side;
import com.google.gerrit.extensions.common.CommentInfo;
@@ -35,31 +31,23 @@
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.Patch;
import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RobotComment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.PatchListCache;
import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.update.BatchUpdateReviewDb;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.ResultSet;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.eclipse.jgit.lib.BatchRefUpdate;
@@ -70,12 +58,7 @@
import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.ReceiveCommand;
-/**
- * Utility functions to manipulate Comments.
- *
- * <p>These methods either query for and update Comments in the NoteDb or ReviewDb, depending on the
- * state of the NotesMigration.
- */
+/** Utility functions to manipulate Comments. */
@Singleton
public class CommentsUtil {
public static final Ordering<Comment> COMMENT_ORDER =
@@ -127,18 +110,13 @@
private final GitRepositoryManager repoManager;
private final AllUsersName allUsers;
- private final NotesMigration migration;
private final String serverId;
@Inject
CommentsUtil(
- GitRepositoryManager repoManager,
- AllUsersName allUsers,
- NotesMigration migration,
- @GerritServerId String serverId) {
+ GitRepositoryManager repoManager, AllUsersName allUsers, @GerritServerId String serverId) {
this.repoManager = repoManager;
this.allUsers = allUsers;
- this.migration = migration;
this.serverId = serverId;
}
@@ -158,7 +136,7 @@
} else {
// Inherit unresolved value from inReplyTo comment if not specified.
Comment.Key key = new Comment.Key(parentUuid, path, psId.patchSetId);
- Optional<Comment> parent = getPublished(ctx.getDb(), ctx.getNotes(), key);
+ Optional<Comment> parent = getPublished(ctx.getNotes(), key);
if (!parent.isPresent()) {
throw new UnprocessableEntityException("Invalid parentUuid supplied for comment");
}
@@ -201,119 +179,64 @@
return c;
}
- public Optional<Comment> getPublished(ReviewDb db, ChangeNotes notes, Comment.Key key)
- throws OrmException {
- if (!migration.readChanges()) {
- return getReviewDb(db, notes, key);
- }
- return publishedByChange(db, notes).stream().filter(c -> key.equals(c.key)).findFirst();
+ public Optional<Comment> getPublished(ChangeNotes notes, Comment.Key key) throws OrmException {
+ return publishedByChange(notes).stream().filter(c -> key.equals(c.key)).findFirst();
}
- public Optional<Comment> getDraft(
- ReviewDb db, ChangeNotes notes, IdentifiedUser user, Comment.Key key) throws OrmException {
- if (!migration.readChanges()) {
- Optional<Comment> c = getReviewDb(db, notes, key);
- if (c.isPresent() && !c.get().author.getId().equals(user.getAccountId())) {
- throw new OrmException(
- String.format(
- "Expected draft %s to belong to account %s, but it belongs to %s",
- key, user.getAccountId(), c.get().author.getId()));
- }
- return c;
- }
- return draftByChangeAuthor(db, notes, user.getAccountId())
+ public Optional<Comment> getDraft(ChangeNotes notes, IdentifiedUser user, Comment.Key key)
+ throws OrmException {
+ return draftByChangeAuthor(notes, user.getAccountId())
.stream()
.filter(c -> key.equals(c.key))
.findFirst();
}
- private Optional<Comment> getReviewDb(ReviewDb db, ChangeNotes notes, Comment.Key key)
- throws OrmException {
- return Optional.ofNullable(
- db.patchComments().get(PatchLineComment.Key.from(notes.getChangeId(), key)))
- .map(plc -> plc.asComment(serverId));
- }
-
- public List<Comment> publishedByChange(ReviewDb db, ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return sort(byCommentStatus(db.patchComments().byChange(notes.getChangeId()), PUBLISHED));
- }
-
+ public List<Comment> publishedByChange(ChangeNotes notes) throws OrmException {
notes.load();
return sort(Lists.newArrayList(notes.getComments().values()));
}
public List<RobotComment> robotCommentsByChange(ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return ImmutableList.of();
- }
-
notes.load();
return sort(Lists.newArrayList(notes.getRobotComments().values()));
}
- public List<Comment> draftByChange(ReviewDb db, ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return sort(byCommentStatus(db.patchComments().byChange(notes.getChangeId()), Status.DRAFT));
- }
-
+ public List<Comment> draftByChange(ChangeNotes notes) throws OrmException {
List<Comment> comments = new ArrayList<>();
for (Ref ref : getDraftRefs(notes.getChangeId())) {
Account.Id account = Account.Id.fromRefSuffix(ref.getName());
if (account != null) {
- comments.addAll(draftByChangeAuthor(db, notes, account));
+ comments.addAll(draftByChangeAuthor(notes, account));
}
}
return sort(comments);
}
- private List<Comment> byCommentStatus(
- ResultSet<PatchLineComment> comments, PatchLineComment.Status status) {
- return toComments(
- serverId, Lists.newArrayList(Iterables.filter(comments, c -> c.getStatus() == status)));
- }
-
- public List<Comment> byPatchSet(ReviewDb db, ChangeNotes notes, PatchSet.Id psId)
- throws OrmException {
- if (!migration.readChanges()) {
- return sort(toComments(serverId, db.patchComments().byPatchSet(psId).toList()));
- }
+ public List<Comment> byPatchSet(ChangeNotes notes, PatchSet.Id psId) throws OrmException {
List<Comment> comments = new ArrayList<>();
- comments.addAll(publishedByPatchSet(db, notes, psId));
+ comments.addAll(publishedByPatchSet(notes, psId));
for (Ref ref : getDraftRefs(notes.getChangeId())) {
Account.Id account = Account.Id.fromRefSuffix(ref.getName());
if (account != null) {
- comments.addAll(draftByPatchSetAuthor(db, psId, account, notes));
+ comments.addAll(draftByPatchSetAuthor(psId, account, notes));
}
}
return sort(comments);
}
- public List<Comment> publishedByChangeFile(
- ReviewDb db, ChangeNotes notes, Change.Id changeId, String file) throws OrmException {
- if (!migration.readChanges()) {
- return sort(
- toComments(serverId, db.patchComments().publishedByChangeFile(changeId, file).toList()));
- }
+ public List<Comment> publishedByChangeFile(ChangeNotes notes, String file) throws OrmException {
return commentsOnFile(notes.load().getComments().values(), file);
}
- public List<Comment> publishedByPatchSet(ReviewDb db, ChangeNotes notes, PatchSet.Id psId)
+ public List<Comment> publishedByPatchSet(ChangeNotes notes, PatchSet.Id psId)
throws OrmException {
- if (!migration.readChanges()) {
- return removeCommentsOnAncestorOfCommitMessage(
- sort(toComments(serverId, db.patchComments().publishedByPatchSet(psId).toList())));
- }
return removeCommentsOnAncestorOfCommitMessage(
commentsOnPatchSet(notes.load().getComments().values(), psId));
}
public List<RobotComment> robotCommentsByPatchSet(ChangeNotes notes, PatchSet.Id psId)
throws OrmException {
- if (!migration.readChanges()) {
- return ImmutableList.of();
- }
return commentsOnPatchSet(notes.load().getRobotComments().values(), psId);
}
@@ -330,49 +253,28 @@
.collect(toList());
}
- public List<Comment> draftByPatchSetAuthor(
- ReviewDb db, PatchSet.Id psId, Account.Id author, ChangeNotes notes) throws OrmException {
- if (!migration.readChanges()) {
- return sort(
- toComments(serverId, db.patchComments().draftByPatchSetAuthor(psId, author).toList()));
- }
+ public List<Comment> draftByPatchSetAuthor(PatchSet.Id psId, Account.Id author, ChangeNotes notes)
+ throws OrmException {
return commentsOnPatchSet(notes.load().getDraftComments(author).values(), psId);
}
- public List<Comment> draftByChangeFileAuthor(
- ReviewDb db, ChangeNotes notes, String file, Account.Id author) throws OrmException {
- if (!migration.readChanges()) {
- return sort(
- toComments(
- serverId,
- db.patchComments()
- .draftByChangeFileAuthor(notes.getChangeId(), file, author)
- .toList()));
- }
+ public List<Comment> draftByChangeFileAuthor(ChangeNotes notes, String file, Account.Id author)
+ throws OrmException {
return commentsOnFile(notes.load().getDraftComments(author).values(), file);
}
- public List<Comment> draftByChangeAuthor(ReviewDb db, ChangeNotes notes, Account.Id author)
+ public List<Comment> draftByChangeAuthor(ChangeNotes notes, Account.Id author)
throws OrmException {
- if (!migration.readChanges()) {
- return Streams.stream(db.patchComments().draftByAuthor(author))
- .filter(c -> c.getPatchSetId().getParentKey().equals(notes.getChangeId()))
- .map(plc -> plc.asComment(serverId))
- .sorted(COMMENT_ORDER)
- .collect(toList());
- }
List<Comment> comments = new ArrayList<>();
comments.addAll(notes.getDraftComments(author).values());
return sort(comments);
}
public void putComments(
- ReviewDb db, ChangeUpdate update, PatchLineComment.Status status, Iterable<Comment> comments)
- throws OrmException {
+ ChangeUpdate update, PatchLineComment.Status status, Iterable<Comment> comments) {
for (Comment c : comments) {
update.putComment(status, c);
}
- db.patchComments().upsert(toPatchLineComments(update.getId(), status, comments));
}
public void putRobotComments(ChangeUpdate update, Iterable<RobotComment> comments) {
@@ -381,37 +283,14 @@
}
}
- public void deleteComments(ReviewDb db, ChangeUpdate update, Iterable<Comment> comments)
- throws OrmException {
+ public void deleteComments(ChangeUpdate update, Iterable<Comment> comments) {
for (Comment c : comments) {
update.deleteComment(c);
}
- db.patchComments()
- .delete(toPatchLineComments(update.getId(), PatchLineComment.Status.DRAFT, comments));
}
public void deleteCommentByRewritingHistory(
- ReviewDb db, ChangeUpdate update, Comment.Key commentKey, PatchSet.Id psId, String newMessage)
- throws OrmException {
- if (PrimaryStorage.of(update.getChange()).equals(PrimaryStorage.REVIEW_DB)) {
- PatchLineComment.Key key =
- new PatchLineComment.Key(new Patch.Key(psId, commentKey.filename), commentKey.uuid);
-
- if (db instanceof BatchUpdateReviewDb) {
- db = ((BatchUpdateReviewDb) db).unsafeGetDelegate();
- }
- db = ReviewDbUtil.unwrapDb(db);
-
- PatchLineComment patchLineComment = db.patchComments().get(key);
-
- if (!patchLineComment.getStatus().equals(PUBLISHED)) {
- throw new OrmException(String.format("comment %s is not published", key));
- }
-
- patchLineComment.setMessage(newMessage);
- db.patchComments().upsert(Collections.singleton(patchLineComment));
- }
-
+ ChangeUpdate update, Comment.Key commentKey, String newMessage) {
update.deleteCommentByRewritingHistory(commentKey.uuid, newMessage);
}
diff --git a/java/com/google/gerrit/server/PatchSetUtil.java b/java/com/google/gerrit/server/PatchSetUtil.java
index f6c7abc..8f26082 100644
--- a/java/com/google/gerrit/server/PatchSetUtil.java
+++ b/java/com/google/gerrit/server/PatchSetUtil.java
@@ -17,7 +17,6 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
import static com.google.gerrit.server.ChangeUtil.PS_ID_ORDER;
-import static com.google.gerrit.server.notedb.PatchSetState.PUBLISHED;
import static java.util.Objects.requireNonNull;
import static java.util.function.Function.identity;
@@ -149,12 +148,6 @@
return ps;
}
- public void publish(ReviewDb db, ChangeUpdate update, PatchSet ps) throws OrmException {
- ensurePatchSetMatches(ps.getId(), update);
- update.setPatchSetState(PUBLISHED);
- db.patchSets().update(Collections.singleton(ps));
- }
-
private static void ensurePatchSetMatches(PatchSet.Id psId, ChangeUpdate update) {
Change.Id changeId = update.getChange().getId();
checkArgument(
diff --git a/java/com/google/gerrit/server/PublishCommentUtil.java b/java/com/google/gerrit/server/PublishCommentUtil.java
index a90f3e7..9d5ecb4 100644
--- a/java/com/google/gerrit/server/PublishCommentUtil.java
+++ b/java/com/google/gerrit/server/PublishCommentUtil.java
@@ -74,7 +74,7 @@
throw new OrmException(e);
}
}
- commentsUtil.putComments(ctx.getDb(), ctx.getUpdate(psId), PUBLISHED, drafts);
+ commentsUtil.putComments(ctx.getUpdate(psId), PUBLISHED, drafts);
}
private static PatchSet.Id psId(ChangeNotes notes, Comment c) {
diff --git a/java/com/google/gerrit/server/change/AbandonOp.java b/java/com/google/gerrit/server/change/AbandonOp.java
index 5affd5c..874f5e4 100644
--- a/java/com/google/gerrit/server/change/AbandonOp.java
+++ b/java/com/google/gerrit/server/change/AbandonOp.java
@@ -105,7 +105,7 @@
update.setStatus(change.getStatus());
message = newMessage(ctx);
- cmUtil.addChangeMessage(ctx.getDb(), update, message);
+ cmUtil.addChangeMessage(update, message);
return true;
}
diff --git a/java/com/google/gerrit/server/change/ChangeInserter.java b/java/com/google/gerrit/server/change/ChangeInserter.java
index 33c7f73..1eb1dc3 100644
--- a/java/com/google/gerrit/server/change/ChangeInserter.java
+++ b/java/com/google/gerrit/server/change/ChangeInserter.java
@@ -459,7 +459,7 @@
patchSet.getCreatedOn(),
message,
ChangeMessagesUtil.uploadedPatchSetTag(workInProgress));
- cmUtil.addChangeMessage(db, update, changeMessage);
+ cmUtil.addChangeMessage(update, changeMessage);
}
return true;
}
diff --git a/java/com/google/gerrit/server/change/ChangeJson.java b/java/com/google/gerrit/server/change/ChangeJson.java
index b7049a7..889a20c 100644
--- a/java/com/google/gerrit/server/change/ChangeJson.java
+++ b/java/com/google/gerrit/server/change/ChangeJson.java
@@ -667,7 +667,7 @@
}
private Collection<ChangeMessageInfo> messages(ChangeData cd) throws OrmException {
- List<ChangeMessage> messages = cmUtil.byChange(db.get(), cd.notes());
+ List<ChangeMessage> messages = cmUtil.byChange(cd.notes());
if (messages.isEmpty()) {
return Collections.emptyList();
}
diff --git a/java/com/google/gerrit/server/change/ChangeResource.java b/java/com/google/gerrit/server/change/ChangeResource.java
index ef8b2f9..1131e94 100644
--- a/java/com/google/gerrit/server/change/ChangeResource.java
+++ b/java/com/google/gerrit/server/change/ChangeResource.java
@@ -167,7 +167,7 @@
// set of accounts that posted a message is too expensive. However everyone who posts a
// message is automatically added as reviewer. Hence if we include removed reviewers we can
// be sure that we have all accounts that posted messages on the change.
- accounts.addAll(approvalUtil.getReviewers(db.get(), notes).all());
+ accounts.addAll(approvalUtil.getReviewers(notes).all());
} catch (OrmException e) {
// This ETag will be invalidated if it loads next time.
}
diff --git a/java/com/google/gerrit/server/change/ConsistencyChecker.java b/java/com/google/gerrit/server/change/ConsistencyChecker.java
index a379f2c..6e5158b 100644
--- a/java/com/google/gerrit/server/change/ConsistencyChecker.java
+++ b/java/com/google/gerrit/server/change/ConsistencyChecker.java
@@ -52,7 +52,6 @@
import com.google.gerrit.server.plugincontext.PluginItemContext;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.update.BatchUpdateOp;
-import com.google.gerrit.server.update.BatchUpdateReviewDb;
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.RepoContext;
import com.google.gerrit.server.update.RetryHelper;
@@ -503,7 +502,7 @@
List<ProblemInfo> currProblems = new ArrayList<>(3);
currProblems.add(notFound);
if (deleteOldPatchSetProblem != null) {
- currProblems.add(insertPatchSetProblem);
+ currProblems.add(deleteOldPatchSetProblem);
}
currProblems.add(insertPatchSetProblem);
@@ -667,15 +666,9 @@
public boolean updateChange(ChangeContext ctx)
throws OrmException, PatchSetInfoNotAvailableException {
// Delete dangling key references.
- ReviewDb db = BatchUpdateReviewDb.unwrap(ctx.getDb());
accountPatchReviewStore.run(s -> s.clearReviewed(psId), OrmException.class);
- db.changeMessages().delete(db.changeMessages().byChange(psId.getParentKey()));
- db.patchSetApprovals().delete(db.patchSetApprovals().byPatchSet(psId));
- db.patchComments().delete(db.patchComments().byPatchSet(psId));
- db.patchSets().deleteKeys(Collections.singleton(psId));
- // NoteDb requires no additional fiddling; setting the state to deleted is
- // sufficient to filter everything else out.
+ // For NoteDb setting the state to deleted is sufficient to filter everything out.
ctx.getUpdate(psId).setPatchSetState(PatchSetState.DELETED);
p.status = Status.FIXED;
diff --git a/java/com/google/gerrit/server/change/PatchSetInserter.java b/java/com/google/gerrit/server/change/PatchSetInserter.java
index 24c4237..a906d6a 100644
--- a/java/com/google/gerrit/server/change/PatchSetInserter.java
+++ b/java/com/google/gerrit/server/change/PatchSetInserter.java
@@ -250,7 +250,7 @@
description);
if (notify != NotifyHandling.NONE) {
- oldReviewers = approvalsUtil.getReviewers(db, ctx.getNotes());
+ oldReviewers = approvalsUtil.getReviewers(ctx.getNotes());
}
if (message != null) {
@@ -275,7 +275,7 @@
db, ctx.getNotes(), patchSet, ctx.getRevWalk(), ctx.getRepoView().getConfig());
}
if (changeMessage != null) {
- cmUtil.addChangeMessage(db, update, changeMessage);
+ cmUtil.addChangeMessage(update, changeMessage);
}
return true;
}
diff --git a/java/com/google/gerrit/server/change/SetAssigneeOp.java b/java/com/google/gerrit/server/change/SetAssigneeOp.java
index f61e95f..dd24ff6 100644
--- a/java/com/google/gerrit/server/change/SetAssigneeOp.java
+++ b/java/com/google/gerrit/server/change/SetAssigneeOp.java
@@ -99,7 +99,7 @@
return true;
}
- private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
+ private void addMessage(ChangeContext ctx, ChangeUpdate update) {
StringBuilder msg = new StringBuilder();
msg.append("Assignee ");
if (oldAssignee == null) {
@@ -113,7 +113,7 @@
}
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_SET_ASSIGNEE);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
}
@Override
diff --git a/java/com/google/gerrit/server/change/SetHashtagsOp.java b/java/com/google/gerrit/server/change/SetHashtagsOp.java
index d11b2df..2c180ed 100644
--- a/java/com/google/gerrit/server/change/SetHashtagsOp.java
+++ b/java/com/google/gerrit/server/change/SetHashtagsOp.java
@@ -125,13 +125,13 @@
}
}
- private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
+ private void addMessage(ChangeContext ctx, ChangeUpdate update) {
StringBuilder msg = new StringBuilder();
appendHashtagMessage(msg, "added", toAdd);
appendHashtagMessage(msg, "removed", toRemove);
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_SET_HASHTAGS);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
}
private void appendHashtagMessage(StringBuilder b, String action, Set<String> hashtags) {
diff --git a/java/com/google/gerrit/server/change/WorkInProgressOp.java b/java/com/google/gerrit/server/change/WorkInProgressOp.java
index 35b4e6e..bc3be51 100644
--- a/java/com/google/gerrit/server/change/WorkInProgressOp.java
+++ b/java/com/google/gerrit/server/change/WorkInProgressOp.java
@@ -135,7 +135,7 @@
return true;
}
- private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
+ private void addMessage(ChangeContext ctx, ChangeUpdate update) {
Change c = ctx.getChange();
StringBuilder buf =
new StringBuilder(c.isWorkInProgress() ? "Set Work In Progress" : "Set Ready For Review");
@@ -154,7 +154,7 @@
? ChangeMessagesUtil.TAG_SET_WIP
: ChangeMessagesUtil.TAG_SET_READY);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
}
@Override
diff --git a/java/com/google/gerrit/server/config/GerritGlobalModule.java b/java/com/google/gerrit/server/config/GerritGlobalModule.java
index b26e875..6eb4ad9 100644
--- a/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -246,7 +246,7 @@
install(new GitModule());
install(new GroupDbModule());
install(new GroupModule());
- install(new NoteDbModule(cfg));
+ install(new NoteDbModule());
install(new PrologModule());
install(new DefaultSubmitRule.Module());
install(new IgnoreSelfApprovalRule.Module());
diff --git a/java/com/google/gerrit/server/config/GerritServerIdProvider.java b/java/com/google/gerrit/server/config/GerritServerIdProvider.java
index c609cc4..4898f55 100644
--- a/java/com/google/gerrit/server/config/GerritServerIdProvider.java
+++ b/java/com/google/gerrit/server/config/GerritServerIdProvider.java
@@ -48,9 +48,7 @@
// We're not generally supposed to do work in provider constructors, but this is a bit of a
// special case because we really need to have the ID available by the time the dbInjector
- // is created. This even applies during MigrateToNoteDb, which otherwise would have been a
- // reasonable place to do the ID generation. Fortunately, it's not much work, and it happens
- // once.
+ // is created. Fortunately, it's not much work, and it happens once.
id = generate();
Config newCfg = readGerritConfig(sitePaths);
newCfg.setString(SECTION, null, KEY, id);
diff --git a/java/com/google/gerrit/server/events/EventFactory.java b/java/com/google/gerrit/server/events/EventFactory.java
index 40ad144..25b96c8 100644
--- a/java/com/google/gerrit/server/events/EventFactory.java
+++ b/java/com/google/gerrit/server/events/EventFactory.java
@@ -222,9 +222,8 @@
* @param a
* @param notes
*/
- public void addAllReviewers(ReviewDb db, ChangeAttribute a, ChangeNotes notes)
- throws OrmException {
- Collection<Account.Id> reviewers = approvalsUtil.getReviewers(db, notes).all();
+ public void addAllReviewers(ChangeAttribute a, ChangeNotes notes) throws OrmException {
+ Collection<Account.Id> reviewers = approvalsUtil.getReviewers(notes).all();
if (!reviewers.isEmpty()) {
a.allReviewers = Lists.newArrayListWithCapacity(reviewers.size());
for (Account.Id id : reviewers) {
diff --git a/java/com/google/gerrit/server/git/MergedByPushOp.java b/java/com/google/gerrit/server/git/MergedByPushOp.java
index b3a1d72..03a93f1 100644
--- a/java/com/google/gerrit/server/git/MergedByPushOp.java
+++ b/java/com/google/gerrit/server/git/MergedByPushOp.java
@@ -151,7 +151,7 @@
ChangeMessage msg =
ChangeMessagesUtil.newMessage(
psId, ctx.getUser(), ctx.getWhen(), msgBuf.toString(), ChangeMessagesUtil.TAG_MERGED);
- cmUtil.addChangeMessage(ctx.getDb(), update, msg);
+ cmUtil.addChangeMessage(update, msg);
PatchSetApproval submitter =
ApprovalsUtil.newApproval(
diff --git a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
index 65b4f73..29c2ca0 100644
--- a/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/ReceiveCommits.java
@@ -649,7 +649,7 @@
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo, rw, ins).updateChangesInParallel();
+ bu.setRepository(repo, rw, ins);
bu.setRefLogMessage("push");
int added = 0;
@@ -802,7 +802,7 @@
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo, rw, ins).updateChangesInParallel();
+ bu.setRepository(repo, rw, ins);
bu.setRefLogMessage("push");
logger.atFine().log("Adding %d replace requests", newChanges.size());
@@ -3125,7 +3125,7 @@
ObjectInserter ins = repo.newObjectInserter();
ObjectReader reader = ins.newReader();
RevWalk rw = new RevWalk(reader)) {
- bu.setRepository(repo, rw, ins).updateChangesInParallel();
+ bu.setRepository(repo, rw, ins);
// TODO(dborowitz): Teach BatchUpdate to ignore missing changes.
RevCommit newTip = rw.parseCommit(cmd.getNewId());
diff --git a/java/com/google/gerrit/server/git/receive/ReplaceOp.java b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
index a580cf6..cedc167 100644
--- a/java/com/google/gerrit/server/git/receive/ReplaceOp.java
+++ b/java/com/google/gerrit/server/git/receive/ReplaceOp.java
@@ -353,7 +353,7 @@
}
msg = createChangeMessage(ctx, reviewMessage);
- cmUtil.addChangeMessage(ctx.getDb(), update, msg);
+ cmUtil.addChangeMessage(update, msg);
if (mergedByPushOp == null) {
resetChange(ctx);
@@ -512,7 +512,7 @@
private List<Comment> publishComments(ChangeContext ctx, boolean workInProgress)
throws OrmException {
List<Comment> comments =
- commentsUtil.draftByChangeAuthor(ctx.getDb(), ctx.getNotes(), ctx.getUser().getAccountId());
+ commentsUtil.draftByChangeAuthor(ctx.getNotes(), ctx.getUser().getAccountId());
publishCommentUtil.publish(
ctx, patchSetId, comments, ChangeMessagesUtil.uploadedPatchSetTag(workInProgress));
return comments;
diff --git a/java/com/google/gerrit/server/index/IndexModule.java b/java/com/google/gerrit/server/index/IndexModule.java
index 3c9538c..a84fbe9 100644
--- a/java/com/google/gerrit/server/index/IndexModule.java
+++ b/java/com/google/gerrit/server/index/IndexModule.java
@@ -125,7 +125,7 @@
factory(ChangeIndexer.Factory.class);
bind(GroupIndexRewriter.class);
- bind(GroupIndexCollection.class);
+ // GroupIndexCollection is already bound very high up in ReviewDbSchemaModule.
listener().to(GroupIndexCollection.class);
factory(GroupIndexerImpl.Factory.class);
diff --git a/java/com/google/gerrit/server/index/change/AllChangesIndexer.java b/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
index 37e288c..8f1433e 100644
--- a/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
+++ b/java/com/google/gerrit/server/index/change/AllChangesIndexer.java
@@ -224,7 +224,7 @@
// It does mean that reindexing after invalidating the DiffSummary cache will be expensive,
// but the goal is to invalidate that cache as infrequently as we possibly can. And besides,
// we don't have concrete proof that improving packfile locality would help.
- notesFactory.scan(repo, db, project).forEach(r -> index(db, r));
+ notesFactory.scan(repo, project).forEach(r -> index(db, r));
} catch (RepositoryNotFoundException rnfe) {
logger.atSevere().log(rnfe.getMessage());
}
diff --git a/java/com/google/gerrit/server/index/change/ChangeIndexer.java b/java/com/google/gerrit/server/index/change/ChangeIndexer.java
index 064af64..7fd3185 100644
--- a/java/com/google/gerrit/server/index/change/ChangeIndexer.java
+++ b/java/com/google/gerrit/server/index/change/ChangeIndexer.java
@@ -33,7 +33,6 @@
import com.google.gerrit.server.index.IndexUtils;
import com.google.gerrit.server.logging.TraceContext;
import com.google.gerrit.server.logging.TraceContext.TraceTimer;
-import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.plugincontext.PluginSetContext;
import com.google.gerrit.server.project.NoSuchChangeException;
@@ -87,8 +86,6 @@
@Nullable private final ChangeIndexCollection indexes;
@Nullable private final ChangeIndex index;
private final SchemaFactory<ReviewDb> schemaFactory;
- private final NotesMigration notesMigration;
- private final ChangeNotes.Factory changeNotesFactory;
private final ChangeData.Factory changeDataFactory;
private final ThreadLocalRequestContext context;
private final ListeningExecutorService batchExecutor;
@@ -102,7 +99,6 @@
@GerritServerConfig Config cfg,
SchemaFactory<ReviewDb> schemaFactory,
NotesMigration notesMigration,
- ChangeNotes.Factory changeNotesFactory,
ChangeData.Factory changeDataFactory,
ThreadLocalRequestContext context,
PluginSetContext<ChangeIndexedListener> indexedListeners,
@@ -112,8 +108,6 @@
@Assisted ChangeIndex index) {
this.executor = executor;
this.schemaFactory = schemaFactory;
- this.notesMigration = notesMigration;
- this.changeNotesFactory = changeNotesFactory;
this.changeDataFactory = changeDataFactory;
this.context = context;
this.indexedListeners = indexedListeners;
@@ -129,7 +123,6 @@
SchemaFactory<ReviewDb> schemaFactory,
@GerritServerConfig Config cfg,
NotesMigration notesMigration,
- ChangeNotes.Factory changeNotesFactory,
ChangeData.Factory changeDataFactory,
ThreadLocalRequestContext context,
PluginSetContext<ChangeIndexedListener> indexedListeners,
@@ -139,8 +132,6 @@
@Assisted ChangeIndexCollection indexes) {
this.executor = executor;
this.schemaFactory = schemaFactory;
- this.notesMigration = notesMigration;
- this.changeNotesFactory = changeNotesFactory;
this.changeDataFactory = changeDataFactory;
this.context = context;
this.indexedListeners = indexedListeners;
@@ -239,8 +230,9 @@
* @param db review database.
* @param change change to index.
*/
+ // TODO(dborowitz): Remove OrmException
public void index(ReviewDb db, Change change) throws IOException, OrmException {
- index(newChangeData(db, change));
+ index(changeDataFactory.create(db, change));
}
/**
@@ -250,9 +242,10 @@
* @param project the project to which the change belongs.
* @param changeId ID of the change to index.
*/
+ // TODO(dborowitz): Remove OrmException
public void index(ReviewDb db, Project.NameKey project, Change.Id changeId)
throws IOException, OrmException {
- index(newChangeData(db, project, changeId));
+ index(changeDataFactory.create(db, project, changeId));
}
/**
@@ -383,7 +376,7 @@
@Override
public Void callImpl(Provider<ReviewDb> db) throws Exception {
- ChangeData cd = newChangeData(db.get(), project, id);
+ ChangeData cd = changeDataFactory.create(db.get(), project, id);
index(cd);
return null;
}
@@ -429,7 +422,7 @@
public Boolean callImpl(Provider<ReviewDb> db) throws Exception {
try {
if (stalenessChecker.isStale(id)) {
- indexImpl(newChangeData(db.get(), project, id));
+ indexImpl(changeDataFactory.create(db.get(), project, id));
return true;
}
} catch (NoSuchChangeException nsce) {
@@ -460,26 +453,4 @@
}
return false;
}
-
- // Avoid auto-rebuilding when reindexing if reading is disabled. This just
- // increases contention on the meta ref from a background indexing thread
- // with little benefit. The next actual write to the entity may still incur a
- // less-contentious rebuild.
- private ChangeData newChangeData(ReviewDb db, Change change) throws OrmException {
- if (!notesMigration.readChanges()) {
- ChangeNotes notes = changeNotesFactory.createWithAutoRebuildingDisabled(change, null);
- return changeDataFactory.create(db, notes);
- }
- return changeDataFactory.create(db, change);
- }
-
- private ChangeData newChangeData(ReviewDb db, Project.NameKey project, Change.Id changeId)
- throws OrmException {
- if (!notesMigration.readChanges()) {
- ChangeNotes notes =
- changeNotesFactory.createWithAutoRebuildingDisabled(db, project, changeId);
- return changeDataFactory.create(db, notes);
- }
- return changeDataFactory.create(db, project, changeId);
- }
}
diff --git a/java/com/google/gerrit/server/mail/receive/MailProcessor.java b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
index 262e82b..6d6f043 100644
--- a/java/com/google/gerrit/server/mail/receive/MailProcessor.java
+++ b/java/com/google/gerrit/server/mail/receive/MailProcessor.java
@@ -290,7 +290,7 @@
}
changeMessage = generateChangeMessage(ctx);
- changeMessagesUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(psId), changeMessage);
+ changeMessagesUtil.addChangeMessage(ctx.getUpdate(psId), changeMessage);
comments = new ArrayList<>();
for (MailComment c : parsedComments) {
@@ -301,10 +301,7 @@
persistentCommentFromMailComment(ctx, c, targetPatchSetForComment(ctx, c, patchSet)));
}
commentsUtil.putComments(
- ctx.getDb(),
- ctx.getUpdate(ctx.getChange().currentPatchSetId()),
- Status.PUBLISHED,
- comments);
+ ctx.getUpdate(ctx.getChange().currentPatchSetId()), Status.PUBLISHED, comments);
return true;
}
diff --git a/java/com/google/gerrit/server/mail/send/CommentSender.java b/java/com/google/gerrit/server/mail/send/CommentSender.java
index e810397..c8aa259 100644
--- a/java/com/google/gerrit/server/mail/send/CommentSender.java
+++ b/java/com/google/gerrit/server/mail/send/CommentSender.java
@@ -316,7 +316,7 @@
Comment.Key key = new Comment.Key(child.parentUuid, child.key.filename, child.key.patchSetId);
try {
- return commentsUtil.getPublished(args.db.get(), changeData.notes(), key);
+ return commentsUtil.getPublished(changeData.notes(), key);
} catch (OrmException e) {
logger.atWarning().log("Could not find the parent of this comment: %s", child);
return Optional.empty();
diff --git a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
index 72f1ba6..32d086c 100644
--- a/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/AbstractChangeNotes.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.notedb;
+import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
import static java.util.Objects.requireNonNull;
@@ -27,8 +28,6 @@
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.ChangeNotesCommit.ChangeNotesRevWalk;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -55,9 +54,6 @@
// Providers required to avoid dependency cycles.
- // ChangeRebuilder -> ChangeNotes.Factory -> Args
- final Provider<ChangeRebuilder> rebuilder;
-
// ChangeNoteCache -> Args
final Provider<ChangeNotesCache> cache;
@@ -70,7 +66,6 @@
LegacyChangeNoteRead legacyChangeNoteRead,
NoteDbMetrics metrics,
Provider<ReviewDb> db,
- Provider<ChangeRebuilder> rebuilder,
Provider<ChangeNotesCache> cache) {
this.repoManager = repoManager;
this.migration = migration;
@@ -79,7 +74,6 @@
this.changeNoteJson = changeNoteJson;
this.metrics = metrics;
this.db = db;
- this.rebuilder = rebuilder;
this.cache = cache;
}
}
@@ -114,22 +108,14 @@
}
protected final Args args;
- protected final PrimaryStorage primaryStorage;
- protected final boolean autoRebuild;
private final Change.Id changeId;
private ObjectId revision;
private boolean loaded;
- AbstractChangeNotes(
- Args args, Change.Id changeId, @Nullable PrimaryStorage primaryStorage, boolean autoRebuild) {
+ AbstractChangeNotes(Args args, Change.Id changeId) {
this.args = requireNonNull(args);
this.changeId = requireNonNull(changeId);
- this.primaryStorage = primaryStorage;
- this.autoRebuild =
- primaryStorage == PrimaryStorage.REVIEW_DB
- && !args.migration.disableChangeReviewDb()
- && autoRebuild;
}
public Change.Id getChangeId() {
@@ -146,18 +132,7 @@
return self();
}
- boolean read = args.migration.readChanges();
- if (!read && primaryStorage == PrimaryStorage.NOTE_DB) {
- throw new OrmException("NoteDb is required to read change " + changeId);
- }
- boolean readOrWrite = read || args.migration.rawWriteChangesSetting();
- if (!readOrWrite) {
- // Don't even open the repo if we neither write to nor read from NoteDb. It's possible that
- // there is some garbage in the noteDbState field and/or the repo, but at this point NoteDb is
- // completely off so it's none of our business.
- loadDefaults();
- return self();
- }
+ checkState(args.migration.readChanges(), "NoteDb is required to read changes");
if (args.migration.failOnLoadForTest()) {
throw new OrmException("Reading from NoteDb is disabled");
}
@@ -166,12 +141,8 @@
// Call openHandle even if reading is disabled, to trigger
// auto-rebuilding before this object may get passed to a ChangeUpdate.
LoadHandle handle = openHandle(repo)) {
- if (read) {
- revision = handle.id();
- onLoad(handle);
- } else {
- loadDefaults();
- }
+ revision = handle.id();
+ onLoad(handle);
loaded = true;
} catch (ConfigInvalidException | IOException e) {
throw new OrmException(e);
@@ -202,7 +173,7 @@
return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), id);
}
- public T reload() throws NoSuchChangeException, OrmException {
+ public T reload() throws OrmException {
loaded = false;
return load();
}
diff --git a/java/com/google/gerrit/server/notedb/ChangeBundle.java b/java/com/google/gerrit/server/notedb/ChangeBundle.java
deleted file mode 100644
index c4d6a91..0000000
--- a/java/com/google/gerrit/server/notedb/ChangeBundle.java
+++ /dev/null
@@ -1,976 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.collect.ImmutableSortedMap.toImmutableSortedMap;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.checkColumns;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.intKeyOrdering;
-import static com.google.gerrit.server.notedb.ChangeBundle.Source.NOTE_DB;
-import static com.google.gerrit.server.notedb.ChangeBundle.Source.REVIEW_DB;
-import static com.google.gerrit.server.util.time.TimeUtil.truncateToSecond;
-import static java.util.Comparator.comparing;
-import static java.util.Comparator.naturalOrder;
-import static java.util.Comparator.nullsFirst;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.toList;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.CharMatcher;
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Strings;
-import com.google.common.collect.Collections2;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedMap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedListMultimap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Streams;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSet.Id;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.server.ChangeUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.ReviewerSet;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
-import com.google.gwtorm.client.Column;
-import com.google.gwtorm.server.OrmException;
-import java.lang.reflect.Field;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-
-/**
- * A bundle of all entities rooted at a single {@link Change} entity.
- *
- * <p>See the {@link Change} Javadoc for a depiction of this tree. Bundles may be compared using
- * {@link #differencesFrom(ChangeBundle)}, which normalizes out the minor implementation differences
- * between ReviewDb and NoteDb.
- */
-public class ChangeBundle {
- public enum Source {
- REVIEW_DB,
- NOTE_DB;
- }
-
- public static ChangeBundle fromNotes(CommentsUtil commentsUtil, ChangeNotes notes)
- throws OrmException {
- return new ChangeBundle(
- notes.getChange(),
- notes.getChangeMessages(),
- notes.getPatchSets().values(),
- notes.getApprovals().values(),
- Iterables.concat(
- CommentsUtil.toPatchLineComments(
- notes.getChangeId(),
- PatchLineComment.Status.DRAFT,
- commentsUtil.draftByChange(null, notes)),
- CommentsUtil.toPatchLineComments(
- notes.getChangeId(),
- PatchLineComment.Status.PUBLISHED,
- commentsUtil.publishedByChange(null, notes))),
- notes.getReviewers(),
- Source.NOTE_DB);
- }
-
- private static ImmutableSortedMap<ChangeMessage.Key, ChangeMessage> changeMessageMap(
- Collection<ChangeMessage> in) {
- return in.stream()
- .collect(
- toImmutableSortedMap(
- comparing((ChangeMessage.Key k) -> k.getParentKey().get())
- .thenComparing(k -> k.get()),
- cm -> cm.getKey(),
- cm -> cm));
- }
-
- // Unlike the *Map comparators, which are intended to make key lists diffable,
- // this comparator sorts first on timestamp, then on every other field.
- private static final Comparator<ChangeMessage> CHANGE_MESSAGE_COMPARATOR =
- comparing(ChangeMessage::getWrittenOn)
- .thenComparing(m -> m.getKey().getParentKey().get())
- .thenComparing(
- m -> m.getPatchSetId() != null ? m.getPatchSetId().get() : null,
- nullsFirst(naturalOrder()))
- .thenComparing(ChangeMessage::getAuthor, intKeyOrdering())
- .thenComparing(ChangeMessage::getMessage, nullsFirst(naturalOrder()));
-
- private static ImmutableList<ChangeMessage> changeMessageList(Iterable<ChangeMessage> in) {
- return Streams.stream(in).sorted(CHANGE_MESSAGE_COMPARATOR).collect(toImmutableList());
- }
-
- private static ImmutableSortedMap<Id, PatchSet> patchSetMap(Iterable<PatchSet> in) {
- return Streams.stream(in)
- .collect(toImmutableSortedMap(patchSetIdComparator(), PatchSet::getId, ps -> ps));
- }
-
- private static ImmutableSortedMap<PatchSetApproval.Key, PatchSetApproval> patchSetApprovalMap(
- Iterable<PatchSetApproval> in) {
- return Streams.stream(in)
- .collect(
- toImmutableSortedMap(
- comparing(PatchSetApproval.Key::getParentKey, patchSetIdComparator())
- .thenComparing(PatchSetApproval.Key::getAccountId, intKeyOrdering())
- .thenComparing(PatchSetApproval.Key::getLabelId),
- PatchSetApproval::getKey,
- a -> a));
- }
-
- private static ImmutableSortedMap<PatchLineComment.Key, PatchLineComment> patchLineCommentMap(
- Iterable<PatchLineComment> in) {
- return Streams.stream(in)
- .collect(
- toImmutableSortedMap(
- comparing(
- (PatchLineComment.Key k) -> k.getParentKey().getParentKey(),
- patchSetIdComparator())
- .thenComparing(PatchLineComment.Key::getParentKey)
- .thenComparing(PatchLineComment.Key::get),
- PatchLineComment::getKey,
- c -> c));
- }
-
- private static Comparator<PatchSet.Id> patchSetIdComparator() {
- return comparing((PatchSet.Id id) -> id.getParentKey().get()).thenComparing(id -> id.get());
- }
-
- static {
- // Initialization-time checks that the column set hasn't changed since the
- // last time this file was updated.
- checkColumns(Change.Id.class, 1);
-
- checkColumns(
- Change.class, 1, 2, 3, 4, 5, 7, 8, 10, 12, 13, 14, 17, 18, 19, 20, 21, 22, 23, 101);
- checkColumns(ChangeMessage.Key.class, 1, 2);
- checkColumns(ChangeMessage.class, 1, 2, 3, 4, 5, 6, 7);
- checkColumns(PatchSet.Id.class, 1, 2);
- checkColumns(PatchSet.class, 1, 2, 3, 4, 6, 8, 9);
- checkColumns(PatchSetApproval.Key.class, 1, 2, 3);
- checkColumns(PatchSetApproval.class, 1, 2, 3, 6, 7, 8);
- checkColumns(PatchLineComment.Key.class, 1, 2);
- checkColumns(PatchLineComment.class, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
- }
-
- private final Change change;
- private final ImmutableList<ChangeMessage> changeMessages;
- private final ImmutableSortedMap<PatchSet.Id, PatchSet> patchSets;
- private final ImmutableMap<PatchSetApproval.Key, PatchSetApproval> patchSetApprovals;
- private final ImmutableMap<PatchLineComment.Key, PatchLineComment> patchLineComments;
- private final ReviewerSet reviewers;
- private final Source source;
-
- public ChangeBundle(
- Change change,
- Iterable<ChangeMessage> changeMessages,
- Iterable<PatchSet> patchSets,
- Iterable<PatchSetApproval> patchSetApprovals,
- Iterable<PatchLineComment> patchLineComments,
- ReviewerSet reviewers,
- Source source) {
- this.change = requireNonNull(change);
- this.changeMessages = changeMessageList(changeMessages);
- this.patchSets = ImmutableSortedMap.copyOfSorted(patchSetMap(patchSets));
- this.patchSetApprovals = ImmutableMap.copyOf(patchSetApprovalMap(patchSetApprovals));
- this.patchLineComments = ImmutableMap.copyOf(patchLineCommentMap(patchLineComments));
- this.reviewers = requireNonNull(reviewers);
- this.source = requireNonNull(source);
-
- for (ChangeMessage m : this.changeMessages) {
- checkArgument(m.getKey().getParentKey().equals(change.getId()));
- }
- for (PatchSet.Id id : this.patchSets.keySet()) {
- checkArgument(id.getParentKey().equals(change.getId()));
- }
- for (PatchSetApproval.Key k : this.patchSetApprovals.keySet()) {
- checkArgument(k.getParentKey().getParentKey().equals(change.getId()));
- }
- for (PatchLineComment.Key k : this.patchLineComments.keySet()) {
- checkArgument(k.getParentKey().getParentKey().getParentKey().equals(change.getId()));
- }
- }
-
- public Change getChange() {
- return change;
- }
-
- public ImmutableCollection<ChangeMessage> getChangeMessages() {
- return changeMessages;
- }
-
- public ImmutableCollection<PatchSet> getPatchSets() {
- return patchSets.values();
- }
-
- public ImmutableCollection<PatchSetApproval> getPatchSetApprovals() {
- return patchSetApprovals.values();
- }
-
- public ImmutableCollection<PatchLineComment> getPatchLineComments() {
- return patchLineComments.values();
- }
-
- public ReviewerSet getReviewers() {
- return reviewers;
- }
-
- public Source getSource() {
- return source;
- }
-
- public ImmutableList<String> differencesFrom(ChangeBundle o) {
- List<String> diffs = new ArrayList<>();
- diffChanges(diffs, this, o);
- diffChangeMessages(diffs, this, o);
- diffPatchSets(diffs, this, o);
- diffPatchSetApprovals(diffs, this, o);
- diffReviewers(diffs, this, o);
- diffPatchLineComments(diffs, this, o);
- return ImmutableList.copyOf(diffs);
- }
-
- private Timestamp getFirstPatchSetTime() {
- if (patchSets.isEmpty()) {
- return change.getCreatedOn();
- }
- return patchSets.firstEntry().getValue().getCreatedOn();
- }
-
- private Timestamp getLatestTimestamp() {
- Ordering<Timestamp> o = Ordering.natural().nullsFirst();
- Timestamp ts = null;
- for (ChangeMessage cm : filterChangeMessages()) {
- ts = o.max(ts, cm.getWrittenOn());
- }
- for (PatchSet ps : getPatchSets()) {
- ts = o.max(ts, ps.getCreatedOn());
- }
- for (PatchSetApproval psa : filterPatchSetApprovals().values()) {
- ts = o.max(ts, psa.getGranted());
- }
- for (PatchLineComment plc : filterPatchLineComments().values()) {
- // Ignore draft comments, as they do not show up in the change meta graph.
- if (plc.getStatus() != PatchLineComment.Status.DRAFT) {
- ts = o.max(ts, plc.getWrittenOn());
- }
- }
- return firstNonNull(ts, change.getLastUpdatedOn());
- }
-
- private Map<PatchSetApproval.Key, PatchSetApproval> filterPatchSetApprovals() {
- return limitToValidPatchSets(patchSetApprovals, PatchSetApproval.Key::getParentKey);
- }
-
- private Map<PatchLineComment.Key, PatchLineComment> filterPatchLineComments() {
- return limitToValidPatchSets(patchLineComments, k -> k.getParentKey().getParentKey());
- }
-
- private <K, V> Map<K, V> limitToValidPatchSets(Map<K, V> in, Function<K, PatchSet.Id> func) {
- return Maps.filterKeys(in, Predicates.compose(validPatchSetPredicate(), func));
- }
-
- private Predicate<PatchSet.Id> validPatchSetPredicate() {
- return patchSets::containsKey;
- }
-
- private Collection<ChangeMessage> filterChangeMessages() {
- final Predicate<PatchSet.Id> validPatchSet = validPatchSetPredicate();
- return Collections2.filter(
- changeMessages,
- m -> {
- PatchSet.Id psId = m.getPatchSetId();
- if (psId == null) {
- return true;
- }
- return validPatchSet.apply(psId);
- });
- }
-
- private static void diffChanges(List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- Change a = bundleA.change;
- Change b = bundleB.change;
- String desc = a.getId().equals(b.getId()) ? describe(a.getId()) : "Changes";
-
- boolean excludeCreatedOn = false;
- boolean excludeCurrentPatchSetId = false;
- boolean excludeTopic = false;
- Timestamp aCreated = a.getCreatedOn();
- Timestamp bCreated = b.getCreatedOn();
- Timestamp aUpdated = a.getLastUpdatedOn();
- Timestamp bUpdated = b.getLastUpdatedOn();
-
- boolean excludeSubject = false;
- boolean excludeOrigSubj = false;
- // Subject is not technically a nullable field, but we observed some null
- // subjects in the wild on googlesource.com, so treat null as empty.
- String aSubj = Strings.nullToEmpty(a.getSubject());
- String bSubj = Strings.nullToEmpty(b.getSubject());
-
- // Allow created timestamp in NoteDb to be any of:
- // - The created timestamp of the change.
- // - The timestamp of the first remaining patch set.
- // - The last updated timestamp, if it is less than the created timestamp.
- //
- // Ignore subject if the NoteDb subject starts with the ReviewDb subject.
- // The NoteDb subject is read directly from the commit, whereas the ReviewDb
- // subject historically may have been truncated to fit in a SQL varchar
- // column.
- //
- // Ignore original subject on the ReviewDb side when comparing to NoteDb.
- // This field may have any number of values:
- // - It may be null, if the change has had no new patch sets pushed since
- // migrating to schema 103.
- // - It may match the first patch set subject, if the change was created
- // after migrating to schema 103.
- // - It may match the subject of the first patch set that was pushed after
- // the migration to schema 103, even though that is neither the subject
- // of the first patch set nor the subject of the last patch set. (See
- // Change#setCurrentPatchSet as of 43b10f86 for this behavior.) This
- // subject of an intermediate patch set is not available to the
- // ChangeBundle; we would have to get the subject from the repo, which is
- // inconvenient at this point.
- //
- // Ignore original subject on the ReviewDb side if it equals the subject of
- // the current patch set.
- //
- // For all of the above subject comparisons, first trim any leading spaces
- // from the NoteDb strings. (We actually do represent the leading spaces
- // faithfully during conversion, but JGit's FooterLine parser trims them
- // when reading.)
- //
- // Ignore empty topic on the ReviewDb side if it is null on the NoteDb side.
- //
- // Ignore currentPatchSetId on NoteDb side if ReviewDb does not point to a
- // valid patch set.
- //
- // Use max timestamp of all ReviewDb entities when comparing with NoteDb.
- if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) {
- boolean createdOnMatchesFirstPs =
- !timestampsDiffer(bundleA, bundleA.getFirstPatchSetTime(), bundleB, bCreated);
- boolean createdOnMatchesLastUpdatedOn =
- !timestampsDiffer(bundleA, aUpdated, bundleB, bCreated);
- boolean createdAfterUpdated = aCreated.compareTo(aUpdated) > 0;
- excludeCreatedOn =
- createdOnMatchesFirstPs || (createdAfterUpdated && createdOnMatchesLastUpdatedOn);
-
- aSubj = cleanReviewDbSubject(aSubj);
- bSubj = cleanNoteDbSubject(bSubj);
- excludeCurrentPatchSetId = !bundleA.validPatchSetPredicate().apply(a.currentPatchSetId());
- excludeSubject = bSubj.startsWith(aSubj) || excludeCurrentPatchSetId;
- excludeOrigSubj = true;
- String aTopic = trimOrNull(a.getTopic());
- excludeTopic =
- Objects.equals(aTopic, b.getTopic()) || ("".equals(aTopic) && b.getTopic() == null);
- aUpdated = bundleA.getLatestTimestamp();
- } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
- boolean createdOnMatchesFirstPs =
- !timestampsDiffer(bundleA, aCreated, bundleB, bundleB.getFirstPatchSetTime());
- boolean createdOnMatchesLastUpdatedOn =
- !timestampsDiffer(bundleA, aCreated, bundleB, bUpdated);
- boolean createdAfterUpdated = bCreated.compareTo(bUpdated) > 0;
- excludeCreatedOn =
- createdOnMatchesFirstPs || (createdAfterUpdated && createdOnMatchesLastUpdatedOn);
-
- aSubj = cleanNoteDbSubject(aSubj);
- bSubj = cleanReviewDbSubject(bSubj);
- excludeCurrentPatchSetId = !bundleB.validPatchSetPredicate().apply(b.currentPatchSetId());
- excludeSubject = aSubj.startsWith(bSubj) || excludeCurrentPatchSetId;
- excludeOrigSubj = true;
- String bTopic = trimOrNull(b.getTopic());
- excludeTopic =
- Objects.equals(bTopic, a.getTopic()) || (a.getTopic() == null && "".equals(bTopic));
- bUpdated = bundleB.getLatestTimestamp();
- }
-
- String subjectField = "subject";
- String updatedField = "lastUpdatedOn";
- List<String> exclude =
- Lists.newArrayList(subjectField, updatedField, "noteDbState", "rowVersion");
- if (excludeCreatedOn) {
- exclude.add("createdOn");
- }
- if (excludeCurrentPatchSetId) {
- exclude.add("currentPatchSetId");
- }
- if (excludeOrigSubj) {
- exclude.add("originalSubject");
- }
- if (excludeTopic) {
- exclude.add("topic");
- }
- diffColumnsExcluding(diffs, Change.class, desc, bundleA, a, bundleB, b, exclude);
-
- // Allow last updated timestamps to either be exactly equal (within slop),
- // or the NoteDb timestamp to be equal to the latest entity timestamp in the
- // whole ReviewDb bundle (within slop).
- if (timestampsDiffer(bundleA, a.getLastUpdatedOn(), bundleB, b.getLastUpdatedOn())) {
- diffTimestamps(
- diffs, desc, bundleA, aUpdated, bundleB, bUpdated, "effective last updated time");
- }
- if (!excludeSubject) {
- diffValues(diffs, desc, aSubj, bSubj, subjectField);
- }
- }
-
- private static String trimOrNull(String s) {
- return s != null ? CharMatcher.whitespace().trimFrom(s) : null;
- }
-
- private static String cleanReviewDbSubject(String s) {
- s = CharMatcher.is(' ').trimLeadingFrom(s);
-
- // An old JGit bug failed to extract subjects from commits with "\r\n"
- // terminators: https://bugs.eclipse.org/bugs/show_bug.cgi?id=400707
- // Changes created with this bug may have "\r\n" converted to "\r " and the
- // entire commit in the subject. The version of JGit used to read NoteDb
- // changes parses these subjects correctly, so we need to clean up old
- // ReviewDb subjects before comparing.
- int rn = s.indexOf("\r \r ");
- if (rn >= 0) {
- s = s.substring(0, rn);
- }
- return NoteDbUtil.sanitizeFooter(s);
- }
-
- private static String cleanNoteDbSubject(String s) {
- return NoteDbUtil.sanitizeFooter(s);
- }
-
- /**
- * Set of fields that must always exactly match between ReviewDb and NoteDb.
- *
- * <p>Used to limit the worst-case quadratic search when pairing off matching messages below.
- */
- @AutoValue
- abstract static class ChangeMessageCandidate {
- static ChangeMessageCandidate create(ChangeMessage cm) {
- return new AutoValue_ChangeBundle_ChangeMessageCandidate(
- cm.getAuthor(), cm.getMessage(), cm.getTag());
- }
-
- @Nullable
- abstract Account.Id author();
-
- @Nullable
- abstract String message();
-
- @Nullable
- abstract String tag();
-
- // Exclude:
- // - patch set, which may be null on ReviewDb side but not NoteDb
- // - UUID, which is always different between ReviewDb and NoteDb
- // - writtenOn, which is fuzzy
- }
-
- private static void diffChangeMessages(
- List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- if (bundleA.source == REVIEW_DB && bundleB.source == REVIEW_DB) {
- // Both came from ReviewDb: check all fields exactly.
- Map<ChangeMessage.Key, ChangeMessage> as = changeMessageMap(bundleA.filterChangeMessages());
- Map<ChangeMessage.Key, ChangeMessage> bs = changeMessageMap(bundleB.filterChangeMessages());
-
- for (ChangeMessage.Key k : diffKeySets(diffs, as, bs)) {
- ChangeMessage a = as.get(k);
- ChangeMessage b = bs.get(k);
- String desc = describe(k);
- diffColumns(diffs, ChangeMessage.class, desc, bundleA, a, bundleB, b);
- }
- return;
- }
- Change.Id id = bundleA.getChange().getId();
- checkArgument(id.equals(bundleB.getChange().getId()));
-
- // Try to pair up matching ChangeMessages from each side, and succeed only
- // if both collections are empty at the end. Quadratic in the worst case,
- // but easy to reason about.
- List<ChangeMessage> as = new LinkedList<>(bundleA.filterChangeMessages());
-
- ListMultimap<ChangeMessageCandidate, ChangeMessage> bs = LinkedListMultimap.create();
- for (ChangeMessage b : bundleB.filterChangeMessages()) {
- bs.put(ChangeMessageCandidate.create(b), b);
- }
-
- Iterator<ChangeMessage> ait = as.iterator();
- A:
- while (ait.hasNext()) {
- ChangeMessage a = ait.next();
- Iterator<ChangeMessage> bit = bs.get(ChangeMessageCandidate.create(a)).iterator();
- while (bit.hasNext()) {
- ChangeMessage b = bit.next();
- if (changeMessagesMatch(bundleA, a, bundleB, b)) {
- ait.remove();
- bit.remove();
- continue A;
- }
- }
- }
-
- if (as.isEmpty() && bs.isEmpty()) {
- return;
- }
- StringBuilder sb =
- new StringBuilder("ChangeMessages differ for Change.Id ").append(id).append('\n');
- if (!as.isEmpty()) {
- sb.append("Only in A:");
- for (ChangeMessage cm : as) {
- sb.append("\n ").append(cm);
- }
- if (!bs.isEmpty()) {
- sb.append('\n');
- }
- }
- if (!bs.isEmpty()) {
- sb.append("Only in B:");
- bs.values()
- .stream()
- .sorted(CHANGE_MESSAGE_COMPARATOR)
- .forEach(cm -> sb.append("\n ").append(cm));
- }
- diffs.add(sb.toString());
- }
-
- private static boolean changeMessagesMatch(
- ChangeBundle bundleA, ChangeMessage a, ChangeBundle bundleB, ChangeMessage b) {
- List<String> tempDiffs = new ArrayList<>();
- String temp = "temp";
-
- // ReviewDb allows timestamps before patch set was created, but NoteDb
- // truncates this to the patch set creation timestamp.
- Timestamp ta = a.getWrittenOn();
- Timestamp tb = b.getWrittenOn();
- PatchSet psa = bundleA.patchSets.get(a.getPatchSetId());
- PatchSet psb = bundleB.patchSets.get(b.getPatchSetId());
- boolean excludePatchSet = false;
- boolean excludeWrittenOn = false;
- if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) {
- excludePatchSet = a.getPatchSetId() == null;
- excludeWrittenOn =
- psa != null
- && psb != null
- && ta.before(psa.getCreatedOn())
- && tb.equals(psb.getCreatedOn());
- } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
- excludePatchSet = b.getPatchSetId() == null;
- excludeWrittenOn =
- psa != null
- && psb != null
- && tb.before(psb.getCreatedOn())
- && ta.equals(psa.getCreatedOn());
- }
-
- List<String> exclude = Lists.newArrayList("key");
- if (excludePatchSet) {
- exclude.add("patchset");
- }
- if (excludeWrittenOn) {
- exclude.add("writtenOn");
- }
-
- diffColumnsExcluding(tempDiffs, ChangeMessage.class, temp, bundleA, a, bundleB, b, exclude);
- return tempDiffs.isEmpty();
- }
-
- private static void diffPatchSets(
- List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- Map<PatchSet.Id, PatchSet> as = bundleA.patchSets;
- Map<PatchSet.Id, PatchSet> bs = bundleB.patchSets;
- Optional<PatchSet.Id> minA = as.keySet().stream().min(intKeyOrdering());
- Optional<PatchSet.Id> minB = bs.keySet().stream().min(intKeyOrdering());
- Set<PatchSet.Id> ids = diffKeySets(diffs, as, bs);
-
- // Old versions of Gerrit had a bug that created patch sets during
- // rebase or submission with a createdOn timestamp earlier than the patch
- // set it was replacing. (In the cases I examined, it was equal to createdOn
- // for the change, but we're not counting on this exact behavior.)
- //
- // ChangeRebuilder ensures patch set events come out in order, but it's hard
- // to predict what the resulting timestamps would look like. So, completely
- // ignore the createdOn timestamps if both:
- // * ReviewDb timestamps are non-monotonic.
- // * NoteDb timestamps are monotonic.
- //
- // Allow the timestamp of the first patch set to match the creation time of
- // the change.
- boolean excludeAllCreatedOn = false;
- if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) {
- excludeAllCreatedOn = !createdOnIsMonotonic(as, ids) && createdOnIsMonotonic(bs, ids);
- } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
- excludeAllCreatedOn = createdOnIsMonotonic(as, ids) && !createdOnIsMonotonic(bs, ids);
- }
-
- for (PatchSet.Id id : ids) {
- PatchSet a = as.get(id);
- PatchSet b = bs.get(id);
- String desc = describe(id);
- String pushCertField = "pushCertificate";
-
- boolean excludeCreatedOn = excludeAllCreatedOn;
- boolean excludeDesc = false;
- if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) {
- excludeDesc = Objects.equals(trimOrNull(a.getDescription()), b.getDescription());
- excludeCreatedOn |=
- Optional.of(id).equals(minB) && b.getCreatedOn().equals(bundleB.change.getCreatedOn());
- } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
- excludeDesc = Objects.equals(a.getDescription(), trimOrNull(b.getDescription()));
- excludeCreatedOn |=
- Optional.of(id).equals(minA) && a.getCreatedOn().equals(bundleA.change.getCreatedOn());
- }
-
- List<String> exclude = Lists.newArrayList(pushCertField);
- if (excludeCreatedOn) {
- exclude.add("createdOn");
- }
- if (excludeDesc) {
- exclude.add("description");
- }
-
- diffColumnsExcluding(diffs, PatchSet.class, desc, bundleA, a, bundleB, b, exclude);
- diffValues(diffs, desc, trimPushCert(a), trimPushCert(b), pushCertField);
- }
- }
-
- private static String trimPushCert(PatchSet ps) {
- if (ps.getPushCertificate() == null) {
- return null;
- }
- return CharMatcher.is('\n').trimTrailingFrom(ps.getPushCertificate());
- }
-
- private static boolean createdOnIsMonotonic(
- Map<?, PatchSet> patchSets, Set<PatchSet.Id> limitToIds) {
- List<PatchSet> orderedById =
- patchSets
- .values()
- .stream()
- .filter(ps -> limitToIds.contains(ps.getId()))
- .sorted(ChangeUtil.PS_ID_ORDER)
- .collect(toList());
- return Ordering.natural().onResultOf(PatchSet::getCreatedOn).isOrdered(orderedById);
- }
-
- private static void diffPatchSetApprovals(
- List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- Map<PatchSetApproval.Key, PatchSetApproval> as = bundleA.filterPatchSetApprovals();
- Map<PatchSetApproval.Key, PatchSetApproval> bs = bundleB.filterPatchSetApprovals();
- for (PatchSetApproval.Key k : diffKeySets(diffs, as, bs)) {
- PatchSetApproval a = as.get(k);
- PatchSetApproval b = bs.get(k);
- String desc = describe(k);
-
- // ReviewDb allows timestamps before patch set was created, but NoteDb
- // truncates this to the patch set creation timestamp.
- //
- // ChangeRebuilder ensures all post-submit approvals happen after the
- // actual submit, so the timestamps may not line up. This shouldn't really
- // happen, because postSubmit shouldn't be set in ReviewDb until after the
- // change is submitted in ReviewDb, but you never know.
- //
- // Due to a quirk of PostReview, post-submit 0 votes might not have the
- // postSubmit bit set in ReviewDb. As these are only used for tombstone
- // purposes, ignore the postSubmit bit in NoteDb in this case.
- Timestamp ta = a.getGranted();
- Timestamp tb = b.getGranted();
- PatchSet psa = requireNonNull(bundleA.patchSets.get(a.getPatchSetId()));
- PatchSet psb = requireNonNull(bundleB.patchSets.get(b.getPatchSetId()));
- boolean excludeGranted = false;
- boolean excludePostSubmit = false;
- List<String> exclude = new ArrayList<>(1);
- if (bundleA.source == REVIEW_DB && bundleB.source == NOTE_DB) {
- excludeGranted =
- (ta.before(psa.getCreatedOn()) && tb.equals(psb.getCreatedOn()))
- || ta.compareTo(tb) < 0;
- excludePostSubmit = a.getValue() == 0 && b.isPostSubmit();
- } else if (bundleA.source == NOTE_DB && bundleB.source == REVIEW_DB) {
- excludeGranted =
- (tb.before(psb.getCreatedOn()) && ta.equals(psa.getCreatedOn()))
- || (tb.compareTo(ta) < 0);
- excludePostSubmit = b.getValue() == 0 && a.isPostSubmit();
- }
-
- // Legacy submit approvals may or may not have tags associated with them,
- // depending on whether ChangeRebuilder happened to group them with the
- // status change.
- boolean excludeTag =
- bundleA.source != bundleB.source && a.isLegacySubmit() && b.isLegacySubmit();
-
- if (excludeGranted) {
- exclude.add("granted");
- }
- if (excludePostSubmit) {
- exclude.add("postSubmit");
- }
- if (excludeTag) {
- exclude.add("tag");
- }
-
- diffColumnsExcluding(diffs, PatchSetApproval.class, desc, bundleA, a, bundleB, b, exclude);
- }
- }
-
- private static void diffReviewers(
- List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- diffSets(diffs, bundleA.reviewers.all(), bundleB.reviewers.all(), "reviewer");
- }
-
- private static void diffPatchLineComments(
- List<String> diffs, ChangeBundle bundleA, ChangeBundle bundleB) {
- Map<PatchLineComment.Key, PatchLineComment> as = bundleA.filterPatchLineComments();
- Map<PatchLineComment.Key, PatchLineComment> bs = bundleB.filterPatchLineComments();
- for (PatchLineComment.Key k : diffKeySets(diffs, as, bs)) {
- PatchLineComment a = as.get(k);
- PatchLineComment b = bs.get(k);
- String desc = describe(k);
- diffColumns(diffs, PatchLineComment.class, desc, bundleA, a, bundleB, b);
- }
- }
-
- private static <T> Set<T> diffKeySets(List<String> diffs, Map<T, ?> a, Map<T, ?> b) {
- if (a.isEmpty() && b.isEmpty()) {
- return a.keySet();
- }
- String clazz = keyClass((!a.isEmpty() ? a.keySet() : b.keySet()).iterator().next());
- return diffSets(diffs, a.keySet(), b.keySet(), clazz);
- }
-
- private static <T> Set<T> diffSets(List<String> diffs, Set<T> as, Set<T> bs, String desc) {
- if (as.isEmpty() && bs.isEmpty()) {
- return as;
- }
-
- Set<T> aNotB = Sets.difference(as, bs);
- Set<T> bNotA = Sets.difference(bs, as);
- if (aNotB.isEmpty() && bNotA.isEmpty()) {
- return as;
- }
- diffs.add(desc + " sets differ: " + aNotB + " only in A; " + bNotA + " only in B");
- return Sets.intersection(as, bs);
- }
-
- private static <T> void diffColumns(
- List<String> diffs,
- Class<T> clazz,
- String desc,
- ChangeBundle bundleA,
- T a,
- ChangeBundle bundleB,
- T b) {
- diffColumnsExcluding(diffs, clazz, desc, bundleA, a, bundleB, b);
- }
-
- private static <T> void diffColumnsExcluding(
- List<String> diffs,
- Class<T> clazz,
- String desc,
- ChangeBundle bundleA,
- T a,
- ChangeBundle bundleB,
- T b,
- String... exclude) {
- diffColumnsExcluding(diffs, clazz, desc, bundleA, a, bundleB, b, Arrays.asList(exclude));
- }
-
- private static <T> void diffColumnsExcluding(
- List<String> diffs,
- Class<T> clazz,
- String desc,
- ChangeBundle bundleA,
- T a,
- ChangeBundle bundleB,
- T b,
- Iterable<String> exclude) {
- Set<String> toExclude = Sets.newLinkedHashSet(exclude);
- for (Field f : clazz.getDeclaredFields()) {
- Column col = f.getAnnotation(Column.class);
- if (col == null) {
- continue;
- } else if (toExclude.remove(f.getName())) {
- continue;
- }
- f.setAccessible(true);
- try {
- if (Timestamp.class.isAssignableFrom(f.getType())) {
- diffTimestamps(diffs, desc, bundleA, a, bundleB, b, f.getName());
- } else {
- diffValues(diffs, desc, f.get(a), f.get(b), f.getName());
- }
- } catch (IllegalAccessException e) {
- throw new IllegalArgumentException(e);
- }
- }
- checkArgument(
- toExclude.isEmpty(),
- "requested columns to exclude not present in %s: %s",
- clazz.getSimpleName(),
- toExclude);
- }
-
- private static void diffTimestamps(
- List<String> diffs,
- String desc,
- ChangeBundle bundleA,
- Object a,
- ChangeBundle bundleB,
- Object b,
- String field) {
- checkArgument(a.getClass() == b.getClass());
- Class<?> clazz = a.getClass();
-
- Timestamp ta;
- Timestamp tb;
- try {
- Field f = clazz.getDeclaredField(field);
- checkArgument(f.getAnnotation(Column.class) != null);
- f.setAccessible(true);
- ta = (Timestamp) f.get(a);
- tb = (Timestamp) f.get(b);
- } catch (IllegalAccessException | NoSuchFieldException | SecurityException e) {
- throw new IllegalArgumentException(e);
- }
- diffTimestamps(diffs, desc, bundleA, ta, bundleB, tb, field);
- }
-
- private static void diffTimestamps(
- List<String> diffs,
- String desc,
- ChangeBundle bundleA,
- Timestamp ta,
- ChangeBundle bundleB,
- Timestamp tb,
- String fieldDesc) {
- if (bundleA.source == bundleB.source || ta == null || tb == null) {
- diffValues(diffs, desc, ta, tb, fieldDesc);
- } else if (bundleA.source == NOTE_DB) {
- diffTimestamps(diffs, desc, bundleA.getChange(), ta, bundleB.getChange(), tb, fieldDesc);
- } else {
- diffTimestamps(diffs, desc, bundleB.getChange(), tb, bundleA.getChange(), ta, fieldDesc);
- }
- }
-
- private static boolean timestampsDiffer(
- ChangeBundle bundleA, Timestamp ta, ChangeBundle bundleB, Timestamp tb) {
- List<String> tempDiffs = new ArrayList<>(1);
- diffTimestamps(tempDiffs, "temp", bundleA, ta, bundleB, tb, "temp");
- return !tempDiffs.isEmpty();
- }
-
- private static void diffTimestamps(
- List<String> diffs,
- String desc,
- Change changeFromNoteDb,
- Timestamp tsFromNoteDb,
- Change changeFromReviewDb,
- Timestamp tsFromReviewDb,
- String field) {
- // Because ChangeRebuilder may batch events together that are several
- // seconds apart, the timestamp in NoteDb may actually be several seconds
- // *earlier* than the timestamp in ReviewDb that it was converted from.
- checkArgument(
- tsFromNoteDb.equals(truncateToSecond(tsFromNoteDb)),
- "%s from NoteDb has non-rounded %s timestamp: %s",
- desc,
- field,
- tsFromNoteDb);
-
- if (tsFromReviewDb.before(changeFromReviewDb.getCreatedOn())
- && tsFromNoteDb.equals(changeFromNoteDb.getCreatedOn())) {
- // Timestamp predates change creation. These are truncated to change
- // creation time during NoteDb conversion, so allow this if the timestamp
- // in NoteDb matches the createdOn time in NoteDb.
- return;
- }
-
- long delta = tsFromReviewDb.getTime() - tsFromNoteDb.getTime();
- long max = ChangeRebuilderImpl.MAX_WINDOW_MS;
- if (delta < 0 || delta > max) {
- diffs.add(
- field
- + " differs for "
- + desc
- + " in NoteDb vs. ReviewDb:"
- + " {"
- + tsFromNoteDb
- + "} != {"
- + tsFromReviewDb
- + "}");
- }
- }
-
- private static void diffValues(
- List<String> diffs, String desc, Object va, Object vb, String name) {
- if (!Objects.equals(va, vb)) {
- diffs.add(name + " differs for " + desc + ": {" + va + "} != {" + vb + "}");
- }
- }
-
- private static String describe(Object key) {
- return keyClass(key) + " " + key;
- }
-
- private static String keyClass(Object obj) {
- Class<?> clazz = obj.getClass();
- String name = clazz.getSimpleName();
- checkArgument(name.endsWith("Key") || name.endsWith("Id"), "not an Id/Key class: %s", name);
- if (name.equals("Key") || name.equals("Id")) {
- return clazz.getEnclosingClass().getSimpleName() + "." + name;
- } else if (name.startsWith("AutoValue_")) {
- return name.substring(name.lastIndexOf('_') + 1);
- }
- return name;
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName()
- + "{id="
- + change.getId()
- + ", ChangeMessage["
- + changeMessages.size()
- + "]"
- + ", PatchSet["
- + patchSets.size()
- + "]"
- + ", PatchSetApproval["
- + patchSetApprovals.size()
- + "]"
- + ", PatchLineComment["
- + patchLineComments.size()
- + "]"
- + "}";
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/ChangeBundleReader.java b/java/com/google/gerrit/server/notedb/ChangeBundleReader.java
deleted file mode 100644
index 3207c3b..0000000
--- a/java/com/google/gerrit/server/notedb/ChangeBundleReader.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-
-public interface ChangeBundleReader {
- @Nullable
- ChangeBundle fromReviewDb(ReviewDb db, Change.Id id) throws OrmException;
-}
diff --git a/java/com/google/gerrit/server/notedb/ChangeNotes.java b/java/com/google/gerrit/server/notedb/ChangeNotes.java
index d2942dc..e5e0d51 100644
--- a/java/com/google/gerrit/server/notedb/ChangeNotes.java
+++ b/java/com/google/gerrit/server/notedb/ChangeNotes.java
@@ -17,7 +17,6 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkState;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
import static java.util.Comparator.comparing;
import static java.util.Objects.requireNonNull;
@@ -28,18 +27,15 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSortedMap;
import com.google.common.collect.ImmutableSortedSet;
-import com.google.common.collect.Iterators;
import com.google.common.collect.ListMultimap;
import com.google.common.collect.MultimapBuilder;
import com.google.common.collect.Multimaps;
import com.google.common.collect.Ordering;
import com.google.common.collect.Sets;
import com.google.common.collect.Sets.SetView;
-import com.google.common.collect.Streams;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
import com.google.gerrit.common.data.SubmitRecord;
-import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
@@ -57,9 +53,7 @@
import com.google.gerrit.server.ReviewerSet;
import com.google.gerrit.server.ReviewerStatusUpdate;
import com.google.gerrit.server.git.RefCache;
-import com.google.gerrit.server.git.RepoRefCache;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.query.change.ChangeData;
@@ -76,8 +70,6 @@
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
-import java.util.Set;
-import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Stream;
import org.eclipse.jgit.errors.ConfigInvalidException;
@@ -186,12 +178,6 @@
return new ChangeNotes(args, loadChangeFromDb(db, project, changeId)).load();
}
- public ChangeNotes createWithAutoRebuildingDisabled(
- ReviewDb db, Project.NameKey project, Change.Id changeId) throws OrmException {
- return new ChangeNotes(args, loadChangeFromDb(db, project, changeId), true, false, null)
- .load();
- }
-
/**
* Create change notes for a change that was loaded from index. This method should only be used
* when database access is harmful and potentially stale data from the index is acceptable.
@@ -205,12 +191,11 @@
public ChangeNotes createForBatchUpdate(Change change, boolean shouldExist)
throws OrmException {
- return new ChangeNotes(args, change, shouldExist, false, null).load();
+ return new ChangeNotes(args, change, shouldExist, null).load();
}
- public ChangeNotes createWithAutoRebuildingDisabled(Change change, RefCache refs)
- throws OrmException {
- return new ChangeNotes(args, change, true, false, refs).load();
+ public ChangeNotes create(Change change, RefCache refs) throws OrmException {
+ return new ChangeNotes(args, change, true, refs).load();
}
// TODO(ekempin): Remove when database backend is deleted
@@ -285,7 +270,7 @@
if (args.migration.readChanges()) {
for (Project.NameKey project : projectCache.all()) {
try (Repository repo = args.repoManager.openRepository(project)) {
- scanNoteDb(repo, db, project)
+ scan(repo, project)
.filter(r -> !r.error().isPresent())
.map(ChangeNotesResult::notes)
.filter(predicate)
@@ -303,79 +288,23 @@
return ImmutableListMultimap.copyOf(m);
}
- public Stream<ChangeNotesResult> scan(Repository repo, ReviewDb db, Project.NameKey project)
+ public Stream<ChangeNotesResult> scan(Repository repo, Project.NameKey project)
throws IOException {
- return args.migration.readChanges() ? scanNoteDb(repo, db, project) : scanReviewDb(repo, db);
- }
-
- private Stream<ChangeNotesResult> scanReviewDb(Repository repo, ReviewDb db)
- throws IOException {
- // Scan IDs that might exist in ReviewDb, assuming that each change has at least one patch set
- // ref. Not all changes might exist: some patch set refs might have been written where the
- // corresponding ReviewDb write failed. These will be silently filtered out by the batch get
- // call below, which is intended.
- Set<Change.Id> ids = scanChangeIds(repo).fromPatchSetRefs();
-
- // A batch size of N may overload get(Iterable), so use something smaller, but still >1.
- return Streams.stream(Iterators.partition(ids.iterator(), 30))
- .flatMap(
- batch -> {
- try {
- return Streams.stream(ReviewDbUtil.unwrapDb(db).changes().get(batch))
- .map(this::toResult)
- .filter(Objects::nonNull);
- } catch (OrmException e) {
- // Return this error for each Id in the input batch.
- return batch.stream().map(id -> ChangeNotesResult.error(id, e));
- }
- });
- }
-
- private Stream<ChangeNotesResult> scanNoteDb(
- Repository repo, ReviewDb db, Project.NameKey project) throws IOException {
ScanResult sr = scanChangeIds(repo);
- PrimaryStorage defaultStorage = args.migration.changePrimaryStorage();
- return sr.all()
- .stream()
- .map(id -> scanOneNoteDbChange(db, project, sr, defaultStorage, id))
- .filter(Objects::nonNull);
+ return sr.all().stream().map(id -> scanOneChange(project, sr, id)).filter(Objects::nonNull);
}
- private ChangeNotesResult scanOneNoteDbChange(
- ReviewDb db,
- Project.NameKey project,
- ScanResult sr,
- PrimaryStorage defaultStorage,
- Change.Id id) {
- Change change;
- try {
- change = readOneReviewDbChange(db, id);
- } catch (OrmException e) {
- return ChangeNotesResult.error(id, e);
- }
-
- if (change == null) {
- if (!sr.fromMetaRefs().contains(id)) {
- // Stray patch set refs can happen due to normal error conditions, e.g. failed
- // push processing, so aren't worth even a warning.
- return null;
- }
- if (defaultStorage == PrimaryStorage.REVIEW_DB) {
- // If changes should exist in ReviewDb, it's worth warning about a meta ref with
- // no corresponding ReviewDb data.
- logger.atWarning().log(
- "skipping change %s found in project %s but not in ReviewDb", id, project);
- return null;
- }
- // TODO(dborowitz): See discussion in NoteDbBatchUpdate#newChangeContext.
- change = ChangeNotes.Factory.newNoteDbOnlyChange(project, id);
- } else if (!change.getProject().equals(project)) {
- logger.atSevere().log(
- "skipping change %s found in project %s because ReviewDb change has project %s",
- id, project, change.getProject());
+ private ChangeNotesResult scanOneChange(Project.NameKey project, ScanResult sr, Change.Id id) {
+ if (!sr.fromMetaRefs().contains(id)) {
+ // Stray patch set refs can happen due to normal error conditions, e.g. failed
+ // push processing, so aren't worth even a warning.
return null;
}
+
+ // TODO(dborowitz): See discussion in NoteDbBatchUpdate#newChangeContext.
+ Change change = ChangeNotes.Factory.newNoteDbOnlyChange(project, id);
+
logger.atFine().log("adding change %s found in project %s", id, project);
return toResult(change);
}
@@ -391,7 +320,7 @@
return ChangeNotesResult.notes(n);
}
- /** Result of {@link #scan(Repository, ReviewDb, Project.NameKey)}. */
+ /** Result of {@link #scan(Repository,Project.NameKey)}. */
@AutoValue
public abstract static class ChangeNotesResult {
static ChangeNotesResult error(Change.Id id, OrmException e) {
@@ -459,7 +388,6 @@
// notes easier.
RevisionNoteMap<ChangeRevisionNote> revisionNoteMap;
- private NoteDbUpdateManager.Result rebuildResult;
private DraftCommentNotes draftCommentNotes;
private RobotCommentNotes robotCommentNotes;
@@ -471,12 +399,11 @@
@VisibleForTesting
public ChangeNotes(Args args, Change change) {
- this(args, change, true, true, null);
+ this(args, change, true, null);
}
- private ChangeNotes(
- Args args, Change change, boolean shouldExist, boolean autoRebuild, @Nullable RefCache refs) {
- super(args, change.getId(), PrimaryStorage.of(change), autoRebuild);
+ private ChangeNotes(Args args, Change change, boolean shouldExist, @Nullable RefCache refs) {
+ super(args, change.getId());
this.change = new Change(change);
this.shouldExist = shouldExist;
this.refs = refs;
@@ -609,8 +536,7 @@
*/
private void loadDraftComments(Account.Id author, @Nullable Ref ref) throws OrmException {
if (draftCommentNotes == null || !author.equals(draftCommentNotes.getAuthor()) || ref != null) {
- draftCommentNotes =
- new DraftCommentNotes(args, change, author, autoRebuild, rebuildResult, ref);
+ draftCommentNotes = new DraftCommentNotes(args, getChangeId(), author, ref);
draftCommentNotes.load();
}
}
@@ -665,8 +591,7 @@
}
@Override
- protected void onLoad(LoadHandle handle)
- throws NoSuchChangeException, IOException, ConfigInvalidException {
+ protected void onLoad(LoadHandle handle) throws NoSuchChangeException, IOException {
ObjectId rev = handle.id();
if (rev == null) {
if (args.migration.readChanges()
@@ -699,89 +624,4 @@
protected ObjectId readRef(Repository repo) throws IOException {
return refs != null ? refs.get(getRefName()).orElse(null) : super.readRef(repo);
}
-
- @Override
- protected LoadHandle openHandle(Repository repo) throws NoSuchChangeException, IOException {
- if (autoRebuild) {
- NoteDbChangeState state = NoteDbChangeState.parse(change);
- if (args.migration.disableChangeReviewDb()) {
- checkState(
- state != null,
- "shouldn't have null NoteDbChangeState when ReviewDb disabled: %s",
- change);
- }
- ObjectId id = readRef(repo);
- if (id == null) {
- // Meta ref doesn't exist in NoteDb.
-
- if (state == null) {
- // Either ReviewDb change is being newly created, or it exists in ReviewDb but has not yet
- // been rebuilt for the first time, e.g. because we just turned on write-only mode. In
- // both cases, we don't want to auto-rebuild, just proceed with an empty ChangeNotes.
- return super.openHandle(repo, id);
- } else if (shouldExist && state.getPrimaryStorage() == PrimaryStorage.NOTE_DB) {
- throw new NoSuchChangeException(getChangeId());
- }
-
- // ReviewDb claims NoteDb state exists, but meta ref isn't present: fall through and
- // auto-rebuild if necessary.
- }
- RefCache refs = this.refs != null ? this.refs : new RepoRefCache(repo);
- if (!NoteDbChangeState.isChangeUpToDate(state, refs, getChangeId())) {
- return rebuildAndOpen(repo, id);
- }
- }
- return super.openHandle(repo);
- }
-
- private LoadHandle rebuildAndOpen(Repository repo, ObjectId oldId) throws IOException {
- Timer1.Context timer = args.metrics.autoRebuildLatency.start(CHANGES);
- try {
- Change.Id cid = getChangeId();
- ReviewDb db = args.db.get();
- ChangeRebuilder rebuilder = args.rebuilder.get();
- NoteDbUpdateManager.Result r;
- try (NoteDbUpdateManager manager = rebuilder.stage(db, cid)) {
- if (manager == null) {
- return super.openHandle(repo, oldId); // May be null in tests.
- }
- manager.setRefLogMessage("Auto-rebuilding change");
- r = manager.stageAndApplyDelta(change);
- try {
- rebuilder.execute(db, cid, manager);
- repo.scanForRepoChanges();
- } catch (OrmException | IOException e) {
- // Rebuilding failed. Most likely cause is contention on one or more
- // change refs; there are other types of errors that can happen during
- // rebuilding, but generally speaking they should happen during stage(),
- // not execute(). Assume that some other worker is going to successfully
- // store the rebuilt state, which is deterministic given an input
- // ChangeBundle.
- //
- // Parse notes from the staged result so we can return something useful
- // to the caller instead of throwing.
- logger.atFine().log("Rebuilding change %s failed: %s", getChangeId(), e.getMessage());
- args.metrics.autoRebuildFailureCount.increment(CHANGES);
- rebuildResult = requireNonNull(r);
- requireNonNull(r.newState());
- requireNonNull(r.staged());
- requireNonNull(r.staged().changeObjects());
- return LoadHandle.create(
- ChangeNotesCommit.newStagedRevWalk(repo, r.staged().changeObjects()),
- r.newState().getChangeMetaId());
- }
- }
- return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), r.newState().getChangeMetaId());
- } catch (NoSuchChangeException e) {
- return super.openHandle(repo, oldId);
- } catch (OrmException e) {
- throw new IOException(e);
- } finally {
- logger.atFine().log(
- "Rebuilt change %s in project %s in %s ms",
- getChangeId(),
- getProjectName(),
- TimeUnit.MILLISECONDS.convert(timer.stop(), TimeUnit.NANOSECONDS));
- }
- }
}
diff --git a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
index e122754..8720c36 100644
--- a/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
+++ b/java/com/google/gerrit/server/notedb/CommentJsonMigrator.java
@@ -26,6 +26,7 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
+import com.google.gerrit.server.UsedAt;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerIdProvider;
import com.google.inject.Inject;
@@ -50,6 +51,7 @@
import org.eclipse.jgit.transport.ReceiveCommand;
import org.eclipse.jgit.util.MutableInteger;
+@UsedAt(UsedAt.Project.GOOGLE)
@Singleton
public class CommentJsonMigrator {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
diff --git a/java/com/google/gerrit/server/notedb/DraftCommentNotes.java b/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
index 8acc8d4..2523c2c 100644
--- a/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
+++ b/java/com/google/gerrit/server/notedb/DraftCommentNotes.java
@@ -16,7 +16,6 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.gerrit.reviewdb.client.RefNames.refsDraftComments;
-import static com.google.gerrit.server.notedb.NoteDbTable.CHANGES;
import static java.util.Objects.requireNonNull;
import com.google.common.annotations.VisibleForTesting;
@@ -25,24 +24,15 @@
import com.google.common.collect.MultimapBuilder;
import com.google.common.flogger.FluentLogger;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.metrics.Timer1;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Comment;
import com.google.gerrit.reviewdb.client.PatchLineComment;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.git.RepoRefCache;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.StagedResult;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.assistedinject.Assisted;
import com.google.inject.assistedinject.AssistedInject;
import java.io.IOException;
-import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.ObjectReader;
@@ -50,53 +40,29 @@
import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.notes.NoteMap;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.transport.ReceiveCommand;
/** View of the draft comments for a single {@link Change} based on the log of its drafts branch. */
public class DraftCommentNotes extends AbstractChangeNotes<DraftCommentNotes> {
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
public interface Factory {
- DraftCommentNotes create(Change change, Account.Id accountId);
-
- DraftCommentNotes createWithAutoRebuildingDisabled(Change.Id changeId, Account.Id accountId);
+ DraftCommentNotes create(Change.Id changeId, Account.Id accountId);
}
- private final Change change;
private final Account.Id author;
- private final NoteDbUpdateManager.Result rebuildResult;
private final Ref ref;
private ImmutableListMultimap<RevId, Comment> comments;
private RevisionNoteMap<ChangeRevisionNote> revisionNoteMap;
@AssistedInject
- DraftCommentNotes(Args args, @Assisted Change change, @Assisted Account.Id author) {
- this(args, change, author, true, null, null);
- }
-
- @AssistedInject
DraftCommentNotes(Args args, @Assisted Change.Id changeId, @Assisted Account.Id author) {
- // PrimaryStorage is unknown; this should only called by
- // PatchLineCommentsUtil#draftByAuthor, which can live with this.
- super(args, changeId, null, false);
- this.change = null;
- this.author = author;
- this.rebuildResult = null;
- this.ref = null;
+ this(args, changeId, author, null);
}
- DraftCommentNotes(
- Args args,
- Change change,
- Account.Id author,
- boolean autoRebuild,
- @Nullable NoteDbUpdateManager.Result rebuildResult,
- @Nullable Ref ref) {
- super(args, change.getId(), PrimaryStorage.of(change), autoRebuild);
- this.change = change;
- this.author = author;
- this.rebuildResult = rebuildResult;
+ DraftCommentNotes(Args args, Change.Id changeId, Account.Id author, @Nullable Ref ref) {
+ super(args, changeId);
+ this.author = requireNonNull(author);
this.ref = ref;
if (ref != null) {
checkArgument(
@@ -181,79 +147,6 @@
return args.allUsers;
}
- @Override
- protected LoadHandle openHandle(Repository repo) throws NoSuchChangeException, IOException {
- if (rebuildResult != null) {
- StagedResult sr = requireNonNull(rebuildResult.staged());
- return LoadHandle.create(
- ChangeNotesCommit.newStagedRevWalk(repo, sr.allUsersObjects()),
- findNewId(sr.allUsersCommands(), getRefName()));
- } else if (change != null && autoRebuild) {
- NoteDbChangeState state = NoteDbChangeState.parse(change);
- // Only check if this particular user's drafts are up to date, to avoid
- // reading unnecessary refs.
- if (!NoteDbChangeState.areDraftsUpToDate(
- state, new RepoRefCache(repo), getChangeId(), author)) {
- return rebuildAndOpen(repo);
- }
- }
- return super.openHandle(repo);
- }
-
- private static ObjectId findNewId(Iterable<ReceiveCommand> cmds, String refName) {
- for (ReceiveCommand cmd : cmds) {
- if (cmd.getRefName().equals(refName)) {
- return cmd.getNewId();
- }
- }
- return null;
- }
-
- private LoadHandle rebuildAndOpen(Repository repo) throws NoSuchChangeException, IOException {
- Timer1.Context timer = args.metrics.autoRebuildLatency.start(CHANGES);
- try {
- Change.Id cid = getChangeId();
- ReviewDb db = args.db.get();
- ChangeRebuilder rebuilder = args.rebuilder.get();
- NoteDbUpdateManager.Result r;
- try (NoteDbUpdateManager manager = rebuilder.stage(db, cid)) {
- if (manager == null) {
- return super.openHandle(repo); // May be null in tests.
- }
- r = manager.stageAndApplyDelta(change);
- try {
- rebuilder.execute(db, cid, manager);
- repo.scanForRepoChanges();
- } catch (OrmException | IOException e) {
- // See ChangeNotes#rebuildAndOpen.
- logger.atFine().log(
- "Rebuilding change %s via drafts failed: %s", getChangeId(), e.getMessage());
- args.metrics.autoRebuildFailureCount.increment(CHANGES);
- requireNonNull(r.staged());
- return LoadHandle.create(
- ChangeNotesCommit.newStagedRevWalk(repo, r.staged().allUsersObjects()), draftsId(r));
- }
- }
- return LoadHandle.create(ChangeNotesCommit.newRevWalk(repo), draftsId(r));
- } catch (NoSuchChangeException e) {
- return super.openHandle(repo);
- } catch (OrmException e) {
- throw new IOException(e);
- } finally {
- logger.atFine().log(
- "Rebuilt change %s in %s in %s ms via drafts",
- getChangeId(),
- change != null ? "project " + change.getProject() : "unknown project",
- TimeUnit.MILLISECONDS.convert(timer.stop(), TimeUnit.NANOSECONDS));
- }
- }
-
- private ObjectId draftsId(NoteDbUpdateManager.Result r) {
- requireNonNull(r);
- requireNonNull(r.newState());
- return r.newState().getDraftIds().get(author);
- }
-
@VisibleForTesting
NoteMap getNoteMap() {
return revisionNoteMap != null ? revisionNoteMap.noteMap : null;
diff --git a/java/com/google/gerrit/server/notedb/GwtormChangeBundleReader.java b/java/com/google/gerrit/server/notedb/GwtormChangeBundleReader.java
deleted file mode 100644
index 347ba48..0000000
--- a/java/com/google/gerrit/server/notedb/GwtormChangeBundleReader.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.ReviewerSet;
-import com.google.gerrit.server.notedb.ChangeBundle.Source;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.util.List;
-
-@Singleton
-public class GwtormChangeBundleReader implements ChangeBundleReader {
- @Inject
- GwtormChangeBundleReader() {}
-
- @Override
- @Nullable
- public ChangeBundle fromReviewDb(ReviewDb db, Change.Id id) throws OrmException {
- Change reviewDbChange = db.changes().get(id);
- if (reviewDbChange == null) {
- return null;
- }
-
- // TODO(dborowitz): Figure out how to do this more consistently, e.g. hand-written inner joins.
- List<PatchSetApproval> approvals = db.patchSetApprovals().byChange(id).toList();
- return new ChangeBundle(
- reviewDbChange,
- db.changeMessages().byChange(id),
- db.patchSets().byChange(id),
- approvals,
- db.patchComments().byChange(id),
- ReviewerSet.fromApprovals(approvals),
- Source.REVIEW_DB);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/MutableNotesMigration.java b/java/com/google/gerrit/server/notedb/MutableNotesMigration.java
index 7f4912b..eb41cbc 100644
--- a/java/com/google/gerrit/server/notedb/MutableNotesMigration.java
+++ b/java/com/google/gerrit/server/notedb/MutableNotesMigration.java
@@ -14,6 +14,7 @@
package com.google.gerrit.server.notedb;
+import com.google.common.annotations.VisibleForTesting;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.inject.Inject;
@@ -79,24 +80,18 @@
/**
* Set the in-memory values returned by this instance to match the given state.
*
- * <p>This method is only intended for use by {@link
- * com.google.gerrit.server.notedb.rebuild.NoteDbMigrator}.
+ * <p>This method is only intended for use by tests.
*
* <p>This <em>only</em> modifies the in-memory state; if this instance was initialized from a
* file-based config, the underlying storage is not updated. Callers are responsible for managing
* the underlying storage on their own.
*/
+ @VisibleForTesting
public MutableNotesMigration setFrom(NotesMigrationState state) {
snapshot.set(state.snapshot());
return this;
}
- /** @see #setFrom(NotesMigrationState) */
- public MutableNotesMigration setFrom(NotesMigration other) {
- snapshot.set(other.snapshot.get());
- return this;
- }
-
private MutableNotesMigration set(Function<Snapshot.Builder, Snapshot.Builder> f) {
snapshot.updateAndGet(s -> f.apply(s.toBuilder()).build());
return this;
diff --git a/java/com/google/gerrit/server/notedb/NoteDbModule.java b/java/com/google/gerrit/server/notedb/NoteDbModule.java
index c76c39b..cf12d84 100644
--- a/java/com/google/gerrit/server/notedb/NoteDbModule.java
+++ b/java/com/google/gerrit/server/notedb/NoteDbModule.java
@@ -17,33 +17,21 @@
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Change.Id;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.Result;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
-import com.google.gerrit.server.notedb.rebuild.NotesMigrationStateListener;
import com.google.inject.TypeLiteral;
import com.google.inject.name.Names;
-import org.eclipse.jgit.lib.Config;
public class NoteDbModule extends FactoryModule {
- private final Config cfg;
private final boolean useTestBindings;
- static NoteDbModule forTest(Config cfg) {
- return new NoteDbModule(cfg, true);
+ static NoteDbModule forTest() {
+ return new NoteDbModule(true);
}
- public NoteDbModule(Config cfg) {
- this(cfg, false);
+ public NoteDbModule() {
+ this(false);
}
- private NoteDbModule(Config cfg, boolean useTestBindings) {
- this.cfg = cfg;
+ private NoteDbModule(boolean useTestBindings) {
this.useTestBindings = useTestBindings;
}
@@ -56,57 +44,10 @@
factory(NoteDbUpdateManager.Factory.class);
factory(RobotCommentNotes.Factory.class);
factory(RobotCommentUpdate.Factory.class);
- DynamicSet.setOf(binder(), NotesMigrationStateListener.class);
if (!useTestBindings) {
install(ChangeNotesCache.module());
- if (cfg.getBoolean("noteDb", null, "testRebuilderWrapper", false)) {
- // Yes, another variety of test bindings with a different way of
- // configuring it.
- bind(ChangeRebuilder.class).to(TestChangeRebuilderWrapper.class);
- } else {
- bind(ChangeRebuilder.class).to(ChangeRebuilderImpl.class);
- }
} else {
- bind(ChangeRebuilder.class)
- .toInstance(
- new ChangeRebuilder(null) {
- @Override
- public Result rebuild(ReviewDb db, Change.Id changeId) {
- return null;
- }
-
- @Override
- public Result rebuildEvenIfReadOnly(ReviewDb db, Id changeId) {
- return null;
- }
-
- @Override
- public Result rebuild(NoteDbUpdateManager manager, ChangeBundle bundle) {
- return null;
- }
-
- @Override
- public NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId) {
- return null;
- }
-
- @Override
- public Result execute(
- ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager) {
- return null;
- }
-
- @Override
- public void buildUpdates(NoteDbUpdateManager manager, ChangeBundle bundle) {
- // Do nothing.
- }
-
- @Override
- public void rebuildReviewDb(ReviewDb db, Project.NameKey project, Id changeId) {
- // Do nothing.
- }
- });
bind(new TypeLiteral<Cache<ChangeNotesCache.Key, ChangeNotesState>>() {})
.annotatedWith(Names.named(ChangeNotesCache.CACHE_NAME))
.toInstance(CacheBuilder.newBuilder().<ChangeNotesCache.Key, ChangeNotesState>build());
diff --git a/java/com/google/gerrit/server/notedb/NotesMigration.java b/java/com/google/gerrit/server/notedb/NotesMigration.java
index c7acaf1..28754a6 100644
--- a/java/com/google/gerrit/server/notedb/NotesMigration.java
+++ b/java/com/google/gerrit/server/notedb/NotesMigration.java
@@ -46,8 +46,7 @@
* <p>This class controls the state of the migration according to options in {@code gerrit.config}.
* In general, any changes to these options should only be made by adventurous administrators, who
* know what they're doing, on non-production data, for the purposes of testing the NoteDb
- * implementation. Changing options quite likely requires re-running {@code MigrateToNoteDb}. For
- * these reasons, the options remain undocumented.
+ * implementation.
*
* <p><strong>Note:</strong> Callers should not assume the values returned by {@code
* NotesMigration}'s methods will not change in a running server.
diff --git a/java/com/google/gerrit/server/notedb/PrimaryStorageMigrator.java b/java/com/google/gerrit/server/notedb/PrimaryStorageMigrator.java
deleted file mode 100644
index 7b427b4..0000000
--- a/java/com/google/gerrit/server/notedb/PrimaryStorageMigrator.java
+++ /dev/null
@@ -1,510 +0,0 @@
-// Copyright (C) 2017 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.notedb;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import com.github.rholder.retry.RetryException;
-import com.github.rholder.retry.Retryer;
-import com.github.rholder.retry.RetryerBuilder;
-import com.github.rholder.retry.StopStrategies;
-import com.github.rholder.retry.WaitStrategies;
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.InternalUser;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.RepoRefCache;
-import com.google.gerrit.server.index.change.ChangeField;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbChangeState.RefState;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.query.change.InternalChangeQuery;
-import com.google.gerrit.server.update.BatchUpdate;
-import com.google.gerrit.server.update.BatchUpdateOp;
-import com.google.gerrit.server.update.ChangeContext;
-import com.google.gerrit.server.update.RetryHelper;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gwtorm.server.AtomicUpdate;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.OrmRuntimeException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeSet;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.atomic.AtomicBoolean;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
-
-/** Helper to migrate the {@link PrimaryStorage} of individual changes. */
-@Singleton
-public class PrimaryStorageMigrator {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- /**
- * Exception thrown during migration if the change has no {@code noteDbState} field at the
- * beginning of the migration.
- */
- public static class NoNoteDbStateException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- private NoNoteDbStateException(Change.Id id) {
- super("change " + id + " has no note_db_state; rebuild it first");
- }
- }
-
- private final AllUsersName allUsers;
- private final ChangeNotes.Factory changeNotesFactory;
- private final ChangeRebuilder rebuilder;
- private final ChangeUpdate.Factory updateFactory;
- private final GitRepositoryManager repoManager;
- private final InternalUser.Factory internalUserFactory;
- private final Provider<InternalChangeQuery> queryProvider;
- private final Provider<ReviewDb> db;
- private final RetryHelper retryHelper;
-
- private final long skewMs;
- private final long timeoutMs;
- private final Retryer<NoteDbChangeState> testEnsureRebuiltRetryer;
-
- @Inject
- PrimaryStorageMigrator(
- @GerritServerConfig Config cfg,
- Provider<ReviewDb> db,
- GitRepositoryManager repoManager,
- AllUsersName allUsers,
- ChangeRebuilder rebuilder,
- ChangeNotes.Factory changeNotesFactory,
- Provider<InternalChangeQuery> queryProvider,
- ChangeUpdate.Factory updateFactory,
- InternalUser.Factory internalUserFactory,
- RetryHelper retryHelper) {
- this(
- cfg,
- db,
- repoManager,
- allUsers,
- rebuilder,
- null,
- changeNotesFactory,
- queryProvider,
- updateFactory,
- internalUserFactory,
- retryHelper);
- }
-
- @VisibleForTesting
- public PrimaryStorageMigrator(
- Config cfg,
- Provider<ReviewDb> db,
- GitRepositoryManager repoManager,
- AllUsersName allUsers,
- ChangeRebuilder rebuilder,
- @Nullable Retryer<NoteDbChangeState> testEnsureRebuiltRetryer,
- ChangeNotes.Factory changeNotesFactory,
- Provider<InternalChangeQuery> queryProvider,
- ChangeUpdate.Factory updateFactory,
- InternalUser.Factory internalUserFactory,
- RetryHelper retryHelper) {
- this.db = db;
- this.repoManager = repoManager;
- this.allUsers = allUsers;
- this.rebuilder = rebuilder;
- this.testEnsureRebuiltRetryer = testEnsureRebuiltRetryer;
- this.changeNotesFactory = changeNotesFactory;
- this.queryProvider = queryProvider;
- this.updateFactory = updateFactory;
- this.internalUserFactory = internalUserFactory;
- this.retryHelper = retryHelper;
- skewMs = NoteDbChangeState.getReadOnlySkew(cfg);
-
- String s = "notedb";
- timeoutMs =
- cfg.getTimeUnit(
- s,
- null,
- "primaryStorageMigrationTimeout",
- MILLISECONDS.convert(60, SECONDS),
- MILLISECONDS);
- }
-
- /**
- * Migrate a change's primary storage from ReviewDb to NoteDb.
- *
- * <p>This method will return only if the primary storage of the change is NoteDb afterwards. (It
- * may return early if the primary storage was already NoteDb.)
- *
- * <p>If this method throws an exception, then the primary storage of the change is probably not
- * NoteDb. (It is possible that the primary storage of the change is NoteDb in this case, but
- * there was an error reading the state.) Moreover, after an exception, the change may be
- * read-only until a lease expires. If the caller chooses to retry, they should wait until the
- * read-only lease expires; this method will fail relatively quickly if called on a read-only
- * change.
- *
- * <p>Note that if the change is read-only after this method throws an exception, that does not
- * necessarily guarantee that the read-only lease was acquired during that particular method
- * invocation; this call may have in fact failed because another thread acquired the lease first.
- *
- * @param id change ID.
- * @throws OrmException if a ReviewDb-level error occurs.
- * @throws IOException if a repo-level error occurs.
- */
- public void migrateToNoteDbPrimary(Change.Id id) throws OrmException, IOException {
- // Since there are multiple non-atomic steps in this method, we need to
- // consider what happens when there is another writer concurrent with the
- // thread executing this method.
- //
- // Let:
- // * OR = other writer writes noteDbState & new data to ReviewDb (in one
- // transaction)
- // * ON = other writer writes to NoteDb
- // * MRO = migrator sets state to read-only
- // * MR = ensureRebuilt writes rebuilt noteDbState to ReviewDb (but does not
- // otherwise update ReviewDb in this transaction)
- // * MN = ensureRebuilt writes rebuilt state to NoteDb
- //
- // Consider all the interleavings of these operations.
- //
- // * OR,ON,MRO,...
- // Other writer completes before migrator begins; this is not a concurrent
- // write.
- // * MRO,...,OR,...
- // OR will fail, since it atomically checks that the noteDbState is not
- // read-only before proceeding. This results in an exception, but not a
- // concurrent write.
- //
- // Thus all the "interesting" interleavings start with OR,MRO, and differ on
- // where ON falls relative to MR/MN.
- //
- // * OR,MRO,ON,MR,MN
- // The other NoteDb write succeeds despite the noteDbState being
- // read-only. Because the read-only state from MRO includes the update
- // from OR, the change is up-to-date at this point. Thus MR,MN is a no-op.
- // The end result is an up-to-date, read-only change.
- //
- // * OR,MRO,MR,ON,MN
- // The change is out-of-date when ensureRebuilt begins, because OR
- // succeeded but the corresponding ON has not happened yet. ON will
- // succeed, because there have been no intervening NoteDb writes. MN will
- // fail, because ON updated the state in NoteDb to something other than
- // what MR claimed. This leaves the change in an out-of-date, read-only
- // state.
- //
- // If this method threw an exception in this case, the change would
- // eventually switch back to read-write when the read-only lease expires,
- // so this situation is recoverable. However, it would be inconvenient for
- // a change to be read-only for so long.
- //
- // Thus, as an optimization, we have a retry loop that attempts
- // ensureRebuilt while still holding the same read-only lease. This
- // effectively results in the interleaving OR,MR,ON,MR,MN; in contrast
- // with the previous case, here, MR/MN actually rebuilds the change. In
- // the case of a write failure, MR/MN might fail and get retried again. If
- // it exceeds the maximum number of retries, an exception is thrown.
- //
- // * OR,MRO,MR,MN,ON
- // The change is out-of-date when ensureRebuilt begins. The change is
- // rebuilt, leaving a new state in NoteDb. ON will fail, because the old
- // NoteDb state has changed since the ref state was read when the update
- // began (prior to OR). This results in an exception from ON, but the end
- // result is still an up-to-date, read-only change. The end user that
- // initiated the other write observes an error, but this is no different
- // from other errors that need retrying, e.g. due to a backend write
- // failure.
-
- Stopwatch sw = Stopwatch.createStarted();
- Change readOnlyChange = setReadOnlyInReviewDb(id); // MRO
- if (readOnlyChange == null) {
- return; // Already migrated.
- }
-
- NoteDbChangeState rebuiltState;
- try {
- // MR,MN
- rebuiltState =
- ensureRebuiltRetryer(sw)
- .call(
- () ->
- ensureRebuilt(
- readOnlyChange.getProject(),
- id,
- NoteDbChangeState.parse(readOnlyChange)));
- } catch (RetryException | ExecutionException e) {
- throw new OrmException(e);
- }
-
- // At this point, the noteDbState in ReviewDb is read-only, and it is
- // guaranteed to match the state actually in NoteDb. Now it is safe to set
- // the primary storage to NoteDb.
-
- setPrimaryStorageNoteDb(id, rebuiltState);
- logger.atFine().log(
- "Migrated change %s to NoteDb primary in %sms", id, sw.elapsed(MILLISECONDS));
- }
-
- private Change setReadOnlyInReviewDb(Change.Id id) throws OrmException {
- AtomicBoolean alreadyMigrated = new AtomicBoolean(false);
- Change result =
- db().changes()
- .atomicUpdate(
- id,
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- NoteDbChangeState state = NoteDbChangeState.parse(change);
- if (state == null) {
- // Could rebuild the change here, but that's more complexity, and this
- // normally shouldn't happen.
- //
- // Known cases where this happens are described in and handled by
- // NoteDbMigrator#canSkipPrimaryStorageMigration.
- throw new NoNoteDbStateException(id);
- }
- // If the change is already read-only, then the lease is held by another
- // (likely failed) migrator thread. Fail early, as we can't take over
- // the lease.
- NoteDbChangeState.checkNotReadOnly(change, skewMs);
- if (state.getPrimaryStorage() != PrimaryStorage.NOTE_DB) {
- Timestamp now = TimeUtil.nowTs();
- Timestamp until = new Timestamp(now.getTime() + timeoutMs);
- change.setNoteDbState(state.withReadOnlyUntil(until).toString());
- } else {
- alreadyMigrated.set(true);
- }
- return change;
- }
- });
- return alreadyMigrated.get() ? null : result;
- }
-
- private Retryer<NoteDbChangeState> ensureRebuiltRetryer(Stopwatch sw) {
- if (testEnsureRebuiltRetryer != null) {
- return testEnsureRebuiltRetryer;
- }
- // Retry the ensureRebuilt step with backoff until half the timeout has
- // expired, leaving the remaining half for the rest of the steps.
- long remainingNanos = (MILLISECONDS.toNanos(timeoutMs) / 2) - sw.elapsed(NANOSECONDS);
- remainingNanos = Math.max(remainingNanos, 0);
- return RetryerBuilder.<NoteDbChangeState>newBuilder()
- .retryIfException(e -> (e instanceof IOException) || (e instanceof OrmException))
- .withWaitStrategy(
- WaitStrategies.join(
- WaitStrategies.exponentialWait(250, MILLISECONDS),
- WaitStrategies.randomWait(50, MILLISECONDS)))
- .withStopStrategy(StopStrategies.stopAfterDelay(remainingNanos, NANOSECONDS))
- .build();
- }
-
- private NoteDbChangeState ensureRebuilt(
- Project.NameKey project, Change.Id id, NoteDbChangeState readOnlyState)
- throws IOException, OrmException, RepositoryNotFoundException {
- try (Repository changeRepo = repoManager.openRepository(project);
- Repository allUsersRepo = repoManager.openRepository(allUsers)) {
- if (!readOnlyState.isUpToDate(new RepoRefCache(changeRepo), new RepoRefCache(allUsersRepo))) {
- NoteDbUpdateManager.Result r = rebuilder.rebuildEvenIfReadOnly(db(), id);
- checkState(
- r.newState().getReadOnlyUntil().equals(readOnlyState.getReadOnlyUntil()),
- "state after rebuilding has different read-only lease: %s != %s",
- r.newState(),
- readOnlyState);
- readOnlyState = r.newState();
- }
- }
- return readOnlyState;
- }
-
- private void setPrimaryStorageNoteDb(Change.Id id, NoteDbChangeState expectedState)
- throws OrmException {
- db().changes()
- .atomicUpdate(
- id,
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- NoteDbChangeState state = NoteDbChangeState.parse(change);
- if (!Objects.equals(state, expectedState)) {
- throw new OrmRuntimeException(badState(state, expectedState));
- }
- Timestamp until = state.getReadOnlyUntil().get();
- if (TimeUtil.nowTs().after(until)) {
- throw new OrmRuntimeException(
- "read-only lease on change " + id + " expired at " + until);
- }
- change.setNoteDbState(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
- return change;
- }
- });
- }
-
- private ReviewDb db() {
- return ReviewDbUtil.unwrapDb(db.get());
- }
-
- private String badState(NoteDbChangeState actual, NoteDbChangeState expected) {
- return "state changed unexpectedly: " + actual + " != " + expected;
- }
-
- public void migrateToReviewDbPrimary(Change.Id id, @Nullable Project.NameKey project)
- throws OrmException, IOException {
- // Migrating back to ReviewDb primary is much simpler than the original migration to NoteDb
- // primary, because when NoteDb is primary, each write only goes to one storage location rather
- // than both. We only need to consider whether a concurrent writer (OR) conflicts with the first
- // setReadOnlyInNoteDb step (MR) in this method.
- //
- // If OR wins, then either:
- // * MR will set read-only after OR is completed, which is not a concurrent write.
- // * MR will fail to set read-only with a lock failure. The caller will have to retry, but the
- // change is not in a read-only state, so behavior is not degraded in the meantime.
- //
- // If MR wins, then either:
- // * OR will fail with a read-only exception (via AbstractChangeNotes#apply).
- // * OR will fail with a lock failure.
- //
- // In all of these scenarios, the change is read-only if and only if MR succeeds.
- //
- // There will be no concurrent writes to ReviewDb for this change until
- // setPrimaryStorageReviewDb completes, because ReviewDb writes are not attempted when primary
- // storage is NoteDb. After the primary storage changes back, it is possible for subsequent
- // NoteDb writes to conflict with the releaseReadOnlyLeaseInNoteDb step, but at this point,
- // since ReviewDb is primary, we are back to ignoring them.
- Stopwatch sw = Stopwatch.createStarted();
- if (project == null) {
- project = getProject(id);
- }
- ObjectId newMetaId = setReadOnlyInNoteDb(project, id);
- rebuilder.rebuildReviewDb(db(), project, id);
- setPrimaryStorageReviewDb(id, newMetaId);
- releaseReadOnlyLeaseInNoteDb(project, id);
- logger.atFine().log(
- "Migrated change %s to ReviewDb primary in %sms", id, sw.elapsed(MILLISECONDS));
- }
-
- private ObjectId setReadOnlyInNoteDb(Project.NameKey project, Change.Id id)
- throws OrmException, IOException {
- Timestamp now = TimeUtil.nowTs();
- Timestamp until = new Timestamp(now.getTime() + timeoutMs);
- ChangeUpdate update =
- updateFactory.create(
- changeNotesFactory.createChecked(db.get(), project, id), internalUserFactory.create());
- update.setReadOnlyUntil(until);
- return update.commit();
- }
-
- private void setPrimaryStorageReviewDb(Change.Id id, ObjectId newMetaId)
- throws OrmException, IOException {
- ImmutableMap.Builder<Account.Id, ObjectId> draftIds = ImmutableMap.builder();
- try (Repository repo = repoManager.openRepository(allUsers)) {
- for (Ref draftRef :
- repo.getRefDatabase().getRefsByPrefix(RefNames.refsDraftCommentsPrefix(id))) {
- Account.Id accountId = Account.Id.fromRef(draftRef.getName());
- if (accountId != null) {
- draftIds.put(accountId, draftRef.getObjectId().copy());
- }
- }
- }
- NoteDbChangeState newState =
- new NoteDbChangeState(
- id,
- PrimaryStorage.REVIEW_DB,
- Optional.of(RefState.create(newMetaId, draftIds.build())),
- Optional.empty());
- db().changes()
- .atomicUpdate(
- id,
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- if (PrimaryStorage.of(change) != PrimaryStorage.NOTE_DB) {
- throw new OrmRuntimeException(
- "change " + id + " is not NoteDb primary: " + change.getNoteDbState());
- }
- change.setNoteDbState(newState.toString());
- return change;
- }
- });
- }
-
- private void releaseReadOnlyLeaseInNoteDb(Project.NameKey project, Change.Id id)
- throws OrmException {
- // Use a BatchUpdate since ReviewDb is primary at this point, so it needs to reflect the update.
- // (In practice retrying won't happen, since we aren't using fused updates at this point.)
- try {
- retryHelper.execute(
- updateFactory -> {
- try (BatchUpdate bu =
- updateFactory.create(
- db.get(), project, internalUserFactory.create(), TimeUtil.nowTs())) {
- bu.addOp(
- id,
- new BatchUpdateOp() {
- @Override
- public boolean updateChange(ChangeContext ctx) {
- ctx.getUpdate(ctx.getChange().currentPatchSetId())
- .setReadOnlyUntil(new Timestamp(0));
- return true;
- }
- });
- bu.execute();
- return null;
- }
- });
- } catch (RestApiException | UpdateException e) {
- throw new OrmException(e);
- }
- }
-
- private Project.NameKey getProject(Change.Id id) throws OrmException {
- List<ChangeData> cds =
- queryProvider.get().setRequestedFields(ChangeField.PROJECT).byLegacyChangeId(id);
- Set<Project.NameKey> projects = new TreeSet<>();
- for (ChangeData cd : cds) {
- projects.add(cd.project());
- }
- if (projects.size() != 1) {
- throw new OrmException(
- "zero or multiple projects found for change "
- + id
- + ", must specify project explicitly: "
- + projects);
- }
- return projects.iterator().next();
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/RobotCommentNotes.java b/java/com/google/gerrit/server/notedb/RobotCommentNotes.java
index a05e6a1..364ad75 100644
--- a/java/com/google/gerrit/server/notedb/RobotCommentNotes.java
+++ b/java/com/google/gerrit/server/notedb/RobotCommentNotes.java
@@ -24,7 +24,6 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.RevId;
import com.google.gerrit.reviewdb.client.RobotComment;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import java.io.IOException;
@@ -49,7 +48,7 @@
@Inject
RobotCommentNotes(Args args, @Assisted Change change) {
- super(args, change.getId(), PrimaryStorage.of(change), false);
+ super(args, change.getId());
this.change = change;
}
diff --git a/java/com/google/gerrit/server/notedb/TestChangeRebuilderWrapper.java b/java/com/google/gerrit/server/notedb/TestChangeRebuilderWrapper.java
deleted file mode 100644
index 11fef24..0000000
--- a/java/com/google/gerrit/server/notedb/TestChangeRebuilderWrapper.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Change.Id;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.Result;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.util.concurrent.atomic.AtomicBoolean;
-
-@VisibleForTesting
-@Singleton
-public class TestChangeRebuilderWrapper extends ChangeRebuilder {
- private final ChangeRebuilderImpl delegate;
- private final AtomicBoolean failNextUpdate;
- private final AtomicBoolean stealNextUpdate;
-
- @Inject
- TestChangeRebuilderWrapper(SchemaFactory<ReviewDb> schemaFactory, ChangeRebuilderImpl rebuilder) {
- super(schemaFactory);
- this.delegate = rebuilder;
- this.failNextUpdate = new AtomicBoolean();
- this.stealNextUpdate = new AtomicBoolean();
- }
-
- public void failNextUpdate() {
- failNextUpdate.set(true);
- }
-
- public void stealNextUpdate() {
- stealNextUpdate.set(true);
- }
-
- @Override
- public Result rebuild(ReviewDb db, Change.Id changeId) throws IOException, OrmException {
- return rebuild(db, changeId, true);
- }
-
- @Override
- public Result rebuildEvenIfReadOnly(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException {
- return rebuild(db, changeId, false);
- }
-
- private Result rebuild(ReviewDb db, Change.Id changeId, boolean checkReadOnly)
- throws IOException, OrmException {
- if (failNextUpdate.getAndSet(false)) {
- throw new IOException("Update failed");
- }
- Result result =
- checkReadOnly
- ? delegate.rebuild(db, changeId)
- : delegate.rebuildEvenIfReadOnly(db, changeId);
- if (stealNextUpdate.getAndSet(false)) {
- throw new IOException("Update stolen");
- }
- return result;
- }
-
- @Override
- public Result rebuild(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws IOException, OrmException {
- // stealNextUpdate doesn't really apply in this case because the IOException
- // would normally come from the manager.execute() method, which isn't called
- // here.
- return delegate.rebuild(manager, bundle);
- }
-
- @Override
- public NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException {
- // Don't inspect stealNextUpdate; that happens in execute() below.
- return delegate.stage(db, changeId);
- }
-
- @Override
- public Result execute(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager)
- throws OrmException, IOException {
- if (failNextUpdate.getAndSet(false)) {
- throw new IOException("Update failed");
- }
- Result result = delegate.execute(db, changeId, manager);
- if (stealNextUpdate.getAndSet(false)) {
- throw new IOException("Update stolen");
- }
- return result;
- }
-
- @Override
- public void buildUpdates(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws IOException, OrmException {
- // Don't check for manual failure; that happens in execute().
- delegate.buildUpdates(manager, bundle);
- }
-
- @Override
- public void rebuildReviewDb(ReviewDb db, Project.NameKey project, Id changeId)
- throws OrmException {
- if (failNextUpdate.getAndSet(false)) {
- throw new OrmException("Update failed");
- }
- delegate.rebuildReviewDb(db, project, changeId);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/AbortUpdateException.java b/java/com/google/gerrit/server/notedb/rebuild/AbortUpdateException.java
deleted file mode 100644
index 0e6d3e9..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/AbortUpdateException.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.gwtorm.server.OrmRuntimeException;
-
-class AbortUpdateException extends OrmRuntimeException {
- private static final long serialVersionUID = 1L;
-
- AbortUpdateException() {
- super("aborted");
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ApprovalEvent.java b/java/com/google/gerrit/server/notedb/rebuild/ApprovalEvent.java
deleted file mode 100644
index 9ecf476..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ApprovalEvent.java
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import java.sql.Timestamp;
-
-class ApprovalEvent extends Event {
- private PatchSetApproval psa;
-
- ApprovalEvent(PatchSetApproval psa, Timestamp changeCreatedOn) {
- super(
- psa.getPatchSetId(),
- psa.getAccountId(),
- psa.getRealAccountId(),
- psa.getGranted(),
- changeCreatedOn,
- psa.getTag());
- this.psa = psa;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return false;
- }
-
- @Override
- protected boolean canHaveTag() {
- // Legacy SUBM approvals don't have a tag field set, but the corresponding
- // ChangeMessage for merging the change does. We need to let these be in the
- // same meta commit so the SUBM approval isn't counted as post-submit.
- return !psa.isLegacySubmit();
- }
-
- @Override
- void apply(ChangeUpdate update) {
- checkUpdate(update);
- update.putApproval(psa.getLabel(), psa.getValue());
- }
-
- @Override
- protected boolean isPostSubmitApproval() {
- return psa.isPostSubmit();
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("approval", psa);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ChangeMessageEvent.java b/java/com/google/gerrit/server/notedb/rebuild/ChangeMessageEvent.java
deleted file mode 100644
index 53c9dc4..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ChangeMessageEvent.java
+++ /dev/null
@@ -1,185 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableMap;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.server.ChangeMessagesUtil;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.sql.Timestamp;
-import java.util.Map;
-import java.util.Optional;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-class ChangeMessageEvent extends Event {
- private static final ImmutableMap<Change.Status, Pattern> STATUS_PATTERNS =
- ImmutableMap.of(
- Change.Status.ABANDONED, Pattern.compile("^Abandoned(\n.*)*$"),
- Change.Status.MERGED,
- Pattern.compile(
- "^Change has been successfully (merged|cherry-picked|rebased|pushed).*$"),
- Change.Status.NEW, Pattern.compile("^Restored(\n.*)*$"));
-
- private static final Pattern PRIVATE_SET_REGEXP = Pattern.compile("^Set private$");
- private static final Pattern PRIVATE_UNSET_REGEXP = Pattern.compile("^Unset private$");
-
- private static final Pattern TOPIC_SET_REGEXP = Pattern.compile("^Topic set to (.+)$");
- private static final Pattern TOPIC_CHANGED_REGEXP =
- Pattern.compile("^Topic changed from (.+) to (.+)$");
- private static final Pattern TOPIC_REMOVED_REGEXP = Pattern.compile("^Topic (.+) removed$");
-
- private static final Pattern WIP_SET_REGEXP = Pattern.compile("^Set Work In Progress$");
- private static final Pattern WIP_UNSET_REGEXP = Pattern.compile("^Set Ready For Review$");
-
- private final Change change;
- private final Change noteDbChange;
- private final Optional<Change.Status> status;
- private final ChangeMessage message;
-
- ChangeMessageEvent(
- Change change, Change noteDbChange, ChangeMessage message, Timestamp changeCreatedOn) {
- super(
- message.getPatchSetId(),
- message.getAuthor(),
- message.getRealAuthor(),
- message.getWrittenOn(),
- changeCreatedOn,
- message.getTag());
- this.change = change;
- this.noteDbChange = noteDbChange;
- this.message = message;
- this.status = parseStatus(message);
- }
-
- @Override
- boolean uniquePerUpdate() {
- return true;
- }
-
- @Override
- protected boolean isSubmit() {
- return status.isPresent() && status.get() == Change.Status.MERGED;
- }
-
- @Override
- protected boolean canHaveTag() {
- return true;
- }
-
- @SuppressWarnings("deprecation")
- @Override
- void apply(ChangeUpdate update) throws OrmException {
- checkUpdate(update);
- update.setChangeMessage(message.getMessage());
- setPrivate(update);
- setTopic(update);
- setWorkInProgress(update);
-
- if (status.isPresent()) {
- Change.Status s = status.get();
- update.fixStatus(s);
- noteDbChange.setStatus(s);
- if (s == Change.Status.MERGED) {
- update.setSubmissionId(change.getSubmissionId());
- noteDbChange.setSubmissionId(change.getSubmissionId());
- }
- }
- }
-
- private static Optional<Change.Status> parseStatus(ChangeMessage message) {
- String msg = message.getMessage();
- if (msg == null) {
- return Optional.empty();
- }
- for (Map.Entry<Change.Status, Pattern> e : STATUS_PATTERNS.entrySet()) {
- if (e.getValue().matcher(msg).matches()) {
- return Optional.of(e.getKey());
- }
- }
- return Optional.empty();
- }
-
- private void setPrivate(ChangeUpdate update) {
- String msg = message.getMessage();
- if (msg == null) {
- return;
- }
- Matcher m = PRIVATE_SET_REGEXP.matcher(msg);
- if (m.matches()) {
- update.setPrivate(true);
- noteDbChange.setPrivate(true);
- return;
- }
-
- m = PRIVATE_UNSET_REGEXP.matcher(msg);
- if (m.matches()) {
- update.setPrivate(false);
- noteDbChange.setPrivate(false);
- }
- }
-
- private void setTopic(ChangeUpdate update) {
- String msg = message.getMessage();
- if (msg == null) {
- return;
- }
- Matcher m = TOPIC_SET_REGEXP.matcher(msg);
- if (m.matches()) {
- String topic = m.group(1);
- update.setTopic(topic);
- noteDbChange.setTopic(topic);
- return;
- }
-
- m = TOPIC_CHANGED_REGEXP.matcher(msg);
- if (m.matches()) {
- String topic = m.group(2);
- update.setTopic(topic);
- noteDbChange.setTopic(topic);
- return;
- }
-
- if (TOPIC_REMOVED_REGEXP.matcher(msg).matches()) {
- update.setTopic(null);
- noteDbChange.setTopic(null);
- }
- }
-
- private void setWorkInProgress(ChangeUpdate update) {
- String msg = Strings.nullToEmpty(message.getMessage());
- String tag = message.getTag();
- if (ChangeMessagesUtil.TAG_SET_WIP.equals(tag)
- || ChangeMessagesUtil.TAG_UPLOADED_WIP_PATCH_SET.equals(tag)
- || WIP_SET_REGEXP.matcher(msg).matches()) {
- update.setWorkInProgress(true);
- noteDbChange.setWorkInProgress(true);
- } else if (ChangeMessagesUtil.TAG_SET_READY.equals(tag)
- || ChangeMessagesUtil.TAG_UPLOADED_PATCH_SET.equals(tag)
- || WIP_UNSET_REGEXP.matcher(msg).matches()) {
- update.setWorkInProgress(false);
- noteDbChange.setWorkInProgress(false);
- }
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("message", message);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilder.java b/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilder.java
deleted file mode 100644
index 8ce9987..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilder.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.Result;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import java.io.IOException;
-
-public abstract class ChangeRebuilder {
- public static class NoPatchSetsException extends OrmException {
- private static final long serialVersionUID = 1L;
-
- NoPatchSetsException(Change.Id changeId) {
- super("Change " + changeId + " cannot be rebuilt because it has no patch sets");
- }
- }
-
- private final SchemaFactory<ReviewDb> schemaFactory;
-
- protected ChangeRebuilder(SchemaFactory<ReviewDb> schemaFactory) {
- this.schemaFactory = schemaFactory;
- }
-
- public final ListenableFuture<Result> rebuildAsync(
- Change.Id id, ListeningExecutorService executor) {
- return executor.submit(
- () -> {
- try (ReviewDb db = schemaFactory.open()) {
- return rebuild(db, id);
- }
- });
- }
-
- /**
- * Rebuild ReviewDb contents by copying from NoteDb.
- *
- * <p>Requires NoteDb to be the primary storage for the change.
- */
- public abstract void rebuildReviewDb(ReviewDb db, Project.NameKey project, Change.Id changeId)
- throws OrmException;
-
- // In the following methods "rebuilding" always refers to copying the state
- // from ReviewDb to NoteDb, i.e. assuming ReviewDb is the primary storage.
-
- public abstract Result rebuild(ReviewDb db, Change.Id changeId) throws IOException, OrmException;
-
- public abstract Result rebuildEvenIfReadOnly(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException;
-
- public abstract Result rebuild(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws IOException, OrmException;
-
- public abstract void buildUpdates(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws IOException, OrmException;
-
- public abstract NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException;
-
- public abstract Result execute(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager)
- throws OrmException, IOException;
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java b/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java
deleted file mode 100644
index 8740710..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ChangeRebuilderImpl.java
+++ /dev/null
@@ -1,687 +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.server.notedb.rebuild;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
-import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_HASHTAGS;
-import static com.google.gerrit.server.notedb.ChangeNoteUtil.FOOTER_PATCH_SET;
-import static java.util.Objects.requireNonNull;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.base.Splitter;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableCollection;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.Lists;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.Sets;
-import com.google.common.collect.Table;
-import com.google.common.primitives.Ints;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchLineComment.Status;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeDraftUpdate;
-import com.google.gerrit.server.notedb.ChangeNoteUtil;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.OpenRepo;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.Result;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.notedb.ReviewerStateInternal;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.project.ProjectCache;
-import com.google.gerrit.server.update.ChainedReceiveCommands;
-import com.google.gwtorm.client.Key;
-import com.google.gwtorm.server.Access;
-import com.google.gwtorm.server.AtomicUpdate;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Optional;
-import java.util.Set;
-import java.util.TreeMap;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-public class ChangeRebuilderImpl extends ChangeRebuilder {
- /**
- * The maximum amount of time between the ReviewDb timestamp of the first and last events batched
- * together into a single NoteDb update.
- *
- * <p>Used to account for the fact that different records with their own timestamps (e.g. {@link
- * PatchSetApproval} and {@link ChangeMessage}) historically didn't necessarily use the same
- * timestamp, and tended to call {@code System.currentTimeMillis()} independently.
- */
- public static final long MAX_WINDOW_MS = SECONDS.toMillis(3);
-
- /**
- * The maximum amount of time between two consecutive events to consider them to be in the same
- * batch.
- */
- static final long MAX_DELTA_MS = SECONDS.toMillis(1);
-
- private final ChangeBundleReader bundleReader;
- private final ChangeDraftUpdate.Factory draftUpdateFactory;
- private final ChangeNoteUtil changeNoteUtil;
- private final ChangeNotes.Factory notesFactory;
- private final ChangeUpdate.Factory updateFactory;
- private final CommentsUtil commentsUtil;
- private final NoteDbUpdateManager.Factory updateManagerFactory;
- private final NotesMigration migration;
- private final PatchListCache patchListCache;
- private final PersonIdent serverIdent;
- private final ProjectCache projectCache;
- private final String serverId;
- private final long skewMs;
-
- @Inject
- ChangeRebuilderImpl(
- @GerritServerConfig Config cfg,
- SchemaFactory<ReviewDb> schemaFactory,
- ChangeBundleReader bundleReader,
- ChangeDraftUpdate.Factory draftUpdateFactory,
- ChangeNoteUtil changeNoteUtil,
- ChangeNotes.Factory notesFactory,
- ChangeUpdate.Factory updateFactory,
- CommentsUtil commentsUtil,
- NoteDbUpdateManager.Factory updateManagerFactory,
- NotesMigration migration,
- PatchListCache patchListCache,
- @GerritPersonIdent PersonIdent serverIdent,
- @Nullable ProjectCache projectCache,
- @GerritServerId String serverId) {
- super(schemaFactory);
- this.bundleReader = bundleReader;
- this.draftUpdateFactory = draftUpdateFactory;
- this.changeNoteUtil = changeNoteUtil;
- this.notesFactory = notesFactory;
- this.updateFactory = updateFactory;
- this.commentsUtil = commentsUtil;
- this.updateManagerFactory = updateManagerFactory;
- this.migration = migration;
- this.patchListCache = patchListCache;
- this.serverIdent = serverIdent;
- this.projectCache = projectCache;
- this.serverId = serverId;
- this.skewMs = NoteDbChangeState.getReadOnlySkew(cfg);
- }
-
- @Override
- public Result rebuild(ReviewDb db, Change.Id changeId) throws IOException, OrmException {
- return rebuild(db, changeId, true);
- }
-
- @Override
- public Result rebuildEvenIfReadOnly(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException {
- return rebuild(db, changeId, false);
- }
-
- private Result rebuild(ReviewDb db, Change.Id changeId, boolean checkReadOnly)
- throws IOException, OrmException {
- db = ReviewDbUtil.unwrapDb(db);
- // Read change just to get project; this instance is then discarded so we can read a consistent
- // ChangeBundle inside a transaction.
- Change change = db.changes().get(changeId);
- if (change == null) {
- throw new NoSuchChangeException(changeId);
- }
- try (NoteDbUpdateManager manager = updateManagerFactory.create(change.getProject())) {
- buildUpdates(manager, bundleReader.fromReviewDb(db, changeId));
- return execute(db, changeId, manager, checkReadOnly, true);
- }
- }
-
- @Override
- public Result rebuild(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws NoSuchChangeException, IOException, OrmException {
- Change change = new Change(bundle.getChange());
- buildUpdates(manager, bundle);
- return manager.stageAndApplyDelta(change);
- }
-
- @Override
- public NoteDbUpdateManager stage(ReviewDb db, Change.Id changeId)
- throws IOException, OrmException {
- db = ReviewDbUtil.unwrapDb(db);
- Change change = checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
- if (change == null) {
- throw new NoSuchChangeException(changeId);
- }
- NoteDbUpdateManager manager = updateManagerFactory.create(change.getProject());
- buildUpdates(manager, bundleReader.fromReviewDb(db, changeId));
- manager.stage();
- return manager;
- }
-
- @Override
- public Result execute(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager)
- throws OrmException, IOException {
- return execute(db, changeId, manager, true, true);
- }
-
- public Result execute(
- ReviewDb db,
- Change.Id changeId,
- NoteDbUpdateManager manager,
- boolean checkReadOnly,
- boolean executeManager)
- throws OrmException, IOException {
- db = ReviewDbUtil.unwrapDb(db);
- Change change = checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
- if (change == null) {
- throw new NoSuchChangeException(changeId);
- }
-
- String oldNoteDbStateStr = change.getNoteDbState();
- Result r = manager.stageAndApplyDelta(change);
- String newNoteDbStateStr = change.getNoteDbState();
- if (newNoteDbStateStr == null) {
- throw new OrmException(
- String.format(
- "Rebuilding change %s produced no writes to NoteDb: %s",
- changeId, bundleReader.fromReviewDb(db, changeId)));
- }
- NoteDbChangeState newNoteDbState =
- requireNonNull(NoteDbChangeState.parse(changeId, newNoteDbStateStr));
- try {
- db.changes()
- .atomicUpdate(
- changeId,
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- if (checkReadOnly) {
- NoteDbChangeState.checkNotReadOnly(change, skewMs);
- }
- String currNoteDbStateStr = change.getNoteDbState();
- if (Objects.equals(currNoteDbStateStr, newNoteDbStateStr)) {
- // Another thread completed the same rebuild we were about to.
- throw new AbortUpdateException();
- } else if (!Objects.equals(oldNoteDbStateStr, currNoteDbStateStr)) {
- // Another thread updated the state to something else.
- throw new ConflictingUpdateRuntimeException(change, oldNoteDbStateStr);
- }
- change.setNoteDbState(newNoteDbStateStr);
- return change;
- }
- });
- } catch (ConflictingUpdateRuntimeException e) {
- // Rethrow as an OrmException so the caller knows to use staged results. Strictly speaking
- // they are not completely up to date, but result we send to the caller is the same as if this
- // rebuild had executed before the other thread.
- throw new ConflictingUpdateException(e);
- } catch (AbortUpdateException e) {
- if (newNoteDbState.isUpToDate(
- manager.getChangeRepo().cmds.getRepoRefCache(),
- manager.getAllUsersRepo().cmds.getRepoRefCache())) {
- // If the state in ReviewDb matches NoteDb at this point, it means another thread
- // successfully completed this rebuild. It's ok to not execute the update in this case,
- // since the object referenced in the Result was flushed to the repo by whatever thread won
- // the race.
- return r;
- }
- // If the state doesn't match, that means another thread attempted this rebuild, but
- // failed. Fall through and try to update the ref again.
- }
- if (migration.failChangeWrites()) {
- // Don't even attempt to execute if read-only, it would fail anyway. But do throw an exception
- // to the caller so they know to use the staged results instead of reading from the repo.
- throw new OrmException(NoteDbUpdateManager.CHANGES_READ_ONLY);
- }
- if (executeManager) {
- manager.execute();
- }
- return r;
- }
-
- static Change checkNoteDbState(Change c) throws OrmException {
- // Can only rebuild a change if its primary storage is ReviewDb.
- NoteDbChangeState s = NoteDbChangeState.parse(c);
- if (s != null && s.getPrimaryStorage() != PrimaryStorage.REVIEW_DB) {
- throw new OrmException(String.format("cannot rebuild change %s with state %s", c.getId(), s));
- }
- return c;
- }
-
- @Override
- public void buildUpdates(NoteDbUpdateManager manager, ChangeBundle bundle)
- throws IOException, OrmException {
- manager.setCheckExpectedState(false).setRefLogMessage("Rebuilding change");
- Change change = new Change(bundle.getChange());
- if (bundle.getPatchSets().isEmpty()) {
- throw new NoPatchSetsException(change.getId());
- }
- if (change.getLastUpdatedOn().compareTo(change.getCreatedOn()) < 0) {
- // A bug in data migration might set created_on to the time of the migration. The
- // correct timestamps were lost, but we can at least set it so created_on is not after
- // last_updated_on.
- // See https://bugs.chromium.org/p/gerrit/issues/detail?id=7397
- change.setCreatedOn(change.getLastUpdatedOn());
- }
-
- // We will rebuild all events, except for draft comments, in buckets based on author and
- // timestamp.
- List<Event> events = new ArrayList<>();
- ListMultimap<Account.Id, DraftCommentEvent> draftCommentEvents =
- MultimapBuilder.hashKeys().arrayListValues().build();
-
- events.addAll(getHashtagsEvents(change, manager));
-
- // Delete ref only after hashtags have been read.
- deleteChangeMetaRef(change, manager.getChangeRepo().cmds);
- deleteDraftRefs(change, manager.getAllUsersRepo());
-
- Integer minPsNum = getMinPatchSetNum(bundle);
- TreeMap<PatchSet.Id, PatchSetEvent> patchSetEvents =
- new TreeMap<>(ReviewDbUtil.intKeyOrdering());
-
- for (PatchSet ps : bundle.getPatchSets()) {
- PatchSetEvent pse = new PatchSetEvent(change, ps, manager.getChangeRepo().rw);
- patchSetEvents.put(ps.getId(), pse);
- events.add(pse);
- for (Comment c : getComments(bundle, serverId, Status.PUBLISHED, ps)) {
- CommentEvent e = new CommentEvent(c, change, ps, patchListCache);
- events.add(e.addDep(pse));
- }
- for (Comment c : getComments(bundle, serverId, Status.DRAFT, ps)) {
- DraftCommentEvent e = new DraftCommentEvent(c, change, ps, patchListCache);
- draftCommentEvents.put(c.author.getId(), e);
- }
- }
- ensurePatchSetOrder(patchSetEvents);
-
- for (PatchSetApproval psa : bundle.getPatchSetApprovals()) {
- PatchSetEvent pse = patchSetEvents.get(psa.getPatchSetId());
- if (pse != null) {
- events.add(new ApprovalEvent(psa, change.getCreatedOn()).addDep(pse));
- }
- }
-
- for (Table.Cell<ReviewerStateInternal, Account.Id, Timestamp> r :
- bundle.getReviewers().asTable().cellSet()) {
- events.add(new ReviewerEvent(r, change.getCreatedOn()));
- }
-
- Change noteDbChange = new Change(null, null, null, null, null);
- for (ChangeMessage msg : bundle.getChangeMessages()) {
- Event msgEvent = new ChangeMessageEvent(change, noteDbChange, msg, change.getCreatedOn());
- if (msg.getPatchSetId() != null) {
- PatchSetEvent pse = patchSetEvents.get(msg.getPatchSetId());
- if (pse == null) {
- continue; // Ignore events for missing patch sets.
- }
- msgEvent.addDep(pse);
- }
- events.add(msgEvent);
- }
-
- sortAndFillEvents(change, noteDbChange, bundle.getPatchSets(), events, minPsNum);
-
- EventList<Event> el = new EventList<>();
- for (Event e : events) {
- if (!el.canAdd(e)) {
- flushEventsToUpdate(manager, el, change);
- checkState(el.canAdd(e));
- }
- el.add(e);
- }
- flushEventsToUpdate(manager, el, change);
-
- EventList<DraftCommentEvent> plcel = new EventList<>();
- for (Account.Id author : draftCommentEvents.keys()) {
- for (DraftCommentEvent e : Ordering.natural().sortedCopy(draftCommentEvents.get(author))) {
- if (!plcel.canAdd(e)) {
- flushEventsToDraftUpdate(manager, plcel, change);
- checkState(plcel.canAdd(e));
- }
- plcel.add(e);
- }
- flushEventsToDraftUpdate(manager, plcel, change);
- }
- }
-
- private static Integer getMinPatchSetNum(ChangeBundle bundle) {
- Integer minPsNum = null;
- for (PatchSet ps : bundle.getPatchSets()) {
- int n = ps.getId().get();
- if (minPsNum == null || n < minPsNum) {
- minPsNum = n;
- }
- }
- return minPsNum;
- }
-
- private static void ensurePatchSetOrder(TreeMap<PatchSet.Id, PatchSetEvent> events) {
- if (events.isEmpty()) {
- return;
- }
- Iterator<PatchSetEvent> it = events.values().iterator();
- PatchSetEvent curr = it.next();
- while (it.hasNext()) {
- PatchSetEvent next = it.next();
- next.addDep(curr);
- curr = next;
- }
- }
-
- private static List<Comment> getComments(
- ChangeBundle bundle, String serverId, PatchLineComment.Status status, PatchSet ps) {
- return bundle
- .getPatchLineComments()
- .stream()
- .filter(c -> c.getPatchSetId().equals(ps.getId()) && c.getStatus() == status)
- .map(plc -> plc.asComment(serverId))
- .sorted(CommentsUtil.COMMENT_ORDER)
- .collect(toList());
- }
-
- private void sortAndFillEvents(
- Change change,
- Change noteDbChange,
- ImmutableCollection<PatchSet> patchSets,
- List<Event> events,
- Integer minPsNum) {
- Event finalUpdates = new FinalUpdatesEvent(change, noteDbChange, patchSets);
- events.add(finalUpdates);
- setPostSubmitDeps(events);
- new EventSorter(events).sort();
-
- // Ensure the first event in the list creates the change, setting the author and any required
- // footers. Also force the creation time of the first patch set to match the creation time of
- // the change.
- Event first = events.get(0);
- if (first instanceof PatchSetEvent && change.getOwner().equals(first.user)) {
- first.when = change.getCreatedOn();
- ((PatchSetEvent) first).createChange = true;
- } else {
- events.add(0, new CreateChangeEvent(change, minPsNum));
- }
-
- // Final pass to correct some inconsistencies.
- //
- // First, fill in any missing patch set IDs using the latest patch set of the change at the time
- // of the event, because NoteDb can't represent actions with no associated patch set ID. This
- // workaround is as if a user added a ChangeMessage on the change by replying from the latest
- // patch set.
- //
- // Start with the first patch set that actually exists. If there are no patch sets at all,
- // minPsNum will be null, so just bail and use 1 as the patch set ID.
- //
- // Second, ensure timestamps are nondecreasing, by copying the previous timestamp if this
- // happens. This assumes that the only way this can happen is due to dependency constraints, and
- // it is ok to give an event the same timestamp as one of its dependencies.
- int ps = firstNonNull(minPsNum, 1);
- for (int i = 0; i < events.size(); i++) {
- Event e = events.get(i);
- if (e.psId == null) {
- e.psId = new PatchSet.Id(change.getId(), ps);
- } else {
- ps = Math.max(ps, e.psId.get());
- }
-
- if (i > 0) {
- Event p = events.get(i - 1);
- if (e.when.before(p.when)) {
- e.when = p.when;
- }
- }
- }
- }
-
- private void setPostSubmitDeps(List<Event> events) {
- Optional<Event> submitEvent =
- Lists.reverse(events).stream().filter(Event::isSubmit).findFirst();
- if (submitEvent.isPresent()) {
- events.stream().filter(Event::isPostSubmitApproval).forEach(e -> e.addDep(submitEvent.get()));
- }
- }
-
- private void flushEventsToUpdate(
- NoteDbUpdateManager manager, EventList<Event> events, Change change)
- throws OrmException, IOException {
- if (events.isEmpty()) {
- return;
- }
- Comparator<String> labelNameComparator;
- if (projectCache != null) {
- labelNameComparator = projectCache.get(change.getProject()).getLabelTypes().nameComparator();
- } else {
- // No project cache available, bail and use natural ordering; there's no semantic difference
- // anyway difference.
- labelNameComparator = Ordering.natural();
- }
- ChangeUpdate update =
- updateFactory.create(
- change,
- events.getAccountId(),
- events.getRealAccountId(),
- newAuthorIdent(events),
- events.getWhen(),
- labelNameComparator);
- update.setAllowWriteToNewRef(true);
- update.setPatchSetId(events.getPatchSetId());
- update.setTag(events.getTag());
- for (Event e : events) {
- e.apply(update);
- }
- manager.add(update);
- events.clear();
- }
-
- private void flushEventsToDraftUpdate(
- NoteDbUpdateManager manager, EventList<DraftCommentEvent> events, Change change) {
- if (events.isEmpty()) {
- return;
- }
- ChangeDraftUpdate update =
- draftUpdateFactory.create(
- change,
- events.getAccountId(),
- events.getRealAccountId(),
- newAuthorIdent(events),
- events.getWhen());
- update.setPatchSetId(events.getPatchSetId());
- for (DraftCommentEvent e : events) {
- e.applyDraft(update);
- }
- manager.add(update);
- events.clear();
- }
-
- private PersonIdent newAuthorIdent(EventList<?> events) {
- Account.Id id = events.getAccountId();
- if (id == null) {
- return new PersonIdent(serverIdent, events.getWhen());
- }
- return changeNoteUtil.newIdent(id, events.getWhen(), serverIdent);
- }
-
- private List<HashtagsEvent> getHashtagsEvents(Change change, NoteDbUpdateManager manager)
- throws IOException {
- String refName = changeMetaRef(change.getId());
- Optional<ObjectId> old = manager.getChangeRepo().getObjectId(refName);
- if (!old.isPresent()) {
- return Collections.emptyList();
- }
-
- RevWalk rw = manager.getChangeRepo().rw;
- List<HashtagsEvent> events = new ArrayList<>();
- rw.reset();
- rw.markStart(rw.parseCommit(old.get()));
- for (RevCommit commit : rw) {
- Account.Id authorId;
- try {
- authorId =
- changeNoteUtil
- .getLegacyChangeNoteRead()
- .parseIdent(commit.getAuthorIdent(), change.getId());
- } catch (ConfigInvalidException e) {
- continue; // Corrupt data, no valid hashtags in this commit.
- }
- PatchSet.Id psId = parsePatchSetId(change, commit);
- Set<String> hashtags = parseHashtags(commit);
- if (authorId == null || psId == null || hashtags == null) {
- continue;
- }
-
- Timestamp commitTime = new Timestamp(commit.getCommitterIdent().getWhen().getTime());
- events.add(new HashtagsEvent(psId, authorId, commitTime, hashtags, change.getCreatedOn()));
- }
- return events;
- }
-
- private Set<String> parseHashtags(RevCommit commit) {
- List<String> hashtagsLines = commit.getFooterLines(FOOTER_HASHTAGS);
- if (hashtagsLines.isEmpty() || hashtagsLines.size() > 1) {
- return null;
- }
-
- if (hashtagsLines.get(0).isEmpty()) {
- return ImmutableSet.of();
- }
- return Sets.newHashSet(Splitter.on(',').split(hashtagsLines.get(0)));
- }
-
- private PatchSet.Id parsePatchSetId(Change change, RevCommit commit) {
- List<String> psIdLines = commit.getFooterLines(FOOTER_PATCH_SET);
- if (psIdLines.size() != 1) {
- return null;
- }
- Integer psId = Ints.tryParse(psIdLines.get(0));
- if (psId == null) {
- return null;
- }
- return new PatchSet.Id(change.getId(), psId);
- }
-
- private void deleteChangeMetaRef(Change change, ChainedReceiveCommands cmds) throws IOException {
- String refName = changeMetaRef(change.getId());
- Optional<ObjectId> old = cmds.get(refName);
- if (old.isPresent()) {
- cmds.add(new ReceiveCommand(old.get(), ObjectId.zeroId(), refName));
- }
- }
-
- private void deleteDraftRefs(Change change, OpenRepo allUsersRepo) throws IOException {
- for (Ref r :
- allUsersRepo
- .repo
- .getRefDatabase()
- .getRefsByPrefix(RefNames.refsDraftCommentsPrefix(change.getId()))) {
- allUsersRepo.cmds.add(new ReceiveCommand(r.getObjectId(), ObjectId.zeroId(), r.getName()));
- }
- }
-
- static void createChange(ChangeUpdate update, Change change) {
- update.setSubjectForCommit("Create change");
- update.setChangeId(change.getKey().get());
- update.setBranch(change.getDest().get());
- update.setSubject(change.getOriginalSubject());
- if (change.getRevertOf() != null) {
- update.setRevertOf(change.getRevertOf().get());
- }
- }
-
- @Override
- public void rebuildReviewDb(ReviewDb db, Project.NameKey project, Change.Id changeId)
- throws OrmException {
- // TODO(dborowitz): Fail fast if changes tables are disabled in ReviewDb.
- ChangeNotes notes = notesFactory.create(db, project, changeId);
- ChangeBundle bundle = ChangeBundle.fromNotes(commentsUtil, notes);
-
- db = ReviewDbUtil.unwrapDb(db);
- db.changes().beginTransaction(changeId);
- try {
- Change c = db.changes().get(changeId);
- if (c != null) {
- PrimaryStorage ps = PrimaryStorage.of(c);
- switch (ps) {
- case REVIEW_DB:
- return; // Nothing to do.
- case NOTE_DB:
- break; // Continue and rebuild.
- default:
- throw new OrmException("primary storage of " + changeId + " is " + ps);
- }
- } else {
- c = notes.getChange();
- }
- db.changes().upsert(Collections.singleton(c));
- putExactlyEntities(
- db.changeMessages(), db.changeMessages().byChange(c.getId()), bundle.getChangeMessages());
- putExactlyEntities(db.patchSets(), db.patchSets().byChange(c.getId()), bundle.getPatchSets());
- putExactlyEntities(
- db.patchSetApprovals(),
- db.patchSetApprovals().byChange(c.getId()),
- bundle.getPatchSetApprovals());
- putExactlyEntities(
- db.patchComments(),
- db.patchComments().byChange(c.getId()),
- bundle.getPatchLineComments());
- db.commit();
- } finally {
- db.rollback();
- }
- }
-
- private static <T, K extends Key<?>> void putExactlyEntities(
- Access<T, K> access, Iterable<T> existing, Collection<T> ents) throws OrmException {
- Set<K> toKeep = access.toMap(ents).keySet();
- access.delete(
- FluentIterable.from(existing).filter(e -> !toKeep.contains(access.primaryKey(e))));
- access.upsert(ents);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/CommentEvent.java b/java/com/google/gerrit/server/notedb/rebuild/CommentEvent.java
deleted file mode 100644
index 8f7b387..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/CommentEvent.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.gerrit.server.CommentsUtil.setCommentRevId;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-
-class CommentEvent extends Event {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- public final Comment c;
- private final Change change;
- private final PatchSet ps;
- private final PatchListCache cache;
-
- CommentEvent(Comment c, Change change, PatchSet ps, PatchListCache cache) {
- super(
- CommentsUtil.getCommentPsId(change.getId(), c),
- c.author.getId(),
- c.getRealAuthor().getId(),
- c.writtenOn,
- change.getCreatedOn(),
- c.tag);
- this.c = c;
- this.change = change;
- this.ps = ps;
- this.cache = cache;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return false;
- }
-
- @Override
- protected boolean canHaveTag() {
- return true;
- }
-
- @Override
- void apply(ChangeUpdate update) {
- checkUpdate(update);
- if (c.revId == null) {
- try {
- setCommentRevId(c, cache, change, ps);
- } catch (PatchListNotAvailableException e) {
- logger.atWarning().log(
- "Unable to determine parent commit of patch set %s (%s); omitting inline comment %s",
- ps.getId(), ps.getRevision(), c);
- return;
- }
- }
- update.putComment(PatchLineComment.Status.PUBLISHED, c);
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("message", c.message);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateException.java b/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateException.java
deleted file mode 100644
index d8e7480..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateException.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// Copyright (C) 2017 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.notedb.rebuild;
-
-import com.google.gwtorm.server.OrmException;
-
-/**
- * {@link com.google.gwtorm.server.OrmException} thrown by {@link ChangeRebuilder} when rebuilding a
- * change failed because another operation modified its {@link
- * com.google.gerrit.server.notedb.NoteDbChangeState}.
- */
-public class ConflictingUpdateException extends OrmException {
- private static final long serialVersionUID = 1L;
-
- // Always created from a ConflictingUpdateRuntimeException because it originates from an
- // AtomicUpdate, which cannot throw checked exceptions.
- ConflictingUpdateException(ConflictingUpdateRuntimeException cause) {
- super(cause.getMessage(), cause);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateRuntimeException.java b/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateRuntimeException.java
deleted file mode 100644
index abfafa2..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ConflictingUpdateRuntimeException.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gwtorm.server.OrmRuntimeException;
-
-class ConflictingUpdateRuntimeException extends OrmRuntimeException {
- private static final long serialVersionUID = 1L;
-
- ConflictingUpdateRuntimeException(Change change, String expectedNoteDbState) {
- super(
- String.format(
- "Expected change %s to have noteDbState %s but was %s",
- change.getId(), expectedNoteDbState, change.getNoteDbState()));
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/CreateChangeEvent.java b/java/com/google/gerrit/server/notedb/rebuild/CreateChangeEvent.java
deleted file mode 100644
index d01071b..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/CreateChangeEvent.java
+++ /dev/null
@@ -1,59 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.io.IOException;
-
-class CreateChangeEvent extends Event {
- private final Change change;
-
- private static PatchSet.Id psId(Change change, Integer minPsNum) {
- int n;
- if (minPsNum == null) {
- // There were no patch sets for the change at all, so something is very
- // wrong. Bail and use 1 as the patch set.
- n = 1;
- } else {
- n = minPsNum;
- }
- return new PatchSet.Id(change.getId(), n);
- }
-
- CreateChangeEvent(Change change, Integer minPsNum) {
- super(
- psId(change, minPsNum),
- change.getOwner(),
- change.getOwner(),
- change.getCreatedOn(),
- change.getCreatedOn(),
- null);
- this.change = change;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return true;
- }
-
- @Override
- void apply(ChangeUpdate update) throws IOException, OrmException {
- checkUpdate(update);
- ChangeRebuilderImpl.createChange(update, change);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/DraftCommentEvent.java b/java/com/google/gerrit/server/notedb/rebuild/DraftCommentEvent.java
deleted file mode 100644
index 2a2795d..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/DraftCommentEvent.java
+++ /dev/null
@@ -1,81 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.gerrit.server.CommentsUtil.setCommentRevId;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.notedb.ChangeDraftUpdate;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-
-class DraftCommentEvent extends Event {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- public final Comment c;
- private final Change change;
- private final PatchSet ps;
- private final PatchListCache cache;
-
- DraftCommentEvent(Comment c, Change change, PatchSet ps, PatchListCache cache) {
- super(
- CommentsUtil.getCommentPsId(change.getId(), c),
- c.author.getId(),
- c.getRealAuthor().getId(),
- c.writtenOn,
- change.getCreatedOn(),
- c.tag);
- this.c = c;
- this.change = change;
- this.ps = ps;
- this.cache = cache;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return false;
- }
-
- @Override
- void apply(ChangeUpdate update) {
- throw new UnsupportedOperationException();
- }
-
- void applyDraft(ChangeDraftUpdate draftUpdate) {
- if (c.revId == null) {
- try {
- setCommentRevId(c, cache, change, ps);
- } catch (PatchListNotAvailableException e) {
- logger.atWarning().log(
- "Unable to determine parent commit of patch set %s (%s);"
- + " omitting draft inline comment %s",
- ps.getId(), ps.getRevision(), c);
- return;
- }
- }
- draftUpdate.putComment(c);
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("message", c.message);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/Event.java b/java/com/google/gerrit/server/notedb/rebuild/Event.java
deleted file mode 100644
index 3957c5c..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/Event.java
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl.MAX_WINDOW_MS;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.collect.ComparisonChain;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.notedb.AbstractChangeUpdate;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Objects;
-
-abstract class Event implements Comparable<Event> {
- // NOTE: EventList only supports direct subclasses, not an arbitrary
- // hierarchy.
-
- final Account.Id user;
- final Account.Id realUser;
- final String tag;
- final boolean predatesChange;
-
- /** Dependencies of this event; other events that must happen before this one. */
- final List<Event> deps;
-
- Timestamp when;
- PatchSet.Id psId;
-
- protected Event(
- PatchSet.Id psId,
- Account.Id effectiveUser,
- Account.Id realUser,
- Timestamp when,
- Timestamp changeCreatedOn,
- String tag) {
- this.psId = psId;
- this.user = effectiveUser;
- this.realUser = realUser != null ? realUser : effectiveUser;
- this.tag = tag;
- // Truncate timestamps at the change's createdOn timestamp.
- predatesChange = when.before(changeCreatedOn);
- this.when = predatesChange ? changeCreatedOn : when;
- deps = new ArrayList<>();
- }
-
- protected void checkUpdate(AbstractChangeUpdate update) {
- checkState(
- Objects.equals(update.getPatchSetId(), psId),
- "cannot apply event for %s to update for %s",
- update.getPatchSetId(),
- psId);
- checkState(
- when.getTime() - update.getWhen().getTime() <= MAX_WINDOW_MS,
- "event at %s outside update window starting at %s",
- when,
- update.getWhen());
- checkState(
- Objects.equals(update.getNullableAccountId(), user),
- "cannot apply event by %s to update by %s",
- user,
- update.getNullableAccountId());
- }
-
- Event addDep(Event e) {
- deps.add(e);
- return this;
- }
-
- /**
- * @return whether this event type must be unique per {@link ChangeUpdate}, i.e. there may be at
- * most one of this type.
- */
- abstract boolean uniquePerUpdate();
-
- abstract void apply(ChangeUpdate update) throws OrmException, IOException;
-
- protected boolean isPostSubmitApproval() {
- return false;
- }
-
- protected boolean isSubmit() {
- return false;
- }
-
- protected boolean canHaveTag() {
- return false;
- }
-
- @Override
- public String toString() {
- ToStringHelper helper =
- MoreObjects.toStringHelper(this)
- .add("psId", psId)
- .add("effectiveUser", user)
- .add("realUser", realUser)
- .add("when", when)
- .add("tag", tag);
- addToString(helper);
- return helper.toString();
- }
-
- /** @param helper toString helper to add fields to */
- protected void addToString(ToStringHelper helper) {}
-
- @Override
- public int compareTo(Event other) {
- return ComparisonChain.start()
- .compareFalseFirst(this.isFinalUpdates(), other.isFinalUpdates())
- .compare(this.when, other.when)
- .compareTrueFirst(isPatchSet(), isPatchSet())
- .compareTrueFirst(this.predatesChange, other.predatesChange)
- .compare(this.user, other.user, ReviewDbUtil.intKeyOrdering())
- .compare(this.realUser, other.realUser, ReviewDbUtil.intKeyOrdering())
- .compare(this.psId, other.psId, ReviewDbUtil.intKeyOrdering().nullsLast())
- .result();
- }
-
- private boolean isPatchSet() {
- return this instanceof PatchSetEvent;
- }
-
- private boolean isFinalUpdates() {
- return this instanceof FinalUpdatesEvent;
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/EventList.java b/java/com/google/gerrit/server/notedb/rebuild/EventList.java
deleted file mode 100644
index e83814d..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/EventList.java
+++ /dev/null
@@ -1,170 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.collect.Lists;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.Objects;
-
-class EventList<E extends Event> implements Iterable<E> {
- private final ArrayList<E> list = new ArrayList<>();
- private boolean isSubmit;
-
- @Override
- public Iterator<E> iterator() {
- return list.iterator();
- }
-
- void add(E e) {
- list.add(e);
- if (e.isSubmit()) {
- isSubmit = true;
- }
- }
-
- void clear() {
- list.clear();
- isSubmit = false;
- }
-
- boolean isEmpty() {
- return list.isEmpty();
- }
-
- boolean canAdd(E e) {
- if (isEmpty()) {
- return true;
- }
- if (e instanceof FinalUpdatesEvent) {
- return false; // FinalUpdatesEvent always gets its own update.
- }
-
- Event last = getLast();
- if (!Objects.equals(e.user, last.user)
- || !Objects.equals(e.realUser, last.realUser)
- || !e.psId.equals(last.psId)) {
- return false; // Different patch set or author.
- }
- if (e.canHaveTag() && canHaveTag() && !Objects.equals(e.tag, getTag())) {
- // We should trust the tag field, and it doesn't match.
- return false;
- }
- if (e.isPostSubmitApproval() && isSubmit) {
- // Post-submit approvals must come after the update that submits.
- return false;
- }
-
- long t = e.when.getTime();
- long tFirst = getFirstTime();
- long tLast = getLastTime();
- checkArgument(t >= tLast, "event %s is before previous event in list %s", e, last);
- if (t - tLast > ChangeRebuilderImpl.MAX_DELTA_MS
- || t - tFirst > ChangeRebuilderImpl.MAX_WINDOW_MS) {
- return false; // Too much time elapsed.
- }
-
- if (!e.uniquePerUpdate()) {
- return true;
- }
- for (Event o : this) {
- if (e.getClass() == o.getClass()) {
- return false; // Only one event of this type allowed per update.
- }
- }
-
- // TODO(dborowitz): Additional heuristics, like keeping events separate if
- // they affect overlapping fields within a single entity.
-
- return true;
- }
-
- Timestamp getWhen() {
- return get(0).when;
- }
-
- PatchSet.Id getPatchSetId() {
- PatchSet.Id id = requireNonNull(get(0).psId);
- for (int i = 1; i < size(); i++) {
- checkState(
- get(i).psId.equals(id), "mismatched patch sets in EventList: %s != %s", id, get(i).psId);
- }
- return id;
- }
-
- Account.Id getAccountId() {
- Account.Id id = get(0).user;
- for (int i = 1; i < size(); i++) {
- checkState(
- Objects.equals(id, get(i).user),
- "mismatched users in EventList: %s != %s",
- id,
- get(i).user);
- }
- return id;
- }
-
- Account.Id getRealAccountId() {
- Account.Id id = get(0).realUser;
- for (int i = 1; i < size(); i++) {
- checkState(
- Objects.equals(id, get(i).realUser),
- "mismatched real users in EventList: %s != %s",
- id,
- get(i).realUser);
- }
- return id;
- }
-
- String getTag() {
- for (E e : Lists.reverse(list)) {
- if (e.tag != null) {
- return e.tag;
- }
- }
- return null;
- }
-
- private boolean canHaveTag() {
- return list.stream().anyMatch(Event::canHaveTag);
- }
-
- private E get(int i) {
- return list.get(i);
- }
-
- private int size() {
- return list.size();
- }
-
- private E getLast() {
- return list.get(list.size() - 1);
- }
-
- private long getLastTime() {
- return getLast().when.getTime();
- }
-
- private long getFirstTime() {
- return list.get(0).when.getTime();
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/EventSorter.java b/java/com/google/gerrit/server/notedb/rebuild/EventSorter.java
deleted file mode 100644
index 077a027..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/EventSorter.java
+++ /dev/null
@@ -1,112 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.SetMultimap;
-import java.util.Collections;
-import java.util.LinkedHashSet;
-import java.util.List;
-import java.util.PriorityQueue;
-
-/**
- * Helper to sort a list of events.
- *
- * <p>Events are sorted in two passes:
- *
- * <ol>
- * <li>Sort by natural order (timestamp, patch set, author, etc.)
- * <li>Postpone any events with dependencies to occur only after all of their dependencies, where
- * this violates natural order.
- * </ol>
- *
- * {@link #sort()} modifies the event list in place (similar to {@link Collections#sort(List)}), but
- * does not modify any event. In particular, events might end up out of order with respect to
- * timestamp; callers are responsible for adjusting timestamps later if they prefer monotonicity.
- */
-class EventSorter {
- private final List<Event> out;
- private final LinkedHashSet<Event> sorted;
- private ListMultimap<Event, Event> waiting;
- private SetMultimap<Event, Event> deps;
-
- EventSorter(List<Event> events) {
- LinkedHashSet<Event> all = new LinkedHashSet<>(events);
- out = events;
-
- for (Event e : events) {
- for (Event d : e.deps) {
- checkArgument(all.contains(d), "dep %s of %s not in input list", d, e);
- }
- }
-
- all.clear();
- sorted = all; // Presized.
- }
-
- void sort() {
- // First pass: sort by natural order.
- PriorityQueue<Event> todo = new PriorityQueue<>(out);
-
- // Populate waiting map after initial sort to preserve natural order.
- waiting = MultimapBuilder.hashKeys().arrayListValues().build();
- deps = MultimapBuilder.hashKeys().hashSetValues().build();
- for (Event e : todo) {
- for (Event d : e.deps) {
- deps.put(e, d);
- waiting.put(d, e);
- }
- }
-
- // Second pass: enforce dependencies.
- int size = out.size();
- while (!todo.isEmpty()) {
- process(todo.remove(), todo);
- }
- checkState(
- sorted.size() == size, "event sort expected %s elements, got %s", size, sorted.size());
-
- // Modify out in-place a la Collections#sort.
- out.clear();
- out.addAll(sorted);
- }
-
- void process(Event e, PriorityQueue<Event> todo) {
- if (sorted.contains(e)) {
- return; // Already emitted.
- }
- if (!deps.get(e).isEmpty()) {
- // Not all events that e depends on have been emitted yet. Ignore e for
- // now; it will get added back to the queue in the block below once its
- // last dependency is processed.
- return;
- }
-
- // All events that e depends on have been emitted, so e can be emitted.
- sorted.add(e);
-
- // Remove e from the dependency set of all events waiting on e, and add
- // those events back to the queue in the original priority order for
- // reconsideration.
- for (Event w : waiting.get(e)) {
- deps.get(w).remove(e);
- todo.add(w);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/FinalUpdatesEvent.java b/java/com/google/gerrit/server/notedb/rebuild/FinalUpdatesEvent.java
deleted file mode 100644
index 55d5a31..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/FinalUpdatesEvent.java
+++ /dev/null
@@ -1,101 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.intKeyOrdering;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.collect.ImmutableCollection;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.util.Objects;
-
-class FinalUpdatesEvent extends Event {
- private final Change change;
- private final Change noteDbChange;
- private final ImmutableCollection<PatchSet> patchSets;
-
- FinalUpdatesEvent(Change change, Change noteDbChange, ImmutableCollection<PatchSet> patchSets) {
- super(
- change.currentPatchSetId(),
- change.getOwner(),
- change.getOwner(),
- change.getLastUpdatedOn(),
- change.getCreatedOn(),
- null);
- this.change = change;
- this.noteDbChange = noteDbChange;
- this.patchSets = patchSets;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return true;
- }
-
- @SuppressWarnings("deprecation")
- @Override
- void apply(ChangeUpdate update) throws OrmException {
- if (!Objects.equals(change.getTopic(), noteDbChange.getTopic())) {
- update.setTopic(change.getTopic());
- }
- if (!statusMatches()) {
- // TODO(dborowitz): Stamp approximate approvals at this time.
- update.fixStatus(change.getStatus());
- }
- if (change.isPrivate() != noteDbChange.isPrivate()) {
- update.setPrivate(change.isPrivate());
- }
- if (change.isWorkInProgress() != noteDbChange.isWorkInProgress()) {
- update.setWorkInProgress(change.isWorkInProgress());
- }
- if (change.getSubmissionId() != null && noteDbChange.getSubmissionId() == null) {
- update.setSubmissionId(change.getSubmissionId());
- }
- if (!Objects.equals(change.getAssignee(), noteDbChange.getAssignee())) {
- // TODO(dborowitz): Parse intermediate values out from messages.
- update.setAssignee(change.getAssignee());
- }
- if (!patchSets.isEmpty() && !highestNumberedPatchSetIsCurrent()) {
- update.setCurrentPatchSet();
- }
- if (!update.isEmpty()) {
- update.setSubjectForCommit("Final NoteDb migration updates");
- }
- }
-
- private boolean statusMatches() {
- return Objects.equals(change.getStatus(), noteDbChange.getStatus());
- }
-
- private boolean highestNumberedPatchSetIsCurrent() {
- PatchSet.Id max = patchSets.stream().map(PatchSet::getId).max(intKeyOrdering()).get();
- return max.equals(change.currentPatchSetId());
- }
-
- @Override
- protected boolean isSubmit() {
- return change.getStatus() == Change.Status.MERGED;
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- if (!statusMatches()) {
- helper.add("status", change.getStatus());
- }
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/GcAllUsers.java b/java/com/google/gerrit/server/notedb/rebuild/GcAllUsers.java
deleted file mode 100644
index f2a5cc6..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/GcAllUsers.java
+++ /dev/null
@@ -1,121 +0,0 @@
-// Copyright (C) 2018 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.notedb.rebuild;
-
-import static java.util.Objects.requireNonNull;
-import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_GC_SECTION;
-import static org.eclipse.jgit.lib.ConfigConstants.CONFIG_KEY_AUTO;
-
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.GarbageCollectionResult;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GarbageCollection;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LocalDiskRepositoryManager;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.function.Consumer;
-import org.eclipse.jgit.lib.Repository;
-
-@Singleton
-public class GcAllUsers {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final AllUsersName allUsers;
- private final GarbageCollection.Factory gcFactory;
- private final GitRepositoryManager repoManager;
-
- @Inject
- GcAllUsers(
- AllUsersName allUsers,
- GarbageCollection.Factory gcFactory,
- GitRepositoryManager repoManager) {
- this.allUsers = allUsers;
- this.gcFactory = gcFactory;
- this.repoManager = repoManager;
- }
-
- public void runWithLogger() {
- // Print log messages using logger, and skip progress.
- run(s -> logger.atInfo().log(s), null);
- }
-
- public void run(PrintWriter writer) {
- // Print both log messages and progress to given writer.
- run(requireNonNull(writer)::println, writer);
- }
-
- private void run(Consumer<String> logOneLine, @Nullable PrintWriter progressWriter) {
- if (!(repoManager instanceof LocalDiskRepositoryManager)) {
- logOneLine.accept("Skipping GC of " + allUsers + "; not a local disk repo");
- return;
- }
- if (!enableAutoGc(logOneLine)) {
- logOneLine.accept(
- "Skipping GC of "
- + allUsers
- + " due to disabling "
- + CONFIG_GC_SECTION
- + "."
- + CONFIG_KEY_AUTO);
- logOneLine.accept(
- "If loading accounts is slow after the NoteDb migration, run `git gc` on "
- + allUsers
- + " manually");
- return;
- }
-
- if (progressWriter == null) {
- // Mimic log line from GarbageCollection.
- logOneLine.accept("collecting garbage for \"" + allUsers + "\":\n");
- }
- GarbageCollectionResult result =
- gcFactory.create().run(ImmutableList.of(allUsers), progressWriter);
- if (!result.hasErrors()) {
- return;
- }
- for (GarbageCollectionResult.Error e : result.getErrors()) {
- switch (e.getType()) {
- case GC_ALREADY_SCHEDULED:
- logOneLine.accept("GC already scheduled for " + e.getProjectName());
- break;
- case GC_FAILED:
- logOneLine.accept("GC failed for " + e.getProjectName());
- break;
- case REPOSITORY_NOT_FOUND:
- logOneLine.accept(e.getProjectName() + " repo not found");
- break;
- default:
- logOneLine.accept("GC failed for " + e.getProjectName() + ": " + e.getType());
- break;
- }
- }
- }
-
- private boolean enableAutoGc(Consumer<String> logOneLine) {
- try (Repository repo = repoManager.openRepository(allUsers)) {
- return repo.getConfig().getInt(CONFIG_GC_SECTION, CONFIG_KEY_AUTO, -1) != 0;
- } catch (IOException e) {
- logOneLine.accept(
- "Error reading config for " + allUsers + ":\n" + Throwables.getStackTraceAsString(e));
- return false;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/HashtagsEvent.java b/java/com/google/gerrit/server/notedb/rebuild/HashtagsEvent.java
deleted file mode 100644
index 4f6f6ad..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/HashtagsEvent.java
+++ /dev/null
@@ -1,62 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.sql.Timestamp;
-import java.util.Set;
-
-class HashtagsEvent extends Event {
- private final Set<String> hashtags;
-
- HashtagsEvent(
- PatchSet.Id psId,
- Account.Id who,
- Timestamp when,
- Set<String> hashtags,
- Timestamp changeCreatdOn) {
- super(
- psId,
- who,
- who,
- when,
- changeCreatdOn,
- // Somewhat confusingly, hashtags do not use the setTag method on
- // AbstractChangeUpdate, so pass null as the tag.
- null);
- this.hashtags = hashtags;
- }
-
- @Override
- boolean uniquePerUpdate() {
- // Since these are produced from existing commits in the old NoteDb graph,
- // we know that there must be one per commit in the rebuilt graph.
- return true;
- }
-
- @Override
- void apply(ChangeUpdate update) throws OrmException {
- update.setHashtags(hashtags);
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("hashtags", hashtags);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/MigrationException.java b/java/com/google/gerrit/server/notedb/rebuild/MigrationException.java
deleted file mode 100644
index 0cf78be..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/MigrationException.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2017 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.notedb.rebuild;
-
-import java.io.IOException;
-
-/** Exception thrown by {@link NoteDbMigrator} when migration fails. */
-public class MigrationException extends IOException {
- private static final long serialVersionUID = 1L;
-
- MigrationException(String message) {
- super(message);
- }
-
- MigrationException(String message, Throwable why) {
- super(message, why);
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java b/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
deleted file mode 100644
index f60744f..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
+++ /dev/null
@@ -1,1035 +0,0 @@
-// Copyright (C) 2017 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.notedb.rebuild;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.unwrapDb;
-import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
-import static com.google.gerrit.server.notedb.NotesMigrationState.NOTE_DB;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_NO_SEQUENCE;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY;
-import static com.google.gerrit.server.notedb.NotesMigrationState.WRITE;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Comparator.comparing;
-import static java.util.Objects.requireNonNull;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Ordering;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Streams;
-import com.google.common.flogger.FluentLogger;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.gerrit.common.FormatUtil;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.git.LockFailureException;
-import com.google.gerrit.git.RefUpdateUtil;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.InternalUser;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.GerritServerConfigProvider;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.WorkQueue;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
-import com.google.gerrit.server.notedb.NoteDbSchemaVersionManager;
-import com.google.gerrit.server.notedb.NoteDbTable;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import com.google.gerrit.server.notedb.PrimaryStorageMigrator;
-import com.google.gerrit.server.notedb.PrimaryStorageMigrator.NoNoteDbStateException;
-import com.google.gerrit.server.notedb.RepoSequence;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder.NoPatchSetsException;
-import com.google.gerrit.server.plugincontext.PluginSetContext;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gerrit.server.update.ChainedReceiveCommands;
-import com.google.gerrit.server.util.ManualRequestContext;
-import com.google.gerrit.server.util.ThreadLocalRequestContext;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.BufferedWriter;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Optional;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Consumer;
-import java.util.function.Predicate;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.internal.storage.file.PackInserter;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.transport.ReceiveCommand;
-import org.eclipse.jgit.util.FS;
-import org.eclipse.jgit.util.io.NullOutputStream;
-
-/** One stop shop for migrating a site's change storage from ReviewDb to NoteDb. */
-public class NoteDbMigrator implements AutoCloseable {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private static final String AUTO_MIGRATE = "autoMigrate";
- private static final String TRIAL = "trial";
-
- public static boolean getAutoMigrate(Config cfg) {
- return cfg.getBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), AUTO_MIGRATE, false);
- }
-
- private static void setAutoMigrate(Config cfg, boolean autoMigrate) {
- cfg.setBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), AUTO_MIGRATE, autoMigrate);
- }
-
- public static boolean getTrialMode(Config cfg) {
- return cfg.getBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), TRIAL, false);
- }
-
- public static void setTrialMode(Config cfg, boolean trial) {
- cfg.setBoolean(SECTION_NOTE_DB, NoteDbTable.CHANGES.key(), TRIAL, trial);
- }
-
- public static class Builder {
- private final Config cfg;
- private final SitePaths sitePaths;
- private final Provider<PersonIdent> serverIdent;
- private final AllUsersName allUsers;
- private final SchemaFactory<ReviewDb> schemaFactory;
- private final GitRepositoryManager repoManager;
- private final NoteDbUpdateManager.Factory updateManagerFactory;
- private final ChangeBundleReader bundleReader;
- private final AllProjectsName allProjects;
- private final InternalUser.Factory userFactory;
- private final ThreadLocalRequestContext requestContext;
- private final ChangeRebuilderImpl rebuilder;
- private final WorkQueue workQueue;
- private final MutableNotesMigration globalNotesMigration;
- private final PrimaryStorageMigrator primaryStorageMigrator;
- private final PluginSetContext<NotesMigrationStateListener> listeners;
- private final NoteDbSchemaVersionManager versionManager;
-
- private int threads;
- private ImmutableList<Project.NameKey> projects = ImmutableList.of();
- private ImmutableList<Change.Id> changes = ImmutableList.of();
- private OutputStream progressOut = NullOutputStream.INSTANCE;
- private NotesMigrationState stopAtState;
- private boolean trial;
- private boolean forceRebuild;
- private int sequenceGap = -1;
- private boolean autoMigrate;
-
- @Inject
- Builder(
- GerritServerConfigProvider configProvider,
- SitePaths sitePaths,
- @GerritPersonIdent Provider<PersonIdent> serverIdent,
- AllUsersName allUsers,
- SchemaFactory<ReviewDb> schemaFactory,
- GitRepositoryManager repoManager,
- NoteDbUpdateManager.Factory updateManagerFactory,
- ChangeBundleReader bundleReader,
- AllProjectsName allProjects,
- ThreadLocalRequestContext requestContext,
- InternalUser.Factory userFactory,
- ChangeRebuilderImpl rebuilder,
- WorkQueue workQueue,
- MutableNotesMigration globalNotesMigration,
- PrimaryStorageMigrator primaryStorageMigrator,
- PluginSetContext<NotesMigrationStateListener> listeners,
- NoteDbSchemaVersionManager versionManager) {
- // Reload gerrit.config/notedb.config on each migrator invocation, in case a previous
- // migration in the same process modified the on-disk contents. This ensures the defaults for
- // trial/autoMigrate get set correctly below.
- this.cfg = configProvider.loadConfig();
- this.sitePaths = sitePaths;
- this.serverIdent = serverIdent;
- this.allUsers = allUsers;
- this.schemaFactory = schemaFactory;
- this.repoManager = repoManager;
- this.updateManagerFactory = updateManagerFactory;
- this.bundleReader = bundleReader;
- this.allProjects = allProjects;
- this.requestContext = requestContext;
- this.userFactory = userFactory;
- this.rebuilder = rebuilder;
- this.workQueue = workQueue;
- this.globalNotesMigration = globalNotesMigration;
- this.primaryStorageMigrator = primaryStorageMigrator;
- this.listeners = listeners;
- this.versionManager = versionManager;
- this.trial = getTrialMode(cfg);
- this.autoMigrate = getAutoMigrate(cfg);
- }
-
- /**
- * Set the number of threads used by parallelizable phases of the migration, such as rebuilding
- * all changes.
- *
- * <p>Not all phases are parallelizable, and calling {@link #rebuild()} directly will do
- * substantial work in the calling thread regardless of the number of threads configured.
- *
- * <p>By default, all work is done in the calling thread.
- *
- * @param threads thread count; if less than 2, all work happens in the calling thread.
- * @return this.
- */
- public Builder setThreads(int threads) {
- this.threads = threads;
- return this;
- }
-
- /**
- * Limit the set of projects that are processed.
- *
- * <p>Incompatible with {@link #setChanges(Collection)}.
- *
- * <p>By default, all projects will be processed.
- *
- * @param projects set of projects; if null or empty, all projects will be processed.
- * @return this.
- */
- public Builder setProjects(@Nullable Collection<Project.NameKey> projects) {
- this.projects = projects != null ? ImmutableList.copyOf(projects) : ImmutableList.of();
- return this;
- }
-
- /**
- * Limit the set of changes that are processed.
- *
- * <p>Incompatible with {@link #setProjects(Collection)}.
- *
- * <p>By default, all changes will be processed.
- *
- * @param changes set of changes; if null or empty, all changes will be processed.
- * @return this.
- */
- public Builder setChanges(@Nullable Collection<Change.Id> changes) {
- this.changes = changes != null ? ImmutableList.copyOf(changes) : ImmutableList.of();
- return this;
- }
-
- /**
- * Set output stream for progress monitors.
- *
- * <p>By default, there is no progress monitor output (although there may be other logs).
- *
- * @param progressOut output stream.
- * @return this.
- */
- public Builder setProgressOut(OutputStream progressOut) {
- this.progressOut = requireNonNull(progressOut);
- return this;
- }
-
- /**
- * Stop at a specific migration state, for testing only.
- *
- * @param stopAtState state to stop at.
- * @return this.
- */
- @VisibleForTesting
- public Builder setStopAtStateForTesting(NotesMigrationState stopAtState) {
- this.stopAtState = stopAtState;
- return this;
- }
-
- /**
- * Rebuild in "trial mode": configure Gerrit to write to and read from NoteDb, but leave
- * ReviewDb as the source of truth for all changes.
- *
- * <p>By default, trial mode is off, and NoteDb is the source of truth for all changes following
- * the migration.
- *
- * @param trial whether to rebuild in trial mode.
- * @return this.
- */
- public Builder setTrialMode(boolean trial) {
- this.trial = trial;
- return this;
- }
-
- /**
- * Rebuild all changes in NoteDb from ReviewDb, even if Gerrit is currently configured to read
- * from NoteDb.
- *
- * <p>Only supported if ReviewDb is still the source of truth for all changes.
- *
- * <p>By default, force rebuilding is off.
- *
- * @param forceRebuild whether to force rebuilding.
- * @return this.
- */
- public Builder setForceRebuild(boolean forceRebuild) {
- this.forceRebuild = forceRebuild;
- return this;
- }
-
- /**
- * Gap between ReviewDb change sequence numbers and NoteDb.
- *
- * <p>If NoteDb sequences are enabled in a running server, there is a race between the migration
- * step that calls {@code nextChangeId()} to seed the ref, and other threads that call {@code
- * nextChangeId()} to create new changes. In order to prevent these operations stepping on one
- * another, we use this value to skip some predefined sequence numbers. This is strongly
- * recommended in a running server.
- *
- * <p>If the migration takes place offline, there is no race with other threads, and this option
- * may be set to 0. However, admins may still choose to use a gap, for example to make it easier
- * to distinguish changes that were created before and after the NoteDb migration.
- *
- * <p>By default, uses the value from {@code noteDb.changes.initialSequenceGap} in {@code
- * gerrit.config}, which defaults to 1000.
- *
- * @param sequenceGap sequence gap size; if negative, use the default.
- * @return this.
- */
- public Builder setSequenceGap(int sequenceGap) {
- this.sequenceGap = sequenceGap;
- return this;
- }
-
- /**
- * Enable auto-migration on subsequent daemon launches.
- *
- * <p>If true, prior to running any migration steps, sets the necessary configuration in {@code
- * gerrit.config} to make {@code gerrit.war daemon} retry the migration on next startup, if it
- * fails.
- *
- * @param autoMigrate whether to set auto-migration config.
- * @return this.
- */
- public Builder setAutoMigrate(boolean autoMigrate) {
- this.autoMigrate = autoMigrate;
- return this;
- }
-
- public NoteDbMigrator build() throws MigrationException {
- return new NoteDbMigrator(
- sitePaths,
- schemaFactory,
- serverIdent,
- allUsers,
- repoManager,
- updateManagerFactory,
- bundleReader,
- allProjects,
- requestContext,
- userFactory,
- rebuilder,
- globalNotesMigration,
- primaryStorageMigrator,
- listeners,
- versionManager,
- threads > 1
- ? MoreExecutors.listeningDecorator(
- workQueue.createQueue(threads, "RebuildChange", true))
- : MoreExecutors.newDirectExecutorService(),
- projects,
- changes,
- progressOut,
- stopAtState,
- trial,
- forceRebuild,
- sequenceGap >= 0 ? sequenceGap : Sequences.getChangeSequenceGap(cfg),
- autoMigrate);
- }
- }
-
- private final FileBasedConfig gerritConfig;
- private final FileBasedConfig noteDbConfig;
- private final SchemaFactory<ReviewDb> schemaFactory;
- private final Provider<PersonIdent> serverIdent;
- private final AllUsersName allUsers;
- private final GitRepositoryManager repoManager;
- private final NoteDbUpdateManager.Factory updateManagerFactory;
- private final ChangeBundleReader bundleReader;
- private final AllProjectsName allProjects;
- private final ThreadLocalRequestContext requestContext;
- private final InternalUser.Factory userFactory;
- private final ChangeRebuilderImpl rebuilder;
- private final MutableNotesMigration globalNotesMigration;
- private final PrimaryStorageMigrator primaryStorageMigrator;
- private final PluginSetContext<NotesMigrationStateListener> listeners;
- private final NoteDbSchemaVersionManager versionManager;
-
- private final ListeningExecutorService executor;
- private final ImmutableList<Project.NameKey> projects;
- private final ImmutableList<Change.Id> changes;
- private final OutputStream progressOut;
- private final NotesMigrationState stopAtState;
- private final boolean trial;
- private final boolean forceRebuild;
- private final int sequenceGap;
- private final boolean autoMigrate;
-
- private NoteDbMigrator(
- SitePaths sitePaths,
- SchemaFactory<ReviewDb> schemaFactory,
- Provider<PersonIdent> serverIdent,
- AllUsersName allUsers,
- GitRepositoryManager repoManager,
- NoteDbUpdateManager.Factory updateManagerFactory,
- ChangeBundleReader bundleReader,
- AllProjectsName allProjects,
- ThreadLocalRequestContext requestContext,
- InternalUser.Factory userFactory,
- ChangeRebuilderImpl rebuilder,
- MutableNotesMigration globalNotesMigration,
- PrimaryStorageMigrator primaryStorageMigrator,
- PluginSetContext<NotesMigrationStateListener> listeners,
- NoteDbSchemaVersionManager versionManager,
- ListeningExecutorService executor,
- ImmutableList<Project.NameKey> projects,
- ImmutableList<Change.Id> changes,
- OutputStream progressOut,
- NotesMigrationState stopAtState,
- boolean trial,
- boolean forceRebuild,
- int sequenceGap,
- boolean autoMigrate)
- throws MigrationException {
- if (!changes.isEmpty() && !projects.isEmpty()) {
- throw new MigrationException("Cannot set both changes and projects");
- }
- if (sequenceGap < 0) {
- throw new MigrationException("Sequence gap must be non-negative: " + sequenceGap);
- }
-
- this.schemaFactory = schemaFactory;
- this.serverIdent = serverIdent;
- this.allUsers = allUsers;
- this.rebuilder = rebuilder;
- this.repoManager = repoManager;
- this.updateManagerFactory = updateManagerFactory;
- this.bundleReader = bundleReader;
- this.allProjects = allProjects;
- this.requestContext = requestContext;
- this.userFactory = userFactory;
- this.globalNotesMigration = globalNotesMigration;
- this.primaryStorageMigrator = primaryStorageMigrator;
- this.listeners = listeners;
- this.versionManager = versionManager;
- this.executor = executor;
- this.projects = projects;
- this.changes = changes;
- this.progressOut = progressOut;
- this.stopAtState = stopAtState;
- this.trial = trial;
- this.forceRebuild = forceRebuild;
- this.sequenceGap = sequenceGap;
- this.autoMigrate = autoMigrate;
-
- // Stack notedb.config over gerrit.config, in the same way as GerritServerConfigProvider.
- this.gerritConfig = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.detect());
- this.noteDbConfig =
- new FileBasedConfig(gerritConfig, sitePaths.notedb_config.toFile(), FS.detect());
- }
-
- @Override
- public void close() {
- executor.shutdownNow();
- }
-
- public void migrate() throws OrmException, IOException {
- if (!changes.isEmpty() || !projects.isEmpty()) {
- throw new MigrationException(
- "Cannot set changes or projects during full migration; call rebuild() instead");
- }
- Optional<NotesMigrationState> maybeState = loadState();
- if (!maybeState.isPresent()) {
- throw new MigrationException("Could not determine initial migration state");
- }
-
- NotesMigrationState state = maybeState.get();
- if (trial && state.compareTo(READ_WRITE_NO_SEQUENCE) > 0) {
- throw new MigrationException(
- "Migration has already progressed past the endpoint of the \"trial mode\" state;"
- + " NoteDb is already the primary storage for some changes");
- }
- if (forceRebuild && state.compareTo(READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY) > 0) {
- throw new MigrationException(
- "Cannot force rebuild changes; NoteDb is already the primary storage for some changes");
- }
- setControlFlags();
-
- boolean rebuilt = false;
- while (state.compareTo(NOTE_DB) < 0) {
- if (state.equals(stopAtState)) {
- return;
- }
- boolean stillNeedsRebuild = forceRebuild && !rebuilt;
- if (trial && state.compareTo(READ_WRITE_NO_SEQUENCE) >= 0) {
- if (stillNeedsRebuild && state == READ_WRITE_NO_SEQUENCE) {
- // We're at the end state of trial mode, but still need a rebuild due to forceRebuild. Let
- // the loop go one more time.
- } else {
- return;
- }
- }
- switch (state) {
- case REVIEW_DB:
- state = turnOnWrites(state);
- break;
- case WRITE:
- state = rebuildAndEnableReads(state);
- rebuilt = true;
- break;
- case READ_WRITE_NO_SEQUENCE:
- if (stillNeedsRebuild) {
- state = rebuildAndEnableReads(state);
- rebuilt = true;
- } else {
- state = enableSequences(state);
- }
- break;
- case READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY:
- if (stillNeedsRebuild) {
- state = rebuildAndEnableReads(state);
- rebuilt = true;
- } else {
- state = setNoteDbPrimary(state);
- }
- break;
- case READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY:
- // The only way we can get here is if there was a failure on a previous run of
- // setNoteDbPrimary, since that method moves to NOTE_DB if it completes
- // successfully. Assume that not all changes were converted and re-run the step.
- // migrateToNoteDbPrimary is a relatively fast no-op for already-migrated changes, so this
- // isn't actually repeating work.
- state = setNoteDbPrimary(state);
- break;
- case NOTE_DB:
- // Done!
- break;
- default:
- throw new MigrationException(
- "Migration out of the following state is not supported:\n" + state.toText());
- }
- }
- }
-
- private NotesMigrationState turnOnWrites(NotesMigrationState prev)
- throws OrmException, IOException {
- versionManager.init();
- return saveState(prev, WRITE);
- }
-
- private NotesMigrationState rebuildAndEnableReads(NotesMigrationState prev)
- throws OrmException, IOException {
- rebuild();
- return saveState(prev, READ_WRITE_NO_SEQUENCE);
- }
-
- private NotesMigrationState enableSequences(NotesMigrationState prev)
- throws OrmException, IOException {
- try (ReviewDb db = schemaFactory.open()) {
- @SuppressWarnings("deprecation")
- final int nextChangeId = db.nextChangeId();
-
- RepoSequence seq =
- new RepoSequence(
- repoManager,
- GitReferenceUpdated.DISABLED,
- allProjects,
- Sequences.NAME_CHANGES,
- // If sequenceGap is 0, this writes into the sequence ref the same ID that is returned
- // by the call to seq.next() below. If we actually used this as a change ID, that
- // would be a problem, but we just discard it, so this is safe.
- () -> nextChangeId + sequenceGap - 1,
- 1,
- nextChangeId);
- seq.next();
- }
- return saveState(prev, READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY);
- }
-
- private NotesMigrationState setNoteDbPrimary(NotesMigrationState prev)
- throws MigrationException, OrmException, IOException {
- checkState(
- projects.isEmpty() && changes.isEmpty(),
- "Should not have attempted setNoteDbPrimary with a subset of changes");
- checkState(
- prev == READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY
- || prev == READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY,
- "Unexpected start state for setNoteDbPrimary: %s",
- prev);
-
- // Before changing the primary storage of old changes, ensure new changes are created with
- // NoteDb primary.
- prev = saveState(prev, READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY);
-
- Stopwatch sw = Stopwatch.createStarted();
- logger.atInfo().log("Setting primary storage to NoteDb");
- List<Change.Id> allChanges;
- try (ReviewDb db = unwrapDb(schemaFactory.open())) {
- allChanges = Streams.stream(db.changes().all()).map(Change::getId).collect(toList());
- }
-
- try (ContextHelper contextHelper = new ContextHelper()) {
- List<ListenableFuture<Boolean>> futures =
- allChanges
- .stream()
- .map(
- id ->
- executor.submit(
- () -> {
- try (ManualRequestContext ctx = contextHelper.open()) {
- try {
- primaryStorageMigrator.migrateToNoteDbPrimary(id);
- } catch (NoNoteDbStateException e) {
- if (canSkipPrimaryStorageMigration(
- ctx.getReviewDbProvider().get(), id)) {
- logger.atWarning().withCause(e).log(
- "Change %s previously failed to rebuild;"
- + " skipping primary storage migration",
- id);
- } else {
- throw e;
- }
- }
- return true;
- } catch (Exception e) {
- logger.atSevere().withCause(e).log(
- "Error migrating primary storage for %s", id);
- return false;
- }
- }))
- .collect(toList());
-
- boolean ok = futuresToBoolean(futures, "Error migrating primary storage");
- double t = sw.elapsed(TimeUnit.MILLISECONDS) / 1000d;
- logger.atInfo().log(
- "Migrated primary storage of %d changes in %.01fs (%.01f/s)\n",
- allChanges.size(), t, allChanges.size() / t);
- if (!ok) {
- throw new MigrationException("Migrating primary storage for some changes failed, see log");
- }
- }
-
- return disableReviewDb(prev);
- }
-
- /**
- * Checks whether a change is so corrupt that it can be completely skipped by the primary storage
- * migration step.
- *
- * <p>To get to the point where this method is called from {@link #setNoteDbPrimary}, it means we
- * attempted to rebuild it, and encountered an error that was then caught in {@link
- * #rebuildProject} and skipped. As a result, there is no {@code noteDbState} field in the change
- * by the time we get to {@link #setNoteDbPrimary}, so {@code migrateToNoteDbPrimary} throws an
- * exception.
- *
- * <p>We have to do this hacky double-checking because we don't have a way for the rebuilding
- * phase to communicate to the primary storage migration phase that the change is skippable. It
- * would be possible to store this info in some field in this class, but there is no guarantee
- * that the rebuild and primary storage migration phases are run in the same JVM invocation.
- *
- * <p>In an ideal world, we could do this through the {@link
- * com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage} enum, having a separate value
- * for errors. However, that would be an invasive change touching many non-migration-related parts
- * of the NoteDb migration code, which is too risky to attempt in the stable branch where this bug
- * had to be fixed.
- *
- * <p>As of this writing, the only case where this happens is when a change has no patch sets.
- */
- private static boolean canSkipPrimaryStorageMigration(ReviewDb db, Change.Id id) {
- try {
- return Iterables.isEmpty(unwrapDb(db).patchSets().byChange(id));
- } catch (Exception e) {
- logger.atSevere().withCause(e).log(
- "Error checking if change %s can be skipped, assuming no", id);
- return false;
- }
- }
-
- private NotesMigrationState disableReviewDb(NotesMigrationState prev) throws IOException {
- return saveState(prev, NOTE_DB, c -> setAutoMigrate(c, false));
- }
-
- private Optional<NotesMigrationState> loadState() throws IOException {
- try {
- gerritConfig.load();
- noteDbConfig.load();
- return NotesMigrationState.forConfig(noteDbConfig);
- } catch (ConfigInvalidException | IllegalArgumentException e) {
- logger.atWarning().withCause(e).log(
- "error reading NoteDb migration options from %s", noteDbConfig.getFile());
- return Optional.empty();
- }
- }
-
- private NotesMigrationState saveState(
- NotesMigrationState expectedOldState, NotesMigrationState newState) throws IOException {
- return saveState(expectedOldState, newState, c -> {});
- }
-
- private NotesMigrationState saveState(
- NotesMigrationState expectedOldState,
- NotesMigrationState newState,
- Consumer<Config> additionalUpdates)
- throws IOException {
- synchronized (globalNotesMigration) {
- // This read-modify-write is racy. We're counting on the fact that no other Gerrit operation
- // modifies gerrit.config, and hoping that admins don't either.
- Optional<NotesMigrationState> actualOldState = loadState();
- if (!actualOldState.equals(Optional.of(expectedOldState))) {
- throw new MigrationException(
- "Cannot move to new state:\n"
- + newState.toText()
- + "\n\n"
- + "Expected this state in gerrit.config:\n"
- + expectedOldState.toText()
- + "\n\n"
- + (actualOldState.isPresent()
- ? "But found this state:\n" + actualOldState.get().toText()
- : "But could not parse the current state"));
- }
-
- preStateChange(expectedOldState, newState);
-
- newState.setConfigValues(noteDbConfig);
- additionalUpdates.accept(noteDbConfig);
- noteDbConfig.save();
-
- // Only set in-memory state once it's been persisted to storage.
- globalNotesMigration.setFrom(newState);
- logger.atInfo().log("Migration state: %s => %s", expectedOldState, newState);
-
- return newState;
- }
- }
-
- private void preStateChange(NotesMigrationState oldState, NotesMigrationState newState)
- throws IOException {
- listeners.runEach(l -> l.preStateChange(oldState, newState), IOException.class);
- }
-
- private void setControlFlags() throws MigrationException {
- synchronized (globalNotesMigration) {
- try {
- noteDbConfig.load();
- setAutoMigrate(noteDbConfig, autoMigrate);
- setTrialMode(noteDbConfig, trial);
- noteDbConfig.save();
- } catch (ConfigInvalidException | IOException e) {
- throw new MigrationException("Error saving auto-migration config", e);
- }
- }
- }
-
- public void rebuild() throws MigrationException, OrmException {
- if (!globalNotesMigration.commitChangeWrites()) {
- throw new MigrationException("Cannot rebuild without noteDb.changes.write=true");
- }
- Stopwatch sw = Stopwatch.createStarted();
- logger.atInfo().log("Rebuilding changes in NoteDb");
-
- ImmutableListMultimap<Project.NameKey, Change.Id> changesByProject = getChangesByProject();
- List<ListenableFuture<Boolean>> futures = new ArrayList<>();
- try (ContextHelper contextHelper = new ContextHelper()) {
- List<Project.NameKey> projectNames =
- Ordering.usingToString().sortedCopy(changesByProject.keySet());
- for (Project.NameKey project : projectNames) {
- ListenableFuture<Boolean> future =
- executor.submit(
- () -> {
- try {
- return rebuildProject(contextHelper.getReviewDb(), changesByProject, project);
- } catch (Exception e) {
- logger.atSevere().withCause(e).log("Error rebuilding project %s", project);
- return false;
- }
- });
- futures.add(future);
- }
-
- boolean ok = futuresToBoolean(futures, "Error rebuilding projects");
- double t = sw.elapsed(TimeUnit.MILLISECONDS) / 1000d;
- logger.atInfo().log(
- "Rebuilt %d changes in %.01fs (%.01f/s)\n",
- changesByProject.size(), t, changesByProject.size() / t);
- if (!ok) {
- throw new MigrationException("Rebuilding some changes failed, see log");
- }
- }
- }
-
- private ImmutableListMultimap<Project.NameKey, Change.Id> getChangesByProject()
- throws OrmException {
- // Memoize all changes so we can close the db connection and allow other threads to use the full
- // connection pool.
- SetMultimap<Project.NameKey, Change.Id> out =
- MultimapBuilder.treeKeys(comparing(Project.NameKey::get))
- .treeSetValues(comparing(Change.Id::get))
- .build();
- try (ReviewDb db = unwrapDb(schemaFactory.open())) {
- if (!projects.isEmpty()) {
- return byProject(db.changes().all(), c -> projects.contains(c.getProject()), out);
- }
- if (!changes.isEmpty()) {
- return byProject(db.changes().get(changes), c -> true, out);
- }
- return byProject(db.changes().all(), c -> true, out);
- }
- }
-
- private static ImmutableListMultimap<Project.NameKey, Change.Id> byProject(
- Iterable<Change> changes,
- Predicate<Change> pred,
- SetMultimap<Project.NameKey, Change.Id> out) {
- Streams.stream(changes).filter(pred).forEach(c -> out.put(c.getProject(), c.getId()));
- return ImmutableListMultimap.copyOf(out);
- }
-
- private static ObjectInserter newPackInserter(Repository repo) {
- if (!(repo instanceof FileRepository)) {
- return repo.newObjectInserter();
- }
- PackInserter ins = ((FileRepository) repo).getObjectDatabase().newPackInserter();
- ins.checkExisting(false);
- return ins;
- }
-
- private boolean rebuildProject(
- ReviewDb db,
- ImmutableListMultimap<Project.NameKey, Change.Id> allChanges,
- Project.NameKey project) {
- checkArgument(allChanges.containsKey(project));
- boolean ok = true;
- ProgressMonitor pm =
- new TextProgressMonitor(
- new PrintWriter(new BufferedWriter(new OutputStreamWriter(progressOut, UTF_8))));
- try (Repository changeRepo = repoManager.openRepository(project);
- // Only use a PackInserter for the change repo, not All-Users.
- //
- // It's not possible to share a single inserter for All-Users across all project tasks, and
- // we don't want to add one pack per project to All-Users. Adding many loose objects is
- // preferable to many packs.
- //
- // Anyway, the number of objects inserted into All-Users is proportional to the number
- // of pending draft comments, which should not be high (relative to the total number of
- // changes), so the number of loose objects shouldn't be too unreasonable.
- ObjectInserter changeIns = newPackInserter(changeRepo);
- ObjectReader changeReader = changeIns.newReader();
- RevWalk changeRw = new RevWalk(changeReader);
- Repository allUsersRepo = repoManager.openRepository(allUsers);
- ObjectInserter allUsersIns = allUsersRepo.newObjectInserter();
- ObjectReader allUsersReader = allUsersIns.newReader();
- RevWalk allUsersRw = new RevWalk(allUsersReader)) {
- ChainedReceiveCommands changeCmds = new ChainedReceiveCommands(changeRepo);
- ChainedReceiveCommands allUsersCmds = new ChainedReceiveCommands(allUsersRepo);
-
- Collection<Change.Id> changes = allChanges.get(project);
- pm.beginTask(FormatUtil.elide("Rebuilding " + project.get(), 50), changes.size());
- int toSave = 0;
- try {
- for (Change.Id changeId : changes) {
- // NoteDbUpdateManager assumes that all commands in its OpenRepo were added by itself, so
- // we can't share the top-level ChainedReceiveCommands. Use a new set of commands sharing
- // the same underlying repo, and copy commands back to the top-level
- // ChainedReceiveCommands later. This also assumes that each ref in the final list of
- // commands was only modified by a single NoteDbUpdateManager; since we use one manager
- // per change, and each ref corresponds to exactly one change, this assumption should be
- // safe.
- ChainedReceiveCommands tmpChangeCmds =
- new ChainedReceiveCommands(changeCmds.getRepoRefCache());
- ChainedReceiveCommands tmpAllUsersCmds =
- new ChainedReceiveCommands(allUsersCmds.getRepoRefCache());
-
- try (NoteDbUpdateManager manager =
- updateManagerFactory
- .create(project)
- .setAtomicRefUpdates(false)
- .setSaveObjects(false)
- .setChangeRepo(changeRepo, changeRw, changeIns, tmpChangeCmds)
- .setAllUsersRepo(allUsersRepo, allUsersRw, allUsersIns, tmpAllUsersCmds)) {
- rebuild(db, changeId, manager);
-
- // Executing with dryRun=true writes all objects to the underlying inserters and adds
- // commands to the ChainedReceiveCommands. Afterwards, we can discard the manager, so we
- // don't keep using any memory beyond what may be buffered in the PackInserter.
- manager.execute(true);
-
- tmpChangeCmds.getCommands().values().forEach(c -> addCommand(changeCmds, c));
- tmpAllUsersCmds.getCommands().values().forEach(c -> addCommand(allUsersCmds, c));
-
- toSave++;
- } catch (NoPatchSetsException e) {
- logger.atWarning().log(e.getMessage());
- } catch (ConflictingUpdateException ex) {
- logger.atWarning().log(
- "Rebuilding detected a conflicting ReviewDb update for change %s;"
- + " will be auto-rebuilt at runtime",
- changeId);
- } catch (Throwable t) {
- logger.atSevere().withCause(t).log("Failed to rebuild change %s", changeId);
- ok = false;
- }
- pm.update(1);
- }
- } finally {
- pm.endTask();
- }
-
- pm.beginTask(FormatUtil.elide("Saving " + project.get(), 50), ProgressMonitor.UNKNOWN);
- try {
- save(changeRepo, changeRw, changeIns, changeCmds);
- save(allUsersRepo, allUsersRw, allUsersIns, allUsersCmds);
- // This isn't really useful progress. If we passed a real ProgressMonitor to
- // BatchRefUpdate#execute we might get something more incremental, but that doesn't allow us
- // to specify the repo name in the task text.
- pm.update(toSave);
- } catch (LockFailureException e) {
- logger.atWarning().log(
- "Rebuilding detected a conflicting NoteDb update for the following refs, which will"
- + " be auto-rebuilt at runtime: %s",
- e.getFailedRefs().stream().distinct().sorted().collect(joining(", ")));
- } catch (IOException e) {
- logger.atSevere().withCause(e).log("Failed to save NoteDb state for %s", project);
- } finally {
- pm.endTask();
- }
- } catch (RepositoryNotFoundException e) {
- logger.atWarning().log("Repository %s not found", project);
- } catch (IOException e) {
- logger.atSevere().withCause(e).log("Failed to rebuild project %s", project);
- }
- return ok;
- }
-
- private void rebuild(ReviewDb db, Change.Id changeId, NoteDbUpdateManager manager)
- throws OrmException, IOException {
- // Match ChangeRebuilderImpl#stage, but without calling manager.stage(), since that can only be
- // called after building updates for all changes.
- Change change =
- ChangeRebuilderImpl.checkNoteDbState(ChangeNotes.readOneReviewDbChange(db, changeId));
- if (change == null) {
- // Could log here instead, but this matches the behavior of ChangeRebuilderImpl#stage.
- throw new NoSuchChangeException(changeId);
- }
- rebuilder.buildUpdates(manager, bundleReader.fromReviewDb(db, changeId));
-
- rebuilder.execute(db, changeId, manager, true, false);
- }
-
- private static void addCommand(ChainedReceiveCommands cmds, ReceiveCommand cmd) {
- // ChainedReceiveCommands doesn't allow no-ops, but these occur when rebuilding a
- // previously-rebuilt change.
- if (!cmd.getOldId().equals(cmd.getNewId())) {
- cmds.add(cmd);
- }
- }
-
- private void save(Repository repo, RevWalk rw, ObjectInserter ins, ChainedReceiveCommands cmds)
- throws IOException {
- if (cmds.isEmpty()) {
- return;
- }
- ins.flush();
- BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
- bru.setRefLogMessage("Migrate changes to NoteDb", false);
- bru.setRefLogIdent(serverIdent.get());
- bru.setAtomic(false);
- bru.setAllowNonFastForwards(true);
- cmds.addTo(bru);
- RefUpdateUtil.executeChecked(bru, rw);
- }
-
- private static boolean futuresToBoolean(List<ListenableFuture<Boolean>> futures, String errMsg) {
- try {
- return Futures.allAsList(futures).get().stream().allMatch(b -> b);
- } catch (InterruptedException | ExecutionException e) {
- logger.atSevere().withCause(e).log(errMsg);
- return false;
- }
- }
-
- private class ContextHelper implements AutoCloseable {
- private final Thread callingThread;
- private ReviewDb db;
- private Runnable closeDb;
-
- ContextHelper() {
- callingThread = Thread.currentThread();
- }
-
- ManualRequestContext open() throws OrmException {
- return new ManualRequestContext(
- userFactory.create(),
- // Reuse the same lazily-opened ReviewDb on the original calling thread, otherwise open
- // SchemaFactory in the normal way.
- Thread.currentThread().equals(callingThread) ? this::getReviewDb : schemaFactory,
- requestContext);
- }
-
- synchronized ReviewDb getReviewDb() throws OrmException {
- if (db == null) {
- ReviewDb actual = schemaFactory.open();
- closeDb = actual::close;
- db =
- new ReviewDbWrapper(unwrapDb(actual)) {
- @Override
- public void close() {
- // Closed by ContextHelper#close.
- }
- };
- }
- return db;
- }
-
- @Override
- public synchronized void close() {
- if (db != null) {
- closeDb.run();
- db = null;
- closeDb = null;
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/NotesMigrationStateListener.java b/java/com/google/gerrit/server/notedb/rebuild/NotesMigrationStateListener.java
deleted file mode 100644
index aef30a2..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/NotesMigrationStateListener.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2017 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.notedb.rebuild;
-
-import com.google.gerrit.extensions.annotations.ExtensionPoint;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import java.io.IOException;
-
-/** Listener for state changes performed by {@link OnlineNoteDbMigrator}. */
-@ExtensionPoint
-public interface NotesMigrationStateListener {
- /**
- * Invoked just before saving the new migration state.
- *
- * @param oldState state prior to this state change.
- * @param newState state after this state change.
- * @throws IOException if an error occurred, which will cause the migration to abort. Exceptions
- * that should be considered non-fatal must be caught (and ideally logged) by the
- * implementation rather than thrown.
- */
- void preStateChange(NotesMigrationState oldState, NotesMigrationState newState)
- throws IOException;
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java b/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java
deleted file mode 100644
index b5a8236..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/OnlineNoteDbMigrator.java
+++ /dev/null
@@ -1,108 +0,0 @@
-// Copyright (C) 2017 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.notedb.rebuild;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.lifecycle.LifecycleModule;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.index.OnlineUpgrader;
-import com.google.gerrit.server.index.VersionManager;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import com.google.inject.name.Named;
-import com.google.inject.name.Names;
-import java.util.concurrent.TimeUnit;
-import org.eclipse.jgit.lib.Config;
-
-@Singleton
-public class OnlineNoteDbMigrator implements LifecycleListener {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private static final String TRIAL = "OnlineNoteDbMigrator/trial";
-
- public static class Module extends LifecycleModule {
- private final boolean trial;
-
- public Module(boolean trial) {
- this.trial = trial;
- }
-
- @Override
- public void configure() {
- listener().to(OnlineNoteDbMigrator.class);
- bindConstant().annotatedWith(Names.named(TRIAL)).to(trial);
- }
- }
-
- private final GcAllUsers gcAllUsers;
- private final OnlineUpgrader indexUpgrader;
- private final Provider<NoteDbMigrator.Builder> migratorBuilderProvider;
- private final boolean upgradeIndex;
- private final boolean trial;
-
- @Inject
- OnlineNoteDbMigrator(
- @GerritServerConfig Config cfg,
- GcAllUsers gcAllUsers,
- OnlineUpgrader indexUpgrader,
- Provider<NoteDbMigrator.Builder> migratorBuilderProvider,
- @Named(TRIAL) boolean trial) {
- this.gcAllUsers = gcAllUsers;
- this.indexUpgrader = indexUpgrader;
- this.migratorBuilderProvider = migratorBuilderProvider;
- this.upgradeIndex = VersionManager.getOnlineUpgrade(cfg);
- this.trial = trial || NoteDbMigrator.getTrialMode(cfg);
- }
-
- @Override
- public void start() {
- Thread t = new Thread(this::migrate);
- t.setDaemon(true);
- t.setName(getClass().getSimpleName());
- t.start();
- }
-
- private void migrate() {
- logger.atInfo().log("Starting online NoteDb migration");
- if (upgradeIndex) {
- logger.atInfo().log(
- "Online index schema upgrades will be deferred until NoteDb migration is complete");
- }
- Stopwatch sw = Stopwatch.createStarted();
- // TODO(dborowitz): Tune threads, maybe expose a progress monitor somewhere.
- try (NoteDbMigrator migrator =
- migratorBuilderProvider.get().setAutoMigrate(true).setTrialMode(trial).build()) {
- migrator.migrate();
- } catch (Exception e) {
- logger.atSevere().withCause(e).log("Error in online NoteDb migration");
- }
- gcAllUsers.runWithLogger();
- logger.atInfo().log("Online NoteDb migration completed in %ss", sw.elapsed(TimeUnit.SECONDS));
-
- if (upgradeIndex) {
- logger.atInfo().log("Starting deferred index schema upgrades");
- indexUpgrader.start();
- }
- }
-
- @Override
- public void stop() {
- // Do nothing; upgrade process uses daemon threads and knows how to recover from failures on
- // next attempt.
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/PatchSetEvent.java b/java/com/google/gerrit/server/notedb/rebuild/PatchSetEvent.java
deleted file mode 100644
index acb80c0..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/PatchSetEvent.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gwtorm.server.OrmException;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.InvalidObjectIdException;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-class PatchSetEvent extends Event {
- private final Change change;
- private final PatchSet ps;
- private final RevWalk rw;
- boolean createChange;
-
- PatchSetEvent(Change change, PatchSet ps, RevWalk rw) {
- super(
- ps.getId(),
- ps.getUploader(),
- ps.getUploader(),
- ps.getCreatedOn(),
- change.getCreatedOn(),
- null);
- this.change = change;
- this.ps = ps;
- this.rw = rw;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return true;
- }
-
- @Override
- void apply(ChangeUpdate update) throws IOException, OrmException {
- checkUpdate(update);
- if (createChange) {
- ChangeRebuilderImpl.createChange(update, change);
- } else {
- update.setSubject(change.getSubject());
- update.setSubjectForCommit("Create patch set " + ps.getPatchSetId());
- }
- setRevision(update, ps);
- update.setPsDescription(ps.getDescription());
- List<String> groups = ps.getGroups();
- if (!groups.isEmpty()) {
- update.setGroups(ps.getGroups());
- }
- }
-
- private void setRevision(ChangeUpdate update, PatchSet ps) throws IOException {
- String rev = ps.getRevision().get();
- String cert = ps.getPushCertificate();
- ObjectId id;
- try {
- id = ObjectId.fromString(rev);
- } catch (InvalidObjectIdException e) {
- update.setRevisionForMissingCommit(rev, cert);
- return;
- }
- try {
- update.setCommit(rw, id, cert);
- } catch (MissingObjectException e) {
- update.setRevisionForMissingCommit(rev, cert);
- return;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/notedb/rebuild/ReviewerEvent.java b/java/com/google/gerrit/server/notedb/rebuild/ReviewerEvent.java
deleted file mode 100644
index 2ecf969..0000000
--- a/java/com/google/gerrit/server/notedb/rebuild/ReviewerEvent.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import com.google.common.base.MoreObjects.ToStringHelper;
-import com.google.common.collect.Table;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.ReviewerStateInternal;
-import com.google.gwtorm.server.OrmException;
-import java.io.IOException;
-import java.sql.Timestamp;
-
-class ReviewerEvent extends Event {
- private Table.Cell<ReviewerStateInternal, Account.Id, Timestamp> reviewer;
-
- ReviewerEvent(
- Table.Cell<ReviewerStateInternal, Account.Id, Timestamp> reviewer,
- Timestamp changeCreatedOn) {
- super(
- // Reviewers aren't generally associated with a particular patch set
- // (although as an implementation detail they were in ReviewDb). Just
- // use the latest patch set at the time of the event.
- null,
- reviewer.getColumnKey(),
- // TODO(dborowitz): Real account ID shouldn't really matter for
- // reviewers, but we might have to deal with this to avoid ChangeBundle
- // diffs when run against real data.
- reviewer.getColumnKey(),
- reviewer.getValue(),
- changeCreatedOn,
- null);
- this.reviewer = reviewer;
- }
-
- @Override
- boolean uniquePerUpdate() {
- return false;
- }
-
- @Override
- void apply(ChangeUpdate update) throws IOException, OrmException {
- checkUpdate(update);
- update.putReviewer(reviewer.getColumnKey(), reviewer.getRowKey());
- }
-
- @Override
- protected void addToString(ToStringHelper helper) {
- helper.add("account", reviewer.getColumnKey()).add("state", reviewer.getRowKey());
- }
-}
diff --git a/java/com/google/gerrit/server/patch/PatchScriptFactory.java b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
index b1e0e3c..dca5098 100644
--- a/java/com/google/gerrit/server/patch/PatchScriptFactory.java
+++ b/java/com/google/gerrit/server/patch/PatchScriptFactory.java
@@ -391,7 +391,7 @@
}
private void loadPublished(Map<Patch.Key, Patch> byKey, String file) throws OrmException {
- for (Comment c : commentsUtil.publishedByChangeFile(db, notes, changeId, file)) {
+ for (Comment c : commentsUtil.publishedByChangeFile(notes, file)) {
comments.include(notes.getChangeId(), c);
PatchSet.Id psId = new PatchSet.Id(notes.getChangeId(), c.key.patchSetId);
Patch.Key pKey = new Patch.Key(psId, c.key.filename);
@@ -404,7 +404,7 @@
private void loadDrafts(Map<Patch.Key, Patch> byKey, Account.Id me, String file)
throws OrmException {
- for (Comment c : commentsUtil.draftByChangeFileAuthor(db, notes, file, me)) {
+ for (Comment c : commentsUtil.draftByChangeFileAuthor(notes, file, me)) {
comments.include(notes.getChangeId(), c);
PatchSet.Id psId = new PatchSet.Id(notes.getChangeId(), c.key.patchSetId);
Patch.Key pKey = new Patch.Key(psId, c.key.filename);
diff --git a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
index 47be6e3..249c872 100644
--- a/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
+++ b/java/com/google/gerrit/server/permissions/DefaultRefFilter.java
@@ -345,7 +345,7 @@
Project.NameKey p = projectState.getNameKey();
Stream<ChangeNotesResult> s;
try {
- s = changeNotesFactory.scan(repo, db.get(), p);
+ s = changeNotesFactory.scan(repo, p);
} catch (IOException e) {
logger.atSevere().withCause(e).log(
"Cannot load changes for project %s, assuming no changes are visible", p);
diff --git a/java/com/google/gerrit/server/query/change/ChangeData.java b/java/com/google/gerrit/server/query/change/ChangeData.java
index 0f5d938..8864de1 100644
--- a/java/com/google/gerrit/server/query/change/ChangeData.java
+++ b/java/com/google/gerrit/server/query/change/ChangeData.java
@@ -750,7 +750,7 @@
if (!lazyLoad) {
return ImmutableListMultimap.of();
}
- allApprovals = approvalsUtil.byChange(db, notes());
+ allApprovals = approvalsUtil.byChange(notes());
}
return allApprovals;
}
@@ -858,7 +858,7 @@
if (!lazyLoad) {
return Collections.emptyList();
}
- publishedComments = commentsUtil.publishedByChange(db, notes());
+ publishedComments = commentsUtil.publishedByChange(notes());
}
return publishedComments;
}
@@ -949,7 +949,7 @@
if (!lazyLoad) {
return Collections.emptyList();
}
- messages = cmUtil.byChange(db, notes());
+ messages = cmUtil.byChange(notes());
}
return messages;
}
@@ -1097,7 +1097,7 @@
}
}
} else {
- for (Comment sc : commentsUtil.draftByChange(db, notes())) {
+ for (Comment sc : commentsUtil.draftByChange(notes())) {
draftsByUser.put(sc.author.getId(), null);
}
}
diff --git a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
index 17c23b6..a190ac5 100644
--- a/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
+++ b/java/com/google/gerrit/server/query/change/OutputStreamQuery.java
@@ -250,7 +250,7 @@
}
if (includeAllReviewers) {
- eventFactory.addAllReviewers(db, c, d.notes());
+ eventFactory.addAllReviewers(c, d.notes());
}
if (includeSubmitRecords) {
diff --git a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
index 108ee0e..3c553a1 100644
--- a/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
+++ b/java/com/google/gerrit/server/restapi/account/DeleteDraftComments.java
@@ -184,12 +184,12 @@
throws OrmException, PatchListNotAvailableException, PermissionBackendException {
ImmutableList.Builder<CommentInfo> comments = ImmutableList.builder();
boolean dirty = false;
- for (Comment c : commentsUtil.draftByChangeAuthor(ctx.getDb(), ctx.getNotes(), accountId)) {
+ for (Comment c : commentsUtil.draftByChangeAuthor(ctx.getNotes(), accountId)) {
dirty = true;
PatchSet.Id psId = new PatchSet.Id(ctx.getChange().getId(), c.key.patchSetId);
setCommentRevId(
c, patchListCache, ctx.getChange(), psUtil.get(ctx.getDb(), ctx.getNotes(), psId));
- commentsUtil.deleteComments(ctx.getDb(), ctx.getUpdate(psId), Collections.singleton(c));
+ commentsUtil.deleteComments(ctx.getUpdate(psId), Collections.singleton(c));
comments.add(commentFormatter.format(c));
}
if (dirty) {
diff --git a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
index 6399cde..c7a8a96 100644
--- a/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
+++ b/java/com/google/gerrit/server/restapi/change/CherryPickChange.java
@@ -361,7 +361,7 @@
if (input.keepReviewers && sourceChange != null) {
ReviewerSet reviewerSet =
approvalsUtil.getReviewers(
- dbProvider.get(), changeNotesFactory.createChecked(dbProvider.get(), sourceChange));
+ changeNotesFactory.createChecked(dbProvider.get(), sourceChange));
Set<Account.Id> reviewers =
new HashSet<>(reviewerSet.byState(ReviewerStateInternal.REVIEWER));
reviewers.add(sourceChange.getOwner());
diff --git a/java/com/google/gerrit/server/restapi/change/Comments.java b/java/com/google/gerrit/server/restapi/change/Comments.java
index f563cc6..22f376b 100644
--- a/java/com/google/gerrit/server/restapi/change/Comments.java
+++ b/java/com/google/gerrit/server/restapi/change/Comments.java
@@ -20,32 +20,27 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.CommentResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
@Singleton
public class Comments implements ChildCollection<RevisionResource, CommentResource> {
private final DynamicMap<RestView<CommentResource>> views;
private final ListRevisionComments list;
- private final Provider<ReviewDb> dbProvider;
private final CommentsUtil commentsUtil;
@Inject
Comments(
DynamicMap<RestView<CommentResource>> views,
ListRevisionComments list,
- Provider<ReviewDb> dbProvider,
CommentsUtil commentsUtil) {
this.views = views;
this.list = list;
- this.dbProvider = dbProvider;
this.commentsUtil = commentsUtil;
}
@@ -65,8 +60,7 @@
String uuid = id.get();
ChangeNotes notes = rev.getNotes();
- for (Comment c :
- commentsUtil.publishedByPatchSet(dbProvider.get(), notes, rev.getPatchSet().getId())) {
+ for (Comment c : commentsUtil.publishedByPatchSet(notes, rev.getPatchSet().getId())) {
if (uuid.equals(c.key.uuid)) {
return new CommentResource(rev, c);
}
diff --git a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
index 0e93c55..773b914 100644
--- a/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/CreateDraftComment.java
@@ -126,8 +126,7 @@
setCommentRevId(comment, patchListCache, ctx.getChange(), ps);
- commentsUtil.putComments(
- ctx.getDb(), ctx.getUpdate(psId), Status.DRAFT, Collections.singleton(comment));
+ commentsUtil.putComments(ctx.getUpdate(psId), Status.DRAFT, Collections.singleton(comment));
ctx.dontBumpLastUpdatedOn();
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteAssignee.java b/java/com/google/gerrit/server/restapi/change/DeleteAssignee.java
index 7d68022..1e9b695 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteAssignee.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteAssignee.java
@@ -114,14 +114,14 @@
return deletedAssignee != null ? deletedAssignee.getAccount().getId() : null;
}
- private void addMessage(ChangeContext ctx, ChangeUpdate update, IdentifiedUser deletedAssignee)
- throws OrmException {
+ private void addMessage(
+ ChangeContext ctx, ChangeUpdate update, IdentifiedUser deletedAssignee) {
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(
ctx,
"Assignee deleted: " + deletedAssignee.getNameEmail(),
ChangeMessagesUtil.TAG_DELETE_ASSIGNEE);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
}
@Override
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteChangeMessage.java b/java/com/google/gerrit/server/restapi/change/DeleteChangeMessage.java
index 881d106..c57f9ec 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteChangeMessage.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteChangeMessage.java
@@ -109,8 +109,7 @@
private ChangeMessageInfo createUpdatedChangeMessageInfo(Change.Id id, int targetIdx)
throws OrmException, PermissionBackendException {
- List<ChangeMessage> messages =
- changeMessagesUtil.byChange(dbProvider.get(), notesFactory.createChecked(id));
+ List<ChangeMessage> messages = changeMessagesUtil.byChange(notesFactory.createChecked(id));
ChangeMessage updatedChangeMessage = messages.get(targetIdx);
AccountLoader accountLoader = accountLoaderFactory.create(true);
ChangeMessageInfo info = createChangeMessageInfo(updatedChangeMessage, accountLoader);
@@ -145,10 +144,9 @@
}
@Override
- public boolean updateChange(ChangeContext ctx) throws OrmException {
+ public boolean updateChange(ChangeContext ctx) {
PatchSet.Id psId = ctx.getChange().currentPatchSetId();
- changeMessagesUtil.replaceChangeMessage(
- ctx.getDb(), ctx.getUpdate(psId), targetMessageIdx, newMessage);
+ changeMessagesUtil.replaceChangeMessage(ctx.getUpdate(psId), targetMessageIdx, newMessage);
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteComment.java b/java/com/google/gerrit/server/restapi/change/DeleteComment.java
index 2ddf359..6279357 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteComment.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteComment.java
@@ -97,7 +97,7 @@
ChangeNotes updatedNotes =
notesFactory.createChecked(rsrc.getRevisionResource().getChange().getId());
- List<Comment> changeComments = commentsUtil.publishedByChange(dbProvider.get(), updatedNotes);
+ List<Comment> changeComments = commentsUtil.publishedByChange(updatedNotes);
Optional<Comment> updatedComment =
changeComments.stream().filter(c -> c.key.equals(rsrc.getComment().key)).findFirst();
if (!updatedComment.isPresent()) {
@@ -127,14 +127,10 @@
@Override
public boolean updateChange(ChangeContext ctx)
- throws ResourceConflictException, OrmException, ResourceNotFoundException {
+ throws ResourceConflictException, ResourceNotFoundException {
PatchSet.Id psId = ctx.getChange().currentPatchSetId();
commentsUtil.deleteCommentByRewritingHistory(
- ctx.getDb(),
- ctx.getUpdate(psId),
- rsrc.getComment().key,
- rsrc.getPatchSet().getId(),
- newMessage);
+ ctx.getUpdate(psId), rsrc.getComment().key, newMessage);
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java b/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
index f8e3add..0d9629f 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteDraftComment.java
@@ -91,7 +91,7 @@
public boolean updateChange(ChangeContext ctx)
throws ResourceNotFoundException, OrmException, PatchListNotAvailableException {
Optional<Comment> maybeComment =
- commentsUtil.getDraft(ctx.getDb(), ctx.getNotes(), ctx.getIdentifiedUser(), key);
+ commentsUtil.getDraft(ctx.getNotes(), ctx.getIdentifiedUser(), key);
if (!maybeComment.isPresent()) {
return false; // Nothing to do.
}
@@ -102,7 +102,7 @@
}
Comment c = maybeComment.get();
setCommentRevId(c, patchListCache, ctx.getChange(), ps);
- commentsUtil.deleteComments(ctx.getDb(), ctx.getUpdate(psId), Collections.singleton(c));
+ commentsUtil.deleteComments(ctx.getUpdate(psId), Collections.singleton(c));
ctx.dontBumpLastUpdatedOn();
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteReviewerOp.java b/java/com/google/gerrit/server/restapi/change/DeleteReviewerOp.java
index 2cc4ce4..b130e62 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteReviewerOp.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteReviewerOp.java
@@ -125,7 +125,7 @@
// Check of removing this reviewer (even if there is no vote processed by the loop below) is OK
removeReviewerControl.checkRemoveReviewer(ctx.getNotes(), ctx.getUser(), reviewerId);
- if (!approvalsUtil.getReviewers(ctx.getDb(), ctx.getNotes()).all().contains(reviewerId)) {
+ if (!approvalsUtil.getReviewers(ctx.getNotes()).all().contains(reviewerId)) {
throw new ResourceNotFoundException();
}
currChange = ctx.getChange();
@@ -171,7 +171,7 @@
changeMessage =
ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_DELETE_REVIEWER);
- cmUtil.addChangeMessage(ctx.getDb(), update, changeMessage);
+ cmUtil.addChangeMessage(update, changeMessage);
return true;
}
@@ -217,7 +217,7 @@
db = ReviewDbUtil.unwrapDb(db);
approvals = db.patchSetApprovals().byChange(changeId);
} else {
- approvals = approvalsUtil.byChange(ctx.getDb(), ctx.getNotes()).values();
+ approvals = approvalsUtil.byChange(ctx.getNotes()).values();
}
return Iterables.filter(approvals, psa -> accountId.equals(psa.getAccountId()));
diff --git a/java/com/google/gerrit/server/restapi/change/DeleteVote.java b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
index 57649fad..e4d067b 100644
--- a/java/com/google/gerrit/server/restapi/change/DeleteVote.java
+++ b/java/com/google/gerrit/server/restapi/change/DeleteVote.java
@@ -218,7 +218,7 @@
msg.append(" by ").append(userFactory.create(accountId).getNameEmail()).append("\n");
changeMessage =
ChangeMessagesUtil.newMessage(ctx, msg.toString(), ChangeMessagesUtil.TAG_DELETE_VOTE);
- cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(psId), changeMessage);
+ cmUtil.addChangeMessage(ctx.getUpdate(psId), changeMessage);
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/DraftComments.java b/java/com/google/gerrit/server/restapi/change/DraftComments.java
index b8e24a5..9f06252 100644
--- a/java/com/google/gerrit/server/restapi/change/DraftComments.java
+++ b/java/com/google/gerrit/server/restapi/change/DraftComments.java
@@ -21,7 +21,6 @@
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestView;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.change.DraftCommentResource;
@@ -36,7 +35,6 @@
private final DynamicMap<RestView<DraftCommentResource>> views;
private final Provider<CurrentUser> user;
private final ListRevisionDrafts list;
- private final Provider<ReviewDb> dbProvider;
private final CommentsUtil commentsUtil;
@Inject
@@ -44,12 +42,10 @@
DynamicMap<RestView<DraftCommentResource>> views,
Provider<CurrentUser> user,
ListRevisionDrafts list,
- Provider<ReviewDb> dbProvider,
CommentsUtil commentsUtil) {
this.views = views;
this.user = user;
this.list = list;
- this.dbProvider = dbProvider;
this.commentsUtil = commentsUtil;
}
@@ -71,7 +67,7 @@
String uuid = id.get();
for (Comment c :
commentsUtil.draftByPatchSetAuthor(
- dbProvider.get(), rev.getPatchSet().getId(), rev.getAccountId(), rev.getNotes())) {
+ rev.getPatchSet().getId(), rev.getAccountId(), rev.getNotes())) {
if (uuid.equals(c.key.uuid)) {
return new DraftCommentResource(rev, c);
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
index 40f4642..42af722 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeComments.java
@@ -57,6 +57,6 @@
.setFillAccounts(true)
.setFillPatchSet(true)
.newCommentFormatter()
- .format(commentsUtil.publishedByChange(db.get(), cd.notes()));
+ .format(commentsUtil.publishedByChange(cd.notes()));
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
index a524f6d..280277c 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeDrafts.java
@@ -57,7 +57,7 @@
}
ChangeData cd = changeDataFactory.create(db.get(), rsrc.getNotes());
List<Comment> drafts =
- commentsUtil.draftByChangeAuthor(db.get(), cd.notes(), rsrc.getUser().getAccountId());
+ commentsUtil.draftByChangeAuthor(cd.notes(), rsrc.getUser().getAccountId());
return commentJson
.get()
.setFillAccounts(false)
diff --git a/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java b/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
index 39c12f7..ba09281 100644
--- a/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
+++ b/java/com/google/gerrit/server/restapi/change/ListChangeMessages.java
@@ -19,30 +19,24 @@
import com.google.gerrit.extensions.common.ChangeMessageInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.account.AccountLoader;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.List;
import java.util.stream.Collectors;
@Singleton
public class ListChangeMessages implements RestReadView<ChangeResource> {
- private final Provider<ReviewDb> dbProvider;
private final ChangeMessagesUtil changeMessagesUtil;
private final AccountLoader accountLoader;
@Inject
public ListChangeMessages(
- Provider<ReviewDb> dbProvider,
- ChangeMessagesUtil changeMessagesUtil,
- AccountLoader.Factory accountLoaderFactory) {
- this.dbProvider = dbProvider;
+ ChangeMessagesUtil changeMessagesUtil, AccountLoader.Factory accountLoaderFactory) {
this.changeMessagesUtil = changeMessagesUtil;
this.accountLoader = accountLoaderFactory.create(true);
}
@@ -50,8 +44,7 @@
@Override
public List<ChangeMessageInfo> apply(ChangeResource resource)
throws OrmException, PermissionBackendException {
- List<ChangeMessage> messages =
- changeMessagesUtil.byChange(dbProvider.get(), resource.getNotes());
+ List<ChangeMessage> messages = changeMessagesUtil.byChange(resource.getNotes());
List<ChangeMessageInfo> messageInfos =
messages
.stream()
diff --git a/java/com/google/gerrit/server/restapi/change/ListReviewers.java b/java/com/google/gerrit/server/restapi/change/ListReviewers.java
index 99d8746..725a89b 100644
--- a/java/com/google/gerrit/server/restapi/change/ListReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/ListReviewers.java
@@ -18,7 +18,6 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ReviewerJson;
@@ -26,7 +25,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.LinkedHashMap;
import java.util.List;
@@ -34,18 +32,13 @@
@Singleton
class ListReviewers implements RestReadView<ChangeResource> {
- private final Provider<ReviewDb> dbProvider;
private final ApprovalsUtil approvalsUtil;
private final ReviewerJson json;
private final ReviewerResource.Factory resourceFactory;
@Inject
ListReviewers(
- Provider<ReviewDb> dbProvider,
- ApprovalsUtil approvalsUtil,
- ReviewerResource.Factory resourceFactory,
- ReviewerJson json) {
- this.dbProvider = dbProvider;
+ ApprovalsUtil approvalsUtil, ReviewerResource.Factory resourceFactory, ReviewerJson json) {
this.approvalsUtil = approvalsUtil;
this.resourceFactory = resourceFactory;
this.json = json;
@@ -55,8 +48,7 @@
public List<ReviewerInfo> apply(ChangeResource rsrc)
throws OrmException, PermissionBackendException {
Map<String, ReviewerResource> reviewers = new LinkedHashMap<>();
- ReviewDb db = dbProvider.get();
- for (Account.Id accountId : approvalsUtil.getReviewers(db, rsrc.getNotes()).all()) {
+ for (Account.Id accountId : approvalsUtil.getReviewers(rsrc.getNotes()).all()) {
if (!reviewers.containsKey(accountId.toString())) {
reviewers.put(accountId.toString(), resourceFactory.create(rsrc, accountId));
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java b/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
index 964e560..f10d92b 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionComments.java
@@ -15,7 +15,6 @@
package com.google.gerrit.server.restapi.change;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.notedb.ChangeNotes;
@@ -27,9 +26,8 @@
@Singleton
public class ListRevisionComments extends ListRevisionDrafts {
@Inject
- ListRevisionComments(
- Provider<ReviewDb> db, Provider<CommentJson> commentJson, CommentsUtil commentsUtil) {
- super(db, commentJson, commentsUtil);
+ ListRevisionComments(Provider<CommentJson> commentJson, CommentsUtil commentsUtil) {
+ super(commentJson, commentsUtil);
}
@Override
@@ -40,6 +38,6 @@
@Override
protected Iterable<Comment> listComments(RevisionResource rsrc) throws OrmException {
ChangeNotes notes = rsrc.getNotes();
- return commentsUtil.publishedByPatchSet(db.get(), notes, rsrc.getPatchSet().getId());
+ return commentsUtil.publishedByPatchSet(notes, rsrc.getPatchSet().getId());
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
index dbd0ccf..3df7e9c 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionDrafts.java
@@ -18,7 +18,6 @@
import com.google.gerrit.extensions.common.CommentInfo;
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.reviewdb.client.Comment;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.CommentsUtil;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.permissions.PermissionBackendException;
@@ -31,21 +30,18 @@
@Singleton
public class ListRevisionDrafts implements RestReadView<RevisionResource> {
- protected final Provider<ReviewDb> db;
protected final Provider<CommentJson> commentJson;
protected final CommentsUtil commentsUtil;
@Inject
- ListRevisionDrafts(
- Provider<ReviewDb> db, Provider<CommentJson> commentJson, CommentsUtil commentsUtil) {
- this.db = db;
+ ListRevisionDrafts(Provider<CommentJson> commentJson, CommentsUtil commentsUtil) {
this.commentJson = commentJson;
this.commentsUtil = commentsUtil;
}
protected Iterable<Comment> listComments(RevisionResource rsrc) throws OrmException {
return commentsUtil.draftByPatchSetAuthor(
- db.get(), rsrc.getPatchSet().getId(), rsrc.getAccountId(), rsrc.getNotes());
+ rsrc.getPatchSet().getId(), rsrc.getAccountId(), rsrc.getNotes());
}
protected boolean includeAuthorInfo() {
diff --git a/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java b/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
index 7add548..6e7ffd9 100644
--- a/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/ListRevisionReviewers.java
@@ -19,7 +19,6 @@
import com.google.gerrit.extensions.restapi.RestReadView;
import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ReviewerJson;
import com.google.gerrit.server.change.ReviewerResource;
@@ -27,7 +26,6 @@
import com.google.gerrit.server.permissions.PermissionBackendException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.util.LinkedHashMap;
import java.util.List;
@@ -35,18 +33,13 @@
@Singleton
class ListRevisionReviewers implements RestReadView<RevisionResource> {
- private final Provider<ReviewDb> dbProvider;
private final ApprovalsUtil approvalsUtil;
private final ReviewerJson json;
private final ReviewerResource.Factory resourceFactory;
@Inject
ListRevisionReviewers(
- Provider<ReviewDb> dbProvider,
- ApprovalsUtil approvalsUtil,
- ReviewerResource.Factory resourceFactory,
- ReviewerJson json) {
- this.dbProvider = dbProvider;
+ ApprovalsUtil approvalsUtil, ReviewerResource.Factory resourceFactory, ReviewerJson json) {
this.approvalsUtil = approvalsUtil;
this.resourceFactory = resourceFactory;
this.json = json;
@@ -60,8 +53,7 @@
}
Map<String, ReviewerResource> reviewers = new LinkedHashMap<>();
- ReviewDb db = dbProvider.get();
- for (Account.Id accountId : approvalsUtil.getReviewers(db, rsrc.getNotes()).all()) {
+ for (Account.Id accountId : approvalsUtil.getReviewers(rsrc.getNotes()).all()) {
if (!reviewers.containsKey(accountId.toString())) {
reviewers.put(accountId.toString(), resourceFactory.create(rsrc, accountId));
}
diff --git a/java/com/google/gerrit/server/restapi/change/Module.java b/java/com/google/gerrit/server/restapi/change/Module.java
index a45a6d8..c7fe653 100644
--- a/java/com/google/gerrit/server/restapi/change/Module.java
+++ b/java/com/google/gerrit/server/restapi/change/Module.java
@@ -96,7 +96,6 @@
get(CHANGE_KIND, "submitted_together").to(SubmittedTogether.class);
post(CHANGE_KIND, "rebase").to(Rebase.CurrentRevision.class);
post(CHANGE_KIND, "index").to(Index.class);
- post(CHANGE_KIND, "rebuild.notedb").to(Rebuild.class);
post(CHANGE_KIND, "move").to(Move.class);
post(CHANGE_KIND, "private").to(PostPrivate.class);
post(CHANGE_KIND, "private.delete").to(DeletePrivateByPost.class);
diff --git a/java/com/google/gerrit/server/restapi/change/Move.java b/java/com/google/gerrit/server/restapi/change/Move.java
index df1d9b9..0f650dd 100644
--- a/java/com/google/gerrit/server/restapi/change/Move.java
+++ b/java/com/google/gerrit/server/restapi/change/Move.java
@@ -252,7 +252,7 @@
}
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(ctx, msgBuf.toString(), ChangeMessagesUtil.TAG_MOVE);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/PostReview.java b/java/com/google/gerrit/server/restapi/change/PostReview.java
index d06766d..ac19cce 100644
--- a/java/com/google/gerrit/server/restapi/change/PostReview.java
+++ b/java/com/google/gerrit/server/restapi/change/PostReview.java
@@ -322,7 +322,7 @@
if (!ccOrReviewer) {
// Check if user was already CCed or reviewing prior to this review.
ReviewerSet currentReviewers =
- approvalsUtil.getReviewers(db.get(), revision.getChangeResource().getNotes());
+ approvalsUtil.getReviewers(revision.getChangeResource().getNotes());
ccOrReviewer = currentReviewers.all().contains(id);
}
@@ -990,7 +990,7 @@
break;
}
ChangeUpdate u = ctx.getUpdate(psId);
- commentsUtil.putComments(ctx.getDb(), u, Status.PUBLISHED, toPublish);
+ commentsUtil.putComments(u, Status.PUBLISHED, toPublish);
comments.addAll(toPublish);
return !toPublish.isEmpty();
}
@@ -1079,7 +1079,7 @@
private Set<CommentSetEntry> readExistingComments(ChangeContext ctx) throws OrmException {
return commentsUtil
- .publishedByChange(ctx.getDb(), ctx.getNotes())
+ .publishedByChange(ctx.getNotes())
.stream()
.map(CommentSetEntry::create)
.collect(toSet());
@@ -1095,8 +1095,7 @@
private Map<String, Comment> changeDrafts(ChangeContext ctx) throws OrmException {
Map<String, Comment> drafts = new HashMap<>();
- for (Comment c :
- commentsUtil.draftByChangeAuthor(ctx.getDb(), ctx.getNotes(), user.getAccountId())) {
+ for (Comment c : commentsUtil.draftByChangeAuthor(ctx.getNotes(), user.getAccountId())) {
c.tag = in.tag;
drafts.put(c.key.uuid, c);
}
@@ -1106,8 +1105,7 @@
private Map<String, Comment> patchSetDrafts(ChangeContext ctx) throws OrmException {
Map<String, Comment> drafts = new HashMap<>();
for (Comment c :
- commentsUtil.draftByPatchSetAuthor(
- ctx.getDb(), psId, user.getAccountId(), ctx.getNotes())) {
+ commentsUtil.draftByPatchSetAuthor(psId, user.getAccountId(), ctx.getNotes())) {
drafts.put(c.key.uuid, c);
}
return drafts;
@@ -1387,7 +1385,7 @@
return current;
}
- private boolean insertMessage(ChangeContext ctx) throws OrmException {
+ private boolean insertMessage(ChangeContext ctx) {
String msg = Strings.nullToEmpty(in.message).trim();
StringBuilder buf = new StringBuilder();
@@ -1411,7 +1409,7 @@
message =
ChangeMessagesUtil.newMessage(
psId, user, ctx.getWhen(), "Patch Set " + psId.get() + ":" + buf, in.tag);
- cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(psId), message);
+ cmUtil.addChangeMessage(ctx.getUpdate(psId), message);
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/PutDescription.java b/java/com/google/gerrit/server/restapi/change/PutDescription.java
index 3b5edb2..a116fc1 100644
--- a/java/com/google/gerrit/server/restapi/change/PutDescription.java
+++ b/java/com/google/gerrit/server/restapi/change/PutDescription.java
@@ -117,7 +117,7 @@
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(
psId, ctx.getUser(), ctx.getWhen(), summary, ChangeMessagesUtil.TAG_SET_DESCRIPTION);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
index 72358bd..dfa32bf 100644
--- a/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
+++ b/java/com/google/gerrit/server/restapi/change/PutDraftComment.java
@@ -118,7 +118,7 @@
public boolean updateChange(ChangeContext ctx)
throws ResourceNotFoundException, OrmException, PatchListNotAvailableException {
Optional<Comment> maybeComment =
- commentsUtil.getDraft(ctx.getDb(), ctx.getNotes(), ctx.getIdentifiedUser(), key);
+ commentsUtil.getDraft(ctx.getNotes(), ctx.getIdentifiedUser(), key);
if (!maybeComment.isPresent()) {
// Disappeared out from under us. Can't easily fall back to insert,
// because the input might be missing required fields. Just give up.
@@ -141,15 +141,12 @@
// Updating the path alters the primary key, which isn't possible.
// Delete then recreate the comment instead of an update.
- commentsUtil.deleteComments(ctx.getDb(), update, Collections.singleton(origComment));
+ commentsUtil.deleteComments(update, Collections.singleton(origComment));
comment.key.filename = in.path;
}
setCommentRevId(comment, patchListCache, ctx.getChange(), ps);
commentsUtil.putComments(
- ctx.getDb(),
- update,
- Status.DRAFT,
- Collections.singleton(update(comment, in, ctx.getWhen())));
+ update, Status.DRAFT, Collections.singleton(update(comment, in, ctx.getWhen())));
ctx.dontBumpLastUpdatedOn();
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/PutTopic.java b/java/com/google/gerrit/server/restapi/change/PutTopic.java
index 7f56c91..60d5088 100644
--- a/java/com/google/gerrit/server/restapi/change/PutTopic.java
+++ b/java/com/google/gerrit/server/restapi/change/PutTopic.java
@@ -123,7 +123,7 @@
ChangeMessage cmsg =
ChangeMessagesUtil.newMessage(ctx, summary, ChangeMessagesUtil.TAG_SET_TOPIC);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/Rebuild.java b/java/com/google/gerrit/server/restapi/change/Rebuild.java
deleted file mode 100644
index dc390cc..0000000
--- a/java/com/google/gerrit/server/restapi/change/Rebuild.java
+++ /dev/null
@@ -1,109 +0,0 @@
-// Copyright (C) 2016 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.restapi.change;
-
-import static java.util.stream.Collectors.joining;
-
-import com.google.gerrit.extensions.common.Input;
-import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.IdString;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.extensions.restapi.RestModifyView;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.change.ChangeResource;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.util.List;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-
-@Singleton
-public class Rebuild implements RestModifyView<ChangeResource, Input> {
-
- private final Provider<ReviewDb> db;
- private final NotesMigration migration;
- private final ChangeRebuilder rebuilder;
- private final ChangeBundleReader bundleReader;
- private final CommentsUtil commentsUtil;
- private final ChangeNotes.Factory notesFactory;
-
- @Inject
- Rebuild(
- Provider<ReviewDb> db,
- NotesMigration migration,
- ChangeRebuilder rebuilder,
- ChangeBundleReader bundleReader,
- CommentsUtil commentsUtil,
- ChangeNotes.Factory notesFactory) {
- this.db = db;
- this.migration = migration;
- this.rebuilder = rebuilder;
- this.bundleReader = bundleReader;
- this.commentsUtil = commentsUtil;
- this.notesFactory = notesFactory;
- }
-
- @Override
- public BinaryResult apply(ChangeResource rsrc, Input input)
- throws ResourceNotFoundException, IOException, OrmException, ConfigInvalidException,
- ResourceConflictException {
- if (!migration.commitChangeWrites()) {
- throw new ResourceNotFoundException();
- }
- if (!migration.readChanges()) {
- // ChangeBundle#fromNotes currently doesn't work if reading isn't enabled,
- // so don't attempt a diff.
- rebuild(rsrc);
- return BinaryResult.create("Rebuilt change successfully");
- }
-
- // Not the same transaction as the rebuild, so may result in spurious diffs
- // in the case of races. This should be easy enough to detect by rerunning.
- ChangeBundle reviewDbBundle =
- bundleReader.fromReviewDb(ReviewDbUtil.unwrapDb(db.get()), rsrc.getId());
- if (reviewDbBundle == null) {
- throw new ResourceConflictException("change is missing in ReviewDb");
- }
- rebuild(rsrc);
- ChangeNotes notes = notesFactory.create(db.get(), rsrc.getChange().getProject(), rsrc.getId());
- ChangeBundle noteDbBundle = ChangeBundle.fromNotes(commentsUtil, notes);
- List<String> diffs = reviewDbBundle.differencesFrom(noteDbBundle);
- if (diffs.isEmpty()) {
- return BinaryResult.create("No differences between ReviewDb and NoteDb");
- }
- return BinaryResult.create(
- diffs.stream().collect(joining("\n", "Differences between ReviewDb and NoteDb:\n", "\n")));
- }
-
- private void rebuild(ChangeResource rsrc)
- throws ResourceNotFoundException, OrmException, IOException {
- try {
- rebuilder.rebuild(db.get(), rsrc.getId());
- } catch (NoSuchChangeException e) {
- throw new ResourceNotFoundException(IdString.fromDecoded(rsrc.getId().toString()));
- }
- }
-}
diff --git a/java/com/google/gerrit/server/restapi/change/Restore.java b/java/com/google/gerrit/server/restapi/change/Restore.java
index d6f9e2b..4411766 100644
--- a/java/com/google/gerrit/server/restapi/change/Restore.java
+++ b/java/com/google/gerrit/server/restapi/change/Restore.java
@@ -130,7 +130,7 @@
update.setStatus(change.getStatus());
message = newMessage(ctx);
- cmUtil.addChangeMessage(ctx.getDb(), update, message);
+ cmUtil.addChangeMessage(update, message);
return true;
}
diff --git a/java/com/google/gerrit/server/restapi/change/Revert.java b/java/com/google/gerrit/server/restapi/change/Revert.java
index 7309fde..dfaad5a 100644
--- a/java/com/google/gerrit/server/restapi/change/Revert.java
+++ b/java/com/google/gerrit/server/restapi/change/Revert.java
@@ -231,7 +231,7 @@
ins.setNotify(input.notify);
ins.setAccountsToNotify(accountsToNotify);
- ReviewerSet reviewerSet = approvalsUtil.getReviewers(db.get(), notes);
+ ReviewerSet reviewerSet = approvalsUtil.getReviewers(notes);
Set<Account.Id> reviewers = new HashSet<>();
reviewers.add(changeToRevert.getOwner());
@@ -318,7 +318,7 @@
}
@Override
- public boolean updateChange(ChangeContext ctx) throws Exception {
+ public boolean updateChange(ChangeContext ctx) {
Change change = ctx.getChange();
PatchSet.Id patchSetId = change.currentPatchSetId();
ChangeMessage changeMessage =
@@ -326,7 +326,7 @@
ctx,
"Created a revert of this change as I" + computedChangeId.name(),
ChangeMessagesUtil.TAG_REVERT);
- cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(patchSetId), changeMessage);
+ cmUtil.addChangeMessage(ctx.getUpdate(patchSetId), changeMessage);
return true;
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java b/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
index d88489e..eb79b79 100644
--- a/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
+++ b/java/com/google/gerrit/server/restapi/change/ReviewerRecommender.java
@@ -27,7 +27,6 @@
import com.google.gerrit.index.query.QueryParseException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.FanOutExecutor;
import com.google.gerrit.server.change.ReviewerSuggestion;
@@ -80,7 +79,6 @@
private final PluginMapContext<ReviewerSuggestion> reviewerSuggestionPluginMap;
private final Provider<InternalChangeQuery> queryProvider;
private final ExecutorService executor;
- private final Provider<ReviewDb> dbProvider;
private final ApprovalsUtil approvalsUtil;
@Inject
@@ -89,7 +87,6 @@
PluginMapContext<ReviewerSuggestion> reviewerSuggestionPluginMap,
Provider<InternalChangeQuery> queryProvider,
@FanOutExecutor ExecutorService executor,
- Provider<ReviewDb> dbProvider,
ApprovalsUtil approvalsUtil,
@GerritServerConfig Config config) {
this.changeQueryBuilder = changeQueryBuilder;
@@ -97,7 +94,6 @@
this.queryProvider = queryProvider;
this.reviewerSuggestionPluginMap = reviewerSuggestionPluginMap;
this.executor = executor;
- this.dbProvider = dbProvider;
this.approvalsUtil = approvalsUtil;
}
@@ -183,7 +179,7 @@
// Remove existing reviewers
approvalsUtil
- .getReviewers(dbProvider.get(), changeNotes)
+ .getReviewers(changeNotes)
.byState(REVIEWER)
.forEach(
r -> {
diff --git a/java/com/google/gerrit/server/restapi/change/Reviewers.java b/java/com/google/gerrit/server/restapi/change/Reviewers.java
index f0aef13..cf69080 100644
--- a/java/com/google/gerrit/server/restapi/change/Reviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/Reviewers.java
@@ -23,14 +23,12 @@
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.restapi.account.AccountsCollection;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
@@ -39,7 +37,6 @@
@Singleton
public class Reviewers implements ChildCollection<ChangeResource, ReviewerResource> {
private final DynamicMap<RestView<ReviewerResource>> views;
- private final Provider<ReviewDb> dbProvider;
private final ApprovalsUtil approvalsUtil;
private final AccountsCollection accounts;
private final ReviewerResource.Factory resourceFactory;
@@ -47,13 +44,11 @@
@Inject
Reviewers(
- Provider<ReviewDb> dbProvider,
ApprovalsUtil approvalsUtil,
AccountsCollection accounts,
ReviewerResource.Factory resourceFactory,
DynamicMap<RestView<ReviewerResource>> views,
ListReviewers list) {
- this.dbProvider = dbProvider;
this.approvalsUtil = approvalsUtil;
this.accounts = accounts;
this.resourceFactory = resourceFactory;
@@ -99,6 +94,6 @@
}
private Collection<Account.Id> fetchAccountIds(ChangeResource rsrc) throws OrmException {
- return approvalsUtil.getReviewers(dbProvider.get(), rsrc.getNotes()).all();
+ return approvalsUtil.getReviewers(rsrc.getNotes()).all();
}
}
diff --git a/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java b/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
index b9b7a4f..60c9a54 100644
--- a/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
+++ b/java/com/google/gerrit/server/restapi/change/RevisionReviewers.java
@@ -24,14 +24,12 @@
import com.google.gerrit.extensions.restapi.TopLevelResource;
import com.google.gerrit.mail.Address;
import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.change.ReviewerResource;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.restapi.account.AccountsCollection;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import com.google.inject.Provider;
import com.google.inject.Singleton;
import java.io.IOException;
import java.util.Collection;
@@ -40,7 +38,6 @@
@Singleton
public class RevisionReviewers implements ChildCollection<RevisionResource, ReviewerResource> {
private final DynamicMap<RestView<ReviewerResource>> views;
- private final Provider<ReviewDb> dbProvider;
private final ApprovalsUtil approvalsUtil;
private final AccountsCollection accounts;
private final ReviewerResource.Factory resourceFactory;
@@ -48,13 +45,11 @@
@Inject
RevisionReviewers(
- Provider<ReviewDb> dbProvider,
ApprovalsUtil approvalsUtil,
AccountsCollection accounts,
ReviewerResource.Factory resourceFactory,
DynamicMap<RestView<ReviewerResource>> views,
ListRevisionReviewers list) {
- this.dbProvider = dbProvider;
this.approvalsUtil = approvalsUtil;
this.accounts = accounts;
this.resourceFactory = resourceFactory;
@@ -89,8 +84,7 @@
throw e;
}
}
- Collection<Account.Id> reviewers =
- approvalsUtil.getReviewers(dbProvider.get(), rsrc.getNotes()).all();
+ Collection<Account.Id> reviewers = approvalsUtil.getReviewers(rsrc.getNotes()).all();
// See if the id exists as a reviewer for this change
if (reviewers.contains(accountId)) {
return resourceFactory.create(rsrc, accountId);
diff --git a/java/com/google/gerrit/server/restapi/change/SetPrivateOp.java b/java/com/google/gerrit/server/restapi/change/SetPrivateOp.java
index 8aac92c..47427dd 100644
--- a/java/com/google/gerrit/server/restapi/change/SetPrivateOp.java
+++ b/java/com/google/gerrit/server/restapi/change/SetPrivateOp.java
@@ -87,7 +87,7 @@
privateStateChanged.fire(change, ps, ctx.getAccount(), ctx.getWhen());
}
- private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
+ private void addMessage(ChangeContext ctx, ChangeUpdate update) {
Change c = ctx.getChange();
StringBuilder buf = new StringBuilder(c.isPrivate() ? "Set private" : "Unset private");
@@ -104,6 +104,6 @@
c.isPrivate()
? ChangeMessagesUtil.TAG_SET_PRIVATE
: ChangeMessagesUtil.TAG_UNSET_PRIVATE);
- cmUtil.addChangeMessage(ctx.getDb(), update, cmsg);
+ cmUtil.addChangeMessage(update, cmsg);
}
}
diff --git a/java/com/google/gerrit/server/schema/BaseDataSourceType.java b/java/com/google/gerrit/server/schema/BaseDataSourceType.java
deleted file mode 100644
index 4b3a570..0000000
--- a/java/com/google/gerrit/server/schema/BaseDataSourceType.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import java.io.IOException;
-import java.io.InputStream;
-
-public abstract class BaseDataSourceType implements DataSourceType {
-
- private static final String DEFAULT_VALIDATION_QUERY = "select 1";
- private final String driver;
-
- protected BaseDataSourceType(String driver) {
- this.driver = driver;
- }
-
- @Override
- public final String getDriver() {
- return driver;
- }
-
- @Override
- public boolean usePool() {
- return true;
- }
-
- @Override
- public String getValidationQuery() {
- return DEFAULT_VALIDATION_QUERY;
- }
-
- @Override
- public ScriptRunner getIndexScript() throws IOException {
- return getScriptRunner("index_generic.sql");
- }
-
- protected static final ScriptRunner getScriptRunner(String path) throws IOException {
- if (path == null) {
- return ScriptRunner.NOOP;
- }
- ScriptRunner runner;
- try (InputStream in = ReviewDb.class.getResourceAsStream(path)) {
- if (in == null) {
- throw new IllegalStateException("SQL script " + path + " not found");
- }
- runner = new ScriptRunner(path, in);
- }
- return runner;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/DB2.java b/java/com/google/gerrit/server/schema/DB2.java
deleted file mode 100644
index fcf8c1f..0000000
--- a/java/com/google/gerrit/server/schema/DB2.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-public class DB2 extends BaseDataSourceType {
- private Config cfg;
-
- @Inject
- public DB2(@GerritServerConfig Config cfg) {
- super("com.ibm.db2.jcc.DB2Driver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbc = new ConfigSection(cfg, "database");
- b.append("jdbc:db2://");
- b.append(hostname(dbc.optional("hostname")));
- b.append(port(dbc.optional("port")));
- b.append("/");
- b.append(dbc.required("database"));
- return b.toString();
- }
-
- @Override
- public String getValidationQuery() {
- return "SELECT 1 FROM SYSIBM.SYSDUMMY1";
- }
-}
diff --git a/java/com/google/gerrit/server/schema/DataSourceModule.java b/java/com/google/gerrit/server/schema/DataSourceModule.java
deleted file mode 100644
index ee57c8b..0000000
--- a/java/com/google/gerrit/server/schema/DataSourceModule.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import com.google.inject.AbstractModule;
-import com.google.inject.name.Names;
-
-public class DataSourceModule extends AbstractModule {
-
- @Override
- protected void configure() {
- bind(DataSourceType.class).annotatedWith(Names.named("db2")).to(DB2.class);
- bind(DataSourceType.class).annotatedWith(Names.named("derby")).to(Derby.class);
- bind(DataSourceType.class).annotatedWith(Names.named("h2")).to(H2.class);
- bind(DataSourceType.class).annotatedWith(Names.named("jdbc")).to(JDBC.class);
- bind(DataSourceType.class).annotatedWith(Names.named("mariadb")).to(MariaDb.class);
- bind(DataSourceType.class).annotatedWith(Names.named("mysql")).to(MySql.class);
- bind(DataSourceType.class).annotatedWith(Names.named("oracle")).to(Oracle.class);
- bind(DataSourceType.class).annotatedWith(Names.named("postgresql")).to(PostgreSQL.class);
- /*
- * DatabaseMetaData.getDatabaseProductName() returns "sap db" for MaxDB.
- * For auto-detection of the DB type (com.google.gerrit.pgm.util.SiteProgram#getDbType)
- * we have to map "sap db" additionally to "maxdb", which is used for explicit configuration.
- */
- bind(DataSourceType.class).annotatedWith(Names.named("maxdb")).to(MaxDb.class);
- bind(DataSourceType.class).annotatedWith(Names.named("sap db")).to(MaxDb.class);
- bind(DataSourceType.class).annotatedWith(Names.named("hana")).to(HANA.class);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/DataSourceProvider.java b/java/com/google/gerrit/server/schema/DataSourceProvider.java
deleted file mode 100644
index d4cfaa6..0000000
--- a/java/com/google/gerrit/server/schema/DataSourceProvider.java
+++ /dev/null
@@ -1,206 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.extensions.events.LifecycleListener;
-import com.google.gerrit.extensions.persistence.DataSourceInterceptor;
-import com.google.gerrit.metrics.CallbackMetric1;
-import com.google.gerrit.metrics.Description;
-import com.google.gerrit.metrics.Field;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.ThreadSettingsConfig;
-import com.google.gwtorm.jdbc.SimpleDataSource;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
-import com.google.inject.Singleton;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.sql.SQLException;
-import java.util.Properties;
-import javax.sql.DataSource;
-import org.apache.commons.dbcp.BasicDataSource;
-import org.eclipse.jgit.lib.Config;
-
-/** Provides access to the DataSource. */
-@Singleton
-public class DataSourceProvider implements Provider<DataSource>, LifecycleListener {
- private static final String DATABASE_KEY = "database";
-
- private final Config cfg;
- private final MetricMaker metrics;
- private final Context ctx;
- private final DataSourceType dst;
- private final ThreadSettingsConfig threadSettingsConfig;
- private DataSource ds;
-
- @Inject
- protected DataSourceProvider(
- @GerritServerConfig Config cfg,
- MetricMaker metrics,
- ThreadSettingsConfig threadSettingsConfig,
- Context ctx,
- DataSourceType dst) {
- this.cfg = cfg;
- this.metrics = metrics;
- this.threadSettingsConfig = threadSettingsConfig;
- this.ctx = ctx;
- this.dst = dst;
- }
-
- @Override
- public synchronized DataSource get() {
- if (ds == null) {
- ds = open(cfg, ctx, dst);
- }
- return ds;
- }
-
- @Override
- public void start() {}
-
- @Override
- public synchronized void stop() {
- if (ds instanceof BasicDataSource) {
- try {
- ((BasicDataSource) ds).close();
- } catch (SQLException e) {
- // Ignore the close failure.
- }
- }
- }
-
- public enum Context {
- SINGLE_USER,
- MULTI_USER
- }
-
- private DataSource open(Config cfg, Context context, DataSourceType dst) {
- ConfigSection dbs = new ConfigSection(cfg, DATABASE_KEY);
- String driver = dbs.optional("driver");
- if (Strings.isNullOrEmpty(driver)) {
- driver = dst.getDriver();
- }
-
- String url = dbs.optional("url");
- if (Strings.isNullOrEmpty(url)) {
- url = dst.getUrl();
- }
-
- String username = dbs.optional("username");
- String password = dbs.optional("password");
- String interceptor = dbs.optional("dataSourceInterceptorClass");
-
- boolean usePool;
- if (context == Context.SINGLE_USER) {
- usePool = false;
- } else {
- usePool = cfg.getBoolean(DATABASE_KEY, "connectionpool", dst.usePool());
- }
-
- if (usePool) {
- final BasicDataSource lds = new BasicDataSource();
- lds.setDriverClassName(driver);
- lds.setUrl(url);
- if (username != null && !username.isEmpty()) {
- lds.setUsername(username);
- }
- if (password != null && !password.isEmpty()) {
- lds.setPassword(password);
- }
- int poolLimit = threadSettingsConfig.getDatabasePoolLimit();
- lds.setMaxActive(poolLimit);
- lds.setMinIdle(cfg.getInt(DATABASE_KEY, "poolminidle", 4));
- lds.setMaxIdle(cfg.getInt(DATABASE_KEY, "poolmaxidle", Math.min(poolLimit, 16)));
- lds.setMaxWait(
- ConfigUtil.getTimeUnit(
- cfg,
- DATABASE_KEY,
- null,
- "poolmaxwait",
- MILLISECONDS.convert(30, SECONDS),
- MILLISECONDS));
- lds.setInitialSize(lds.getMinIdle());
- long evictIdleTimeMs = 1000L * 60;
- lds.setMinEvictableIdleTimeMillis(evictIdleTimeMs);
- lds.setTimeBetweenEvictionRunsMillis(evictIdleTimeMs / 2);
- lds.setTestOnBorrow(true);
- lds.setTestOnReturn(true);
- lds.setValidationQuery(dst.getValidationQuery());
- lds.setValidationQueryTimeout(5);
- exportPoolMetrics(lds);
- return intercept(interceptor, lds);
- }
- // Don't use the connection pool.
- //
- try {
- final Properties p = new Properties();
- p.setProperty("driver", driver);
- p.setProperty("url", url);
- if (username != null) {
- p.setProperty("user", username);
- }
- if (password != null) {
- p.setProperty("password", password);
- }
- return intercept(interceptor, new SimpleDataSource(p));
- } catch (SQLException se) {
- throw new ProvisionException("Database unavailable", se);
- }
- }
-
- private void exportPoolMetrics(BasicDataSource pool) {
- CallbackMetric1<Boolean, Integer> cnt =
- metrics.newCallbackMetric(
- "sql/connection_pool/connections",
- Integer.class,
- new Description("SQL database connections").setGauge().setUnit("connections"),
- Field.ofBoolean("active"));
- metrics.newTrigger(
- cnt,
- () -> {
- synchronized (pool) {
- cnt.set(true, pool.getNumActive());
- cnt.set(false, pool.getNumIdle());
- }
- });
- }
-
- private DataSource intercept(String interceptor, DataSource ds) {
- if (interceptor == null) {
- return ds;
- }
- try {
- Constructor<?> c = Class.forName(interceptor).getConstructor();
- DataSourceInterceptor datasourceInterceptor = (DataSourceInterceptor) c.newInstance();
- return datasourceInterceptor.intercept("reviewDb", ds);
- } catch (ClassNotFoundException
- | SecurityException
- | NoSuchMethodException
- | IllegalArgumentException
- | InstantiationException
- | IllegalAccessException
- | InvocationTargetException e) {
- throw new ProvisionException("Cannot intercept datasource", e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/DataSourceType.java b/java/com/google/gerrit/server/schema/DataSourceType.java
deleted file mode 100644
index cbdcf0f..0000000
--- a/java/com/google/gerrit/server/schema/DataSourceType.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import java.io.IOException;
-
-/** Abstraction of a supported database platform */
-public interface DataSourceType {
-
- String getDriver();
-
- String getUrl();
-
- String getValidationQuery();
-
- boolean usePool();
-
- /**
- * Return a ScriptRunner that runs the index script. Must not return {@code null}, but may return
- * a ScriptRunner that does nothing.
- *
- * @throws IOException
- */
- ScriptRunner getIndexScript() throws IOException;
-}
diff --git a/java/com/google/gerrit/server/schema/DatabaseModule.java b/java/com/google/gerrit/server/schema/DatabaseModule.java
index 38a7751..c65b20e 100644
--- a/java/com/google/gerrit/server/schema/DatabaseModule.java
+++ b/java/com/google/gerrit/server/schema/DatabaseModule.java
@@ -14,13 +14,9 @@
package com.google.gerrit.server.schema;
-import static com.google.inject.Scopes.SINGLETON;
-
import com.google.gerrit.extensions.config.FactoryModule;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.GwtormChangeBundleReader;
-import com.google.gwtorm.jdbc.Database;
+import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.Key;
import com.google.inject.TypeLiteral;
@@ -31,11 +27,11 @@
protected void configure() {
TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
new TypeLiteral<SchemaFactory<ReviewDb>>() {};
- TypeLiteral<Database<ReviewDb>> database = new TypeLiteral<Database<ReviewDb>>() {};
-
bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
- bind(Key.get(schemaFactory, ReviewDbFactory.class)).to(database).in(SINGLETON);
- bind(database).toProvider(ReviewDbDatabaseProvider.class);
- bind(ChangeBundleReader.class).to(GwtormChangeBundleReader.class);
+ bind(Key.get(schemaFactory, ReviewDbFactory.class))
+ .toInstance(
+ () -> {
+ throw new OrmException("ReviewDb no longer exists");
+ });
}
}
diff --git a/java/com/google/gerrit/server/schema/Derby.java b/java/com/google/gerrit/server/schema/Derby.java
deleted file mode 100644
index 9fb761d..0000000
--- a/java/com/google/gerrit/server/schema/Derby.java
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-class Derby extends BaseDataSourceType {
-
- protected final Config cfg;
- private final SitePaths site;
-
- @Inject
- Derby(@GerritServerConfig Config cfg, SitePaths site) {
- super("org.apache.derby.jdbc.EmbeddedDriver");
- this.cfg = cfg;
- this.site = site;
- }
-
- @Override
- public String getUrl() {
- String database = cfg.getString("database", null, "database");
- if (database == null || database.isEmpty()) {
- database = "db/ReviewDB";
- }
- return "jdbc:derby:" + site.resolve(database).toString() + ";create=true";
- }
-
- @Override
- public String getValidationQuery() {
- return "values 1";
- }
-}
diff --git a/java/com/google/gerrit/server/schema/GroupBundle.java b/java/com/google/gerrit/server/schema/GroupBundle.java
deleted file mode 100644
index 26cd96a..0000000
--- a/java/com/google/gerrit/server/schema/GroupBundle.java
+++ /dev/null
@@ -1,778 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.collect.ImmutableSet.toImmutableSet;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.checkColumns;
-import static java.util.Comparator.naturalOrder;
-import static java.util.Comparator.nullsLast;
-import static java.util.stream.Collectors.toList;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Multimaps;
-import com.google.common.collect.Streams;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.AccountGroupById;
-import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
-import com.google.gerrit.reviewdb.client.AccountGroupMember;
-import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
-import com.google.gerrit.server.group.InternalGroup;
-import com.google.gerrit.server.group.db.AuditLogReader;
-import com.google.gerrit.server.group.db.GroupConfig;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Comparator;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
-import java.util.function.Function;
-import java.util.stream.Stream;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Repository;
-
-/**
- * A bundle of all entities rooted at a single {@link AccountGroup} entity.
- *
- * <p>Used primarily during the migration process. Most callers should prefer {@link InternalGroup}
- * instead.
- */
-@AutoValue
-abstract class GroupBundle {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- static {
- // Initialization-time checks that the column set hasn't changed since the
- // last time this file was updated.
- checkColumns(AccountGroup.NameKey.class, 1);
- checkColumns(AccountGroup.UUID.class, 1);
- checkColumns(AccountGroup.Id.class, 1);
- checkColumns(AccountGroup.class, 1, 2, 4, 7, 9, 10, 11);
-
- checkColumns(AccountGroupById.Key.class, 1, 2);
- checkColumns(AccountGroupById.class, 1);
-
- checkColumns(AccountGroupByIdAud.Key.class, 1, 2, 3);
- checkColumns(AccountGroupByIdAud.class, 1, 2, 3, 4);
-
- checkColumns(AccountGroupMember.Key.class, 1, 2);
- checkColumns(AccountGroupMember.class, 1);
-
- checkColumns(AccountGroupMemberAudit.Key.class, 1, 2, 3);
- checkColumns(AccountGroupMemberAudit.class, 1, 2, 3, 4);
- }
-
- public enum Source {
- REVIEW_DB("ReviewDb"),
- NOTE_DB("NoteDb");
-
- private final String name;
-
- private Source(String name) {
- this.name = name;
- }
-
- @Override
- public String toString() {
- return name;
- }
- }
-
- @Singleton
- public static class Factory {
- private final AuditLogReader auditLogReader;
-
- @Inject
- Factory(AuditLogReader auditLogReader) {
- this.auditLogReader = auditLogReader;
- }
-
- public GroupBundle fromNoteDb(
- Project.NameKey projectName, Repository repo, AccountGroup.UUID uuid)
- throws ConfigInvalidException, IOException {
- GroupConfig groupConfig = GroupConfig.loadForGroup(projectName, repo, uuid);
- InternalGroup internalGroup = groupConfig.getLoadedGroup().get();
- AccountGroup.Id groupId = internalGroup.getId();
-
- AccountGroup accountGroup =
- new AccountGroup(
- internalGroup.getNameKey(),
- internalGroup.getId(),
- internalGroup.getGroupUUID(),
- internalGroup.getCreatedOn());
- accountGroup.setDescription(internalGroup.getDescription());
- accountGroup.setOwnerGroupUUID(internalGroup.getOwnerGroupUUID());
- accountGroup.setVisibleToAll(internalGroup.isVisibleToAll());
-
- return create(
- Source.NOTE_DB,
- accountGroup,
- internalGroup
- .getMembers()
- .stream()
- .map(
- accountId ->
- new AccountGroupMember(new AccountGroupMember.Key(accountId, groupId)))
- .collect(toImmutableSet()),
- auditLogReader.getMembersAudit(repo, uuid),
- internalGroup
- .getSubgroups()
- .stream()
- .map(
- subgroupUuid ->
- new AccountGroupById(new AccountGroupById.Key(groupId, subgroupUuid)))
- .collect(toImmutableSet()),
- auditLogReader.getSubgroupsAudit(repo, uuid));
- }
-
- public static GroupBundle fromReviewDb(ReviewDb db, AccountGroup.UUID groupUuid)
- throws OrmException {
- JdbcSchema jdbcSchema = ReviewDbWrapper.unwrapJbdcSchema(db);
- AccountGroup group = readAccountGroupFromReviewDb(jdbcSchema, groupUuid);
- AccountGroup.Id groupId = group.getId();
-
- return create(
- Source.REVIEW_DB,
- group,
- readAccountGroupMembersFromReviewDb(jdbcSchema, groupId),
- readAccountGroupMemberAuditsFromReviewDb(jdbcSchema, groupId),
- readAccountGroupSubgroupsFromReviewDb(jdbcSchema, groupId),
- readAccountGroupSubgroupAuditsFromReviewDb(jdbcSchema, groupId));
- }
-
- private static AccountGroup readAccountGroupFromReviewDb(
- JdbcSchema jdbcSchema, AccountGroup.UUID groupUuid) throws OrmException {
- try (Statement stmt = jdbcSchema.getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT group_id,"
- + " name,"
- + " created_on,"
- + " description,"
- + " owner_group_uuid,"
- + " visible_to_all"
- + " FROM account_groups"
- + " WHERE group_uuid = '"
- + groupUuid.get()
- + "'")) {
- if (!rs.next()) {
- throw new OrmException(String.format("Group %s not found", groupUuid));
- }
-
- AccountGroup.Id groupId = new AccountGroup.Id(rs.getInt(1));
- AccountGroup.NameKey groupName = new AccountGroup.NameKey(rs.getString(2));
- Timestamp createdOn = rs.getTimestamp(3);
- String description = rs.getString(4);
- AccountGroup.UUID ownerGroupUuid = new AccountGroup.UUID(rs.getString(5));
- boolean visibleToAll = "Y".equals(rs.getString(6));
-
- AccountGroup group = new AccountGroup(groupName, groupId, groupUuid, createdOn);
- group.setDescription(description);
- group.setOwnerGroupUUID(ownerGroupUuid);
- group.setVisibleToAll(visibleToAll);
-
- if (rs.next()) {
- throw new OrmException(String.format("Group UUID %s is ambiguous", groupUuid));
- }
-
- return group;
- } catch (SQLException e) {
- throw new OrmException(
- String.format("Failed to read account group %s from ReviewDb", groupUuid.get()), e);
- }
- }
-
- private static List<AccountGroupMember> readAccountGroupMembersFromReviewDb(
- JdbcSchema jdbcSchema, AccountGroup.Id groupId) throws OrmException {
- try (Statement stmt = jdbcSchema.getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT account_id"
- + " FROM account_group_members"
- + " WHERE group_id = '"
- + groupId.get()
- + "'")) {
- List<AccountGroupMember> members = new ArrayList<>();
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
- members.add(new AccountGroupMember(new AccountGroupMember.Key(accountId, groupId)));
- }
- return members;
- } catch (SQLException e) {
- throw new OrmException(
- String.format(
- "Failed to read members of account group %s from ReviewDb", groupId.get()),
- e);
- }
- }
-
- private static List<AccountGroupMemberAudit> readAccountGroupMemberAuditsFromReviewDb(
- JdbcSchema jdbcSchema, AccountGroup.Id groupId) throws OrmException {
- try (Statement stmt = jdbcSchema.getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT account_id, added_by, added_on, removed_by, removed_on"
- + " FROM account_group_members_audit"
- + " WHERE group_id = '"
- + groupId.get()
- + "'")) {
- List<AccountGroupMemberAudit> audits = new ArrayList<>();
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
-
- Account.Id addedBy = new Account.Id(rs.getInt(2));
- Timestamp addedOn = rs.getTimestamp(3);
-
- Timestamp removedOn = rs.getTimestamp(5);
- Account.Id removedBy = removedOn != null ? new Account.Id(rs.getInt(4)) : null;
-
- AccountGroupMemberAudit.Key key =
- new AccountGroupMemberAudit.Key(accountId, groupId, addedOn);
- AccountGroupMemberAudit audit = new AccountGroupMemberAudit(key, addedBy);
- audit.removed(removedBy, removedOn);
- audits.add(audit);
- }
- return audits;
- } catch (SQLException e) {
- throw new OrmException(
- String.format(
- "Failed to read member audits of account group %s from ReviewDb", groupId.get()),
- e);
- }
- }
-
- private static List<AccountGroupById> readAccountGroupSubgroupsFromReviewDb(
- JdbcSchema jdbcSchema, AccountGroup.Id groupId) throws OrmException {
- try (Statement stmt = jdbcSchema.getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT include_uuid"
- + " FROM account_group_by_id"
- + " WHERE group_id = '"
- + groupId.get()
- + "'")) {
- List<AccountGroupById> subgroups = new ArrayList<>();
- while (rs.next()) {
- AccountGroup.UUID includedGroupUuid = new AccountGroup.UUID(rs.getString(1));
- subgroups.add(new AccountGroupById(new AccountGroupById.Key(groupId, includedGroupUuid)));
- }
- return subgroups;
- } catch (SQLException e) {
- throw new OrmException(
- String.format(
- "Failed to read subgroups of account group %s from ReviewDb", groupId.get()),
- e);
- }
- }
-
- private static List<AccountGroupByIdAud> readAccountGroupSubgroupAuditsFromReviewDb(
- JdbcSchema jdbcSchema, AccountGroup.Id groupId) throws OrmException {
- try (Statement stmt = jdbcSchema.getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT include_uuid, added_by, added_on, removed_by, removed_on"
- + " FROM account_group_by_id_aud"
- + " WHERE group_id = '"
- + groupId.get()
- + "'")) {
- List<AccountGroupByIdAud> audits = new ArrayList<>();
- while (rs.next()) {
- AccountGroup.UUID includedGroupUuid = new AccountGroup.UUID(rs.getString(1));
-
- Account.Id addedBy = new Account.Id(rs.getInt(2));
- Timestamp addedOn = rs.getTimestamp(3);
-
- Timestamp removedOn = rs.getTimestamp(5);
- Account.Id removedBy = removedOn != null ? new Account.Id(rs.getInt(4)) : null;
-
- AccountGroupByIdAud.Key key =
- new AccountGroupByIdAud.Key(groupId, includedGroupUuid, addedOn);
- AccountGroupByIdAud audit = new AccountGroupByIdAud(key, addedBy);
- audit.removed(removedBy, removedOn);
- audits.add(audit);
- }
- return audits;
- } catch (SQLException e) {
- throw new OrmException(
- String.format(
- "Failed to read subgroup audits of account group %s from ReviewDb", groupId.get()),
- e);
- }
- }
- }
-
- private static final Comparator<AccountGroupMember> ACCOUNT_GROUP_MEMBER_COMPARATOR =
- Comparator.comparingInt((AccountGroupMember m) -> m.getAccountGroupId().get())
- .thenComparingInt(m -> m.getAccountId().get());
-
- private static final Comparator<AccountGroupMemberAudit> ACCOUNT_GROUP_MEMBER_AUDIT_COMPARATOR =
- Comparator.comparingInt((AccountGroupMemberAudit a) -> a.getGroupId().get())
- .thenComparing(AccountGroupMemberAudit::getAddedOn)
- .thenComparingInt(a -> a.getAddedBy().get())
- .thenComparingInt(a -> a.getMemberId().get())
- .thenComparing(
- a -> a.getRemovedBy() != null ? a.getRemovedBy().get() : null,
- nullsLast(naturalOrder()))
- .thenComparing(AccountGroupMemberAudit::getRemovedOn, nullsLast(naturalOrder()));
-
- private static final Comparator<AccountGroupById> ACCOUNT_GROUP_BY_ID_COMPARATOR =
- Comparator.comparingInt((AccountGroupById m) -> m.getGroupId().get())
- .thenComparing(AccountGroupById::getIncludeUUID);
-
- private static final Comparator<AccountGroupByIdAud> ACCOUNT_GROUP_BY_ID_AUD_COMPARATOR =
- Comparator.comparingInt((AccountGroupByIdAud a) -> a.getGroupId().get())
- .thenComparing(AccountGroupByIdAud::getAddedOn)
- .thenComparingInt(a -> a.getAddedBy().get())
- .thenComparing(AccountGroupByIdAud::getIncludeUUID)
- .thenComparing(
- a -> a.getRemovedBy() != null ? a.getRemovedBy().get() : null,
- nullsLast(naturalOrder()))
- .thenComparing(AccountGroupByIdAud::getRemovedOn, nullsLast(naturalOrder()));
-
- private static final Comparator<AuditEntry> AUDIT_ENTRY_COMPARATOR =
- Comparator.comparing(AuditEntry::getTimestamp)
- .thenComparing(AuditEntry::getAction, Comparator.comparingInt(Action::getOrder));
-
- public static GroupBundle create(
- Source source,
- AccountGroup group,
- Iterable<AccountGroupMember> members,
- Iterable<AccountGroupMemberAudit> memberAudit,
- Iterable<AccountGroupById> byId,
- Iterable<AccountGroupByIdAud> byIdAudit) {
- AccountGroup.UUID uuid = group.getGroupUUID();
- return new AutoValue_GroupBundle.Builder()
- .source(source)
- .group(group)
- .members(
- logIfNotUnique(
- source, uuid, members, ACCOUNT_GROUP_MEMBER_COMPARATOR, AccountGroupMember.class))
- .memberAudit(
- logIfNotUnique(
- source,
- uuid,
- memberAudit,
- ACCOUNT_GROUP_MEMBER_AUDIT_COMPARATOR,
- AccountGroupMemberAudit.class))
- .byId(
- logIfNotUnique(
- source, uuid, byId, ACCOUNT_GROUP_BY_ID_COMPARATOR, AccountGroupById.class))
- .byIdAudit(
- logIfNotUnique(
- source,
- uuid,
- byIdAudit,
- ACCOUNT_GROUP_BY_ID_AUD_COMPARATOR,
- AccountGroupByIdAud.class))
- .build();
- }
-
- private static <T> ImmutableSet<T> logIfNotUnique(
- Source source,
- AccountGroup.UUID uuid,
- Iterable<T> iterable,
- Comparator<T> comparator,
- Class<T> clazz) {
- List<T> list = Streams.stream(iterable).sorted(comparator).collect(toList());
- ImmutableSet<T> set = ImmutableSet.copyOf(list);
- if (set.size() != list.size()) {
- // One way this can happen is that distinct audit entities can compare equal, because
- // AccountGroup{MemberAudit,ByIdAud}.Key does not include the addedOn timestamp in its
- // members() list. However, this particular issue only applies to pure adds, since removedOn
- // *is* included in equality. As a result, if this happens, it means the audit log is already
- // corrupt, and it's not clear if we can programmatically repair it. For migrating to NoteDb,
- // we'll try our best to recreate it, but no guarantees it will match the real sequence of
- // attempted operations, which is in any case lost in the mists of time.
- logger.atWarning().log(
- "group %s in %s has duplicate %s entities: %s",
- uuid, source, clazz.getSimpleName(), iterable);
- }
- return set;
- }
-
- static Builder builder() {
- return new AutoValue_GroupBundle.Builder().members().memberAudit().byId().byIdAudit();
- }
-
- public static ImmutableList<String> compareWithAudits(
- GroupBundle reviewDbBundle, GroupBundle noteDbBundle) {
- return compare(reviewDbBundle, noteDbBundle, true);
- }
-
- public static ImmutableList<String> compareWithoutAudits(
- GroupBundle reviewDbBundle, GroupBundle noteDbBundle) {
- return compare(reviewDbBundle, noteDbBundle, false);
- }
-
- private static ImmutableList<String> compare(
- GroupBundle reviewDbBundle, GroupBundle noteDbBundle, boolean compareAudits) {
- // Normalize the ReviewDb bundle to what we expect in NoteDb. This means that values in error
- // messages will not reflect the actual data in ReviewDb, but it will make it easier for humans
- // to see the difference.
- reviewDbBundle = reviewDbBundle.truncateToSecond();
- AccountGroup reviewDbGroup = new AccountGroup(reviewDbBundle.group());
- reviewDbGroup.setDescription(Strings.emptyToNull(reviewDbGroup.getDescription()));
- reviewDbBundle = reviewDbBundle.toBuilder().group(reviewDbGroup).build();
-
- checkArgument(
- reviewDbBundle.source() == Source.REVIEW_DB,
- "first bundle's source must be %s: %s",
- Source.REVIEW_DB,
- reviewDbBundle);
- checkArgument(
- noteDbBundle.source() == Source.NOTE_DB,
- "second bundle's source must be %s: %s",
- Source.NOTE_DB,
- noteDbBundle);
-
- ImmutableList.Builder<String> result = ImmutableList.builder();
- if (!reviewDbBundle.group().equals(noteDbBundle.group())) {
- result.add(
- "AccountGroups differ\n"
- + ("ReviewDb: " + reviewDbBundle.group() + "\n")
- + ("NoteDb : " + noteDbBundle.group()));
- }
- if (!reviewDbBundle.members().equals(noteDbBundle.members())) {
- result.add(
- "AccountGroupMembers differ\n"
- + ("ReviewDb: " + reviewDbBundle.members() + "\n")
- + ("NoteDb : " + noteDbBundle.members()));
- }
- if (compareAudits
- && !areMemberAuditsConsideredEqual(
- reviewDbBundle.memberAudit(), noteDbBundle.memberAudit())) {
- result.add(
- "AccountGroupMemberAudits differ\n"
- + ("ReviewDb: " + reviewDbBundle.memberAudit() + "\n")
- + ("NoteDb : " + noteDbBundle.memberAudit()));
- }
- if (!reviewDbBundle.byId().equals(noteDbBundle.byId())) {
- result.add(
- "AccountGroupByIds differ\n"
- + ("ReviewDb: " + reviewDbBundle.byId() + "\n")
- + ("NoteDb : " + noteDbBundle.byId()));
- }
- if (compareAudits
- && !areByIdAuditsConsideredEqual(reviewDbBundle.byIdAudit(), noteDbBundle.byIdAudit())) {
- result.add(
- "AccountGroupByIdAudits differ\n"
- + ("ReviewDb: " + reviewDbBundle.byIdAudit() + "\n")
- + ("NoteDb : " + noteDbBundle.byIdAudit()));
- }
- return result.build();
- }
-
- private static boolean areMemberAuditsConsideredEqual(
- ImmutableSet<AccountGroupMemberAudit> reviewDbMemberAudits,
- ImmutableSet<AccountGroupMemberAudit> noteDbMemberAudits) {
- ListMultimap<String, AuditEntry> reviewDbMemberAuditsByMemberId =
- toMemberAuditEntriesByMemberId(reviewDbMemberAudits);
- ListMultimap<String, AuditEntry> noteDbMemberAuditsByMemberId =
- toMemberAuditEntriesByMemberId(noteDbMemberAudits);
-
- return areConsideredEqual(reviewDbMemberAuditsByMemberId, noteDbMemberAuditsByMemberId);
- }
-
- private static boolean areByIdAuditsConsideredEqual(
- ImmutableSet<AccountGroupByIdAud> reviewDbByIdAudits,
- ImmutableSet<AccountGroupByIdAud> noteDbByIdAudits) {
- ListMultimap<String, AuditEntry> reviewDbByIdAuditsById =
- toByIdAuditEntriesById(reviewDbByIdAudits);
- ListMultimap<String, AuditEntry> noteDbByIdAuditsById =
- toByIdAuditEntriesById(noteDbByIdAudits);
-
- return areConsideredEqual(reviewDbByIdAuditsById, noteDbByIdAuditsById);
- }
-
- private static ListMultimap<String, AuditEntry> toMemberAuditEntriesByMemberId(
- ImmutableSet<AccountGroupMemberAudit> memberAudits) {
- return memberAudits
- .stream()
- .flatMap(GroupBundle::toAuditEntries)
- .collect(
- Multimaps.toMultimap(
- AuditEntry::getTarget,
- Function.identity(),
- MultimapBuilder.hashKeys().arrayListValues()::build));
- }
-
- private static Stream<AuditEntry> toAuditEntries(AccountGroupMemberAudit memberAudit) {
- AuditEntry additionAuditEntry =
- AuditEntry.create(
- Action.ADD,
- memberAudit.getAddedBy(),
- memberAudit.getMemberId(),
- memberAudit.getAddedOn());
- if (memberAudit.isActive()) {
- return Stream.of(additionAuditEntry);
- }
-
- AuditEntry removalAuditEntry =
- AuditEntry.create(
- Action.REMOVE,
- memberAudit.getRemovedBy(),
- memberAudit.getMemberId(),
- memberAudit.getRemovedOn());
- return Stream.of(additionAuditEntry, removalAuditEntry);
- }
-
- private static ListMultimap<String, AuditEntry> toByIdAuditEntriesById(
- ImmutableSet<AccountGroupByIdAud> byIdAudits) {
- return byIdAudits
- .stream()
- .flatMap(GroupBundle::toAuditEntries)
- .collect(
- Multimaps.toMultimap(
- AuditEntry::getTarget,
- Function.identity(),
- MultimapBuilder.hashKeys().arrayListValues()::build));
- }
-
- private static Stream<AuditEntry> toAuditEntries(AccountGroupByIdAud byIdAudit) {
- AuditEntry additionAuditEntry =
- AuditEntry.create(
- Action.ADD, byIdAudit.getAddedBy(), byIdAudit.getIncludeUUID(), byIdAudit.getAddedOn());
- if (byIdAudit.isActive()) {
- return Stream.of(additionAuditEntry);
- }
-
- AuditEntry removalAuditEntry =
- AuditEntry.create(
- Action.REMOVE,
- byIdAudit.getRemovedBy(),
- byIdAudit.getIncludeUUID(),
- byIdAudit.getRemovedOn());
- return Stream.of(additionAuditEntry, removalAuditEntry);
- }
-
- /**
- * Determines whether the audit log entries are equal except for redundant entries. Entries of the
- * same type (addition/removal) which follow directly on each other according to their timestamp
- * are considered redundant.
- */
- private static boolean areConsideredEqual(
- ListMultimap<String, AuditEntry> reviewDbMemberAuditsByTarget,
- ListMultimap<String, AuditEntry> noteDbMemberAuditsByTarget) {
- for (String target : reviewDbMemberAuditsByTarget.keySet()) {
- ImmutableList<AuditEntry> reviewDbAuditEntries =
- reviewDbMemberAuditsByTarget
- .get(target)
- .stream()
- .sorted(AUDIT_ENTRY_COMPARATOR)
- .collect(toImmutableList());
- ImmutableSet<AuditEntry> noteDbAuditEntries =
- noteDbMemberAuditsByTarget
- .get(target)
- .stream()
- .sorted(AUDIT_ENTRY_COMPARATOR)
- .collect(toImmutableSet());
-
- int reviewDbIndex = 0;
- for (AuditEntry noteDbAuditEntry : noteDbAuditEntries) {
- Set<AuditEntry> redundantReviewDbAuditEntries = new HashSet<>();
- while (reviewDbIndex < reviewDbAuditEntries.size()) {
- AuditEntry reviewDbAuditEntry = reviewDbAuditEntries.get(reviewDbIndex);
- if (!reviewDbAuditEntry.getAction().equals(noteDbAuditEntry.getAction())) {
- break;
- }
- redundantReviewDbAuditEntries.add(reviewDbAuditEntry);
- reviewDbIndex++;
- }
-
- // The order of the entries is not perfect as ReviewDb included milliseconds for timestamps
- // and we cut off everything below seconds due to NoteDb/git. Consequently, we don't have a
- // way to know in this method in which exact order additions/removals within the same second
- // happened. The best we can do is to group all additions within the same second as
- // redundant entries and the removals afterward. To compensate that we possibly group
- // non-redundant additions/removals, we also accept NoteDb audit entries which just occur
- // anywhere as ReviewDb audit entries.
- if (!redundantReviewDbAuditEntries.contains(noteDbAuditEntry)
- && !reviewDbAuditEntries.contains(noteDbAuditEntry)) {
- return false;
- }
- }
-
- if (reviewDbIndex < reviewDbAuditEntries.size()) {
- // Some of the ReviewDb audit log entries aren't matched by NoteDb audit log entries.
- return false;
- }
- }
- return true;
- }
-
- public AccountGroup.Id id() {
- return group().getId();
- }
-
- public AccountGroup.UUID uuid() {
- return group().getGroupUUID();
- }
-
- public abstract Source source();
-
- public abstract AccountGroup group();
-
- public abstract ImmutableSet<AccountGroupMember> members();
-
- public abstract ImmutableSet<AccountGroupMemberAudit> memberAudit();
-
- public abstract ImmutableSet<AccountGroupById> byId();
-
- public abstract ImmutableSet<AccountGroupByIdAud> byIdAudit();
-
- public abstract Builder toBuilder();
-
- public GroupBundle truncateToSecond() {
- AccountGroup newGroup = new AccountGroup(group());
- if (newGroup.getCreatedOn() != null) {
- newGroup.setCreatedOn(TimeUtil.truncateToSecond(newGroup.getCreatedOn()));
- }
- return toBuilder()
- .group(newGroup)
- .memberAudit(
- memberAudit().stream().map(GroupBundle::truncateToSecond).collect(toImmutableSet()))
- .byIdAudit(
- byIdAudit().stream().map(GroupBundle::truncateToSecond).collect(toImmutableSet()))
- .build();
- }
-
- private static AccountGroupMemberAudit truncateToSecond(AccountGroupMemberAudit a) {
- AccountGroupMemberAudit result =
- new AccountGroupMemberAudit(
- new AccountGroupMemberAudit.Key(
- a.getKey().getParentKey(),
- a.getKey().getGroupId(),
- TimeUtil.truncateToSecond(a.getKey().getAddedOn())),
- a.getAddedBy());
- if (a.getRemovedOn() != null) {
- result.removed(a.getRemovedBy(), TimeUtil.truncateToSecond(a.getRemovedOn()));
- }
- return result;
- }
-
- private static AccountGroupByIdAud truncateToSecond(AccountGroupByIdAud a) {
- AccountGroupByIdAud result =
- new AccountGroupByIdAud(
- new AccountGroupByIdAud.Key(
- a.getKey().getParentKey(),
- a.getKey().getIncludeUUID(),
- TimeUtil.truncateToSecond(a.getKey().getAddedOn())),
- a.getAddedBy());
- if (a.getRemovedOn() != null) {
- result.removed(a.getRemovedBy(), TimeUtil.truncateToSecond(a.getRemovedOn()));
- }
- return result;
- }
-
- public InternalGroup toInternalGroup() {
- return InternalGroup.create(
- group(),
- members().stream().map(AccountGroupMember::getAccountId).collect(toImmutableSet()),
- byId().stream().map(AccountGroupById::getIncludeUUID).collect(toImmutableSet()));
- }
-
- @Override
- public int hashCode() {
- throw new UnsupportedOperationException(
- "hashCode is not supported because equals is not supported");
- }
-
- @Override
- public boolean equals(Object o) {
- throw new UnsupportedOperationException("Use GroupBundle.compare(a, b) instead of equals");
- }
-
- @AutoValue
- abstract static class AuditEntry {
- private static AuditEntry create(
- Action action, Account.Id userId, Account.Id memberId, Timestamp timestamp) {
- return new AutoValue_GroupBundle_AuditEntry(
- action, userId, String.valueOf(memberId.get()), timestamp);
- }
-
- private static AuditEntry create(
- Action action, Account.Id userId, AccountGroup.UUID subgroupId, Timestamp timestamp) {
- return new AutoValue_GroupBundle_AuditEntry(action, userId, subgroupId.get(), timestamp);
- }
-
- abstract Action getAction();
-
- abstract Account.Id getUserId();
-
- abstract String getTarget();
-
- abstract Timestamp getTimestamp();
- }
-
- enum Action {
- ADD(1),
- REMOVE(2);
-
- private final int order;
-
- Action(int order) {
- this.order = order;
- }
-
- public int getOrder() {
- return order;
- }
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder source(Source source);
-
- abstract Builder group(AccountGroup group);
-
- abstract Builder members(AccountGroupMember... member);
-
- abstract Builder members(Iterable<AccountGroupMember> member);
-
- abstract Builder memberAudit(AccountGroupMemberAudit... audit);
-
- abstract Builder memberAudit(Iterable<AccountGroupMemberAudit> audit);
-
- abstract Builder byId(AccountGroupById... byId);
-
- abstract Builder byId(Iterable<AccountGroupById> byId);
-
- abstract Builder byIdAudit(AccountGroupByIdAud... audit);
-
- abstract Builder byIdAudit(Iterable<AccountGroupByIdAud> audit);
-
- abstract GroupBundle build();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/GroupRebuilder.java b/java/com/google/gerrit/server/schema/GroupRebuilder.java
deleted file mode 100644
index 0157025a..0000000
--- a/java/com/google/gerrit/server/schema/GroupRebuilder.java
+++ /dev/null
@@ -1,303 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.common.collect.ImmutableSet.toImmutableSet;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Sets;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.AccountGroupById;
-import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
-import com.google.gerrit.reviewdb.client.AccountGroupMember;
-import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.git.meta.VersionedMetaData.BatchMetaDataUpdate;
-import com.google.gerrit.server.group.db.AuditLogFormatter;
-import com.google.gerrit.server.group.db.GroupConfig;
-import com.google.gerrit.server.group.db.InternalGroupCreation;
-import com.google.gerrit.server.group.db.InternalGroupUpdate;
-import com.google.gerrit.server.group.db.InternalGroupUpdate.MemberModification;
-import com.google.gerrit.server.group.db.InternalGroupUpdate.SubgroupModification;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.Comparator;
-import java.util.Map;
-import java.util.NavigableSet;
-import java.util.Optional;
-import java.util.function.Consumer;
-import java.util.stream.Stream;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.CommitBuilder;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-/** Helper for rebuilding an entire group's NoteDb refs. */
-class GroupRebuilder {
- private final PersonIdent serverIdent;
- private final AllUsersName allUsers;
- private final AuditLogFormatter auditLogFormatter;
-
- public GroupRebuilder(
- PersonIdent serverIdent, AllUsersName allUsers, AuditLogFormatter auditLogFormatter) {
- this.serverIdent = serverIdent;
- this.allUsers = allUsers;
- this.auditLogFormatter = auditLogFormatter;
- }
-
- public void rebuild(Repository allUsersRepo, GroupBundle bundle, @Nullable BatchRefUpdate bru)
- throws IOException, ConfigInvalidException, OrmDuplicateKeyException {
- AccountGroup group = bundle.group();
- InternalGroupCreation groupCreation =
- InternalGroupCreation.builder()
- .setId(bundle.id())
- .setNameKey(group.getNameKey())
- .setGroupUUID(group.getGroupUUID())
- .build();
- GroupConfig groupConfig = GroupConfig.createForNewGroup(allUsers, allUsersRepo, groupCreation);
- groupConfig.setAllowSaveEmptyName();
-
- InternalGroupUpdate.Builder updateBuilder =
- InternalGroupUpdate.builder()
- .setOwnerGroupUUID(group.getOwnerGroupUUID())
- .setVisibleToAll(group.isVisibleToAll())
- .setUpdatedOn(group.getCreatedOn());
- if (bundle.group().getDescription() != null) {
- updateBuilder.setDescription(group.getDescription());
- }
- groupConfig.setGroupUpdate(updateBuilder.build(), auditLogFormatter);
-
- Map<Key, Collection<Event>> events = toEvents(bundle).asMap();
- PersonIdent nowServerIdent = getServerIdent(events);
-
- MetaDataUpdate md = createMetaDataUpdate(allUsers, allUsersRepo, bru);
-
- // Creation is done by the server (unlike later audit events).
- PersonIdent created = new PersonIdent(nowServerIdent, group.getCreatedOn());
- md.getCommitBuilder().setAuthor(created);
- md.getCommitBuilder().setCommitter(created);
-
- // Rebuild group ref.
- try (BatchMetaDataUpdate batch = groupConfig.openUpdate(md)) {
- batch.write(groupConfig, md.getCommitBuilder());
-
- for (Map.Entry<Key, Collection<Event>> e : events.entrySet()) {
- InternalGroupUpdate.Builder ub = InternalGroupUpdate.builder();
- e.getValue().forEach(event -> event.update().accept(ub));
- ub.setUpdatedOn(e.getKey().when());
- groupConfig.setGroupUpdate(ub.build(), auditLogFormatter);
-
- PersonIdent currServerIdent = new PersonIdent(nowServerIdent, e.getKey().when());
- CommitBuilder cb = new CommitBuilder();
- cb.setAuthor(
- e.getKey()
- .accountId()
- .map(id -> auditLogFormatter.getParsableAuthorIdent(id, currServerIdent))
- .orElse(currServerIdent));
- cb.setCommitter(currServerIdent);
- batch.write(groupConfig, cb);
- }
-
- batch.createRef(groupConfig.getRefName());
- }
- }
-
- private ListMultimap<Key, Event> toEvents(GroupBundle bundle) {
- ListMultimap<Key, Event> result =
- MultimapBuilder.treeKeys(Key.COMPARATOR).arrayListValues(1).build();
- Event e;
-
- for (AccountGroupMemberAudit a : bundle.memberAudit()) {
- checkArgument(
- a.getKey().getGroupId().equals(bundle.id()),
- "key %s does not match group %s",
- a.getKey(),
- bundle.id());
- Account.Id accountId = a.getKey().getParentKey();
- e = event(Type.ADD_MEMBER, a.getAddedBy(), a.getKey().getAddedOn(), addMember(accountId));
- result.put(e.key(), e);
- if (!a.isActive()) {
- e = event(Type.REMOVE_MEMBER, a.getRemovedBy(), a.getRemovedOn(), removeMember(accountId));
- result.put(e.key(), e);
- }
- }
-
- for (AccountGroupByIdAud a : bundle.byIdAudit()) {
- checkArgument(
- a.getKey().getParentKey().equals(bundle.id()),
- "key %s does not match group %s",
- a.getKey(),
- bundle.id());
- AccountGroup.UUID uuid = a.getKey().getIncludeUUID();
- e = event(Type.ADD_GROUP, a.getAddedBy(), a.getKey().getAddedOn(), addGroup(uuid));
- result.put(e.key(), e);
- if (!a.isActive()) {
- e = event(Type.REMOVE_GROUP, a.getRemovedBy(), a.getRemovedOn(), removeGroup(uuid));
- result.put(e.key(), e);
- }
- }
-
- // Due to clock skew, audit events may be in the future relative to this machine. Ensure the
- // fixup event happens after any other events, both for the purposes of sorting Keys correctly
- // and to avoid non-monotonic timestamps in the commit history.
- Timestamp maxTs =
- Stream.concat(result.keySet().stream().map(Key::when), Stream.of(TimeUtil.nowTs()))
- .max(Comparator.naturalOrder())
- .get();
- Timestamp fixupTs = new Timestamp(maxTs.getTime() + 1);
- e = serverEvent(Type.FIXUP, fixupTs, setCurrentMembership(bundle));
- result.put(e.key(), e);
-
- return result;
- }
-
- private PersonIdent getServerIdent(Map<Key, Collection<Event>> events) {
- // Created with MultimapBuilder.treeKeys, so the keySet is navigable.
- Key lastKey = ((NavigableSet<Key>) events.keySet()).last();
- checkState(lastKey.type() == Type.FIXUP);
- return new PersonIdent(
- serverIdent.getName(),
- serverIdent.getEmailAddress(),
- Iterables.getOnlyElement(events.get(lastKey)).when(),
- serverIdent.getTimeZone());
- }
-
- private static MetaDataUpdate createMetaDataUpdate(
- Project.NameKey projectName, Repository repository, @Nullable BatchRefUpdate batchRefUpdate) {
- return new MetaDataUpdate(
- GitReferenceUpdated.DISABLED, projectName, repository, batchRefUpdate);
- }
-
- private static Consumer<InternalGroupUpdate.Builder> addMember(Account.Id toAdd) {
- return b -> {
- MemberModification prev = b.getMemberModification();
- b.setMemberModification(in -> Sets.union(prev.apply(in), ImmutableSet.of(toAdd)));
- };
- }
-
- private static Consumer<InternalGroupUpdate.Builder> removeMember(Account.Id toRemove) {
- return b -> {
- MemberModification prev = b.getMemberModification();
- b.setMemberModification(in -> Sets.difference(prev.apply(in), ImmutableSet.of(toRemove)));
- };
- }
-
- private static Consumer<InternalGroupUpdate.Builder> addGroup(AccountGroup.UUID toAdd) {
- return b -> {
- SubgroupModification prev = b.getSubgroupModification();
- b.setSubgroupModification(in -> Sets.union(prev.apply(in), ImmutableSet.of(toAdd)));
- };
- }
-
- private static Consumer<InternalGroupUpdate.Builder> removeGroup(AccountGroup.UUID toRemove) {
- return b -> {
- SubgroupModification prev = b.getSubgroupModification();
- b.setSubgroupModification(in -> Sets.difference(prev.apply(in), ImmutableSet.of(toRemove)));
- };
- }
-
- private static Consumer<InternalGroupUpdate.Builder> setCurrentMembership(GroupBundle bundle) {
- // Overwrite members and subgroups with the current values. The storage layer will do the
- // set differences to compute the appropriate delta, if any.
- return b ->
- b.setMemberModification(
- in ->
- bundle
- .members()
- .stream()
- .map(AccountGroupMember::getAccountId)
- .collect(toImmutableSet()))
- .setSubgroupModification(
- in ->
- bundle
- .byId()
- .stream()
- .map(AccountGroupById::getIncludeUUID)
- .collect(toImmutableSet()));
- }
-
- private static Event event(
- Type type,
- Account.Id accountId,
- Timestamp when,
- Consumer<InternalGroupUpdate.Builder> update) {
- return new AutoValue_GroupRebuilder_Event(type, Optional.of(accountId), when, update);
- }
-
- private static Event serverEvent(
- Type type, Timestamp when, Consumer<InternalGroupUpdate.Builder> update) {
- return new AutoValue_GroupRebuilder_Event(type, Optional.empty(), when, update);
- }
-
- @AutoValue
- abstract static class Event {
- abstract Type type();
-
- abstract Optional<Account.Id> accountId();
-
- abstract Timestamp when();
-
- abstract Consumer<InternalGroupUpdate.Builder> update();
-
- Key key() {
- return new AutoValue_GroupRebuilder_Key(accountId(), when(), type());
- }
- }
-
- /**
- * Distinct event types.
- *
- * <p>Events at the same time by the same user are batched together by type. The types should
- * correspond to the possible batch operations supported by AuditService.
- */
- enum Type {
- ADD_MEMBER,
- REMOVE_MEMBER,
- ADD_GROUP,
- REMOVE_GROUP,
- FIXUP;
- }
-
- @AutoValue
- abstract static class Key {
- static final Comparator<Key> COMPARATOR =
- Comparator.comparing(Key::when)
- .thenComparing(
- k -> k.accountId().map(Account.Id::get).orElse(null),
- Comparator.nullsFirst(Comparator.naturalOrder()))
- .thenComparing(Key::type);
-
- abstract Optional<Account.Id> accountId();
-
- abstract Timestamp when();
-
- abstract Type type();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/H2.java b/java/com/google/gerrit/server/schema/H2.java
deleted file mode 100644
index 840eaf0..0000000
--- a/java/com/google/gerrit/server/schema/H2.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.inject.Inject;
-import java.nio.file.Path;
-import org.eclipse.jgit.lib.Config;
-
-class H2 extends BaseDataSourceType {
-
- protected final Config cfg;
- private final SitePaths site;
-
- @Inject
- H2(SitePaths site, @GerritServerConfig Config cfg) {
- super("org.h2.Driver");
- this.cfg = cfg;
- this.site = site;
- }
-
- @Override
- public String getUrl() {
- String database = cfg.getString("database", null, "database");
- if (database == null || database.isEmpty()) {
- database = "db/ReviewDB";
- }
- return appendUrlOptions(cfg, createUrl(site.resolve(database)));
- }
-
- public static String createUrl(Path path) {
- return new StringBuilder().append("jdbc:h2:").append(path.toUri().toString()).toString();
- }
-
- public static String appendUrlOptions(Config cfg, String url) {
- long h2CacheSize = cfg.getLong("database", "h2", "cacheSize", -1);
- boolean h2AutoServer = cfg.getBoolean("database", "h2", "autoServer", false);
-
- StringBuilder urlBuilder = new StringBuilder().append(url);
-
- if (h2CacheSize >= 0) {
- // H2 CACHE_SIZE is always given in KB
- urlBuilder.append(";CACHE_SIZE=").append(h2CacheSize / 1024);
- }
- if (h2AutoServer) {
- urlBuilder.append(";AUTO_SERVER=TRUE");
- }
- return urlBuilder.toString();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/HANA.java b/java/com/google/gerrit/server/schema/HANA.java
deleted file mode 100644
index f9811c6..0000000
--- a/java/com/google/gerrit/server/schema/HANA.java
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import java.io.IOException;
-import org.eclipse.jgit.lib.Config;
-
-class HANA extends BaseDataSourceType {
-
- private Config cfg;
-
- @Inject
- HANA(@GerritServerConfig Config cfg) {
- super("com.sap.db.jdbc.Driver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbs = new ConfigSection(cfg, "database");
- b.append("jdbc:sap://");
- b.append(hostname(dbs.required("hostname")));
- b.append(port(dbs.optional("port")));
- String database = dbs.optional("database");
- if (!Strings.isNullOrEmpty(database)) {
- b.append("?databaseName=").append(database);
- }
- return b.toString();
- }
-
- @Override
- public ScriptRunner getIndexScript() throws IOException {
- // HANA uses column tables and should not require additional indices
- return ScriptRunner.NOOP;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/JDBC.java b/java/com/google/gerrit/server/schema/JDBC.java
deleted file mode 100644
index d188df4..0000000
--- a/java/com/google/gerrit/server/schema/JDBC.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import com.google.gerrit.server.config.ConfigUtil;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-class JDBC extends BaseDataSourceType {
-
- protected final Config cfg;
-
- @Inject
- JDBC(@GerritServerConfig Config cfg) {
- super(ConfigUtil.getRequired(cfg, "database", "driver"));
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- return ConfigUtil.getRequired(cfg, "database", "url");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java b/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
index 83a0986..1ef69db 100644
--- a/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
+++ b/java/com/google/gerrit/server/schema/JdbcAccountPatchReviewStore.java
@@ -32,6 +32,7 @@
import com.google.gerrit.server.config.ThreadSettingsConfig;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
+import java.nio.file.Path;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
@@ -115,7 +116,7 @@
private static String getUrl(@GerritServerConfig Config cfg, SitePaths sitePaths) {
String url = cfg.getString(ACCOUNT_PATCH_REVIEW_DB, null, URL);
if (url == null) {
- return H2.createUrl(sitePaths.db_dir.resolve("account_patch_reviews"));
+ return createH2Url(sitePaths.db_dir.resolve("account_patch_reviews"));
}
return url;
}
@@ -352,4 +353,8 @@
}
return 0;
}
+
+ private static String createH2Url(Path path) {
+ return new StringBuilder().append("jdbc:h2:").append(path.toUri().toString()).toString();
+ }
}
diff --git a/java/com/google/gerrit/server/schema/JdbcUtil.java b/java/com/google/gerrit/server/schema/JdbcUtil.java
index dddf23a..3995339 100644
--- a/java/com/google/gerrit/server/schema/JdbcUtil.java
+++ b/java/com/google/gerrit/server/schema/JdbcUtil.java
@@ -28,6 +28,7 @@
return hostname;
}
+ // TODO(dborowitz): Still used by plugins post-ReviewDb?
@UsedAt(UsedAt.Project.PLUGINS_ALL)
public static String port(String port) {
if (port != null && !port.isEmpty()) {
diff --git a/java/com/google/gerrit/server/schema/MariaDb.java b/java/com/google/gerrit/server/schema/MariaDb.java
deleted file mode 100644
index 6c5dd35..0000000
--- a/java/com/google/gerrit/server/schema/MariaDb.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-class MariaDb extends BaseDataSourceType {
- private final Config cfg;
-
- @Inject
- MariaDb(@GerritServerConfig Config cfg) {
- super("org.mariadb.jdbc.Driver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- StringBuilder b = new StringBuilder();
- ConfigSection dbs = new ConfigSection(cfg, "database");
- b.append("jdbc:mariadb://");
- b.append(hostname(dbs.optional("hostname")));
- b.append(port(dbs.optional("port")));
- b.append("/");
- b.append(dbs.required("database"));
- b.append("?useBulkStmts=false");
- return b.toString();
- }
-
- @Override
- public boolean usePool() {
- // MariaDB has given us trouble with the connection pool,
- // sometimes the backend disconnects and the pool winds
- // up with a stale connection. Fortunately opening up
- // a new MariaDB connection is usually very fast.
- return false;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/MaxDb.java b/java/com/google/gerrit/server/schema/MaxDb.java
deleted file mode 100644
index d552eb65..0000000
--- a/java/com/google/gerrit/server/schema/MaxDb.java
+++ /dev/null
@@ -1,50 +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.server.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import java.io.IOException;
-import org.eclipse.jgit.lib.Config;
-
-class MaxDb extends BaseDataSourceType {
-
- private Config cfg;
-
- @Inject
- MaxDb(@GerritServerConfig Config cfg) {
- super("com.sap.dbtech.jdbc.DriverSapDB");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbs = new ConfigSection(cfg, "database");
- b.append("jdbc:sapdb://");
- b.append(hostname(dbs.optional("hostname")));
- b.append("/");
- b.append(dbs.required("database"));
- return b.toString();
- }
-
- @Override
- public ScriptRunner getIndexScript() throws IOException {
- return getScriptRunner("index_maxdb.sql");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/MySql.java b/java/com/google/gerrit/server/schema/MySql.java
deleted file mode 100644
index e5f59d7..0000000
--- a/java/com/google/gerrit/server/schema/MySql.java
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-class MySql extends BaseDataSourceType {
-
- private Config cfg;
-
- @Inject
- MySql(@GerritServerConfig Config cfg) {
- super("com.mysql.jdbc.Driver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbs = new ConfigSection(cfg, "database");
- b.append("jdbc:mysql://");
- b.append(hostname(dbs.optional("hostname")));
- b.append(port(dbs.optional("port")));
- b.append("/");
- b.append(dbs.required("database"));
- // See
- // https://stackoverflow.com/questions/42084633/table-name-pattern-can-not-be-null-or-empty-in-java
- b.append("?nullNamePatternMatchesAll=true");
- return b.toString();
- }
-
- @Override
- public boolean usePool() {
- // MySQL has given us trouble with the connection pool,
- // sometimes the backend disconnects and the pool winds
- // up with a stale connection. Fortunately opening up
- // a new MySQL connection is usually very fast.
- return false;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/NoChangesReviewDb.java b/java/com/google/gerrit/server/schema/NoChangesReviewDb.java
index 80a18b9..bdb2b0d 100644
--- a/java/com/google/gerrit/server/schema/NoChangesReviewDb.java
+++ b/java/com/google/gerrit/server/schema/NoChangesReviewDb.java
@@ -27,7 +27,6 @@
import com.google.gerrit.reviewdb.server.PatchSetAccess;
import com.google.gerrit.reviewdb.server.PatchSetApprovalAccess;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.SchemaVersionAccess;
import com.google.gwtorm.server.Access;
import com.google.gwtorm.server.ListResultSet;
import com.google.gwtorm.server.ResultSet;
@@ -60,11 +59,6 @@
}
@Override
- public SchemaVersionAccess schemaVersion() {
- throw new UnsupportedOperationException(GONE);
- }
-
- @Override
public ChangeAccess changes() {
return changes;
}
diff --git a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
index 436b67f..602b639 100644
--- a/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
+++ b/java/com/google/gerrit/server/schema/NoteDbSchemaUpdater.java
@@ -28,6 +28,7 @@
import com.google.common.collect.ImmutableSortedSet;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.Sequences;
+import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.git.GitRepositoryManager;
@@ -38,13 +39,17 @@
import com.google.inject.Inject;
import java.io.IOException;
import java.util.stream.IntStream;
+import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.Repository;
public class NoteDbSchemaUpdater {
private final Config cfg;
+ private final AllProjectsName allProjectsName;
private final AllUsersName allUsersName;
private final GitRepositoryManager repoManager;
+ private final SchemaCreator schemaCreator;
private final NotesMigration notesMigration;
private final NoteDbSchemaVersionManager versionManager;
private final NoteDbSchemaVersion.Arguments args;
@@ -53,15 +58,19 @@
@Inject
NoteDbSchemaUpdater(
@GerritServerConfig Config cfg,
+ AllUsersName allUsersName,
+ AllProjectsName allProjectsName,
+ GitRepositoryManager repoManager,
+ SchemaCreator schemaCreator,
NotesMigration notesMigration,
NoteDbSchemaVersionManager versionManager,
- NoteDbSchemaVersion.Arguments args,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName) {
+ NoteDbSchemaVersion.Arguments args) {
this(
cfg,
+ allProjectsName,
allUsersName,
repoManager,
+ schemaCreator,
notesMigration,
versionManager,
args,
@@ -70,15 +79,19 @@
NoteDbSchemaUpdater(
Config cfg,
+ AllProjectsName allProjectsName,
AllUsersName allUsersName,
GitRepositoryManager repoManager,
+ SchemaCreator schemaCreator,
NotesMigration notesMigration,
NoteDbSchemaVersionManager versionManager,
NoteDbSchemaVersion.Arguments args,
ImmutableSortedMap<Integer, Class<? extends NoteDbSchemaVersion>> schemaVersions) {
this.cfg = cfg;
+ this.allProjectsName = allProjectsName;
this.allUsersName = allUsersName;
this.repoManager = repoManager;
+ this.schemaCreator = schemaCreator;
this.notesMigration = notesMigration;
this.versionManager = versionManager;
this.args = args;
@@ -91,6 +104,9 @@
// only option.
return;
}
+
+ ensureSchemaCreated();
+
int currentVersion = versionManager.read();
if (currentVersion == 0) {
// The only valid case where there is no refs/meta/version is when running 3.x init for the
@@ -111,6 +127,18 @@
}
}
+ private void ensureSchemaCreated() throws OrmException {
+ try {
+ try {
+ repoManager.openRepository(allProjectsName).close();
+ } catch (RepositoryNotFoundException e) {
+ schemaCreator.create();
+ }
+ } catch (IOException | ConfigInvalidException e) {
+ throw new OrmException("Cannot initialize Gerrit site");
+ }
+ }
+
private void checkNoteDbConfigFor216() throws OrmException {
// Check that the NoteDb migration config matches what we expect from a site that both:
// * Completed the change migration to NoteDB.
diff --git a/java/com/google/gerrit/server/schema/Oracle.java b/java/com/google/gerrit/server/schema/Oracle.java
deleted file mode 100644
index 4ff7243..0000000
--- a/java/com/google/gerrit/server/schema/Oracle.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import org.eclipse.jgit.lib.Config;
-
-public class Oracle extends BaseDataSourceType {
- private Config cfg;
-
- @Inject
- public Oracle(@GerritServerConfig Config cfg) {
- super("oracle.jdbc.driver.OracleDriver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbc = new ConfigSection(cfg, "database");
- b.append("jdbc:oracle:thin:@");
- b.append(hostname(dbc.optional("hostname")));
- b.append(port(dbc.optional("port")));
- b.append(":");
- b.append(dbc.required("instance"));
- return b.toString();
- }
-
- @Override
- public String getValidationQuery() {
- return "select 1 from dual";
- }
-}
diff --git a/java/com/google/gerrit/server/schema/PostgreSQL.java b/java/com/google/gerrit/server/schema/PostgreSQL.java
deleted file mode 100644
index d6aee94..0000000
--- a/java/com/google/gerrit/server/schema/PostgreSQL.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2012 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.schema;
-
-import static com.google.gerrit.server.schema.JdbcUtil.hostname;
-import static com.google.gerrit.server.schema.JdbcUtil.port;
-
-import com.google.gerrit.server.config.ConfigSection;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.inject.Inject;
-import java.io.IOException;
-import org.eclipse.jgit.lib.Config;
-
-class PostgreSQL extends BaseDataSourceType {
-
- private Config cfg;
-
- @Inject
- PostgreSQL(@GerritServerConfig Config cfg) {
- super("org.postgresql.Driver");
- this.cfg = cfg;
- }
-
- @Override
- public String getUrl() {
- final StringBuilder b = new StringBuilder();
- final ConfigSection dbc = new ConfigSection(cfg, "database");
- b.append("jdbc:postgresql://");
- b.append(hostname(dbc.optional("hostname")));
- b.append(port(dbc.optional("port")));
- b.append("/");
- b.append(dbc.required("database"));
- return b.toString();
- }
-
- @Override
- public ScriptRunner getIndexScript() throws IOException {
- return getScriptRunner("index_postgres.sql");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java b/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java
deleted file mode 100644
index 0fbaeca..0000000
--- a/java/com/google/gerrit/server/schema/ReviewDbDatabaseProvider.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.Database;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
-import com.google.inject.name.Named;
-import javax.sql.DataSource;
-
-/** Provides the {@code Database<ReviewDb>} database handle. */
-final class ReviewDbDatabaseProvider implements Provider<Database<ReviewDb>> {
- private final DataSource datasource;
-
- @Inject
- ReviewDbDatabaseProvider(@Named("ReviewDb") final DataSource ds) {
- datasource = ds;
- }
-
- @Override
- public Database<ReviewDb> get() {
- try {
- return new Database<>(datasource, ReviewDb.class);
- } catch (OrmException e) {
- throw new ProvisionException("Cannot create ReviewDb", e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java
index da8898a4..c777133 100644
--- a/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java
+++ b/java/com/google/gerrit/server/schema/ReviewDbSchemaModule.java
@@ -27,8 +27,10 @@
import com.google.gerrit.server.config.AnonymousCowardNameProvider;
import com.google.gerrit.server.config.GerritServerId;
import com.google.gerrit.server.config.GerritServerIdProvider;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
import org.eclipse.jgit.lib.PersonIdent;
+// TODO(dborowitz): Rename, since this no longer has anything to do with ReviewDb.
/** Validate the schema and connect to Git. */
public class ReviewDbSchemaModule extends FactoryModule {
@Override
@@ -49,5 +51,11 @@
.annotatedWith(GerritServerId.class)
.toProvider(GerritServerIdProvider.class)
.in(SINGLETON);
+
+ // It feels wrong to have this binding in a seemingly unrelated module, but it's a dependency of
+ // SchemaCreatorImpl, so it's needed.
+ // TODO(dborowitz): Is there any way to untangle this?
+ bind(GroupIndexCollection.class);
+ bind(SchemaCreator.class).to(SchemaCreatorImpl.class);
}
}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java
deleted file mode 100644
index 86f4560..0000000
--- a/java/com/google/gerrit/server/schema/ReviewDbSchemaUpdater.java
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
-import com.google.inject.Inject;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Provider;
-import com.google.inject.Stage;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-
-/** Creates or updates the current database schema. */
-public class ReviewDbSchemaUpdater {
- private final SchemaFactory<ReviewDb> schema;
- private final ReviewDbSchemaCreator creator;
- private final Provider<ReviewDbSchemaVersion> updater;
-
- @Inject
- ReviewDbSchemaUpdater(
- @ReviewDbFactory SchemaFactory<ReviewDb> schema,
- ReviewDbSchemaCreator creator,
- Injector parent) {
- this.schema = schema;
- this.creator = creator;
- this.updater = buildInjector(parent).getProvider(ReviewDbSchemaVersion.class);
- }
-
- private static Injector buildInjector(Injector parent) {
- // Use DEVELOPMENT mode to allow lazy initialization of the
- // graph. This avoids touching ancient schema versions that
- // are behind this installation's current version.
- return Guice.createInjector(
- Stage.DEVELOPMENT,
- new AbstractModule() {
- @Override
- protected void configure() {
- bind(ReviewDbSchemaVersion.class).to(ReviewDbSchemaVersion.C);
-
- for (Key<?> k :
- new Key<?>[] {
- Key.get(PersonIdent.class, GerritPersonIdent.class),
- Key.get(String.class, AnonymousCowardName.class),
- Key.get(Config.class, GerritServerConfig.class),
- }) {
- rebind(parent, k);
- }
-
- for (Class<?> c :
- new Class<?>[] {
- AllProjectsName.class,
- AllUsersCreator.class,
- AllUsersName.class,
- GitRepositoryManager.class,
- SitePaths.class,
- SystemGroupBackend.class,
- }) {
- rebind(parent, Key.get(c));
- }
- }
-
- private <T> void rebind(Injector parent, Key<T> c) {
- bind(c).toProvider(parent.getProvider(c));
- }
- });
- }
-
- public void update(UpdateUI ui) throws OrmException {
- try (ReviewDb db = ReviewDbUtil.unwrapDb(schema.open())) {
-
- final ReviewDbSchemaVersion u = updater.get();
- final CurrentSchemaVersion version = getSchemaVersion(db);
- if (version == null) {
- try {
- creator.create(db);
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Cannot initialize schema", e);
- }
-
- } else {
- try {
- u.check(ui, version, db);
- } catch (SQLException e) {
- throw new OrmException("Cannot upgrade schema", e);
- }
- }
- }
- }
-
- @VisibleForTesting
- public ReviewDbSchemaVersion getLatestSchemaVersion() {
- return updater.get();
- }
-
- private CurrentSchemaVersion getSchemaVersion(ReviewDb db) {
- try {
- return db.schemaVersion().get(new CurrentSchemaVersion.Key());
- } catch (OrmException e) {
- return null;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java b/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java
deleted file mode 100644
index f911a8f..0000000
--- a/java/com/google/gerrit/server/schema/ReviewDbSchemaVersion.java
+++ /dev/null
@@ -1,227 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Stopwatch;
-import com.google.common.collect.Lists;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.UsedAt;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Provider;
-import java.sql.PreparedStatement;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-
-/** A version of the database schema. */
-public abstract class ReviewDbSchemaVersion {
- /** The current schema version. */
- // DO NOT upgrade this version in the master branch. Future versions must all be implemented as
- // NoteDbSchemaVersions. It may be upgraded on the stable-2.16 branch, in which case this will
- // need to be updated upon merging. In any case, this number must not exceed the first NoteDb
- // schema version (180).
- public static final Class<Schema_170> C = Schema_170.class;
-
- static {
- checkState(C.equals(Schema_170.class));
- checkState(guessVersion(C) < 180);
- }
-
- public static int getBinaryVersion() {
- return guessVersion(C);
- }
-
- private final Provider<? extends ReviewDbSchemaVersion> prior;
- private final int versionNbr;
-
- protected ReviewDbSchemaVersion(Provider<? extends ReviewDbSchemaVersion> prior) {
- this.prior = prior;
- this.versionNbr = guessVersion(getClass());
- }
-
- @UsedAt(UsedAt.Project.PLUGIN_DELETE_PROJECT)
- public static int guessVersion(Class<?> c) {
- String n = c.getName();
- n = n.substring(n.lastIndexOf('_') + 1);
- while (n.startsWith("0")) {
- n = n.substring(1);
- }
- return Integer.parseInt(n);
- }
-
- /** @return the {@link CurrentSchemaVersion#versionNbr} this step targets. */
- public final int getVersionNbr() {
- return versionNbr;
- }
-
- @VisibleForTesting
- public final ReviewDbSchemaVersion getPrior() {
- return prior.get();
- }
-
- public final void check(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
- throws OrmException, SQLException {
- if (curr.versionNbr == versionNbr) {
- // Nothing to do, we are at the correct schema.
- } else if (curr.versionNbr > versionNbr) {
- throw new OrmException(
- "Cannot downgrade database schema from version "
- + curr.versionNbr
- + " to "
- + versionNbr
- + ".");
- } else {
- upgradeFrom(ui, curr, db);
- }
- }
-
- /** Runs check on the prior schema version, and then upgrades. */
- private void upgradeFrom(UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
- throws OrmException, SQLException {
- List<ReviewDbSchemaVersion> pending = pending(curr.versionNbr);
- updateSchema(pending, ui, db);
- migrateData(pending, ui, curr, db);
-
- JdbcSchema s = (JdbcSchema) db;
- final List<String> pruneList = new ArrayList<>();
- s.pruneSchema(
- new StatementExecutor() {
- @Override
- public void execute(String sql) {
- pruneList.add(sql);
- }
-
- @Override
- public void close() {
- // Do nothing.
- }
- });
-
- try (JdbcExecutor e = new JdbcExecutor(s)) {
- if (!pruneList.isEmpty()) {
- ui.pruneSchema(e, pruneList);
- }
- }
- }
-
- private List<ReviewDbSchemaVersion> pending(int curr) {
- List<ReviewDbSchemaVersion> r = Lists.newArrayListWithCapacity(versionNbr - curr);
- for (ReviewDbSchemaVersion v = this; curr < v.getVersionNbr(); v = v.prior.get()) {
- r.add(v);
- }
- Collections.reverse(r);
- return r;
- }
-
- private void updateSchema(List<ReviewDbSchemaVersion> pending, UpdateUI ui, ReviewDb db)
- throws OrmException, SQLException {
- for (ReviewDbSchemaVersion v : pending) {
- ui.message(String.format("Upgrading schema to %d ...", v.getVersionNbr()));
- v.preUpdateSchema(db);
- }
-
- JdbcSchema s = (JdbcSchema) db;
- try (JdbcExecutor e = new JdbcExecutor(s)) {
- s.updateSchema(e);
- }
- }
-
- /**
- * Invoked before updateSchema adds new columns/tables.
- *
- * @param db open database handle.
- * @throws OrmException if a Gerrit-specific exception occurred.
- * @throws SQLException if an underlying SQL exception occurred.
- */
- protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {}
-
- private void migrateData(
- List<ReviewDbSchemaVersion> pending, UpdateUI ui, CurrentSchemaVersion curr, ReviewDb db)
- throws OrmException, SQLException {
- for (ReviewDbSchemaVersion v : pending) {
- Stopwatch sw = Stopwatch.createStarted();
- ui.message(String.format("Migrating data to schema %d ...", v.getVersionNbr()));
- v.migrateData(db, ui);
- v.finish(curr, db);
- ui.message(String.format("\t> Done (%.3f s)", sw.elapsed(TimeUnit.MILLISECONDS) / 1000d));
- }
- }
-
- /**
- * Invoked between updateSchema (adds new columns/tables) and pruneSchema (removes deleted
- * columns/tables).
- *
- * @param db open database handle.
- * @param ui interface for interacting with the user.
- * @throws OrmException if a Gerrit-specific exception occurred.
- * @throws SQLException if an underlying SQL exception occurred.
- */
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {}
-
- /** Mark the current schema version. */
- protected void finish(CurrentSchemaVersion curr, ReviewDb db) throws OrmException {
- curr.versionNbr = versionNbr;
- db.schemaVersion().update(Collections.singleton(curr));
- }
-
- /** Rename an existing table. */
- protected static void renameTable(ReviewDb db, String from, String to) throws OrmException {
- JdbcSchema s = (JdbcSchema) db;
- try (JdbcExecutor e = new JdbcExecutor(s)) {
- s.renameTable(e, from, to);
- }
- }
-
- /** Rename an existing column. */
- protected static void renameColumn(ReviewDb db, String table, String from, String to)
- throws OrmException {
- JdbcSchema s = (JdbcSchema) db;
- try (JdbcExecutor e = new JdbcExecutor(s)) {
- s.renameColumn(e, table, from, to);
- }
- }
-
- /** Execute an SQL statement. */
- protected static void execute(ReviewDb db, String sql) throws SQLException {
- try (Statement s = newStatement(db)) {
- s.execute(sql);
- }
- }
-
- /** Open a new single statement. */
- protected static Statement newStatement(ReviewDb db) throws SQLException {
- return ((JdbcSchema) db).getConnection().createStatement();
- }
-
- /** Open a new prepared statement. */
- protected static PreparedStatement prepareStatement(ReviewDb db, String sql) throws SQLException {
- return ((JdbcSchema) db).getConnection().prepareStatement(sql);
- }
-
- /** Open a new statement executor. */
- protected static JdbcExecutor newExecutor(ReviewDb db) throws OrmException {
- return new JdbcExecutor(((JdbcSchema) db).getConnection());
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_168.java b/java/com/google/gerrit/server/schema/SchemaCreator.java
similarity index 70%
rename from java/com/google/gerrit/server/schema/Schema_168.java
rename to java/com/google/gerrit/server/schema/SchemaCreator.java
index fff4049..78a8422 100644
--- a/java/com/google/gerrit/server/schema/Schema_168.java
+++ b/java/com/google/gerrit/server/schema/SchemaCreator.java
@@ -14,13 +14,11 @@
package com.google.gerrit.server.schema;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
+import com.google.gwtorm.server.OrmException;
+import java.io.IOException;
+import org.eclipse.jgit.errors.ConfigInvalidException;
-/** Drop group tables. */
-public class Schema_168 extends ReviewDbSchemaVersion {
- @Inject
- Schema_168(Provider<Schema_167> prior) {
- super(prior);
- }
+/** Populates initial repository data. */
+public interface SchemaCreator {
+ void create() throws OrmException, IOException, ConfigInvalidException;
}
diff --git a/java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java b/java/com/google/gerrit/server/schema/SchemaCreatorImpl.java
similarity index 89%
rename from java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java
rename to java/com/google/gerrit/server/schema/SchemaCreatorImpl.java
index 3954d67..0d184a3 100644
--- a/java/com/google/gerrit/server/schema/ReviewDbSchemaCreator.java
+++ b/java/com/google/gerrit/server/schema/SchemaCreatorImpl.java
@@ -20,8 +20,6 @@
import com.google.gerrit.git.RefUpdateUtil;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.GerritPersonIdent;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.account.GroupUUID;
@@ -38,27 +36,26 @@
import com.google.gerrit.server.group.db.InternalGroupUpdate;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
import com.google.gwtorm.server.OrmDuplicateKeyException;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import java.io.IOException;
-import java.util.Collections;
import org.eclipse.jgit.errors.ConfigInvalidException;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.Config;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.lib.Repository;
-/** Creates the current database schema and populates initial code rows. */
-public class ReviewDbSchemaCreator {
+// TODO(dborowitz): The current NoteDb implementation mirrors the old ReviewDb code: this class is
+// called to create the site early on in NoteDbSchemaUpdater#update. This logic is a little
+// confusing and could stand to be reworked. Another smell is that this is an interface only for
+// testing purposes.
+public class SchemaCreatorImpl implements SchemaCreator {
private final GitRepositoryManager repoManager;
private final AllProjectsCreator allProjectsCreator;
private final AllUsersCreator allUsersCreator;
private final AllUsersName allUsersName;
private final PersonIdent serverUser;
- private final DataSourceType dataSourceType;
private final GroupIndexCollection indexCollection;
private final String serverId;
@@ -67,13 +64,12 @@
private final AllProjectsName allProjectsName;
@Inject
- public ReviewDbSchemaCreator(
+ public SchemaCreatorImpl(
GitRepositoryManager repoManager,
AllProjectsCreator ap,
AllUsersCreator auc,
AllUsersName allUsersName,
@GerritPersonIdent PersonIdent au,
- DataSourceType dst,
GroupIndexCollection ic,
String serverId,
Config config,
@@ -84,7 +80,6 @@
allUsersCreator = auc;
this.allUsersName = allUsersName;
serverUser = au;
- dataSourceType = dst;
indexCollection = ic;
this.serverId = serverId;
@@ -93,16 +88,8 @@
this.metricMaker = metricMaker;
}
- public void create(ReviewDb db) throws OrmException, IOException, ConfigInvalidException {
- final JdbcSchema jdbc = (JdbcSchema) db;
- try (JdbcExecutor e = new JdbcExecutor(jdbc)) {
- jdbc.updateSchema(e);
- }
-
- final CurrentSchemaVersion sVer = CurrentSchemaVersion.create();
- sVer.versionNbr = ReviewDbSchemaVersion.getBinaryVersion();
- db.schemaVersion().insert(Collections.singleton(sVer));
-
+ @Override
+ public void create() throws OrmException, IOException, ConfigInvalidException {
GroupReference admins = createGroupReference("Administrators");
GroupReference batchUsers = createGroupReference("Non-Interactive Users");
@@ -123,8 +110,6 @@
createAdminsGroup(seqs, allUsersRepo, admins);
createBatchUsersGroup(seqs, allUsersRepo, batchUsers, admins.getUUID());
}
-
- dataSourceType.getIndexScript().run(db);
}
private void createAdminsGroup(
diff --git a/java/com/google/gerrit/server/schema/Schema_100.java b/java/com/google/gerrit/server/schema/Schema_100.java
deleted file mode 100644
index b5105a9..0000000
--- a/java/com/google/gerrit/server/schema/Schema_100.java
+++ /dev/null
@@ -1,27 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_100 extends ReviewDbSchemaVersion {
- @Inject
- Schema_100(Provider<Schema_99> prior) {
- super(prior);
- }
-
- // No database migration; merges are rechecked on reindex.
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_101.java b/java/com/google/gerrit/server/schema/Schema_101.java
deleted file mode 100644
index 753d992..0000000
--- a/java/com/google/gerrit/server/schema/Schema_101.java
+++ /dev/null
@@ -1,144 +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.server.schema;
-
-import com.google.common.base.Joiner;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcExecutor;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.ColumnModel;
-import com.google.gwtorm.schema.RelationModel;
-import com.google.gwtorm.schema.java.JavaSchemaModel;
-import com.google.gwtorm.schema.sql.DialectPostgreSQL;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.Connection;
-import java.sql.DatabaseMetaData;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.TreeMap;
-
-public class Schema_101 extends ReviewDbSchemaVersion {
-
- private static class PrimaryKey {
- String oldNameInDb;
- List<String> cols;
- }
-
- private Connection conn;
- private SqlDialect dialect;
-
- @Inject
- Schema_101(Provider<Schema_100> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- conn = ((JdbcSchema) db).getConnection();
- dialect = ((JdbcSchema) db).getDialect();
- Map<String, PrimaryKey> corrections = findPKUpdates();
- if (corrections.isEmpty()) {
- return;
- }
-
- ui.message("Wrong Primary Key Column Order Detected");
- ui.message("The following tables are affected:");
- ui.message(Joiner.on(", ").join(corrections.keySet()));
- ui.message("fixing primary keys...");
- try (JdbcExecutor executor = new JdbcExecutor(conn)) {
- for (Map.Entry<String, PrimaryKey> c : corrections.entrySet()) {
- ui.message(String.format(" table: %s ... ", c.getKey()));
- recreatePK(executor, c.getKey(), c.getValue(), ui);
- ui.message("done");
- }
- ui.message("done");
- }
- }
-
- private Map<String, PrimaryKey> findPKUpdates() throws OrmException, SQLException {
- Map<String, PrimaryKey> corrections = new TreeMap<>();
- DatabaseMetaData meta = conn.getMetaData();
- JavaSchemaModel jsm = new JavaSchemaModel(ReviewDb.class);
- for (RelationModel rm : jsm.getRelations()) {
- String tableName = rm.getRelationName();
- List<String> expectedPKCols = relationPK(rm);
- PrimaryKey actualPK = dbTablePK(meta, tableName);
- if (!expectedPKCols.equals(actualPK.cols)) {
- actualPK.cols = expectedPKCols;
- corrections.put(tableName, actualPK);
- }
- }
- return corrections;
- }
-
- private List<String> relationPK(RelationModel rm) {
- Collection<ColumnModel> cols = rm.getPrimaryKeyColumns();
- List<String> pk = new ArrayList<>(cols.size());
- for (ColumnModel cm : cols) {
- pk.add(cm.getColumnName().toLowerCase(Locale.US));
- }
- return pk;
- }
-
- private PrimaryKey dbTablePK(DatabaseMetaData meta, String tableName) throws SQLException {
- if (meta.storesUpperCaseIdentifiers()) {
- tableName = tableName.toUpperCase();
- } else if (meta.storesLowerCaseIdentifiers()) {
- tableName = tableName.toLowerCase();
- }
-
- try (ResultSet cols = meta.getPrimaryKeys(null, null, tableName)) {
- PrimaryKey pk = new PrimaryKey();
- Map<Short, String> seqToName = new TreeMap<>();
- while (cols.next()) {
- seqToName.put(cols.getShort("KEY_SEQ"), cols.getString("COLUMN_NAME"));
- if (pk.oldNameInDb == null) {
- pk.oldNameInDb = cols.getString("PK_NAME");
- }
- }
-
- pk.cols = new ArrayList<>(seqToName.size());
- for (String name : seqToName.values()) {
- pk.cols.add(name.toLowerCase(Locale.US));
- }
- return pk;
- }
- }
-
- private void recreatePK(StatementExecutor executor, String tableName, PrimaryKey pk, UpdateUI ui)
- throws OrmException {
- if (pk.oldNameInDb == null) {
- ui.message(String.format("warning: primary key for table %s didn't exist ... ", tableName));
- } else {
- if (dialect instanceof DialectPostgreSQL) {
- // postgresql doesn't support the ALTER TABLE foo DROP PRIMARY KEY form
- executor.execute("ALTER TABLE " + tableName + " DROP CONSTRAINT " + pk.oldNameInDb);
- } else {
- executor.execute("ALTER TABLE " + tableName + " DROP PRIMARY KEY");
- }
- }
- executor.execute(
- "ALTER TABLE " + tableName + " ADD PRIMARY KEY(" + Joiner.on(",").join(pk.cols) + ")");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_102.java b/java/com/google/gerrit/server/schema/Schema_102.java
deleted file mode 100644
index 2bd52c2..0000000
--- a/java/com/google/gerrit/server/schema/Schema_102.java
+++ /dev/null
@@ -1,70 +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.server.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.DialectPostgreSQL;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.util.Set;
-import java.util.regex.Pattern;
-
-public class Schema_102 extends ReviewDbSchemaVersion {
- @Inject
- Schema_102(Provider<Schema_101> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- SqlDialect dialect = schema.getDialect();
- try (StatementExecutor e = newExecutor(db)) {
- // Drop left over indexes that were missed to be removed in schema 84.
- // See "Delete SQL index support" commit for more details:
- // d4ae3a16d5e1464574bd04f429a63eb9c02b3b43
- Pattern pattern =
- Pattern.compile("^changes_(allOpen|allClosed|byBranchClosed)$", Pattern.CASE_INSENSITIVE);
- String table = "changes";
- Set<String> listIndexes = dialect.listIndexes(schema.getConnection(), table);
- for (String index : listIndexes) {
- if (pattern.matcher(index).matches()) {
- dialect.dropIndex(e, table, index);
- }
- }
-
- dialect.dropIndex(e, table, "changes_byProjectOpen");
- if (dialect instanceof DialectPostgreSQL) {
- e.execute(
- "CREATE INDEX changes_byProjectOpen"
- + " ON "
- + table
- + " (dest_project_name, last_updated_on)"
- + " WHERE open = 'Y'");
- } else {
- e.execute(
- "CREATE INDEX changes_byProjectOpen"
- + " ON "
- + table
- + " (open, dest_project_name, last_updated_on)");
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_103.java b/java/com/google/gerrit/server/schema/Schema_103.java
deleted file mode 100644
index 1906b66..0000000
--- a/java/com/google/gerrit/server/schema/Schema_103.java
+++ /dev/null
@@ -1,27 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_103 extends ReviewDbSchemaVersion {
- @Inject
- Schema_103(Provider<Schema_102> prior) {
- super(prior);
- }
-
- // Adds originalSubject column
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_104.java b/java/com/google/gerrit/server/schema/Schema_104.java
deleted file mode 100644
index 9b4d67c..0000000
--- a/java/com/google/gerrit/server/schema/Schema_104.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_104 extends ReviewDbSchemaVersion {
- @Inject
- Schema_104(Provider<Schema_103> prior) {
- super(prior);
- }
-
- // Remove old change screen
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_105.java b/java/com/google/gerrit/server/schema/Schema_105.java
deleted file mode 100644
index 56e19ef..0000000
--- a/java/com/google/gerrit/server/schema/Schema_105.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Sets;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-
-public class Schema_105 extends ReviewDbSchemaVersion {
- private static final String TABLE = "changes";
-
- @Inject
- Schema_105(Provider<Schema_104> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException, OrmException {
- JdbcSchema schema = (JdbcSchema) db;
- SqlDialect dialect = schema.getDialect();
-
- Map<String, OrmException> errors = new HashMap<>();
- try (StatementExecutor e = newExecutor(db)) {
- for (String index : listChangesIndexes(schema)) {
- ui.message("Dropping index " + index + " on table " + TABLE);
- try {
- dialect.dropIndex(e, TABLE, index);
- } catch (OrmException err) {
- errors.put(index, err);
- }
- }
- }
-
- for (String index : listChangesIndexes(schema)) {
- String msg = "Failed to drop index " + index;
- OrmException err = errors.get(index);
- if (err != null) {
- msg += ": " + err.getMessage();
- }
- ui.message(msg);
- }
- }
-
- private Set<String> listChangesIndexes(JdbcSchema schema) throws SQLException {
- // List of all changes indexes ever created or dropped, found with the
- // following command:
- // find g* -name \*.sql | xargs git log -i -p -S' index changes_' | grep -io ' index
- // changes_\w*' | cut -d' ' -f3 | tr A-Z a-z | sort -u
- // Used rather than listIndexes as we're not sure whether it might include
- // primary key indexes.
- Set<String> allChanges =
- ImmutableSet.of(
- "changes_allclosed",
- "changes_allopen",
- "changes_bybranchclosed",
- "changes_byownerclosed",
- "changes_byowneropen",
- "changes_byproject",
- "changes_byprojectopen",
- "changes_key",
- "changes_submitted");
- return Sets.intersection(
- schema.getDialect().listIndexes(schema.getConnection(), TABLE), allChanges);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_106.java b/java/com/google/gerrit/server/schema/Schema_106.java
deleted file mode 100644
index a3f99fc..0000000
--- a/java/com/google/gerrit/server/schema/Schema_106.java
+++ /dev/null
@@ -1,159 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LocalDiskRepositoryManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintWriter;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.SortedSet;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.Future;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_106 extends ReviewDbSchemaVersion {
- // we can use multiple threads per CPU as we can expect that threads will be
- // waiting for IO
- private static final int THREADS_PER_CPU = 4;
- private final GitRepositoryManager repoManager;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_106(
- Provider<Schema_105> prior,
- GitRepositoryManager repoManager,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- if (!(repoManager instanceof LocalDiskRepositoryManager)) {
- return;
- }
-
- ui.message("listing all repositories ...");
- SortedSet<Project.NameKey> repoList = repoManager.list();
- ui.message("done");
-
- ui.message(String.format("creating reflog files for %s branches ...", RefNames.REFS_CONFIG));
-
- ExecutorService executorPool = createExecutor(ui, repoList.size());
- List<Future<Void>> futures = new ArrayList<>();
-
- for (Project.NameKey project : repoList) {
- Callable<Void> callable = new ReflogCreator(project);
- futures.add(executorPool.submit(callable));
- }
-
- executorPool.shutdown();
- try {
- for (Future<Void> future : futures) {
- try {
- future.get();
- } catch (ExecutionException e) {
- ui.message(e.getCause().getMessage());
- }
- }
- ui.message("done");
- } catch (InterruptedException ex) {
- String msg =
- String.format(
- "Migration step 106 was interrupted. "
- + "Reflog created in %d of %d repositories only.",
- countDone(futures), repoList.size());
- ui.message(msg);
- }
- }
-
- private static int countDone(List<Future<Void>> futures) {
- int count = 0;
- for (Future<Void> future : futures) {
- if (future.isDone()) {
- count++;
- }
- }
-
- return count;
- }
-
- private ExecutorService createExecutor(UpdateUI ui, int repoCount) {
- int procs = Runtime.getRuntime().availableProcessors();
- int threads = Math.min(procs * THREADS_PER_CPU, repoCount);
- ui.message(String.format("... using %d threads ...", threads));
- return Executors.newFixedThreadPool(threads);
- }
-
- private class ReflogCreator implements Callable<Void> {
- private final Project.NameKey project;
-
- ReflogCreator(Project.NameKey project) {
- this.project = project;
- }
-
- @Override
- public Void call() throws IOException {
- try (Repository repo = repoManager.openRepository(project)) {
- File metaConfigLog = new File(repo.getDirectory(), "logs/" + RefNames.REFS_CONFIG);
- if (metaConfigLog.exists()) {
- return null;
- }
-
- if (!metaConfigLog.getParentFile().mkdirs() || !metaConfigLog.createNewFile()) {
- throw new IOException();
- }
-
- ObjectId metaConfigId = repo.resolve(RefNames.REFS_CONFIG);
- if (metaConfigId != null) {
- try (PrintWriter writer = new PrintWriter(metaConfigLog, UTF_8.name())) {
- writer.print(ObjectId.zeroId().name());
- writer.print(" ");
- writer.print(metaConfigId.name());
- writer.print(" ");
- writer.print(serverUser.toExternalString());
- writer.print("\t");
- writer.print("create reflog");
- writer.println();
- }
- }
- return null;
- } catch (IOException e) {
- throw new IOException(
- String.format(
- "ERROR: Failed to create reflog file for the %s branch in repository %s",
- RefNames.REFS_CONFIG, project.get()));
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_107.java b/java/com/google/gerrit/server/schema/Schema_107.java
deleted file mode 100644
index bef8c65..0000000
--- a/java/com/google/gerrit/server/schema/Schema_107.java
+++ /dev/null
@@ -1,37 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_107 extends ReviewDbSchemaVersion {
-
- @Inject
- Schema_107(Provider<Schema_106> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement()) {
- stmt.executeUpdate("UPDATE accounts set mute_common_path_prefixes = 'Y'");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_108.java b/java/com/google/gerrit/server/schema/Schema_108.java
deleted file mode 100644
index b2ab042..0000000
--- a/java/com/google/gerrit/server/schema/Schema_108.java
+++ /dev/null
@@ -1,190 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.SetMultimap;
-import com.google.common.collect.Sets;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Change.Status;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.GroupCollector;
-import com.google.gerrit.server.project.NoSuchChangeException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-import org.eclipse.jgit.errors.MissingObjectException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefDatabase;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevObject;
-import org.eclipse.jgit.revwalk.RevSort;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class Schema_108 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
-
- @Inject
- Schema_108(Provider<Schema_107> prior, GitRepositoryManager repoManager) {
- super(prior);
- this.repoManager = repoManager;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- ui.message("Listing all changes ...");
- SetMultimap<Project.NameKey, Change.Id> openByProject = getOpenChangesByProject(db, ui);
- ui.message("done");
-
- ui.message("Updating groups for open changes ...");
- int i = 0;
- for (Map.Entry<Project.NameKey, Collection<Change.Id>> e : openByProject.asMap().entrySet()) {
- try (Repository repo = repoManager.openRepository(e.getKey());
- RevWalk rw = new RevWalk(repo)) {
- updateProjectGroups(db, repo, rw, (Set<Change.Id>) e.getValue(), ui);
- } catch (IOException | NoSuchChangeException err) {
- throw new OrmException(err);
- }
- if (++i % 100 == 0) {
- ui.message(" done " + i + " projects ...");
- }
- }
- ui.message("done");
- }
-
- private void updateProjectGroups(
- ReviewDb db, Repository repo, RevWalk rw, Set<Change.Id> changes, UpdateUI ui)
- throws OrmException, IOException {
- // Match sorting in ReceiveCommits.
- rw.reset();
- rw.sort(RevSort.TOPO);
- rw.sort(RevSort.REVERSE, true);
-
- RefDatabase refdb = repo.getRefDatabase();
- for (Ref ref : refdb.getRefsByPrefix(Constants.R_HEADS)) {
- RevCommit c = maybeParseCommit(rw, ref.getObjectId(), ui);
- if (c != null) {
- rw.markUninteresting(c);
- }
- }
-
- ListMultimap<ObjectId, Ref> changeRefsBySha =
- MultimapBuilder.hashKeys().arrayListValues().build();
- ListMultimap<ObjectId, PatchSet.Id> patchSetsBySha =
- MultimapBuilder.hashKeys().arrayListValues().build();
- for (Ref ref : refdb.getRefsByPrefix(RefNames.REFS_CHANGES)) {
- ObjectId id = ref.getObjectId();
- if (ref.getObjectId() == null) {
- continue;
- }
- id = id.copy();
- changeRefsBySha.put(id, ref);
- PatchSet.Id psId = PatchSet.Id.fromRef(ref.getName());
- if (psId != null && changes.contains(psId.getParentKey())) {
- patchSetsBySha.put(id, psId);
- RevCommit c = maybeParseCommit(rw, id, ui);
- if (c != null) {
- rw.markStart(c);
- }
- }
- }
-
- GroupCollector collector = GroupCollector.createForSchemaUpgradeOnly(changeRefsBySha, db);
- RevCommit c;
- while ((c = rw.next()) != null) {
- collector.visit(c);
- }
-
- updateGroups(db, collector, patchSetsBySha);
- }
-
- private static void updateGroups(
- ReviewDb db, GroupCollector collector, ListMultimap<ObjectId, PatchSet.Id> patchSetsBySha)
- throws OrmException {
- Map<PatchSet.Id, PatchSet> patchSets =
- db.patchSets().toMap(db.patchSets().get(patchSetsBySha.values()));
- for (Map.Entry<ObjectId, Collection<String>> e : collector.getGroups().asMap().entrySet()) {
- for (PatchSet.Id psId : patchSetsBySha.get(e.getKey())) {
- PatchSet ps = patchSets.get(psId);
- if (ps != null) {
- ps.setGroups(ImmutableList.copyOf(e.getValue()));
- }
- }
- }
-
- db.patchSets().update(patchSets.values());
- }
-
- private SetMultimap<Project.NameKey, Change.Id> getOpenChangesByProject(ReviewDb db, UpdateUI ui)
- throws OrmException {
- SortedSet<Project.NameKey> projects = repoManager.list();
- SortedSet<Project.NameKey> nonExistentProjects = Sets.newTreeSet();
- SetMultimap<Project.NameKey, Change.Id> openByProject =
- MultimapBuilder.hashKeys().hashSetValues().build();
- for (Change c : db.changes().all()) {
- Status status = c.getStatus();
- if (status != null && status.isClosed()) {
- continue;
- }
-
- Project.NameKey projectKey = c.getProject();
- if (!projects.contains(projectKey)) {
- nonExistentProjects.add(projectKey);
- } else {
- // The old "submitted" state is not supported anymore
- // (thus status is null) but it was an opened state and needs
- // to be migrated as such
- openByProject.put(projectKey, c.getId());
- }
- }
-
- if (!nonExistentProjects.isEmpty()) {
- ui.message("Detected open changes referring to the following non-existent projects:");
- ui.message(Joiner.on(", ").join(nonExistentProjects));
- ui.message(
- "It is highly recommended to remove\n"
- + "the obsolete open changes, comments and patch-sets from your DB.\n");
- }
- return openByProject;
- }
-
- private static RevCommit maybeParseCommit(RevWalk rw, ObjectId id, UpdateUI ui)
- throws IOException {
- if (id != null) {
- try {
- RevObject obj = rw.parseAny(id);
- return (obj instanceof RevCommit) ? (RevCommit) obj : null;
- } catch (MissingObjectException moe) {
- ui.message("Missing object: " + id.getName() + "\n");
- }
- }
- return null;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_109.java b/java/com/google/gerrit/server/schema/Schema_109.java
deleted file mode 100644
index f582741..0000000
--- a/java/com/google/gerrit/server/schema/Schema_109.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_109 extends ReviewDbSchemaVersion {
- @Inject
- Schema_109(Provider<Schema_108> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (StatementExecutor e = newExecutor(db)) {
- e.execute("UPDATE changes SET status = 'n', created_on = created_on WHERE status = 's'");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_110.java b/java/com/google/gerrit/server/schema/Schema_110.java
deleted file mode 100644
index 6da10f6..0000000
--- a/java/com/google/gerrit/server/schema/Schema_110.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_110 extends ReviewDbSchemaVersion {
- @Inject
- Schema_110(Provider<Schema_109> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_111.java b/java/com/google/gerrit/server/schema/Schema_111.java
deleted file mode 100644
index 7ba48c2..0000000
--- a/java/com/google/gerrit/server/schema/Schema_111.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_111 extends ReviewDbSchemaVersion {
- @Inject
- Schema_111(Provider<Schema_110> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_112.java b/java/com/google/gerrit/server/schema/Schema_112.java
deleted file mode 100644
index 5a764d0..0000000
--- a/java/com/google/gerrit/server/schema/Schema_112.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_112 extends ReviewDbSchemaVersion {
- @Inject
- Schema_112(Provider<Schema_111> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_113.java b/java/com/google/gerrit/server/schema/Schema_113.java
deleted file mode 100644
index 2876636..0000000
--- a/java/com/google/gerrit/server/schema/Schema_113.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_113 extends ReviewDbSchemaVersion {
- @Inject
- Schema_113(Provider<Schema_112> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_114.java b/java/com/google/gerrit/server/schema/Schema_114.java
deleted file mode 100644
index 7bee00c..0000000
--- a/java/com/google/gerrit/server/schema/Schema_114.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_114 extends ReviewDbSchemaVersion {
- @Inject
- Schema_114(Provider<Schema_113> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_115.java b/java/com/google/gerrit/server/schema/Schema_115.java
deleted file mode 100644
index 28cfe22..0000000
--- a/java/com/google/gerrit/server/schema/Schema_115.java
+++ /dev/null
@@ -1,209 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.server.config.ConfigUtil.storeSection;
-import static java.util.Objects.requireNonNull;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo;
-import com.google.gerrit.extensions.client.DiffPreferencesInfo.Whitespace;
-import com.google.gerrit.extensions.client.Theme;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.UserConfigSections;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.patch.PatchListKey;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.ResultSetMetaData;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Map;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class Schema_115 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager mgr;
- private final AllUsersName allUsersName;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_115(
- Provider<Schema_114> prior,
- GitRepositoryManager mgr,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.mgr = mgr;
- this.allUsersName = allUsersName;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- Map<Account.Id, DiffPreferencesInfo> imports = new HashMap<>();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs = stmt.executeQuery("SELECT * FROM account_diff_preferences")) {
- Set<String> availableColumns = getColumns(rs);
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt("id"));
- DiffPreferencesInfo prefs = new DiffPreferencesInfo();
- if (availableColumns.contains("context")) {
- prefs.context = (int) rs.getShort("context");
- }
- if (availableColumns.contains("expand_all_comments")) {
- prefs.expandAllComments = toBoolean(rs.getString("expand_all_comments"));
- }
- if (availableColumns.contains("hide_line_numbers")) {
- prefs.hideLineNumbers = toBoolean(rs.getString("hide_line_numbers"));
- }
- if (availableColumns.contains("hide_top_menu")) {
- prefs.hideTopMenu = toBoolean(rs.getString("hide_top_menu"));
- }
- if (availableColumns.contains("ignore_whitespace")) {
- // Enum with char as value
- prefs.ignoreWhitespace = toWhitespace(rs.getString("ignore_whitespace"));
- }
- if (availableColumns.contains("intraline_difference")) {
- prefs.intralineDifference = toBoolean(rs.getString("intraline_difference"));
- }
- if (availableColumns.contains("line_length")) {
- prefs.lineLength = rs.getInt("line_length");
- }
- if (availableColumns.contains("manual_review")) {
- prefs.manualReview = toBoolean(rs.getString("manual_review"));
- }
- if (availableColumns.contains("render_entire_file")) {
- prefs.renderEntireFile = toBoolean(rs.getString("render_entire_file"));
- }
- if (availableColumns.contains("retain_header")) {
- prefs.retainHeader = toBoolean(rs.getString("retain_header"));
- }
- if (availableColumns.contains("show_line_endings")) {
- prefs.showLineEndings = toBoolean(rs.getString("show_line_endings"));
- }
- if (availableColumns.contains("show_tabs")) {
- prefs.showTabs = toBoolean(rs.getString("show_tabs"));
- }
- if (availableColumns.contains("show_whitespace_errors")) {
- prefs.showWhitespaceErrors = toBoolean(rs.getString("show_whitespace_errors"));
- }
- if (availableColumns.contains("skip_deleted")) {
- prefs.skipDeleted = toBoolean(rs.getString("skip_deleted"));
- }
- if (availableColumns.contains("skip_uncommented")) {
- prefs.skipUncommented = toBoolean(rs.getString("skip_uncommented"));
- }
- if (availableColumns.contains("syntax_highlighting")) {
- prefs.syntaxHighlighting = toBoolean(rs.getString("syntax_highlighting"));
- }
- if (availableColumns.contains("tab_size")) {
- prefs.tabSize = rs.getInt("tab_size");
- }
- if (availableColumns.contains("theme")) {
- // Enum with name as values; can be null
- prefs.theme = toTheme(rs.getString("theme"));
- }
- if (availableColumns.contains("hide_empty_pane")) {
- prefs.hideEmptyPane = toBoolean(rs.getString("hide_empty_pane"));
- }
- if (availableColumns.contains("auto_hide_diff_table_header")) {
- prefs.autoHideDiffTableHeader = toBoolean(rs.getString("auto_hide_diff_table_header"));
- }
- imports.put(accountId, prefs);
- }
- }
-
- if (imports.isEmpty()) {
- return;
- }
-
- try (Repository git = mgr.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- for (Map.Entry<Account.Id, DiffPreferencesInfo> e : imports.entrySet()) {
- try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- VersionedAccountPreferences p = VersionedAccountPreferences.forUser(e.getKey());
- p.load(md);
- storeSection(
- p.getConfig(),
- UserConfigSections.DIFF,
- null,
- e.getValue(),
- DiffPreferencesInfo.defaults());
- p.commit(md);
- }
- }
-
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-
- private Set<String> getColumns(ResultSet rs) throws SQLException {
- ResultSetMetaData metaData = rs.getMetaData();
- int columnCount = metaData.getColumnCount();
- Set<String> columns = new HashSet<>(columnCount);
- for (int i = 1; i <= columnCount; i++) {
- columns.add(metaData.getColumnLabel(i).toLowerCase());
- }
- return columns;
- }
-
- private static Theme toTheme(String v) {
- if (v == null) {
- return Theme.DEFAULT;
- }
- return Theme.valueOf(v);
- }
-
- private static Whitespace toWhitespace(String v) {
- requireNonNull(v);
- if (v.isEmpty()) {
- return Whitespace.IGNORE_NONE;
- }
- Whitespace r = PatchListKey.WHITESPACE_TYPES.inverse().get(v.charAt(0));
- if (r == null) {
- throw new IllegalArgumentException("Cannot find Whitespace type for: " + v);
- }
- return r;
- }
-
- private static boolean toBoolean(String v) {
- checkState(!Strings.isNullOrEmpty(v));
- return v.equals("Y");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_116.java b/java/com/google/gerrit/server/schema/Schema_116.java
deleted file mode 100644
index 5174d92..0000000
--- a/java/com/google/gerrit/server/schema/Schema_116.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_116 extends ReviewDbSchemaVersion {
- @Inject
- Schema_116(Provider<Schema_115> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_117.java b/java/com/google/gerrit/server/schema/Schema_117.java
deleted file mode 100644
index d848bec..0000000
--- a/java/com/google/gerrit/server/schema/Schema_117.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Set;
-
-public class Schema_117 extends ReviewDbSchemaVersion {
- @Inject
- Schema_117(Provider<Schema_116> prior) {
- super(prior);
- }
-
- @Override
- protected void preUpdateSchema(ReviewDb db) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- Connection connection = schema.getConnection();
- String tableName = "patch_sets";
- String oldColumnName = "push_certficate";
- String newColumnName = "push_certificate";
- Set<String> columns = schema.getDialect().listColumns(connection, tableName);
- if (columns.contains(oldColumnName)) {
- renameColumn(db, tableName, oldColumnName, newColumnName);
- }
- try (Statement stmt = schema.getConnection().createStatement()) {
- stmt.execute("ALTER TABLE " + tableName + " MODIFY " + newColumnName + " clob");
- } catch (SQLException e) {
- // Ignore. Type may have already been modified manually.
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_118.java b/java/com/google/gerrit/server/schema/Schema_118.java
deleted file mode 100644
index e55afda..0000000
--- a/java/com/google/gerrit/server/schema/Schema_118.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_118 extends ReviewDbSchemaVersion {
- @Inject
- Schema_118(Provider<Schema_117> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_119.java b/java/com/google/gerrit/server/schema/Schema_119.java
deleted file mode 100644
index 9423d81..0000000
--- a/java/com/google/gerrit/server/schema/Schema_119.java
+++ /dev/null
@@ -1,233 +0,0 @@
-// Copyright (C) 2015 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.schema;
-
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_GIT;
-import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.ANON_HTTP;
-import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.HTTP;
-import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.REPO_DOWNLOAD;
-import static com.google.gerrit.reviewdb.client.CoreDownloadSchemes.SSH;
-import static com.google.gerrit.server.config.ConfigUtil.storeSection;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.ImmutableMap;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DateFormat;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DiffView;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.DownloadCommand;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.EmailStrategy;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.ReviewCategoryStrategy;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo.TimeFormat;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.UserConfigSections;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class Schema_119 extends ReviewDbSchemaVersion {
- private static final ImmutableMap<String, String> LEGACY_DISPLAYNAME_MAP =
- ImmutableMap.<String, String>of(
- "ANON_GIT", ANON_GIT,
- "ANON_HTTP", ANON_HTTP,
- "HTTP", HTTP,
- "SSH", SSH,
- "REPO_DOWNLOAD", REPO_DOWNLOAD);
-
- private final GitRepositoryManager mgr;
- private final AllUsersName allUsersName;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_119(
- Provider<Schema_118> prior,
- GitRepositoryManager mgr,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.mgr = mgr;
- this.allUsersName = allUsersName;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- Connection connection = schema.getConnection();
- String tableName = "accounts";
- String emailStrategy = "email_strategy";
- Set<String> columns = schema.getDialect().listColumns(connection, tableName);
- Map<Account.Id, GeneralPreferencesInfo> imports = new HashMap<>();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "select "
- + "account_id, "
- + "maximum_page_size, "
- + "show_site_header, "
- + "use_flash_clipboard, "
- + "download_url, "
- + "download_command, "
- + (columns.contains(emailStrategy)
- ? emailStrategy + ", "
- : "copy_self_on_email, ")
- + "date_format, "
- + "time_format, "
- + "relative_date_in_change_table, "
- + "diff_view, "
- + "size_bar_in_change_table, "
- + "legacycid_in_change_table, "
- + "review_category_strategy, "
- + "mute_common_path_prefixes "
- + "from "
- + tableName)) {
- while (rs.next()) {
- GeneralPreferencesInfo p = new GeneralPreferencesInfo();
- Account.Id accountId = new Account.Id(rs.getInt(1));
- p.changesPerPage = (int) rs.getShort(2);
- p.showSiteHeader = toBoolean(rs.getString(3));
- p.useFlashClipboard = toBoolean(rs.getString(4));
- p.downloadScheme = convertToModernNames(rs.getString(5));
- p.downloadCommand = toDownloadCommand(rs.getString(6));
- p.emailStrategy = toEmailStrategy(rs.getString(7), columns.contains(emailStrategy));
- p.dateFormat = toDateFormat(rs.getString(8));
- p.timeFormat = toTimeFormat(rs.getString(9));
- p.relativeDateInChangeTable = toBoolean(rs.getString(10));
- p.diffView = toDiffView(rs.getString(11));
- p.sizeBarInChangeTable = toBoolean(rs.getString(12));
- p.legacycidInChangeTable = toBoolean(rs.getString(13));
- p.reviewCategoryStrategy = toReviewCategoryStrategy(rs.getString(14));
- p.muteCommonPathPrefixes = toBoolean(rs.getString(15));
- p.defaultBaseForMerges = GeneralPreferencesInfo.defaults().defaultBaseForMerges;
- imports.put(accountId, p);
- }
- }
-
- if (imports.isEmpty()) {
- return;
- }
-
- try (Repository git = mgr.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- for (Map.Entry<Account.Id, GeneralPreferencesInfo> e : imports.entrySet()) {
- try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- VersionedAccountPreferences p = VersionedAccountPreferences.forUser(e.getKey());
- p.load(md);
- storeSection(
- p.getConfig(),
- UserConfigSections.GENERAL,
- null,
- e.getValue(),
- GeneralPreferencesInfo.defaults());
- p.commit(md);
- }
- }
-
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-
- private String convertToModernNames(String s) {
- return !Strings.isNullOrEmpty(s) && LEGACY_DISPLAYNAME_MAP.containsKey(s)
- ? LEGACY_DISPLAYNAME_MAP.get(s)
- : s;
- }
-
- private static DownloadCommand toDownloadCommand(String v) {
- if (v == null) {
- return DownloadCommand.CHECKOUT;
- }
- return DownloadCommand.valueOf(v);
- }
-
- private static DateFormat toDateFormat(String v) {
- if (v == null) {
- return DateFormat.STD;
- }
- return DateFormat.valueOf(v);
- }
-
- private static TimeFormat toTimeFormat(String v) {
- if (v == null) {
- return TimeFormat.HHMM_12;
- }
- return TimeFormat.valueOf(v);
- }
-
- private static DiffView toDiffView(String v) {
- if (v == null) {
- return DiffView.SIDE_BY_SIDE;
- }
- return DiffView.valueOf(v);
- }
-
- private static EmailStrategy toEmailStrategy(String v, boolean emailStrategyColumnExists)
- throws OrmException {
- if (v == null) {
- return EmailStrategy.ENABLED;
- }
- if (emailStrategyColumnExists) {
- return EmailStrategy.valueOf(v);
- }
- if (v.equals("N")) {
- // EMAIL_STRATEGY='ENABLED' WHERE (COPY_SELF_ON_EMAIL='N')
- return EmailStrategy.ENABLED;
- } else if (v.equals("Y")) {
- // EMAIL_STRATEGY='CC_ON_OWN_COMMENTS' WHERE (COPY_SELF_ON_EMAIL='Y')
- return EmailStrategy.CC_ON_OWN_COMMENTS;
- } else {
- throw new OrmException("invalid value in accounts.copy_self_on_email: " + v);
- }
- }
-
- private static ReviewCategoryStrategy toReviewCategoryStrategy(String v) {
- if (v == null) {
- return ReviewCategoryStrategy.NONE;
- }
- return ReviewCategoryStrategy.valueOf(v);
- }
-
- private static boolean toBoolean(String v) {
- checkState(!Strings.isNullOrEmpty(v));
- return v.equals("Y");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_120.java b/java/com/google/gerrit/server/schema/Schema_120.java
deleted file mode 100644
index 9a1c15b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_120.java
+++ /dev/null
@@ -1,122 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.gerrit.common.data.SubscribeSection;
-import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.RefSpec;
-
-public class Schema_120 extends ReviewDbSchemaVersion {
-
- private final GitRepositoryManager mgr;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_120(
- Provider<Schema_119> prior,
- GitRepositoryManager mgr,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.mgr = mgr;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- private void allowSubmoduleSubscription(Branch.NameKey subbranch, Branch.NameKey superBranch)
- throws OrmException {
- try (Repository git = mgr.openRepository(subbranch.getParentKey());
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, subbranch.getParentKey(), git, bru)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage("Added superproject subscription during upgrade");
- ProjectConfig pc = projectConfigFactory.read(md);
-
- SubscribeSection s = null;
- for (SubscribeSection s1 : pc.getSubscribeSections(subbranch)) {
- if (s1.getProject().equals(superBranch.getParentKey())) {
- s = s1;
- }
- }
- if (s == null) {
- s = new SubscribeSection(superBranch.getParentKey());
- pc.addSubscribeSection(s);
- }
- RefSpec newRefSpec = new RefSpec(subbranch.get() + ":" + superBranch.get());
-
- if (!s.getMatchingRefSpecs().contains(newRefSpec)) {
- // For the migration we use only exact RefSpecs, we're not trying to
- // generalize it.
- s.addMatchingRefSpec(newRefSpec);
- }
-
- pc.commit(md);
- }
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- } catch (ConfigInvalidException | IOException e) {
- throw new OrmException(e);
- }
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- ui.message("Generating Superproject subscriptions table to submodule ACLs");
-
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT "
- + "super_project_project_name, "
- + "super_project_branch_name, "
- + "submodule_project_name, "
- + "submodule_branch_name "
- + "FROM submodule_subscriptions")) {
- while (rs.next()) {
- Project.NameKey superproject = new Project.NameKey(rs.getString(1));
- Branch.NameKey superbranch = new Branch.NameKey(superproject, rs.getString(2));
-
- Project.NameKey submodule = new Project.NameKey(rs.getString(3));
- Branch.NameKey subbranch = new Branch.NameKey(submodule, rs.getString(4));
-
- allowSubmoduleSubscription(subbranch, superbranch);
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_121.java b/java/com/google/gerrit/server/schema/Schema_121.java
deleted file mode 100644
index bb994ef..0000000
--- a/java/com/google/gerrit/server/schema/Schema_121.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_121 extends ReviewDbSchemaVersion {
- @Inject
- Schema_121(Provider<Schema_120> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_122.java b/java/com/google/gerrit/server/schema/Schema_122.java
deleted file mode 100644
index cce1419..0000000
--- a/java/com/google/gerrit/server/schema/Schema_122.java
+++ /dev/null
@@ -1,27 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_122 extends ReviewDbSchemaVersion {
- @Inject
- Schema_122(Provider<Schema_121> prior) {
- super(prior);
- }
-
- // Adds tag column
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_123.java b/java/com/google/gerrit/server/schema/Schema_123.java
deleted file mode 100644
index cd84188..0000000
--- a/java/com/google/gerrit/server/schema/Schema_123.java
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.StarredChangesUtil;
-import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Map;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-public class Schema_123 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_123(
- Provider<Schema_122> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- ListMultimap<Account.Id, Change.Id> imports =
- MultimapBuilder.hashKeys().arrayListValues().build();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs = stmt.executeQuery("SELECT account_id, change_id FROM starred_changes")) {
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
- Change.Id changeId = new Change.Id(rs.getInt(2));
- imports.put(accountId, changeId);
- }
- }
-
- if (imports.isEmpty()) {
- return;
- }
-
- try (Repository git = repoManager.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- ObjectId id = StarredChangesUtil.writeLabels(git, StarredChangesUtil.DEFAULT_LABELS);
- for (Map.Entry<Account.Id, Change.Id> e : imports.entries()) {
- bru.addCommand(
- new ReceiveCommand(
- ObjectId.zeroId(), id, RefNames.refsStarredChanges(e.getValue(), e.getKey())));
- }
- bru.execute(rw, new TextProgressMonitor());
- } catch (IOException | IllegalLabelException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_124.java b/java/com/google/gerrit/server/schema/Schema_124.java
deleted file mode 100644
index 7e2fa42..0000000
--- a/java/com/google/gerrit/server/schema/Schema_124.java
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static java.util.Comparator.comparing;
-
-import com.google.common.base.Strings;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.common.collect.Ordering;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.AccountSshKey;
-import com.google.gerrit.server.account.VersionedAuthorizedKeys;
-import com.google.gerrit.server.account.VersionedAuthorizedKeys.SimpleSshKeyCreator;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class Schema_124 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_124(
- Provider<Schema_123> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- ListMultimap<Account.Id, AccountSshKey> imports =
- MultimapBuilder.hashKeys().arrayListValues().build();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT "
- + "account_id, "
- + "seq, "
- + "ssh_public_key, "
- + "valid "
- + "FROM account_ssh_keys")) {
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
- int seq = rs.getInt(2);
- String sshPublicKey = rs.getString(3);
- boolean valid = toBoolean(rs.getString(4));
- AccountSshKey key = AccountSshKey.create(accountId, seq, sshPublicKey, valid);
- imports.put(accountId, key);
- }
- }
-
- if (imports.isEmpty()) {
- return;
- }
-
- try (Repository git = repoManager.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
-
- for (Map.Entry<Account.Id, Collection<AccountSshKey>> e : imports.asMap().entrySet()) {
- try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
-
- VersionedAuthorizedKeys authorizedKeys =
- new VersionedAuthorizedKeys(new SimpleSshKeyCreator(), e.getKey());
- authorizedKeys.load(md);
- authorizedKeys.setKeys(fixInvalidSequenceNumbers(e.getValue()));
- authorizedKeys.commit(md);
- }
- }
-
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-
- private Collection<AccountSshKey> fixInvalidSequenceNumbers(Collection<AccountSshKey> keys) {
- Ordering<AccountSshKey> o = Ordering.from(comparing(AccountSshKey::seq));
- List<AccountSshKey> fixedKeys = new ArrayList<>(keys);
- AccountSshKey minKey = o.min(keys);
- while (minKey.seq() <= 0) {
- AccountSshKey fixedKey =
- AccountSshKey.create(
- minKey.accountId(), Math.max(o.max(keys).seq() + 1, 1), minKey.sshPublicKey());
- Collections.replaceAll(fixedKeys, minKey, fixedKey);
- minKey = o.min(fixedKeys);
- }
- return fixedKeys;
- }
-
- private static boolean toBoolean(String v) {
- return !Strings.isNullOrEmpty(v) && v.equalsIgnoreCase("Y");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_125.java b/java/com/google/gerrit/server/schema/Schema_125.java
deleted file mode 100644
index cc0d9e7..0000000
--- a/java/com/google/gerrit/server/schema/Schema_125.java
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.schema.AclUtil.grant;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.LabelType;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.RefPattern;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Map;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_125 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG =
- "Assign default permissions on user branches\n"
- + "\n"
- + "By default each user should be able to read and update the own user\n"
- + "branch. Also the user should be able to approve and submit changes for\n"
- + "the own user branch. Assign default permissions for this and remove the\n"
- + "old exclusive read protection from the user branches.\n";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final AllProjectsName allProjectsName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_125(
- Provider<Schema_124> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- AllProjectsName allProjectsName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.allProjectsName = allProjectsName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
-
- config
- .getAccessSection(RefNames.REFS_USERS + "*", true)
- .remove(new Permission(Permission.READ));
- GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
- AccessSection users =
- config.getAccessSection(
- RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}", true);
- grant(config, users, Permission.READ, true, registered);
- grant(config, users, Permission.PUSH, true, registered);
- grant(config, users, Permission.SUBMIT, true, registered);
-
- for (LabelType lt : getLabelTypes(config)) {
- if ("Code-Review".equals(lt.getName()) || "Verified".equals(lt.getName())) {
- grant(config, users, lt, lt.getMin().getValue(), lt.getMax().getValue(), registered);
- }
- }
-
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-
- private Collection<LabelType> getLabelTypes(ProjectConfig config)
- throws IOException, ConfigInvalidException {
- Map<String, LabelType> labelTypes = new HashMap<>(config.getLabelSections());
- Project.NameKey parent = config.getProject().getParent(allProjectsName);
- while (parent != null) {
- try (Repository git = repoManager.openRepository(parent);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, parent, git)) {
- ProjectConfig parentConfig = projectConfigFactory.read(md);
- for (LabelType lt : parentConfig.getLabelSections().values()) {
- if (!labelTypes.containsKey(lt.getName())) {
- labelTypes.put(lt.getName(), lt);
- }
- }
- parent = parentConfig.getProject().getParent(allProjectsName);
- }
- }
- return labelTypes.values();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_126.java b/java/com/google/gerrit/server/schema/Schema_126.java
deleted file mode 100644
index f3004ba..0000000
--- a/java/com/google/gerrit/server/schema/Schema_126.java
+++ /dev/null
@@ -1,89 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.schema.AclUtil.grant;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.RefPattern;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_126 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG = "Fix default permissions on user branches";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_126(
- Provider<Schema_125> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
-
- String refsUsersShardedId = RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}";
- config.remove(config.getAccessSection(refsUsersShardedId));
-
- GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
- AccessSection users = config.getAccessSection(refsUsersShardedId, true);
- grant(config, users, Permission.READ, false, true, registered);
- grant(config, users, Permission.PUSH, false, true, registered);
- grant(config, users, Permission.SUBMIT, false, true, registered);
-
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_127.java b/java/com/google/gerrit/server/schema/Schema_127.java
deleted file mode 100644
index 8e4175c..0000000
--- a/java/com/google/gerrit/server/schema/Schema_127.java
+++ /dev/null
@@ -1,87 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.config.ThreadSettingsConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import org.eclipse.jgit.lib.Config;
-
-public class Schema_127 extends ReviewDbSchemaVersion {
- private static final int MAX_BATCH_SIZE = 1000;
-
- private final SitePaths sitePaths;
- private final Config cfg;
- private final ThreadSettingsConfig threadSettingsConfig;
-
- @Inject
- Schema_127(
- Provider<Schema_126> prior,
- SitePaths sitePaths,
- @GerritServerConfig Config cfg,
- ThreadSettingsConfig threadSettingsConfig) {
- super(prior);
- this.sitePaths = sitePaths;
- this.cfg = cfg;
- this.threadSettingsConfig = threadSettingsConfig;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- JdbcAccountPatchReviewStore jdbcAccountPatchReviewStore =
- JdbcAccountPatchReviewStore.createAccountPatchReviewStore(
- cfg, sitePaths, threadSettingsConfig);
- jdbcAccountPatchReviewStore.dropTableIfExists();
- jdbcAccountPatchReviewStore.createTableIfNotExists();
- try (Connection con = jdbcAccountPatchReviewStore.getConnection();
- PreparedStatement stmt =
- con.prepareStatement(
- "INSERT INTO account_patch_reviews "
- + "(account_id, change_id, patch_set_id, file_name) VALUES "
- + "(?, ?, ?, ?)")) {
- int batchCount = 0;
-
- try (Statement s = newStatement(db);
- ResultSet rs = s.executeQuery("SELECT * from account_patch_reviews")) {
- while (rs.next()) {
- stmt.setInt(1, rs.getInt("account_id"));
- stmt.setInt(2, rs.getInt("change_id"));
- stmt.setInt(3, rs.getInt("patch_set_id"));
- stmt.setString(4, rs.getString("file_name"));
- stmt.addBatch();
- batchCount++;
- if (batchCount >= MAX_BATCH_SIZE) {
- stmt.executeBatch();
- batchCount = 0;
- }
- }
- }
- if (batchCount > 0) {
- stmt.executeBatch();
- }
- } catch (SQLException e) {
- throw jdbcAccountPatchReviewStore.convertError("insert", e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_128.java b/java/com/google/gerrit/server/schema/Schema_128.java
deleted file mode 100644
index cd2718b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_128.java
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.schema.AclUtil.grant;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_128 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG = "Add addPatchSet permission to all projects";
-
- private final GitRepositoryManager repoManager;
- private final AllProjectsName allProjectsName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_128(
- Provider<Schema_127> prior,
- GitRepositoryManager repoManager,
- AllProjectsName allProjectsName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allProjectsName = allProjectsName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allProjectsName);
- MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
-
- GroupReference registered = systemGroupBackend.getGroup(REGISTERED_USERS);
- AccessSection refsFor = config.getAccessSection("refs/for/*", true);
- grant(config, refsFor, Permission.ADD_PATCH_SET, false, false, registered);
-
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_129.java b/java/com/google/gerrit/server/schema/Schema_129.java
deleted file mode 100644
index f7cd8c3..0000000
--- a/java/com/google/gerrit/server/schema/Schema_129.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_129 extends ReviewDbSchemaVersion {
-
- @Inject
- Schema_129(Provider<Schema_128> prior) {
- super(prior);
- }
-
- @Override
- protected void preUpdateSchema(ReviewDb db) throws OrmException {
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement()) {
- stmt.execute("ALTER TABLE patch_sets MODIFY groups clob");
- } catch (SQLException e) {
- // Ignore. Type may have already been modified manually.
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_130.java b/java/com/google/gerrit/server/schema/Schema_130.java
deleted file mode 100644
index e550121..0000000
--- a/java/com/google/gerrit/server/schema/Schema_130.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static java.util.stream.Collectors.joining;
-
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_130 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG =
- "Remove force option from 'Push Annotated Tag' permission\n"
- + "\n"
- + "The force option on 'Push Annotated Tag' had no effect and is no longer\n"
- + "supported.";
-
- private final GitRepositoryManager repoManager;
- private final PersonIdent serverUser;
- private final ProjectConfigSchemaUpdate.Factory projectConfigSchemaUpdateFactory;
-
- @Inject
- Schema_130(
- Provider<Schema_129> prior,
- GitRepositoryManager repoManager,
- @GerritPersonIdent PersonIdent serverUser,
- ProjectConfigSchemaUpdate.Factory projectConfigSchemaUpdateFactory) {
- super(prior);
- this.repoManager = repoManager;
- this.serverUser = serverUser;
- this.projectConfigSchemaUpdateFactory = projectConfigSchemaUpdateFactory;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- SortedSet<Project.NameKey> repoList = repoManager.list();
- SortedSet<Project.NameKey> repoUpgraded = new TreeSet<>();
- ui.message("\tMigrating " + repoList.size() + " repositories ...");
- for (Project.NameKey projectName : repoList) {
- try (Repository git = repoManager.openRepository(projectName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
- ProjectConfigSchemaUpdate cfg = projectConfigSchemaUpdateFactory.read(md);
- cfg.removeForceFromPermission("pushTag");
- if (cfg.isUpdated()) {
- repoUpgraded.add(projectName);
- }
- cfg.save(serverUser, COMMIT_MSG);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException("Cannot migrate project " + projectName, ex);
- }
- }
- ui.message("\tMigration completed: " + repoUpgraded.size() + " repositories updated:");
- ui.message("\t" + repoUpgraded.stream().map(Project.NameKey::get).collect(joining(" ")));
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_131.java b/java/com/google/gerrit/server/schema/Schema_131.java
deleted file mode 100644
index b37ae4b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_131.java
+++ /dev/null
@@ -1,79 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static java.util.stream.Collectors.joining;
-
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.SortedSet;
-import java.util.TreeSet;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_131 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG =
- "Rename 'Push Annotated/Signed Tag' permission to 'Create Annotated/Signed Tag'";
-
- private final GitRepositoryManager repoManager;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_131(
- Provider<Schema_130> prior,
- GitRepositoryManager repoManager,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- SortedSet<Project.NameKey> repoList = repoManager.list();
- SortedSet<Project.NameKey> repoUpgraded = new TreeSet<>();
- ui.message("\tMigrating " + repoList.size() + " repositories ...");
- for (Project.NameKey projectName : repoList) {
- try (Repository git = repoManager.openRepository(projectName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, projectName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
- if (config.hasLegacyPermissions()) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- repoUpgraded.add(projectName);
- }
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException("Cannot migrate project " + projectName, ex);
- }
- }
- ui.message("\tMigration completed: " + repoUpgraded.size() + " repositories updated:");
- ui.message("\t" + repoUpgraded.stream().map(Project.NameKey::get).collect(joining(" ")));
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_132.java b/java/com/google/gerrit/server/schema/Schema_132.java
deleted file mode 100644
index 72ec590..0000000
--- a/java/com/google/gerrit/server/schema/Schema_132.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_132 extends ReviewDbSchemaVersion {
- @Inject
- Schema_132(Provider<Schema_131> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_133.java b/java/com/google/gerrit/server/schema/Schema_133.java
deleted file mode 100644
index 29cd6e9..0000000
--- a/java/com/google/gerrit/server/schema/Schema_133.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_133 extends ReviewDbSchemaVersion {
- @Inject
- Schema_133(Provider<Schema_132> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_134.java b/java/com/google/gerrit/server/schema/Schema_134.java
deleted file mode 100644
index 298ac03..0000000
--- a/java/com/google/gerrit/server/schema/Schema_134.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_134 extends ReviewDbSchemaVersion {
- @Inject
- Schema_134(Provider<Schema_133> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_135.java b/java/com/google/gerrit/server/schema/Schema_135.java
deleted file mode 100644
index 03ef84a..0000000
--- a/java/com/google/gerrit/server/schema/Schema_135.java
+++ /dev/null
@@ -1,104 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.PROJECT_OWNERS;
-import static java.util.stream.Collectors.toSet;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.Set;
-import java.util.stream.Stream;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_135 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG =
- "Allow admins and project owners to create refs/meta/config";
-
- private final GitRepositoryManager repoManager;
- private final AllProjectsName allProjectsName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_135(
- Provider<Schema_134> prior,
- GitRepositoryManager repoManager,
- AllProjectsName allProjectsName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allProjectsName = allProjectsName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allProjectsName);
- MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allProjectsName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
-
- AccessSection meta = config.getAccessSection(RefNames.REFS_CONFIG, true);
- Permission createRefsMetaConfigPermission = meta.getPermission(Permission.CREATE, true);
-
- Set<GroupReference> groups =
- Stream.concat(
- config
- .getAccessSection(AccessSection.GLOBAL_CAPABILITIES, true)
- .getPermission(GlobalCapability.ADMINISTRATE_SERVER, true)
- .getRules()
- .stream()
- .map(PermissionRule::getGroup),
- Stream.of(systemGroupBackend.getGroup(PROJECT_OWNERS)))
- .filter(g -> createRefsMetaConfigPermission.getRule(g) == null)
- .collect(toSet());
-
- for (GroupReference group : groups) {
- createRefsMetaConfigPermission.add(new PermissionRule(config.resolve(group)));
- }
-
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_136.java b/java/com/google/gerrit/server/schema/Schema_136.java
deleted file mode 100644
index 11eda7b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_136.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_136 extends ReviewDbSchemaVersion {
- @Inject
- Schema_136(Provider<Schema_135> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_137.java b/java/com/google/gerrit/server/schema/Schema_137.java
deleted file mode 100644
index a6ea83b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_137.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/* change the type of SystemConfig#sitePath to CLOB */
-public class Schema_137 extends ReviewDbSchemaVersion {
- @Inject
- Schema_137(Provider<Schema_136> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_138.java b/java/com/google/gerrit/server/schema/Schema_138.java
deleted file mode 100644
index 61d55ec..0000000
--- a/java/com/google/gerrit/server/schema/Schema_138.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/* Add resolved field to PatchLineComment */
-public class Schema_138 extends ReviewDbSchemaVersion {
- @Inject
- Schema_138(Provider<Schema_137> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_139.java b/java/com/google/gerrit/server/schema/Schema_139.java
deleted file mode 100644
index a234be5..0000000
--- a/java/com/google/gerrit/server/schema/Schema_139.java
+++ /dev/null
@@ -1,212 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import static com.google.common.base.Preconditions.checkState;
-
-import com.google.auto.value.AutoValue;
-import com.google.common.base.Strings;
-import com.google.common.collect.ListMultimap;
-import com.google.common.collect.MultimapBuilder;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.AccountConfig;
-import com.google.gerrit.server.account.InternalAccountUpdate;
-import com.google.gerrit.server.account.ProjectWatches.NotifyType;
-import com.google.gerrit.server.account.ProjectWatches.ProjectWatchKey;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.Collection;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-public class Schema_139 extends ReviewDbSchemaVersion {
- private static final String MSG = "Migrate project watches to git";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_139(
- Provider<Schema_138> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- ListMultimap<Account.Id, ProjectWatch> imports =
- MultimapBuilder.hashKeys().arrayListValues().build();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT "
- + "account_id, "
- + "project_name, "
- + "filter, "
- + "notify_abandoned_changes, "
- + "notify_all_comments, "
- + "notify_new_changes, "
- + "notify_new_patch_sets, "
- + "notify_submitted_changes "
- + "FROM account_project_watches")) {
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
- ProjectWatch.Builder b =
- ProjectWatch.builder()
- .project(new Project.NameKey(rs.getString(2)))
- .filter(rs.getString(3))
- .notifyAbandonedChanges(toBoolean(rs.getString(4)))
- .notifyAllComments(toBoolean(rs.getString(5)))
- .notifyNewChanges(toBoolean(rs.getString(6)))
- .notifyNewPatchSets(toBoolean(rs.getString(7)))
- .notifySubmittedChanges(toBoolean(rs.getString(8)));
- imports.put(accountId, b.build());
- }
- }
-
- if (imports.isEmpty()) {
- return;
- }
-
- try (Repository git = repoManager.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- bru.setRefLogIdent(serverUser);
- bru.setRefLogMessage(MSG, false);
-
- for (Map.Entry<Account.Id, Collection<ProjectWatch>> e : imports.asMap().entrySet()) {
- Map<ProjectWatchKey, Set<NotifyType>> projectWatches = new HashMap<>();
- for (ProjectWatch projectWatch : e.getValue()) {
- ProjectWatchKey key =
- ProjectWatchKey.create(projectWatch.project(), projectWatch.filter());
- if (projectWatches.containsKey(key)) {
- throw new OrmDuplicateKeyException(
- "Duplicate key for watched project: " + key.toString());
- }
- Set<NotifyType> notifyValues = EnumSet.noneOf(NotifyType.class);
- if (projectWatch.notifyAbandonedChanges()) {
- notifyValues.add(NotifyType.ABANDONED_CHANGES);
- }
- if (projectWatch.notifyAllComments()) {
- notifyValues.add(NotifyType.ALL_COMMENTS);
- }
- if (projectWatch.notifyNewChanges()) {
- notifyValues.add(NotifyType.NEW_CHANGES);
- }
- if (projectWatch.notifyNewPatchSets()) {
- notifyValues.add(NotifyType.NEW_PATCHSETS);
- }
- if (projectWatch.notifySubmittedChanges()) {
- notifyValues.add(NotifyType.SUBMITTED_CHANGES);
- }
- projectWatches.put(key, notifyValues);
- }
-
- try (MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git, bru)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(MSG);
-
- AccountConfig accountConfig = new AccountConfig(e.getKey(), allUsersName, git);
- accountConfig.load(md);
- accountConfig.setAccountUpdate(
- InternalAccountUpdate.builder()
- .deleteProjectWatches(accountConfig.getProjectWatches().keySet())
- .updateProjectWatches(projectWatches)
- .build());
- accountConfig.commit(md);
- }
- }
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- } catch (IOException | ConfigInvalidException ex) {
- throw new OrmException(ex);
- }
- }
-
- @AutoValue
- abstract static class ProjectWatch {
- abstract Project.NameKey project();
-
- abstract @Nullable String filter();
-
- abstract boolean notifyAbandonedChanges();
-
- abstract boolean notifyAllComments();
-
- abstract boolean notifyNewChanges();
-
- abstract boolean notifyNewPatchSets();
-
- abstract boolean notifySubmittedChanges();
-
- static Builder builder() {
- return new AutoValue_Schema_139_ProjectWatch.Builder();
- }
-
- @AutoValue.Builder
- abstract static class Builder {
- abstract Builder project(Project.NameKey project);
-
- abstract Builder filter(@Nullable String filter);
-
- abstract Builder notifyAbandonedChanges(boolean notifyAbandonedChanges);
-
- abstract Builder notifyAllComments(boolean notifyAllComments);
-
- abstract Builder notifyNewChanges(boolean notifyNewChanges);
-
- abstract Builder notifyNewPatchSets(boolean notifyNewPatchSets);
-
- abstract Builder notifySubmittedChanges(boolean notifySubmittedChanges);
-
- abstract ProjectWatch build();
- }
- }
-
- private static boolean toBoolean(String v) {
- checkState(!Strings.isNullOrEmpty(v));
- return v.equals("Y");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_140.java b/java/com/google/gerrit/server/schema/Schema_140.java
deleted file mode 100644
index f59368c..0000000
--- a/java/com/google/gerrit/server/schema/Schema_140.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Remove ChangeMessage sequence. */
-public class Schema_140 extends ReviewDbSchemaVersion {
- @Inject
- Schema_140(Provider<Schema_139> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_141.java b/java/com/google/gerrit/server/schema/Schema_141.java
deleted file mode 100644
index ce1c910..0000000
--- a/java/com/google/gerrit/server/schema/Schema_141.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Add status field to account. */
-public class Schema_141 extends ReviewDbSchemaVersion {
- @Inject
- Schema_141(Provider<Schema_140> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_142.java b/java/com/google/gerrit/server/schema/Schema_142.java
deleted file mode 100644
index 9e06c52..0000000
--- a/java/com/google/gerrit/server/schema/Schema_142.java
+++ /dev/null
@@ -1,77 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.gerrit.server.account.externalids.ExternalId.SCHEME_USERNAME;
-
-import com.google.common.base.Strings;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.account.HashedPassword;
-import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_142 extends ReviewDbSchemaVersion {
- private static final int MAX_BATCH_SIZE = 1000;
-
- @Inject
- Schema_142(Provider<Schema_141> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (PreparedStatement updateStmt =
- ((JdbcSchema) db)
- .getConnection()
- .prepareStatement(
- "UPDATE account_external_ids " + "SET password = ? " + "WHERE external_id = ?")) {
- int batchCount = 0;
-
- try (Statement stmt = newStatement(db);
- ResultSet rs =
- stmt.executeQuery("SELECT external_id, password FROM account_external_ids")) {
- while (rs.next()) {
- String externalId = rs.getString("external_id");
- String password = rs.getString("password");
- if (!ExternalId.Key.parse(externalId).isScheme(SCHEME_USERNAME)
- || Strings.isNullOrEmpty(password)) {
- continue;
- }
-
- HashedPassword hashed = HashedPassword.fromPassword(password);
- updateStmt.setString(1, hashed.encode());
- updateStmt.setString(2, externalId);
- updateStmt.addBatch();
- batchCount++;
- if (batchCount >= MAX_BATCH_SIZE) {
- updateStmt.executeBatch();
- batchCount = 0;
- }
- }
- }
-
- if (batchCount > 0) {
- updateStmt.executeBatch();
- }
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_143.java b/java/com/google/gerrit/server/schema/Schema_143.java
deleted file mode 100644
index 10d108f..0000000
--- a/java/com/google/gerrit/server/schema/Schema_143.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Add isPrivate field to change. */
-public class Schema_143 extends ReviewDbSchemaVersion {
- @Inject
- Schema_143(Provider<Schema_142> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_144.java b/java/com/google/gerrit/server/schema/Schema_144.java
deleted file mode 100644
index 0aad504..0000000
--- a/java/com/google/gerrit/server/schema/Schema_144.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2016 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.schema;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.account.externalids.ExternalIdNotes;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashSet;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_144 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG = "Import external IDs from ReviewDb";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final PersonIdent serverIdent;
-
- @Inject
- Schema_144(
- Provider<Schema_143> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverIdent) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverIdent = serverIdent;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- Set<ExternalId> toAdd = new HashSet<>();
- try (Statement stmt = ((JdbcSchema) db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT "
- + "account_id, "
- + "email_address, "
- + "password, "
- + "external_id "
- + "FROM account_external_ids")) {
- while (rs.next()) {
- Account.Id accountId = new Account.Id(rs.getInt(1));
- String email = rs.getString(2);
- String password = rs.getString(3);
- String externalId = rs.getString(4);
-
- toAdd.add(ExternalId.create(ExternalId.Key.parse(externalId), accountId, email, password));
- }
- }
-
- try {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- ExternalIdNotes extIdNotes = ExternalIdNotes.loadNoCacheUpdate(allUsersName, repo);
- extIdNotes.upsert(toAdd);
- try (MetaDataUpdate metaDataUpdate =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, repo)) {
- metaDataUpdate.getCommitBuilder().setAuthor(serverIdent);
- metaDataUpdate.getCommitBuilder().setCommitter(serverIdent);
- metaDataUpdate.getCommitBuilder().setMessage(COMMIT_MSG);
- extIdNotes.commit(metaDataUpdate);
- }
- }
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Failed to migrate external IDs to NoteDb", e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_145.java b/java/com/google/gerrit/server/schema/Schema_145.java
deleted file mode 100644
index 1207632..0000000
--- a/java/com/google/gerrit/server/schema/Schema_145.java
+++ /dev/null
@@ -1,50 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-/** Create account_external_ids_byEmail index. */
-public class Schema_145 extends ReviewDbSchemaVersion {
-
- @Inject
- Schema_145(Provider<Schema_144> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- SqlDialect dialect = schema.getDialect();
- try (StatementExecutor e = newExecutor(db)) {
- try {
- dialect.dropIndex(e, "account_external_ids", "account_external_ids_byEmail");
- } catch (OrmException ex) {
- // Ignore. The index did not exist.
- }
- e.execute(
- "CREATE INDEX account_external_ids_byEmail"
- + " ON account_external_ids"
- + " (email_address)");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_146.java b/java/com/google/gerrit/server/schema/Schema_146.java
deleted file mode 100644
index 2930408..0000000
--- a/java/com/google/gerrit/server/schema/Schema_146.java
+++ /dev/null
@@ -1,196 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.util.HashMap;
-import java.util.Map;
-import org.eclipse.jgit.lib.CommitBuilder;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevSort;
-import org.eclipse.jgit.revwalk.RevWalk;
-
-/**
- * Make sure that for every account a user branch exists that has an initial empty commit with the
- * registration date as commit time.
- *
- * <p>For accounts that don't have a user branch yet the user branch is created with an initial
- * empty commit that has the registration date as commit time.
- *
- * <p>For accounts that already have a user branch the user branch is rewritten and an initial empty
- * commit with the registration date as commit time is inserted (if such a commit doesn't exist
- * yet).
- */
-public class Schema_146 extends ReviewDbSchemaVersion {
- private static final String CREATE_ACCOUNT_MSG = "Create Account";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final PersonIdent serverIdent;
-
- @Inject
- Schema_146(
- Provider<Schema_145> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverIdent) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverIdent = serverIdent;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository repo = repoManager.openRepository(allUsersName);
- RevWalk rw = new RevWalk(repo);
- ObjectInserter oi = repo.newObjectInserter()) {
- ObjectId emptyTree = emptyTree(oi);
-
- for (Map.Entry<Account.Id, Timestamp> e : scanAccounts(db).entrySet()) {
- String refName = RefNames.refsUsers(e.getKey());
- Ref ref = repo.exactRef(refName);
- if (ref != null) {
- rewriteUserBranch(repo, rw, oi, emptyTree, ref, e.getValue());
- } else {
- createUserBranch(repo, oi, emptyTree, e.getKey(), e.getValue());
- }
- }
- } catch (IOException e) {
- throw new OrmException("Failed to rewrite user branches.", e);
- }
- }
-
- private void rewriteUserBranch(
- Repository repo,
- RevWalk rw,
- ObjectInserter oi,
- ObjectId emptyTree,
- Ref ref,
- Timestamp registeredOn)
- throws IOException {
- ObjectId current = createInitialEmptyCommit(oi, emptyTree, registeredOn);
-
- rw.reset();
- rw.sort(RevSort.TOPO);
- rw.sort(RevSort.REVERSE, true);
- rw.markStart(rw.parseCommit(ref.getObjectId()));
-
- RevCommit c;
- while ((c = rw.next()) != null) {
- if (isInitialEmptyCommit(emptyTree, c)) {
- return;
- }
-
- CommitBuilder cb = new CommitBuilder();
- cb.setParentId(current);
- cb.setTreeId(c.getTree());
- cb.setAuthor(c.getAuthorIdent());
- cb.setCommitter(c.getCommitterIdent());
- cb.setMessage(c.getFullMessage());
- cb.setEncoding(c.getEncoding());
- current = oi.insert(cb);
- }
-
- oi.flush();
-
- RefUpdate ru = repo.updateRef(ref.getName());
- ru.setExpectedOldObjectId(ref.getObjectId());
- ru.setNewObjectId(current);
- ru.setForceUpdate(true);
- ru.setRefLogIdent(serverIdent);
- ru.setRefLogMessage(getClass().getSimpleName(), true);
- Result result = ru.update();
- if (result != Result.FORCED) {
- throw new IOException(
- String.format("Failed to update ref %s: %s", ref.getName(), result.name()));
- }
- }
-
- public void createUserBranch(
- Repository repo,
- ObjectInserter oi,
- ObjectId emptyTree,
- Account.Id accountId,
- Timestamp registeredOn)
- throws IOException {
- ObjectId id = createInitialEmptyCommit(oi, emptyTree, registeredOn);
-
- String refName = RefNames.refsUsers(accountId);
- RefUpdate ru = repo.updateRef(refName);
- ru.setExpectedOldObjectId(ObjectId.zeroId());
- ru.setNewObjectId(id);
- ru.setRefLogIdent(serverIdent);
- ru.setRefLogMessage(CREATE_ACCOUNT_MSG, false);
- Result result = ru.update();
- if (result != Result.NEW) {
- throw new IOException(String.format("Failed to update ref %s: %s", refName, result.name()));
- }
- }
-
- private ObjectId createInitialEmptyCommit(
- ObjectInserter oi, ObjectId emptyTree, Timestamp registrationDate) throws IOException {
- PersonIdent ident = new PersonIdent(serverIdent, registrationDate);
-
- CommitBuilder cb = new CommitBuilder();
- cb.setTreeId(emptyTree);
- cb.setCommitter(ident);
- cb.setAuthor(ident);
- cb.setMessage(CREATE_ACCOUNT_MSG);
- return oi.insert(cb);
- }
-
- private boolean isInitialEmptyCommit(ObjectId emptyTree, RevCommit c) {
- return c.getParentCount() == 0
- && c.getTree().equals(emptyTree)
- && c.getShortMessage().equals(CREATE_ACCOUNT_MSG);
- }
-
- private static ObjectId emptyTree(ObjectInserter oi) throws IOException {
- return oi.insert(Constants.OBJ_TREE, new byte[] {});
- }
-
- private Map<Account.Id, Timestamp> scanAccounts(ReviewDb db) throws SQLException {
- try (Statement stmt = newStatement(db);
- ResultSet rs = stmt.executeQuery("SELECT account_id, registered_on FROM accounts")) {
- HashMap<Account.Id, Timestamp> m = new HashMap<>();
- while (rs.next()) {
- m.put(new Account.Id(rs.getInt(1)), rs.getTimestamp(2));
- }
- return m;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_147.java b/java/com/google/gerrit/server/schema/Schema_147.java
deleted file mode 100644
index f317e9a..0000000
--- a/java/com/google/gerrit/server/schema/Schema_147.java
+++ /dev/null
@@ -1,100 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static java.util.stream.Collectors.toSet;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashSet;
-import java.util.Objects;
-import java.util.Set;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.RefUpdate.Result;
-import org.eclipse.jgit.lib.Repository;
-
-/** Delete user branches for which no account exists. */
-public class Schema_147 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_147(
- Provider<Schema_146> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- Set<Account.Id> accountIdsFromReviewDb = scanAccounts(db);
- Set<Account.Id> accountIdsFromUserBranches =
- repo.getRefDatabase()
- .getRefsByPrefix(RefNames.REFS_USERS)
- .stream()
- .map(r -> Account.Id.fromRef(r.getName()))
- .filter(Objects::nonNull)
- .collect(toSet());
- accountIdsFromUserBranches.removeAll(accountIdsFromReviewDb);
- for (Account.Id accountId : accountIdsFromUserBranches) {
- deleteUserBranch(repo, accountId);
- }
- } catch (IOException e) {
- throw new OrmException("Failed to delete user branches for non-existing accounts.", e);
- }
- }
-
- private Set<Account.Id> scanAccounts(ReviewDb db) throws SQLException {
- try (Statement stmt = newStatement(db);
- ResultSet rs = stmt.executeQuery("SELECT account_id FROM accounts")) {
- Set<Account.Id> ids = new HashSet<>();
- while (rs.next()) {
- ids.add(new Account.Id(rs.getInt(1)));
- }
- return ids;
- }
- }
-
- private void deleteUserBranch(Repository allUsersRepo, Account.Id accountId) throws IOException {
- String refName = RefNames.refsUsers(accountId);
- Ref ref = allUsersRepo.exactRef(refName);
- if (ref == null) {
- return;
- }
-
- RefUpdate ru = allUsersRepo.updateRef(refName);
- ru.setExpectedOldObjectId(ref.getObjectId());
- ru.setNewObjectId(ObjectId.zeroId());
- ru.setForceUpdate(true);
- Result result = ru.delete();
- if (result != Result.FORCED) {
- throw new IOException(String.format("Failed to delete ref %s: %s", refName, result.name()));
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_148.java b/java/com/google/gerrit/server/schema/Schema_148.java
deleted file mode 100644
index 949dd5a..0000000
--- a/java/com/google/gerrit/server/schema/Schema_148.java
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.common.primitives.Ints;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.account.externalids.ExternalIdNotes;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_148 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG = "Make account IDs of external IDs human-readable";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_148(
- Provider<Schema_147> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- ExternalIdNotes extIdNotes = ExternalIdNotes.loadNoCacheUpdate(allUsersName, repo);
- for (ExternalId extId : extIdNotes.all()) {
- if (needsUpdate(extId)) {
- extIdNotes.upsert(extId);
- }
- }
-
- try (MetaDataUpdate metaDataUpdate =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, repo)) {
- metaDataUpdate.getCommitBuilder().setAuthor(serverUser);
- metaDataUpdate.getCommitBuilder().setCommitter(serverUser);
- metaDataUpdate.getCommitBuilder().setMessage(COMMIT_MSG);
- extIdNotes.commit(metaDataUpdate);
- }
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Failed to update external IDs", e);
- }
- }
-
- private static boolean needsUpdate(ExternalId extId) {
- Config cfg = new Config();
- cfg.setInt("externalId", extId.key().get(), "accountId", extId.accountId().get());
- return Ints.tryParse(cfg.getString("externalId", extId.key().get(), "accountId")) == null;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_149.java b/java/com/google/gerrit/server/schema/Schema_149.java
deleted file mode 100644
index 156091b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_149.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Add workInProgress field to change. */
-public class Schema_149 extends ReviewDbSchemaVersion {
- @Inject
- Schema_149(Provider<Schema_148> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_150.java b/java/com/google/gerrit/server/schema/Schema_150.java
deleted file mode 100644
index 71736f3..0000000
--- a/java/com/google/gerrit/server/schema/Schema_150.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Drop ACCOUNT_EXTERNAL_IDS table. */
-public class Schema_150 extends ReviewDbSchemaVersion {
- @Inject
- Schema_150(Provider<Schema_149> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_151.java b/java/com/google/gerrit/server/schema/Schema_151.java
deleted file mode 100644
index 0e8700f..0000000
--- a/java/com/google/gerrit/server/schema/Schema_151.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Optional;
-
-/** A schema which adds the 'created on' field to groups. */
-public class Schema_151 extends ReviewDbSchemaVersion {
- @Inject
- protected Schema_151(Provider<Schema_150> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (PreparedStatement groupUpdate =
- prepareStatement(db, "UPDATE account_groups SET created_on = ? WHERE group_id = ?");
- PreparedStatement addedOnRetrieval =
- prepareStatement(
- db,
- "SELECT added_on FROM account_group_members_audit WHERE group_id = ?"
- + " ORDER BY added_on ASC")) {
- List<AccountGroup.Id> accountGroups = getAllGroupIds(db);
- for (AccountGroup.Id groupId : accountGroups) {
- Optional<Timestamp> firstTimeMentioned = getFirstTimeMentioned(addedOnRetrieval, groupId);
- Timestamp createdOn = firstTimeMentioned.orElseGet(AccountGroup::auditCreationInstantTs);
-
- groupUpdate.setTimestamp(1, createdOn);
- groupUpdate.setInt(2, groupId.get());
- groupUpdate.executeUpdate();
- }
- }
- }
-
- private static Optional<Timestamp> getFirstTimeMentioned(
- PreparedStatement addedOnRetrieval, AccountGroup.Id groupId) throws SQLException {
- addedOnRetrieval.setInt(1, groupId.get());
- try (ResultSet resultSet = addedOnRetrieval.executeQuery()) {
- if (resultSet.next()) {
- return Optional.of(resultSet.getTimestamp(1));
- }
- }
- return Optional.empty();
- }
-
- private static List<AccountGroup.Id> getAllGroupIds(ReviewDb db) throws SQLException {
- try (Statement stmt = newStatement(db);
- ResultSet rs = stmt.executeQuery("SELECT group_id FROM account_groups")) {
- List<AccountGroup.Id> groupIds = new ArrayList<>();
- while (rs.next()) {
- groupIds.add(new AccountGroup.Id(rs.getInt(1)));
- }
- return groupIds;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_152.java b/java/com/google/gerrit/server/schema/Schema_152.java
deleted file mode 100644
index b605e90..0000000
--- a/java/com/google/gerrit/server/schema/Schema_152.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-/** Drop unused indexes from accounts table. */
-public class Schema_152 extends ReviewDbSchemaVersion {
- @Inject
- Schema_152(Provider<Schema_151> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- SqlDialect dialect = schema.getDialect();
- try (StatementExecutor e = newExecutor(db)) {
- dialect.dropIndex(e, "accounts", "accounts_byFullName");
- } catch (OrmException ex) {
- // Ignore. The index did not exist.
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_153.java b/java/com/google/gerrit/server/schema/Schema_153.java
deleted file mode 100644
index 7d1f63e..0000000
--- a/java/com/google/gerrit/server/schema/Schema_153.java
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Add reviewStarted field to change. */
-public class Schema_153 extends ReviewDbSchemaVersion {
- @Inject
- Schema_153(Provider<Schema_152> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (StatementExecutor e = newExecutor(db)) {
- // Initialize review_started to a sensible default value according to
- // whether change is currently WIP. No migration is needed in NoteDb,
- // where the value of review_started is always derived from the history
- // of assignments to work_in_progress.
- e.execute(
- "UPDATE changes SET review_started = 'Y', created_on = created_on WHERE work_in_progress = 'N'");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_154.java b/java/com/google/gerrit/server/schema/Schema_154.java
deleted file mode 100644
index 8c97010..0000000
--- a/java/com/google/gerrit/server/schema/Schema_154.java
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static java.util.stream.Collectors.toMap;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.AccountConfig;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.Connection;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-
-/** Migrate accounts to NoteDb. */
-public class Schema_154 extends ReviewDbSchemaVersion {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private static final String TABLE = "accounts";
- private static final ImmutableMap<String, AccountSetter> ACCOUNT_FIELDS_MAP =
- ImmutableMap.<String, AccountSetter>builder()
- .put("full_name", (a, rs, field) -> a.setFullName(rs.getString(field)))
- .put("preferred_email", (a, rs, field) -> a.setPreferredEmail(rs.getString(field)))
- .put("status", (a, rs, field) -> a.setStatus(rs.getString(field)))
- .put("inactive", (a, rs, field) -> a.setActive(rs.getString(field).equals("N")))
- .build();
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final Provider<PersonIdent> serverIdent;
-
- @Inject
- Schema_154(
- Provider<Schema_153> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent Provider<PersonIdent> serverIdent) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverIdent = serverIdent;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- ProgressMonitor pm = new TextProgressMonitor();
- pm.beginTask("Collecting accounts", ProgressMonitor.UNKNOWN);
- Set<Account> accounts = scanAccounts(db, pm);
- pm.endTask();
- pm.beginTask("Migrating accounts to NoteDb", accounts.size());
- for (Account account : accounts) {
- updateAccountInNoteDb(repo, account);
- pm.update(1);
- }
- pm.endTask();
- }
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Migrating accounts to NoteDb failed", e);
- }
- }
-
- private Set<Account> scanAccounts(ReviewDb db, ProgressMonitor pm) throws SQLException {
- Map<String, AccountSetter> fields = getFields(db);
- if (fields.isEmpty()) {
- logger.atWarning().log("Only account_id and registered_on fields are migrated for accounts");
- }
-
- List<String> queryFields = new ArrayList<>();
- queryFields.add("account_id");
- queryFields.add("registered_on");
- queryFields.addAll(fields.keySet());
- String query = "SELECT " + String.join(", ", queryFields) + String.format(" FROM %s", TABLE);
- try (Statement stmt = newStatement(db);
- ResultSet rs = stmt.executeQuery(query)) {
- Set<Account> s = new HashSet<>();
- while (rs.next()) {
- Account a = new Account(new Account.Id(rs.getInt(1)), rs.getTimestamp(2));
- for (Map.Entry<String, AccountSetter> field : fields.entrySet()) {
- field.getValue().set(a, rs, field.getKey());
- }
- s.add(a);
- pm.update(1);
- }
- return s;
- }
- }
-
- private Map<String, AccountSetter> getFields(ReviewDb db) throws SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- Connection connection = schema.getConnection();
- Set<String> columns = schema.getDialect().listColumns(connection, TABLE);
- return ACCOUNT_FIELDS_MAP
- .entrySet()
- .stream()
- .filter(e -> columns.contains(e.getKey()))
- .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));
- }
-
- private void updateAccountInNoteDb(Repository allUsersRepo, Account account)
- throws IOException, ConfigInvalidException {
- MetaDataUpdate md =
- new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, allUsersRepo);
- PersonIdent ident = serverIdent.get();
- md.getCommitBuilder().setAuthor(ident);
- md.getCommitBuilder().setCommitter(ident);
- new AccountConfig(account.getId(), allUsersName, allUsersRepo)
- .load()
- .setAccount(account)
- .commit(md);
- }
-
- @FunctionalInterface
- private interface AccountSetter {
- void set(Account a, ResultSet rs, String field) throws SQLException;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_155.java b/java/com/google/gerrit/server/schema/Schema_155.java
deleted file mode 100644
index e9372a5..0000000
--- a/java/com/google/gerrit/server/schema/Schema_155.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.RepoSequence;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-/** Create account sequence in NoteDb */
-public class Schema_155 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_155(
- Provider<Schema_154> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- RepoSequence accountSeq =
- new RepoSequence(
- repoManager,
- GitReferenceUpdated.DISABLED,
- allUsersName,
- Sequences.NAME_ACCOUNTS,
- () -> ReviewDb.FIRST_ACCOUNT_ID,
- 1);
-
- // consume one account ID to ensure that the account sequence is initialized in NoteDb
- accountSeq.next();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_156.java b/java/com/google/gerrit/server/schema/Schema_156.java
deleted file mode 100644
index 237161c..0000000
--- a/java/com/google/gerrit/server/schema/Schema_156.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Add revertOf field to change. */
-public class Schema_156 extends ReviewDbSchemaVersion {
- @Inject
- Schema_156(Provider<Schema_155> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_157.java b/java/com/google/gerrit/server/schema/Schema_157.java
deleted file mode 100644
index 20a8c4b..0000000
--- a/java/com/google/gerrit/server/schema/Schema_157.java
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-/** Drop unused indexes from accounts table. */
-public class Schema_157 extends ReviewDbSchemaVersion {
- @Inject
- Schema_157(Provider<Schema_156> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- JdbcSchema schema = (JdbcSchema) db;
- SqlDialect dialect = schema.getDialect();
- try (StatementExecutor e = newExecutor(db)) {
- dialect.dropIndex(e, "accounts", "accounts_byPreferredEmail");
- } catch (OrmException ex) {
- // Ignore. The index did not exist.
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_158.java b/java/com/google/gerrit/server/schema/Schema_158.java
deleted file mode 100644
index 3b7d9e8..0000000
--- a/java/com/google/gerrit/server/schema/Schema_158.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Drop ACCOUNTS table. */
-public class Schema_158 extends ReviewDbSchemaVersion {
- @Inject
- Schema_158(Provider<Schema_157> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_159.java b/java/com/google/gerrit/server/schema/Schema_159.java
deleted file mode 100644
index ddb5765..0000000
--- a/java/com/google/gerrit/server/schema/Schema_159.java
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-/** Migrate draft changes to private or wip changes. */
-public class Schema_159 extends ReviewDbSchemaVersion {
-
- private enum DraftWorkflowMigrationStrategy {
- PRIVATE,
- WORK_IN_PROGRESS
- }
-
- @Inject
- Schema_159(Provider<Schema_158> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- DraftWorkflowMigrationStrategy strategy = DraftWorkflowMigrationStrategy.WORK_IN_PROGRESS;
- if (ui.yesno(false, "Migrate draft changes to private changes (default is work-in-progress)")) {
- strategy = DraftWorkflowMigrationStrategy.PRIVATE;
- }
- ui.message(
- String.format("Replace draft changes with %s changes ...", strategy.name().toLowerCase()));
- try (StatementExecutor e = newExecutor(db)) {
- String column =
- strategy == DraftWorkflowMigrationStrategy.PRIVATE ? "is_private" : "work_in_progress";
- // Mark changes private/WIP and NEW if either:
- // * they have status DRAFT
- // * they have status NEW and have any draft patch sets
- e.execute(
- String.format(
- "UPDATE changes "
- + "SET %s = 'Y', "
- + " status = 'n', "
- + " created_on = created_on "
- + "WHERE status = 'd' "
- + " OR (status = 'n' "
- + " AND EXISTS "
- + " (SELECT * "
- + " FROM patch_sets "
- + " WHERE patch_sets.change_id = changes.change_id "
- + " AND patch_sets.draft = 'Y')) ",
- column));
- }
- ui.message("done");
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_160.java b/java/com/google/gerrit/server/schema/Schema_160.java
deleted file mode 100644
index 10f5c9d..0000000
--- a/java/com/google/gerrit/server/schema/Schema_160.java
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.gerrit.server.git.UserConfigSections.KEY_URL;
-import static com.google.gerrit.server.git.UserConfigSections.MY;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.Accounts;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.CommitBuilder;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-
-/**
- * Remove "My Drafts" menu items for all users and server-wide default preferences.
- *
- * <p>Since draft changes no longer exist, these menu items are obsolete.
- *
- * <p>Only matches menu items (with any name) where the URL exactly matches one of the following,
- * with or without leading {@code #}:
- *
- * <ul>
- * <li>/q/is:draft
- * <li>/q/owner:self+is:draft
- * </ul>
- *
- * In particular, this includes the <a
- * href="https://gerrit.googlesource.com/gerrit/+/v2.14.4/gerrit-server/src/main/java/com/google/gerrit/server/account/GeneralPreferencesLoader.java#144">default
- * from version 2.14 and earlier</a>.
- *
- * <p>Other menus containing {@code is:draft} in other positions are not affected; this is still a
- * valid predicate that matches no changes.
- */
-public class Schema_160 extends ReviewDbSchemaVersion {
- @VisibleForTesting static final ImmutableList<String> DEFAULT_DRAFT_ITEMS;
-
- static {
- String ownerSelfIsDraft = "/q/owner:self+is:draft";
- String isDraft = "/q/is:draft";
- DEFAULT_DRAFT_ITEMS =
- ImmutableList.of(ownerSelfIsDraft, '#' + ownerSelfIsDraft, isDraft, '#' + isDraft);
- }
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final Provider<PersonIdent> serverIdent;
-
- @Inject
- Schema_160(
- Provider<Schema_159> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritPersonIdent Provider<PersonIdent> serverIdent) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.serverIdent = serverIdent;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- ProgressMonitor pm = new TextProgressMonitor();
- pm.beginTask("Removing \"My Drafts\" menu items", ProgressMonitor.UNKNOWN);
- for (Account.Id id : (Iterable<Account.Id>) Accounts.readUserRefs(repo)::iterator) {
- removeMyDrafts(repo, RefNames.refsUsers(id), pm);
- }
- removeMyDrafts(repo, RefNames.REFS_USERS_DEFAULT, pm);
- pm.endTask();
- }
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Removing \"My Drafts\" menu items failed", e);
- }
- }
-
- private void removeMyDrafts(Repository repo, String ref, ProgressMonitor pm)
- throws IOException, ConfigInvalidException {
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, repo);
- PersonIdent ident = serverIdent.get();
- md.getCommitBuilder().setAuthor(ident);
- md.getCommitBuilder().setCommitter(ident);
- Prefs prefs = new Prefs(ref);
- prefs.load(allUsersName, repo);
- prefs.removeMyDrafts();
- prefs.commit(md);
- if (prefs.dirty()) {
- pm.update(1);
- }
- }
-
- private static class Prefs extends VersionedAccountPreferences {
- private boolean dirty;
-
- Prefs(String ref) {
- super(ref);
- }
-
- @Override
- protected boolean onSave(CommitBuilder commit) throws IOException, ConfigInvalidException {
- if (!dirty) {
- return false;
- }
- commit.setMessage("Remove \"My Drafts\" menu items");
- return super.onSave(commit);
- }
-
- void removeMyDrafts() {
- Config cfg = getConfig();
- for (String item : cfg.getSubsections(MY)) {
- String value = cfg.getString(MY, item, KEY_URL);
- if (DEFAULT_DRAFT_ITEMS.contains(value)) {
- cfg.unsetSection(MY, item);
- dirty = true;
- }
- }
- }
-
- boolean dirty() {
- return dirty;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_161.java b/java/com/google/gerrit/server/schema/Schema_161.java
deleted file mode 100644
index 4627abe..0000000
--- a/java/com/google/gerrit/server/schema/Schema_161.java
+++ /dev/null
@@ -1,114 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.primitives.Ints;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.StarredChangesUtil;
-import com.google.gerrit.server.StarredChangesUtil.IllegalLabelException;
-import com.google.gerrit.server.StarredChangesUtil.StarRef;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-public class Schema_161 extends ReviewDbSchemaVersion {
- private static final String MUTE_LABEL = "mute";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_161(
- Provider<Schema_160> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allUsersName);
- RevWalk rw = new RevWalk(git)) {
- BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate();
- bru.setAllowNonFastForwards(true);
-
- for (Ref ref : git.getRefDatabase().getRefsByPrefix(RefNames.REFS_STARRED_CHANGES)) {
- StarRef starRef = StarredChangesUtil.readLabels(git, ref.getName());
-
- Set<Integer> mutedPatchSets =
- StarredChangesUtil.getStarredPatchSets(starRef.labels(), MUTE_LABEL);
- if (mutedPatchSets.isEmpty()) {
- continue;
- }
-
- Set<Integer> reviewedPatchSets =
- StarredChangesUtil.getStarredPatchSets(
- starRef.labels(), StarredChangesUtil.REVIEWED_LABEL);
- Set<Integer> unreviewedPatchSets =
- StarredChangesUtil.getStarredPatchSets(
- starRef.labels(), StarredChangesUtil.UNREVIEWED_LABEL);
-
- List<String> newLabels =
- starRef
- .labels()
- .stream()
- .map(
- l -> {
- if (l.startsWith(MUTE_LABEL)) {
- Integer mutedPatchSet = Ints.tryParse(l.substring(MUTE_LABEL.length() + 1));
- if (mutedPatchSet == null) {
- // unexpected format of mute label, must be a label that was manually
- // set, just leave it alone
- return l;
- }
- if (!reviewedPatchSets.contains(mutedPatchSet)
- && !unreviewedPatchSets.contains(mutedPatchSet)) {
- // convert mute label to reviewed label
- return StarredChangesUtil.REVIEWED_LABEL + "/" + mutedPatchSet;
- }
- // else patch set is muted but has either reviewed or unreviewed label
- // -> just drop the mute label
- return null;
- }
- return l;
- })
- .filter(Objects::nonNull)
- .collect(toList());
-
- ObjectId id = StarredChangesUtil.writeLabels(git, newLabels);
- bru.addCommand(new ReceiveCommand(ref.getTarget().getObjectId(), id, ref.getName()));
- }
- bru.execute(rw, new TextProgressMonitor());
- } catch (IOException | IllegalLabelException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_162.java b/java/com/google/gerrit/server/schema/Schema_162.java
deleted file mode 100644
index 3d3a192..0000000
--- a/java/com/google/gerrit/server/schema/Schema_162.java
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-public class Schema_162 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllProjectsName allProjectsName;
- private final AllUsersName allUsersName;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_162(
- Provider<Schema_161> prior,
- GitRepositoryManager repoManager,
- AllProjectsName allProjectsName,
- AllUsersName allUsersName,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allProjectsName = allProjectsName;
- this.allUsersName = allUsersName;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- ProjectConfig cfg = projectConfigFactory.read(md);
- if (allProjectsName.equals(cfg.getProject().getParent(allProjectsName))) {
- return;
- }
- cfg.getProject().setParentName(allProjectsName);
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(
- String.format("Make %s inherit from %s", allUsersName.get(), allProjectsName.get()));
- cfg.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_163.java b/java/com/google/gerrit/server/schema/Schema_163.java
deleted file mode 100644
index 4b3659de..0000000
--- a/java/com/google/gerrit/server/schema/Schema_163.java
+++ /dev/null
@@ -1,55 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.RepoSequence;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-/** Create group sequence in NoteDb */
-public class Schema_163 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_163(
- Provider<Schema_162> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- RepoSequence groupSeq =
- new RepoSequence(
- repoManager,
- GitReferenceUpdated.DISABLED,
- allUsersName,
- Sequences.NAME_GROUPS,
- () -> ReviewDb.FIRST_GROUP_ID,
- 1);
-
- // consume one account ID to ensure that the group sequence is initialized in NoteDb
- groupSeq.next();
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_164.java b/java/com/google/gerrit/server/schema/Schema_164.java
deleted file mode 100644
index b6c3118..0000000
--- a/java/com/google/gerrit/server/schema/Schema_164.java
+++ /dev/null
@@ -1,88 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static com.google.gerrit.server.schema.AclUtil.grant;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-/** Grant read on group branches */
-public class Schema_164 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG = "Grant read permissions on group branches";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_164(
- Provider<Schema_163> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
-
- ProjectConfig config = projectConfigFactory.read(md);
- AccessSection groups = config.getAccessSection(RefNames.REFS_GROUPS + "*", true);
- grant(
- config,
- groups,
- Permission.READ,
- false,
- true,
- systemGroupBackend.getGroup(REGISTERED_USERS));
- config.commit(md);
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Failed to grant read permissions on group branches", e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_165.java b/java/com/google/gerrit/server/schema/Schema_165.java
deleted file mode 100644
index d80c770..0000000
--- a/java/com/google/gerrit/server/schema/Schema_165.java
+++ /dev/null
@@ -1,145 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-
-import com.google.gerrit.common.data.AccessSection;
-import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.data.PermissionRule;
-import com.google.gerrit.common.data.PermissionRule.Action;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.project.RefPattern;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.SQLException;
-import java.util.Optional;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-/** Make default Label-Code-Review permission on user branches exclusive. */
-public class Schema_165 extends ReviewDbSchemaVersion {
- private static final String COMMIT_MSG =
- "Make default Label-Code-Review permission on user branches exclusive";
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final SystemGroupBackend systemGroupBackend;
- private final ProjectConfig.Factory projectConfigFactory;
- private final PersonIdent serverUser;
-
- @Inject
- Schema_165(
- Provider<Schema_164> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- SystemGroupBackend systemGroupBackend,
- ProjectConfig.Factory projectConfigFactory,
- @GerritPersonIdent PersonIdent serverUser) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.systemGroupBackend = systemGroupBackend;
- this.projectConfigFactory = projectConfigFactory;
- this.serverUser = serverUser;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- ProjectConfig config = projectConfigFactory.read(md);
- Optional<Permission> permission = findDefaultPermission(config);
- if (!permission.isPresent()) {
- // the default permission was not found, hence it cannot be fixed
- return;
- }
-
- permission.get().setExclusiveGroup(true);
-
- md.getCommitBuilder().setAuthor(serverUser);
- md.getCommitBuilder().setCommitter(serverUser);
- md.setMessage(COMMIT_MSG);
- config.commit(md);
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException(
- "Failed to make default Label-Code-Review permission on user branches exclusive", e);
- }
- }
-
- /**
- * Searches for the default "Label-Code-Review" permission on the user branch and returns it if it
- * was found. If it was not found (e.g. because it was removed or modified) {@link
- * Optional#empty()} is returned.
- */
- private Optional<Permission> findDefaultPermission(ProjectConfig config) {
- AccessSection users =
- config.getAccessSection(
- RefNames.REFS_USERS + "${" + RefPattern.USERID_SHARDED + "}", false);
- if (users == null) {
- // default permission was removed
- return Optional.empty();
- }
-
- Permission permission = users.getPermission(Permission.LABEL + "Code-Review", false);
- return isDefaultPermissionUntouched(permission) ? Optional.of(permission) : Optional.empty();
- }
-
- /**
- * Checks whether the given permission matches the default "Label-Code-Review" permission on the
- * user branch that was initially setup by {@link AllUsersCreator}.
- */
- private boolean isDefaultPermissionUntouched(Permission permission) {
- if (permission == null) {
- // default permission was removed
- return false;
- } else if (permission.getExclusiveGroup()) {
- // default permission was modified
- return false;
- }
-
- if (permission.getRules().size() != 1) {
- // default permission was modified
- return false;
- }
-
- PermissionRule rule = permission.getRule(systemGroupBackend.getGroup(REGISTERED_USERS));
- if (rule == null) {
- // default permission was removed
- return false;
- }
-
- if (rule.getAction() != Action.ALLOW
- || rule.getForce()
- || rule.getMin() != -2
- || rule.getMax() != 2) {
- // default permission was modified
- return false;
- }
-
- return true;
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_166.java b/java/com/google/gerrit/server/schema/Schema_166.java
deleted file mode 100644
index 901df56..0000000
--- a/java/com/google/gerrit/server/schema/Schema_166.java
+++ /dev/null
@@ -1,52 +0,0 @@
-// Copyright (C) 2018 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.schema;
-
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-
-/** Set HEAD for All-Users to refs/meta/config. */
-public class Schema_166 extends ReviewDbSchemaVersion {
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
-
- @Inject
- Schema_166(
- Provider<Schema_165> prior, GitRepositoryManager repoManager, AllUsersName allUsersName) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (Repository git = repoManager.openRepository(allUsersName)) {
- RefUpdate u = git.updateRef(Constants.HEAD);
- u.link(RefNames.REFS_CONFIG);
- } catch (IOException e) {
- throw new OrmException(String.format("Failed to update HEAD for %s", allUsersName.get()), e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_167.java b/java/com/google/gerrit/server/schema/Schema_167.java
deleted file mode 100644
index 44d89f9..0000000
--- a/java/com/google/gerrit/server/schema/Schema_167.java
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright (C) 2018 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.schema;
-
-import static com.google.gerrit.server.notedb.NoteDbTable.GROUPS;
-import static com.google.gerrit.server.notedb.NotesMigration.DISABLE_REVIEW_DB;
-import static com.google.gerrit.server.notedb.NotesMigration.SECTION_NOTE_DB;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.GroupDescription;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.git.RefUpdateUtil;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.account.AccountConfig;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.GerritServerIdProvider;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.group.db.AuditLogFormatter;
-import com.google.gerrit.server.group.db.GroupNameNotes;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-
-/** Migrate groups from ReviewDb to NoteDb. */
-public class Schema_167 extends ReviewDbSchemaVersion {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final GitRepositoryManager repoManager;
- private final AllUsersName allUsersName;
- private final Config gerritConfig;
- private final SitePaths sitePaths;
- private final PersonIdent serverIdent;
- private final SystemGroupBackend systemGroupBackend;
-
- @Inject
- protected Schema_167(
- Provider<Schema_166> prior,
- GitRepositoryManager repoManager,
- AllUsersName allUsersName,
- @GerritServerConfig Config gerritConfig,
- SitePaths sitePaths,
- @GerritPersonIdent PersonIdent serverIdent,
- SystemGroupBackend systemGroupBackend) {
- super(prior);
- this.repoManager = repoManager;
- this.allUsersName = allUsersName;
- this.gerritConfig = gerritConfig;
- this.sitePaths = sitePaths;
- this.serverIdent = serverIdent;
- this.systemGroupBackend = systemGroupBackend;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- if (gerritConfig.getBoolean(SECTION_NOTE_DB, GROUPS.key(), DISABLE_REVIEW_DB, false)) {
- // Groups in ReviewDb have already been disabled, nothing to do.
- return;
- }
-
- try (Repository allUsersRepo = repoManager.openRepository(allUsersName)) {
- List<GroupReference> allGroupReferences = readGroupReferencesFromReviewDb(db);
-
- BatchRefUpdate batchRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
- writeAllGroupNamesToNoteDb(allUsersRepo, allGroupReferences, batchRefUpdate);
-
- GroupRebuilder groupRebuilder = createGroupRebuilder(db, allUsersRepo);
- for (GroupReference groupReference : allGroupReferences) {
- migrateOneGroupToNoteDb(
- db, allUsersRepo, groupRebuilder, groupReference.getUUID(), batchRefUpdate);
- }
-
- RefUpdateUtil.executeChecked(batchRefUpdate, allUsersRepo);
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException(
- String.format("Failed to migrate groups to NoteDb for %s", allUsersName.get()), e);
- }
- }
-
- private List<GroupReference> readGroupReferencesFromReviewDb(ReviewDb db) throws SQLException {
- try (Statement stmt = ReviewDbWrapper.unwrapJbdcSchema(db).getConnection().createStatement();
- ResultSet rs = stmt.executeQuery("SELECT group_uuid, name FROM account_groups")) {
- List<GroupReference> allGroupReferences = new ArrayList<>();
- while (rs.next()) {
- AccountGroup.UUID groupUuid = new AccountGroup.UUID(rs.getString(1));
- String groupName = rs.getString(2);
- allGroupReferences.add(new GroupReference(groupUuid, groupName));
- }
- return allGroupReferences;
- }
- }
-
- private void writeAllGroupNamesToNoteDb(
- Repository allUsersRepo,
- List<GroupReference> allGroupReferences,
- BatchRefUpdate batchRefUpdate)
- throws IOException {
- try (ObjectInserter inserter = allUsersRepo.newObjectInserter()) {
- GroupNameNotes.updateAllGroups(
- allUsersRepo, inserter, batchRefUpdate, allGroupReferences, serverIdent);
- inserter.flush();
- }
- }
-
- private GroupRebuilder createGroupRebuilder(ReviewDb db, Repository allUsersRepo)
- throws IOException, ConfigInvalidException {
- AuditLogFormatter auditLogFormatter =
- createAuditLogFormatter(db, allUsersRepo, gerritConfig, sitePaths);
- return new GroupRebuilder(serverIdent, allUsersName, auditLogFormatter);
- }
-
- private AuditLogFormatter createAuditLogFormatter(
- ReviewDb db, Repository allUsersRepo, Config gerritConfig, SitePaths sitePaths)
- throws IOException, ConfigInvalidException {
- String serverId = new GerritServerIdProvider(gerritConfig, sitePaths).get();
- SimpleInMemoryAccountCache accountCache =
- new SimpleInMemoryAccountCache(allUsersName, allUsersRepo);
- SimpleInMemoryGroupCache groupCache = new SimpleInMemoryGroupCache(db);
- return AuditLogFormatter.create(
- accountCache::get,
- uuid -> {
- if (systemGroupBackend.handles(uuid)) {
- return Optional.ofNullable(systemGroupBackend.get(uuid));
- }
- return groupCache.get(uuid);
- },
- serverId);
- }
-
- private static void migrateOneGroupToNoteDb(
- ReviewDb db,
- Repository allUsersRepo,
- GroupRebuilder rebuilder,
- AccountGroup.UUID uuid,
- BatchRefUpdate batchRefUpdate)
- throws ConfigInvalidException, IOException, OrmException {
- GroupBundle reviewDbBundle = GroupBundle.Factory.fromReviewDb(db, uuid);
- RefUpdateUtil.deleteChecked(allUsersRepo, RefNames.refsGroups(uuid));
- rebuilder.rebuild(allUsersRepo, reviewDbBundle, batchRefUpdate);
- }
-
- // The regular account cache isn't available during init. -> Use a simple replacement which tries
- // to load every account only once from disk.
- private static class SimpleInMemoryAccountCache {
- private final AllUsersName allUsersName;
- private final Repository allUsersRepo;
- private Map<Account.Id, Optional<Account>> accounts = new HashMap<>();
-
- public SimpleInMemoryAccountCache(AllUsersName allUsersName, Repository allUsersRepo) {
- this.allUsersName = allUsersName;
- this.allUsersRepo = allUsersRepo;
- }
-
- public Optional<Account> get(Account.Id accountId) {
- accounts.computeIfAbsent(accountId, this::load);
- return accounts.get(accountId);
- }
-
- private Optional<Account> load(Account.Id accountId) {
- try {
- AccountConfig accountConfig =
- new AccountConfig(accountId, allUsersName, allUsersRepo).load();
- return accountConfig.getLoadedAccount();
- } catch (IOException | ConfigInvalidException ignored) {
- logger.atWarning().withCause(ignored).log(
- "Failed to load account %s."
- + " Cannot get account name for group audit log commit messages.",
- accountId.get());
- return Optional.empty();
- }
- }
- }
-
- // The regular GroupBackends (especially external GroupBackends) and our internal group cache
- // aren't available during init. -> Use a simple replacement which tries to look up only internal
- // groups and which loads every internal group only once from disc. (There's no way we can look up
- // external groups during init. As we need those groups only for cosmetic aspects in
- // AuditLogFormatter, it's safe to exclude them.)
- private static class SimpleInMemoryGroupCache {
- private final ReviewDb db;
- private Map<AccountGroup.UUID, Optional<GroupDescription.Basic>> groups = new HashMap<>();
-
- public SimpleInMemoryGroupCache(ReviewDb db) {
- this.db = db;
- }
-
- public Optional<GroupDescription.Basic> get(AccountGroup.UUID groupUuid) {
- groups.computeIfAbsent(groupUuid, this::load);
- return groups.get(groupUuid);
- }
-
- private Optional<GroupDescription.Basic> load(AccountGroup.UUID groupUuid) {
- if (!AccountGroup.isInternalGroup(groupUuid)) {
- return Optional.empty();
- }
-
- List<GroupDescription.Basic> groupDescriptions = getGroupDescriptions(groupUuid);
- if (groupDescriptions.size() == 1) {
- return Optional.of(Iterables.getOnlyElement(groupDescriptions));
- }
- return Optional.empty();
- }
-
- private List<GroupDescription.Basic> getGroupDescriptions(AccountGroup.UUID groupUuid) {
- try (Statement stmt = ReviewDbWrapper.unwrapJbdcSchema(db).getConnection().createStatement();
- ResultSet rs =
- stmt.executeQuery(
- "SELECT name FROM account_groups where group_uuid = '" + groupUuid + "'")) {
- List<GroupDescription.Basic> groupDescriptions = new ArrayList<>();
- while (rs.next()) {
- String groupName = rs.getString(1);
- groupDescriptions.add(toGroupDescription(groupUuid, groupName));
- }
- return groupDescriptions;
- } catch (SQLException ignored) {
- logger.atWarning().withCause(ignored).log(
- "Failed to load group %s."
- + " Cannot get group name for group audit log commit messages.",
- groupUuid.get());
- return ImmutableList.of();
- }
- }
-
- private static GroupDescription.Basic toGroupDescription(
- AccountGroup.UUID groupUuid, String groupName) {
- return new GroupDescription.Basic() {
- @Override
- public AccountGroup.UUID getGroupUUID() {
- return groupUuid;
- }
-
- @Override
- public String getName() {
- return groupName;
- }
-
- @Nullable
- @Override
- public String getEmailAddress() {
- return null;
- }
-
- @Nullable
- @Override
- public String getUrl() {
- return null;
- }
- };
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_169.java b/java/com/google/gerrit/server/schema/Schema_169.java
deleted file mode 100644
index 11601e4..0000000
--- a/java/com/google/gerrit/server/schema/Schema_169.java
+++ /dev/null
@@ -1,92 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.CommentJsonMigrator;
-import com.google.gerrit.server.notedb.CommentJsonMigrator.ProjectMigrationResult;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.util.SortedSet;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ProgressMonitor;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.TextProgressMonitor;
-
-/** Migrate NoteDb inline comments to JSON format. */
-public class Schema_169 extends ReviewDbSchemaVersion {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
- private final CommentJsonMigrator migrator;
- private final GitRepositoryManager repoManager;
- private final NotesMigration notesMigration;
-
- @Inject
- Schema_169(
- Provider<Schema_168> prior,
- CommentJsonMigrator migrator,
- GitRepositoryManager repoManager,
- @GerritServerConfig Config config) {
- super(prior);
- this.migrator = migrator;
- this.repoManager = repoManager;
- this.notesMigration = MutableNotesMigration.fromConfig(config);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException {
- migrateData(ui);
- }
-
- @VisibleForTesting
- protected void migrateData(UpdateUI ui) throws OrmException {
- // If the migration hasn't started, no need to look for non-JSON
- if (!notesMigration.commitChangeWrites()) {
- return;
- }
-
- boolean ok = true;
- ProgressMonitor pm = new TextProgressMonitor();
- SortedSet<Project.NameKey> projects = repoManager.list();
- pm.beginTask("Migrating projects", projects.size());
- int skipped = 0;
- for (Project.NameKey project : projects) {
- try (Repository repo = repoManager.openRepository(project)) {
- ProjectMigrationResult progress = migrator.migrateProject(project, repo, false);
- skipped += progress.skipped;
- } catch (IOException e) {
- ok = false;
- logger.atWarning().log("Error migrating project " + project, e);
- }
- pm.update(1);
- }
-
- pm.endTask();
- ui.message(
- "Skipped " + skipped + " project" + (skipped == 1 ? "" : "s") + " with no legacy comments");
-
- if (!ok) {
- throw new OrmException("Migration failed");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_170.java b/java/com/google/gerrit/server/schema/Schema_170.java
deleted file mode 100644
index 6a86494..0000000
--- a/java/com/google/gerrit/server/schema/Schema_170.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2018 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_170 extends ReviewDbSchemaVersion {
- @Inject
- Schema_170(Provider<Schema_169> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_83.java b/java/com/google/gerrit/server/schema/Schema_83.java
deleted file mode 100644
index 95b7e6f..0000000
--- a/java/com/google/gerrit/server/schema/Schema_83.java
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.ProvisionException;
-
-public class Schema_83 extends ReviewDbSchemaVersion {
-
- @Inject
- Schema_83() {
- super(
- new Provider<ReviewDbSchemaVersion>() {
- @Override
- public ReviewDbSchemaVersion get() {
- throw new ProvisionException("Upgrade first to 2.8 or 2.9");
- }
- });
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_84.java b/java/com/google/gerrit/server/schema/Schema_84.java
deleted file mode 100644
index 415b2e3..0000000
--- a/java/com/google/gerrit/server/schema/Schema_84.java
+++ /dev/null
@@ -1,26 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_84 extends ReviewDbSchemaVersion {
-
- @Inject
- Schema_84(Provider<Schema_83> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_85.java b/java/com/google/gerrit/server/schema/Schema_85.java
deleted file mode 100644
index ee8fbdb..0000000
--- a/java/com/google/gerrit/server/schema/Schema_85.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_85 extends ReviewDbSchemaVersion {
- @Inject
- Schema_85(Provider<Schema_84> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_86.java b/java/com/google/gerrit/server/schema/Schema_86.java
deleted file mode 100644
index e468345..0000000
--- a/java/com/google/gerrit/server/schema/Schema_86.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_86 extends ReviewDbSchemaVersion {
- @Inject
- Schema_86(Provider<Schema_85> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_87.java b/java/com/google/gerrit/server/schema/Schema_87.java
deleted file mode 100644
index 79884ba..0000000
--- a/java/com/google/gerrit/server/schema/Schema_87.java
+++ /dev/null
@@ -1,80 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.HashSet;
-import java.util.Optional;
-import java.util.Set;
-
-public class Schema_87 extends ReviewDbSchemaVersion {
- @Inject
- Schema_87(Provider<Schema_86> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try (PreparedStatement uuidRetrieval =
- prepareStatement(db, "SELECT group_uuid FROM account_groups WHERE group_id = ?");
- PreparedStatement groupDeletion =
- prepareStatement(db, "DELETE FROM account_groups WHERE group_id = ?");
- PreparedStatement groupNameDeletion =
- prepareStatement(db, "DELETE FROM account_group_names WHERE group_id = ?")) {
- for (AccountGroup.Id id : scanSystemGroups(db)) {
- Optional<AccountGroup.UUID> groupUuid = getUuid(uuidRetrieval, id);
- if (groupUuid.filter(SystemGroupBackend::isSystemGroup).isPresent()) {
- groupDeletion.setInt(1, id.get());
- groupDeletion.executeUpdate();
-
- groupNameDeletion.setInt(1, id.get());
- groupNameDeletion.executeUpdate();
- }
- }
- }
- }
-
- private static Optional<AccountGroup.UUID> getUuid(
- PreparedStatement uuidRetrieval, AccountGroup.Id id) throws SQLException {
- uuidRetrieval.setInt(1, id.get());
- try (ResultSet uuidResults = uuidRetrieval.executeQuery()) {
- if (uuidResults.next()) {
- Optional.of(new AccountGroup.UUID(uuidResults.getString(1)));
- }
- }
- return Optional.empty();
- }
-
- private static Set<AccountGroup.Id> scanSystemGroups(ReviewDb db) throws SQLException {
- try (Statement stmt = newStatement(db);
- ResultSet rs =
- stmt.executeQuery("SELECT group_id FROM account_groups WHERE group_type = 'SYSTEM'")) {
- Set<AccountGroup.Id> ids = new HashSet<>();
- while (rs.next()) {
- ids.add(new AccountGroup.Id(rs.getInt(1)));
- }
- return ids;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_88.java b/java/com/google/gerrit/server/schema/Schema_88.java
deleted file mode 100644
index d5e9994..0000000
--- a/java/com/google/gerrit/server/schema/Schema_88.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_88 extends ReviewDbSchemaVersion {
- @Inject
- Schema_88(Provider<Schema_87> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_89.java b/java/com/google/gerrit/server/schema/Schema_89.java
deleted file mode 100644
index 3d352da..0000000
--- a/java/com/google/gerrit/server/schema/Schema_89.java
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.StatementExecutor;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-
-public class Schema_89 extends ReviewDbSchemaVersion {
- @Inject
- Schema_89(Provider<Schema_88> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- SqlDialect dialect = ((JdbcSchema) db).getDialect();
- try (StatementExecutor e = newExecutor(db)) {
- dialect.dropIndex(e, "patch_set_approvals", "patch_set_approvals_openByUser");
- dialect.dropIndex(e, "patch_set_approvals", "patch_set_approvals_closedByU");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_90.java b/java/com/google/gerrit/server/schema/Schema_90.java
deleted file mode 100644
index 3831f33..0000000
--- a/java/com/google/gerrit/server/schema/Schema_90.java
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_90 extends ReviewDbSchemaVersion {
- @Inject
- Schema_90(Provider<Schema_89> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
- try (Statement stmt = newStatement(db)) {
- stmt.executeUpdate("UPDATE accounts set size_bar_in_change_table = 'Y'");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_91.java b/java/com/google/gerrit/server/schema/Schema_91.java
deleted file mode 100644
index 6dd2d58..0000000
--- a/java/com/google/gerrit/server/schema/Schema_91.java
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright (C) 2013 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.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_91 extends ReviewDbSchemaVersion {
- @Inject
- Schema_91(Provider<Schema_90> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_92.java b/java/com/google/gerrit/server/schema/Schema_92.java
deleted file mode 100644
index 9af33c0..0000000
--- a/java/com/google/gerrit/server/schema/Schema_92.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_92 extends ReviewDbSchemaVersion {
- @Inject
- Schema_92(Provider<Schema_91> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_93.java b/java/com/google/gerrit/server/schema/Schema_93.java
deleted file mode 100644
index e9a6691..0000000
--- a/java/com/google/gerrit/server/schema/Schema_93.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_93 extends ReviewDbSchemaVersion {
- @Inject
- Schema_93(Provider<Schema_92> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_94.java b/java/com/google/gerrit/server/schema/Schema_94.java
deleted file mode 100644
index 1551650..0000000
--- a/java/com/google/gerrit/server/schema/Schema_94.java
+++ /dev/null
@@ -1,35 +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.server.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_94 extends ReviewDbSchemaVersion {
- @Inject
- Schema_94(Provider<Schema_93> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
- try (Statement stmt = newStatement(db)) {
- stmt.execute("CREATE INDEX patch_sets_byRevision ON patch_sets (revision)");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_95.java b/java/com/google/gerrit/server/schema/Schema_95.java
deleted file mode 100644
index 19dfa97..0000000
--- a/java/com/google/gerrit/server/schema/Schema_95.java
+++ /dev/null
@@ -1,42 +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.server.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.sql.SQLException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-
-public class Schema_95 extends ReviewDbSchemaVersion {
- private final AllUsersCreator allUsersCreator;
-
- @Inject
- Schema_95(Provider<Schema_94> prior, AllUsersCreator allUsersCreator) {
- super(prior);
- this.allUsersCreator = allUsersCreator;
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws OrmException, SQLException {
- try {
- allUsersCreator.create();
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException(e);
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_96.java b/java/com/google/gerrit/server/schema/Schema_96.java
deleted file mode 100644
index 2eb9a87..0000000
--- a/java/com/google/gerrit/server/schema/Schema_96.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_96 extends ReviewDbSchemaVersion {
- @Inject
- Schema_96(Provider<Schema_95> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_97.java b/java/com/google/gerrit/server/schema/Schema_97.java
deleted file mode 100644
index 98f548e..0000000
--- a/java/com/google/gerrit/server/schema/Schema_97.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_97 extends ReviewDbSchemaVersion {
- @Inject
- Schema_97(Provider<Schema_96> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_98.java b/java/com/google/gerrit/server/schema/Schema_98.java
deleted file mode 100644
index 8a7498f..0000000
--- a/java/com/google/gerrit/server/schema/Schema_98.java
+++ /dev/null
@@ -1,39 +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.server.schema;
-
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.SQLException;
-import java.sql.Statement;
-
-public class Schema_98 extends ReviewDbSchemaVersion {
- @Inject
- Schema_98(Provider<Schema_97> prior) {
- super(prior);
- }
-
- @Override
- protected void migrateData(ReviewDb db, UpdateUI ui) throws SQLException {
- ui.message("Migrate user preference showUserInReview to reviewCategoryStrategy");
- try (Statement stmt = newStatement(db)) {
- stmt.executeUpdate(
- "UPDATE accounts SET "
- + "REVIEW_CATEGORY_STRATEGY='NAME' "
- + "WHERE (SHOW_USER_IN_REVIEW='Y')");
- }
- }
-}
diff --git a/java/com/google/gerrit/server/schema/Schema_99.java b/java/com/google/gerrit/server/schema/Schema_99.java
deleted file mode 100644
index ca3a959..0000000
--- a/java/com/google/gerrit/server/schema/Schema_99.java
+++ /dev/null
@@ -1,25 +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.server.schema;
-
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-public class Schema_99 extends ReviewDbSchemaVersion {
- @Inject
- Schema_99(Provider<Schema_98> prior) {
- super(prior);
- }
-}
diff --git a/java/com/google/gerrit/server/schema/ScriptRunner.java b/java/com/google/gerrit/server/schema/ScriptRunner.java
deleted file mode 100644
index f4cba98..0000000
--- a/java/com/google/gerrit/server/schema/ScriptRunner.java
+++ /dev/null
@@ -1,125 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-
-import com.google.common.base.CharMatcher;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.schema.sql.SqlDialect;
-import com.google.gwtorm.server.OrmException;
-import java.io.BufferedReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.List;
-
-/** Parses an SQL script from a resource file and later runs it. */
-class ScriptRunner {
- private final String name;
- private final List<String> commands;
-
- static final ScriptRunner NOOP =
- new ScriptRunner(null, null) {
- @Override
- void run(ReviewDb db) {}
- };
-
- ScriptRunner(String scriptName, InputStream script) {
- this.name = scriptName;
- try {
- this.commands = script != null ? parse(script) : null;
- } catch (IOException e) {
- throw new IllegalStateException("Cannot parse " + name, e);
- }
- }
-
- void run(ReviewDb db) throws OrmException {
- try {
- final JdbcSchema schema = (JdbcSchema) db;
- final Connection c = schema.getConnection();
- final SqlDialect dialect = schema.getDialect();
- try (Statement stmt = c.createStatement()) {
- for (String sql : commands) {
- try {
- if (!dialect.isStatementDelimiterSupported()) {
- sql = CharMatcher.is(';').trimTrailingFrom(sql);
- }
- stmt.execute(sql);
- } catch (SQLException e) {
- throw new OrmException("Error in " + name + ":\n" + sql, e);
- }
- }
- }
- } catch (SQLException e) {
- throw new OrmException("Cannot run statements for " + name, e);
- }
- }
-
- private List<String> parse(InputStream in) throws IOException {
- try (BufferedReader br = new BufferedReader(new InputStreamReader(in, UTF_8))) {
- String delimiter = ";";
- List<String> commands = new ArrayList<>();
- StringBuilder buffer = new StringBuilder();
- String line;
- while ((line = br.readLine()) != null) {
- if (line.isEmpty()) {
- continue;
- }
- if (line.startsWith("--")) {
- continue;
- }
-
- if (buffer.length() == 0 && line.toLowerCase().startsWith("delimiter ")) {
- delimiter = line.substring("delimiter ".length()).trim();
- continue;
- }
-
- if (buffer.length() > 0) {
- buffer.append('\n');
- }
- buffer.append(line);
-
- if (isDone(delimiter, line, buffer)) {
- String cmd = buffer.toString();
- commands.add(cmd);
- buffer = new StringBuilder();
- }
- }
- if (buffer.length() > 0) {
- commands.add(buffer.toString());
- }
- return commands;
- }
- }
-
- private boolean isDone(String delimiter, String line, StringBuilder buffer) {
- if (";".equals(delimiter)) {
- return buffer.charAt(buffer.length() - 1) == ';';
-
- } else if (line.equals(delimiter)) {
- buffer.setLength(buffer.length() - delimiter.length());
- return true;
-
- } else {
- return false;
- }
- }
-}
diff --git a/java/com/google/gerrit/server/submit/MergeOp.java b/java/com/google/gerrit/server/submit/MergeOp.java
index 8e018a5..81e2661 100644
--- a/java/com/google/gerrit/server/submit/MergeOp.java
+++ b/java/com/google/gerrit/server/submit/MergeOp.java
@@ -911,7 +911,7 @@
cd.getId(),
new BatchUpdateOp() {
@Override
- public boolean updateChange(ChangeContext ctx) throws OrmException {
+ public boolean updateChange(ChangeContext ctx) {
Change change = ctx.getChange();
if (!change.getStatus().isOpen()) {
return false;
@@ -926,8 +926,7 @@
change.getLastUpdatedOn(),
ChangeMessagesUtil.TAG_MERGED,
"Project was deleted.");
- cmUtil.addChangeMessage(
- ctx.getDb(), ctx.getUpdate(change.currentPatchSetId()), msg);
+ cmUtil.addChangeMessage(ctx.getUpdate(change.currentPatchSetId()), msg);
return true;
}
diff --git a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
index 3be4c31..fd49042 100644
--- a/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
+++ b/java/com/google/gerrit/server/submit/SubmitStrategyOp.java
@@ -32,7 +32,6 @@
import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
@@ -483,9 +482,8 @@
psId, ctx.getUser(), ctx.getWhen(), body, ChangeMessagesUtil.TAG_MERGED);
}
- private void setMerged(ChangeContext ctx, ChangeMessage msg) throws OrmException {
+ private void setMerged(ChangeContext ctx, ChangeMessage msg) {
Change c = ctx.getChange();
- ReviewDb db = ctx.getDb();
logger.atFine().log("Setting change %s merged", c.getId());
c.setStatus(Change.Status.MERGED);
c.setSubmissionId(args.submissionId.toStringForStorage());
@@ -494,7 +492,7 @@
// which is not the user from the update context. addMergedMessage was able
// to do this in the past.
if (msg != null) {
- args.cmUtil.addChangeMessage(db, ctx.getUpdate(msg.getPatchSetId()), msg);
+ args.cmUtil.addChangeMessage(ctx.getUpdate(msg.getPatchSetId()), msg);
}
}
diff --git a/java/com/google/gerrit/server/update/BatchUpdate.java b/java/com/google/gerrit/server/update/BatchUpdate.java
index b3472d2..a768888 100644
--- a/java/com/google/gerrit/server/update/BatchUpdate.java
+++ b/java/com/google/gerrit/server/update/BatchUpdate.java
@@ -39,7 +39,6 @@
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.validators.OnSubmitValidators;
import com.google.gerrit.server.logging.RequestId;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.project.InvalidChangeOperationException;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.NoSuchProjectException;
@@ -93,7 +92,6 @@
return new FactoryModule() {
@Override
public void configure() {
- factory(ReviewDbBatchUpdate.AssistedFactory.class);
factory(NoteDbBatchUpdate.AssistedFactory.class);
}
};
@@ -101,27 +99,17 @@
@Singleton
public static class Factory {
- private final NotesMigration migration;
- private final ReviewDbBatchUpdate.AssistedFactory reviewDbBatchUpdateFactory;
private final NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory;
// TODO(dborowitz): Make this non-injectable to force all callers to use RetryHelper.
@Inject
- Factory(
- NotesMigration migration,
- ReviewDbBatchUpdate.AssistedFactory reviewDbBatchUpdateFactory,
- NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory) {
- this.migration = migration;
- this.reviewDbBatchUpdateFactory = reviewDbBatchUpdateFactory;
+ Factory(NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory) {
this.noteDbBatchUpdateFactory = noteDbBatchUpdateFactory;
}
public BatchUpdate create(
ReviewDb db, Project.NameKey project, CurrentUser user, Timestamp when) {
- if (migration.disableChangeReviewDb()) {
- return noteDbBatchUpdateFactory.create(db, project, user, when);
- }
- return reviewDbBatchUpdateFactory.create(db, project, user, when);
+ return noteDbBatchUpdateFactory.create(db, project, user, when);
}
@SuppressWarnings({"rawtypes", "unchecked"})
@@ -135,15 +123,9 @@
// method above, which always returns instances of the type we expect. Just to be safe,
// copy them into an ImmutableList so there is no chance the callee can pollute the input
// collection.
- if (migration.disableChangeReviewDb()) {
- ImmutableList<NoteDbBatchUpdate> noteDbUpdates =
- (ImmutableList) ImmutableList.copyOf(updates);
- NoteDbBatchUpdate.execute(noteDbUpdates, listener, dryRun);
- } else {
- ImmutableList<ReviewDbBatchUpdate> reviewDbUpdates =
- (ImmutableList) ImmutableList.copyOf(updates);
- ReviewDbBatchUpdate.execute(reviewDbUpdates, listener, dryRun);
- }
+ ImmutableList<NoteDbBatchUpdate> noteDbUpdates =
+ (ImmutableList) ImmutableList.copyOf(updates);
+ NoteDbBatchUpdate.execute(noteDbUpdates, listener, dryRun);
}
private static void checkDifferentProject(Collection<BatchUpdate> updates) {
@@ -174,25 +156,6 @@
return o;
}
- static boolean getUpdateChangesInParallel(Collection<? extends BatchUpdate> updates) {
- checkArgument(!updates.isEmpty());
- Boolean p = null;
- for (BatchUpdate u : updates) {
- if (p == null) {
- p = u.updateChangesInParallel;
- } else if (u.updateChangesInParallel != p) {
- throw new IllegalArgumentException("cannot mix parallel and non-parallel operations");
- }
- }
- // Properly implementing this would involve hoisting the parallel loop up
- // even further. As of this writing, the only user is ReceiveCommits,
- // which only executes a single BatchUpdate at a time. So bail for now.
- checkArgument(
- !p || updates.size() <= 1,
- "cannot execute ChangeOps in parallel with more than 1 BatchUpdate");
- return p;
- }
-
static void wrapAndThrowException(Exception e) throws UpdateException, RestApiException {
Throwables.throwIfUnchecked(e);
@@ -234,8 +197,6 @@
protected PushCertificate pushCert;
protected String refLogMessage;
- private boolean updateChangesInParallel;
-
protected BatchUpdate(
GitRepositoryManager repoManager,
PersonIdent serverIdent,
@@ -296,18 +257,6 @@
return this;
}
- /**
- * Execute {@link BatchUpdateOp#updateChange(ChangeContext)} in parallel for each change.
- *
- * <p>This improves performance of writing to multiple changes in separate ReviewDb transactions.
- * When only NoteDb is used, updates to all changes are written in a single batch ref update, so
- * parallelization is not used and this option is ignored.
- */
- public BatchUpdate updateChangesInParallel() {
- this.updateChangesInParallel = true;
- return this;
- }
-
protected void initRepository() throws IOException {
if (repoView == null) {
repoView = new RepoView(repoManager, project);
diff --git a/java/com/google/gerrit/server/update/RetryHelper.java b/java/com/google/gerrit/server/update/RetryHelper.java
index c8d338b..9bdf293 100644
--- a/java/com/google/gerrit/server/update/RetryHelper.java
+++ b/java/com/google/gerrit/server/update/RetryHelper.java
@@ -41,7 +41,6 @@
import com.google.gerrit.metrics.Histogram1;
import com.google.gerrit.metrics.MetricMaker;
import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.inject.Inject;
import com.google.inject.Singleton;
import java.time.Duration;
@@ -141,7 +140,6 @@
return options().build();
}
- private final NotesMigration migration;
private final Metrics metrics;
private final BatchUpdate.Factory updateFactory;
private final Map<ActionType, Duration> defaultTimeouts;
@@ -152,24 +150,18 @@
RetryHelper(
@GerritServerConfig Config cfg,
Metrics metrics,
- NotesMigration migration,
- ReviewDbBatchUpdate.AssistedFactory reviewDbBatchUpdateFactory,
NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory) {
- this(cfg, metrics, migration, reviewDbBatchUpdateFactory, noteDbBatchUpdateFactory, null);
+ this(cfg, metrics, noteDbBatchUpdateFactory, null);
}
@VisibleForTesting
public RetryHelper(
@GerritServerConfig Config cfg,
Metrics metrics,
- NotesMigration migration,
- ReviewDbBatchUpdate.AssistedFactory reviewDbBatchUpdateFactory,
NoteDbBatchUpdate.AssistedFactory noteDbBatchUpdateFactory,
@Nullable Consumer<RetryerBuilder<?>> overwriteDefaultRetryerStrategySetup) {
this.metrics = metrics;
- this.migration = migration;
- this.updateFactory =
- new BatchUpdate.Factory(migration, reviewDbBatchUpdateFactory, noteDbBatchUpdateFactory);
+ this.updateFactory = new BatchUpdate.Factory(noteDbBatchUpdateFactory);
Duration defaultTimeout =
Duration.ofMillis(
@@ -229,16 +221,6 @@
public <T> T execute(ChangeAction<T> changeAction, Options opts)
throws RestApiException, UpdateException {
try {
- if (!migration.disableChangeReviewDb()) {
- // Either we aren't full-NoteDb, or the underlying ref storage doesn't support atomic
- // transactions. Either way, retrying a partially-failed operation is not idempotent, so
- // don't do it automatically. Let the end user decide whether they want to retry.
- return executeWithTimeoutCount(
- ActionType.CHANGE_UPDATE,
- () -> changeAction.call(updateFactory),
- RetryerBuilder.<T>newBuilder().build());
- }
-
return execute(
ActionType.CHANGE_UPDATE,
() -> changeAction.call(updateFactory),
diff --git a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java b/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
deleted file mode 100644
index b859895..0000000
--- a/java/com/google/gerrit/server/update/ReviewDbBatchUpdate.java
+++ /dev/null
@@ -1,842 +0,0 @@
-// Copyright (C) 2015 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.update;
-
-import static com.google.common.base.Preconditions.checkState;
-import static java.util.Comparator.comparing;
-import static java.util.Objects.requireNonNull;
-import static java.util.concurrent.TimeUnit.NANOSECONDS;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.base.Stopwatch;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.flogger.FluentLogger;
-import com.google.common.util.concurrent.Futures;
-import com.google.common.util.concurrent.ListenableFuture;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.common.util.concurrent.MoreExecutors;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.git.LockFailureException;
-import com.google.gerrit.metrics.Description;
-import com.google.gerrit.metrics.Description.Units;
-import com.google.gerrit.metrics.Field;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.metrics.Timer1;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.ChangeUpdateExecutor;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.InsertedObject;
-import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.google.gerrit.server.logging.TraceContext;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager.MismatchedStateException;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Singleton;
-import com.google.inject.assistedinject.Assisted;
-import java.io.IOException;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.TimeZone;
-import java.util.TreeMap;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutionException;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.NullProgressMonitor;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
-
-/**
- * {@link BatchUpdate} implementation that supports mixed ReviewDb/NoteDb operations, depending on
- * the migration state specified in {@link NotesMigration}.
- *
- * <p>When performing change updates in a mixed ReviewDb/NoteDb environment with ReviewDb primary,
- * the order of operations is very subtle:
- *
- * <ol>
- * <li>Stage NoteDb updates to get the new NoteDb state, but do not write to the repo.
- * <li>Write the new state in the Change entity, and commit this to ReviewDb.
- * <li>Update NoteDb, ignoring any write failures.
- * </ol>
- *
- * The implementation in this class is well-tested, and it is strongly recommended that you not
- * attempt to reimplement this logic. Use {@code BatchUpdate} if at all possible.
- */
-public class ReviewDbBatchUpdate extends BatchUpdate {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- public interface AssistedFactory {
- ReviewDbBatchUpdate create(
- ReviewDb db, Project.NameKey project, CurrentUser user, Timestamp when);
- }
-
- class ContextImpl implements Context {
- @Override
- public RepoView getRepoView() throws IOException {
- return ReviewDbBatchUpdate.this.getRepoView();
- }
-
- @Override
- public RevWalk getRevWalk() throws IOException {
- return getRepoView().getRevWalk();
- }
-
- @Override
- public Project.NameKey getProject() {
- return project;
- }
-
- @Override
- public Timestamp getWhen() {
- return when;
- }
-
- @Override
- public TimeZone getTimeZone() {
- return tz;
- }
-
- @Override
- public ReviewDb getDb() {
- return db;
- }
-
- @Override
- public CurrentUser getUser() {
- return user;
- }
-
- @Override
- public Order getOrder() {
- return order;
- }
- }
-
- private class RepoContextImpl extends ContextImpl implements RepoContext {
- @Override
- public ObjectInserter getInserter() throws IOException {
- return getRepoView().getInserterWrapper();
- }
-
- @Override
- public void addRefUpdate(ReceiveCommand cmd) throws IOException {
- initRepository();
- repoView.getCommands().add(cmd);
- }
- }
-
- private class ChangeContextImpl extends ContextImpl implements ChangeContext {
- private final ChangeNotes notes;
- private final Map<PatchSet.Id, ChangeUpdate> updates;
- private final ReviewDbWrapper dbWrapper;
- private final Repository threadLocalRepo;
- private final RevWalk threadLocalRevWalk;
-
- private boolean deleted;
- private boolean bumpLastUpdatedOn = true;
-
- protected ChangeContextImpl(
- ChangeNotes notes, ReviewDbWrapper dbWrapper, Repository repo, RevWalk rw) {
- this.notes = requireNonNull(notes);
- this.dbWrapper = dbWrapper;
- this.threadLocalRepo = repo;
- this.threadLocalRevWalk = rw;
- updates = new TreeMap<>(comparing(PatchSet.Id::get));
- }
-
- @Override
- public ReviewDb getDb() {
- requireNonNull(dbWrapper);
- return dbWrapper;
- }
-
- @Override
- public RevWalk getRevWalk() {
- return threadLocalRevWalk;
- }
-
- @Override
- public ChangeUpdate getUpdate(PatchSet.Id psId) {
- ChangeUpdate u = updates.get(psId);
- if (u == null) {
- u = changeUpdateFactory.create(notes, user, when);
- if (newChanges.containsKey(notes.getChangeId())) {
- u.setAllowWriteToNewRef(true);
- }
- u.setPatchSetId(psId);
- updates.put(psId, u);
- }
- return u;
- }
-
- @Override
- public ChangeNotes getNotes() {
- return notes;
- }
-
- @Override
- public void dontBumpLastUpdatedOn() {
- bumpLastUpdatedOn = false;
- }
-
- @Override
- public void deleteChange() {
- deleted = true;
- }
- }
-
- @Singleton
- private static class Metrics {
- final Timer1<Boolean> executeChangeOpsLatency;
-
- @Inject
- Metrics(MetricMaker metricMaker) {
- executeChangeOpsLatency =
- metricMaker.newTimer(
- "batch_update/execute_change_ops",
- new Description("BatchUpdate change update latency, excluding reindexing")
- .setCumulative()
- .setUnit(Units.MILLISECONDS),
- Field.ofBoolean("success"));
- }
- }
-
- static void execute(
- ImmutableList<ReviewDbBatchUpdate> updates, BatchUpdateListener listener, boolean dryrun)
- throws UpdateException, RestApiException {
- if (updates.isEmpty()) {
- return;
- }
- try {
- Order order = getOrder(updates, listener);
- boolean updateChangesInParallel = getUpdateChangesInParallel(updates);
- switch (order) {
- case REPO_BEFORE_DB:
- for (ReviewDbBatchUpdate u : updates) {
- u.executeUpdateRepo();
- }
- listener.afterUpdateRepos();
- for (ReviewDbBatchUpdate u : updates) {
- u.executeRefUpdates(dryrun);
- }
- listener.afterUpdateRefs();
- for (ReviewDbBatchUpdate u : updates) {
- u.reindexChanges(u.executeChangeOps(updateChangesInParallel, dryrun));
- }
- listener.afterUpdateChanges();
- break;
- case DB_BEFORE_REPO:
- for (ReviewDbBatchUpdate u : updates) {
- u.reindexChanges(u.executeChangeOps(updateChangesInParallel, dryrun));
- }
- for (ReviewDbBatchUpdate u : updates) {
- u.executeUpdateRepo();
- }
- for (ReviewDbBatchUpdate u : updates) {
- u.executeRefUpdates(dryrun);
- }
- break;
- default:
- throw new IllegalStateException("invalid execution order: " + order);
- }
-
- ChangeIndexer.allAsList(
- updates.stream().flatMap(u -> u.indexFutures.stream()).collect(toList()))
- .get();
-
- // Fire ref update events only after all mutations are finished, since callers may assume a
- // patch set ref being created means the change was created, or a branch advancing meaning
- // some changes were closed.
- updates
- .stream()
- .filter(u -> u.batchRefUpdate != null)
- .forEach(
- u -> u.gitRefUpdated.fire(u.project, u.batchRefUpdate, u.getAccount().orElse(null)));
-
- if (!dryrun) {
- for (ReviewDbBatchUpdate u : updates) {
- u.executePostOps();
- }
- }
- } catch (Exception e) {
- wrapAndThrowException(e);
- }
- }
-
- private final AllUsersName allUsers;
- private final ChangeIndexer indexer;
- private final ChangeNotes.Factory changeNotesFactory;
- private final ChangeUpdate.Factory changeUpdateFactory;
- private final GitReferenceUpdated gitRefUpdated;
- private final ListeningExecutorService changeUpdateExector;
- private final Metrics metrics;
- private final NoteDbUpdateManager.Factory updateManagerFactory;
- private final NotesMigration notesMigration;
- private final ReviewDb db;
- private final SchemaFactory<ReviewDb> schemaFactory;
- private final long skewMs;
-
- @SuppressWarnings("deprecation")
- private final List<com.google.common.util.concurrent.CheckedFuture<?, IOException>> indexFutures =
- new ArrayList<>();
-
- @Inject
- ReviewDbBatchUpdate(
- @GerritServerConfig Config cfg,
- AllUsersName allUsers,
- ChangeIndexer indexer,
- ChangeNotes.Factory changeNotesFactory,
- @ChangeUpdateExecutor ListeningExecutorService changeUpdateExector,
- ChangeUpdate.Factory changeUpdateFactory,
- @GerritPersonIdent PersonIdent serverIdent,
- GitReferenceUpdated gitRefUpdated,
- GitRepositoryManager repoManager,
- Metrics metrics,
- NoteDbUpdateManager.Factory updateManagerFactory,
- NotesMigration notesMigration,
- SchemaFactory<ReviewDb> schemaFactory,
- @Assisted ReviewDb db,
- @Assisted Project.NameKey project,
- @Assisted CurrentUser user,
- @Assisted Timestamp when) {
- super(repoManager, serverIdent, project, user, when);
- this.allUsers = allUsers;
- this.changeNotesFactory = changeNotesFactory;
- this.changeUpdateExector = changeUpdateExector;
- this.changeUpdateFactory = changeUpdateFactory;
- this.gitRefUpdated = gitRefUpdated;
- this.indexer = indexer;
- this.metrics = metrics;
- this.notesMigration = notesMigration;
- this.schemaFactory = schemaFactory;
- this.updateManagerFactory = updateManagerFactory;
- this.db = db;
- skewMs = NoteDbChangeState.getReadOnlySkew(cfg);
- }
-
- @Override
- public void execute(BatchUpdateListener listener) throws UpdateException, RestApiException {
- execute(ImmutableList.of(this), listener, false);
- }
-
- @Override
- protected Context newContext() {
- return new ContextImpl();
- }
-
- private void executeUpdateRepo() throws UpdateException, RestApiException {
- try {
- logDebug("Executing updateRepo on %d ops", ops.size());
- RepoContextImpl ctx = new RepoContextImpl();
- for (BatchUpdateOp op : ops.values()) {
- op.updateRepo(ctx);
- }
-
- logDebug("Executing updateRepo on %d RepoOnlyOps", repoOnlyOps.size());
- for (RepoOnlyOp op : repoOnlyOps) {
- op.updateRepo(ctx);
- }
-
- if (onSubmitValidators != null && !getRefUpdates().isEmpty()) {
- // Validation of refs has to take place here and not at the beginning of executeRefUpdates.
- // Otherwise, failing validation in a second BatchUpdate object will happen *after* the
- // first update's executeRefUpdates has finished, hence after first repo's refs have been
- // updated, which is too late.
- onSubmitValidators.validate(
- project, ctx.getRevWalk().getObjectReader(), repoView.getCommands());
- }
-
- if (repoView != null) {
- logDebug("Flushing inserter");
- repoView.getInserter().flush();
- } else {
- logDebug("No objects to flush");
- }
- } catch (Exception e) {
- Throwables.throwIfInstanceOf(e, RestApiException.class);
- throw new UpdateException(e);
- }
- }
-
- private void executeRefUpdates(boolean dryrun) throws IOException, RestApiException {
- if (getRefUpdates().isEmpty()) {
- logDebug("No ref updates to execute");
- return;
- }
- // May not be opened if the caller added ref updates but no new objects.
- // TODO(dborowitz): Really?
- initRepository();
- batchRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
- batchRefUpdate.setPushCertificate(pushCert);
- batchRefUpdate.setRefLogMessage(refLogMessage, true);
- batchRefUpdate.setAllowNonFastForwards(true);
- repoView.getCommands().addTo(batchRefUpdate);
- if (user.isIdentifiedUser()) {
- batchRefUpdate.setRefLogIdent(user.asIdentifiedUser().newRefLogIdent(when, tz));
- }
- logDebug("Executing batch of %d ref updates", batchRefUpdate.getCommands().size());
- if (dryrun) {
- return;
- }
-
- // Force BatchRefUpdate to read newly referenced objects using a new RevWalk, rather than one
- // that might have access to unflushed objects.
- try (RevWalk updateRw = new RevWalk(repoView.getRepository())) {
- batchRefUpdate.execute(updateRw, NullProgressMonitor.INSTANCE);
- }
- boolean ok = true;
- for (ReceiveCommand cmd : batchRefUpdate.getCommands()) {
- if (cmd.getResult() != ReceiveCommand.Result.OK) {
- ok = false;
- break;
- }
- }
- if (!ok) {
- throw new RestApiException("BatchRefUpdate failed: " + batchRefUpdate);
- }
- }
-
- private List<ChangeTask> executeChangeOps(boolean parallel, boolean dryrun)
- throws UpdateException, RestApiException {
- List<ChangeTask> tasks;
- boolean success = false;
- Stopwatch sw = Stopwatch.createStarted();
- try {
- logDebug("Executing change ops (parallel? %s)", parallel);
- ListeningExecutorService executor =
- parallel ? changeUpdateExector : MoreExecutors.newDirectExecutorService();
-
- tasks = new ArrayList<>(ops.keySet().size());
- try {
- if (notesMigration.commitChangeWrites() && repoView != null) {
- // A NoteDb change may have been rebuilt since the repo was originally
- // opened, so make sure we see that.
- logDebug("Preemptively scanning for repo changes");
- repoView.getRepository().scanForRepoChanges();
- }
- if (!ops.isEmpty() && notesMigration.failChangeWrites()) {
- // Fail fast before attempting any writes if changes are read-only, as
- // this is a programmer error.
- logDebug("Failing early due to read-only Changes table");
- throw new OrmException(NoteDbUpdateManager.CHANGES_READ_ONLY);
- }
- List<ListenableFuture<?>> futures = new ArrayList<>(ops.keySet().size());
- for (Map.Entry<Change.Id, Collection<BatchUpdateOp>> e : ops.asMap().entrySet()) {
- ChangeTask task =
- new ChangeTask(e.getKey(), e.getValue(), Thread.currentThread(), dryrun);
- tasks.add(task);
- if (!parallel) {
- logDebug("Direct execution of task for ops: %s", ops);
- }
- futures.add(executor.submit(task));
- }
- if (parallel) {
- logDebug(
- "Waiting on futures for %d ops spanning %d changes", ops.size(), ops.keySet().size());
- }
- Futures.allAsList(futures).get();
-
- if (notesMigration.commitChangeWrites()) {
- if (!dryrun) {
- executeNoteDbUpdates(tasks);
- }
- }
- success = true;
- } catch (ExecutionException | InterruptedException e) {
- Throwables.throwIfInstanceOf(e.getCause(), UpdateException.class);
- Throwables.throwIfInstanceOf(e.getCause(), RestApiException.class);
- throw new UpdateException(e);
- } catch (OrmException | IOException e) {
- throw new UpdateException(e);
- }
- } finally {
- metrics.executeChangeOpsLatency.record(success, sw.elapsed(NANOSECONDS), NANOSECONDS);
- }
- return tasks;
- }
-
- private void reindexChanges(List<ChangeTask> tasks) {
- // Reindex changes.
- for (ChangeTask task : tasks) {
- if (task.deleted) {
- indexFutures.add(indexer.deleteAsync(task.id));
- } else if (task.dirty) {
- indexFutures.add(indexer.indexAsync(project, task.id));
- }
- }
- }
-
- private void executeNoteDbUpdates(List<ChangeTask> tasks)
- throws ResourceConflictException, IOException {
- // Aggregate together all NoteDb ref updates from the ops we executed,
- // possibly in parallel. Each task had its own NoteDbUpdateManager instance
- // with its own thread-local copy of the repo(s), but each of those was just
- // used for staging updates and was never executed.
- //
- // Use a new BatchRefUpdate as the original batchRefUpdate field is intended
- // for use only by the updateRepo phase.
- //
- // See the comments in NoteDbUpdateManager#execute() for why we execute the
- // updates on the change repo first.
- logDebug("Executing NoteDb updates for %d changes", tasks.size());
- try {
- initRepository();
- BatchRefUpdate changeRefUpdate = repoView.getRepository().getRefDatabase().newBatchUpdate();
- boolean hasAllUsersCommands = false;
- try (ObjectInserter ins = repoView.getRepository().newObjectInserter()) {
- int objs = 0;
- for (ChangeTask task : tasks) {
- if (task.noteDbResult == null) {
- logDebug("No-op update to %s", task.id);
- continue;
- }
- for (ReceiveCommand cmd : task.noteDbResult.changeCommands()) {
- changeRefUpdate.addCommand(cmd);
- }
- for (InsertedObject obj : task.noteDbResult.changeObjects()) {
- objs++;
- ins.insert(obj.type(), obj.data().toByteArray());
- }
- hasAllUsersCommands |= !task.noteDbResult.allUsersCommands().isEmpty();
- }
- logDebug(
- "Collected %d objects and %d ref updates to change repo",
- objs, changeRefUpdate.getCommands().size());
- executeNoteDbUpdate(getRevWalk(), ins, changeRefUpdate);
- }
-
- if (hasAllUsersCommands) {
- try (Repository allUsersRepo = repoManager.openRepository(allUsers);
- RevWalk allUsersRw = new RevWalk(allUsersRepo);
- ObjectInserter allUsersIns = allUsersRepo.newObjectInserter()) {
- int objs = 0;
- BatchRefUpdate allUsersRefUpdate = allUsersRepo.getRefDatabase().newBatchUpdate();
- for (ChangeTask task : tasks) {
- for (ReceiveCommand cmd : task.noteDbResult.allUsersCommands()) {
- allUsersRefUpdate.addCommand(cmd);
- }
- for (InsertedObject obj : task.noteDbResult.allUsersObjects()) {
- allUsersIns.insert(obj.type(), obj.data().toByteArray());
- }
- }
- logDebug(
- "Collected %d objects and %d ref updates to All-Users",
- objs, allUsersRefUpdate.getCommands().size());
- executeNoteDbUpdate(allUsersRw, allUsersIns, allUsersRefUpdate);
- }
- } else {
- logDebug("No All-Users updates");
- }
- } catch (IOException e) {
- if (tasks.stream().allMatch(t -> t.storage == PrimaryStorage.REVIEW_DB)) {
- // Ignore all errors trying to update NoteDb at this point. We've already written the
- // NoteDbChangeStates to ReviewDb, which means if any state is out of date it will be
- // rebuilt the next time it is needed.
- //
- // Always log even without RequestId.
- logger.atFine().withCause(e).log("Ignoring NoteDb update error after ReviewDb write");
-
- // Otherwise, we can't prove it's safe to ignore the error, either because some change had
- // NOTE_DB primary, or a task failed before determining the primary storage.
- } else if (e instanceof LockFailureException) {
- // LOCK_FAILURE is a special case indicating there was a conflicting write to a meta ref,
- // although it happened too late for us to produce anything but a generic error message.
- throw new ResourceConflictException("Updating change failed due to conflicting write", e);
- }
- throw e;
- }
- }
-
- private void executeNoteDbUpdate(RevWalk rw, ObjectInserter ins, BatchRefUpdate bru)
- throws IOException {
- if (bru.getCommands().isEmpty()) {
- logDebug("No commands, skipping flush and ref update");
- return;
- }
- ins.flush();
- bru.setAllowNonFastForwards(true);
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- for (ReceiveCommand cmd : bru.getCommands()) {
- // TODO(dborowitz): LOCK_FAILURE for NoteDb primary should be retried.
- if (cmd.getResult() != ReceiveCommand.Result.OK) {
- throw new IOException("Update failed: " + bru);
- }
- }
- }
-
- private class ChangeTask implements Callable<Void> {
- final Change.Id id;
- private final Collection<BatchUpdateOp> changeOps;
- private final Thread mainThread;
- private final boolean dryrun;
-
- PrimaryStorage storage;
- NoteDbUpdateManager.StagedResult noteDbResult;
- boolean dirty;
- boolean deleted;
-
- private ChangeTask(
- Change.Id id, Collection<BatchUpdateOp> changeOps, Thread mainThread, boolean dryrun) {
- this.id = id;
- this.changeOps = changeOps;
- this.mainThread = mainThread;
- this.dryrun = dryrun;
- }
-
- @Override
- public Void call() throws Exception {
- try (TraceContext traceContext =
- TraceContext.open()
- .addTag("TASK_ID", id.toString() + "-" + Thread.currentThread().getId())) {
- if (Thread.currentThread() == mainThread) {
- initRepository();
- Repository repo = repoView.getRepository();
- try (RevWalk rw = new RevWalk(repo)) {
- call(ReviewDbBatchUpdate.this.db, repo, rw);
- }
- } else {
- // Possible optimization: allow Ops to declare whether they need to
- // access the repo from updateChange, and don't open in this thread
- // unless we need it. However, as of this writing the only operations
- // that are executed in parallel are during ReceiveCommits, and they
- // all need the repo open anyway. (The non-parallel case above does not
- // reopen the repo.)
- try (ReviewDb threadLocalDb = schemaFactory.open();
- Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
- call(threadLocalDb, repo, rw);
- }
- }
- return null;
- }
- }
-
- private void call(ReviewDb db, Repository repo, RevWalk rw) throws Exception {
- @SuppressWarnings("resource") // Not always opened.
- NoteDbUpdateManager updateManager = null;
- try {
- db.changes().beginTransaction(id);
- try {
- ChangeContextImpl ctx = newChangeContext(db, repo, rw, id);
- NoteDbChangeState oldState = NoteDbChangeState.parse(ctx.getChange());
- NoteDbChangeState.checkNotReadOnly(oldState, skewMs);
-
- storage = PrimaryStorage.of(oldState);
- if (storage == PrimaryStorage.NOTE_DB && !notesMigration.readChanges()) {
- throw new OrmException("must have NoteDb enabled to update change " + id);
- }
-
- // Call updateChange on each op.
- logDebug("Calling updateChange on %s ops", changeOps.size());
- for (BatchUpdateOp op : changeOps) {
- dirty |= op.updateChange(ctx);
- }
- if (!dirty) {
- logDebug("No ops reported dirty, short-circuiting");
- return;
- }
- deleted = ctx.deleted;
- if (deleted) {
- logDebug("Change was deleted");
- }
-
- // Stage the NoteDb update and store its state in the Change.
- if (notesMigration.commitChangeWrites()) {
- updateManager = stageNoteDbUpdate(ctx, deleted);
- }
-
- if (storage == PrimaryStorage.REVIEW_DB) {
- // If primary storage of this change is in ReviewDb, bump
- // lastUpdatedOn or rowVersion and commit. Otherwise, don't waste
- // time updating ReviewDb at all.
- Iterable<Change> cs = changesToUpdate(ctx);
- if (isNewChange(id)) {
- // Insert rather than upsert in case of a race on change IDs.
- logDebug("Inserting change");
- db.changes().insert(cs);
- } else if (deleted) {
- logDebug("Deleting change");
- db.changes().delete(cs);
- } else {
- logDebug("Updating change");
- db.changes().update(cs);
- }
- if (!dryrun) {
- db.commit();
- }
- } else {
- logDebug("Skipping ReviewDb write since primary storage is %s", storage);
- }
- } finally {
- db.rollback();
- }
-
- // Do not execute the NoteDbUpdateManager, as we don't want too much
- // contention on the underlying repo, and we would rather use a single
- // ObjectInserter/BatchRefUpdate later.
- //
- // TODO(dborowitz): May or may not be worth trying to batch together
- // flushed inserters as well.
- if (storage == PrimaryStorage.NOTE_DB) {
- // Should have failed above if NoteDb is disabled.
- checkState(notesMigration.commitChangeWrites());
- noteDbResult = updateManager.stage().get(id);
- } else if (notesMigration.commitChangeWrites()) {
- try {
- noteDbResult = updateManager.stage().get(id);
- } catch (IOException ex) {
- // Ignore all errors trying to update NoteDb at this point. We've
- // already written the NoteDbChangeState to ReviewDb, which means
- // if the state is out of date it will be rebuilt the next time it
- // is needed.
- logger.atFine().withCause(ex).log("Ignoring NoteDb update error after ReviewDb write");
- }
- }
- } catch (Exception e) {
- logDebug("Error updating change (should be rethrown)", e);
- Throwables.propagateIfPossible(e, RestApiException.class);
- throw new UpdateException(e);
- } finally {
- if (updateManager != null) {
- updateManager.close();
- }
- }
- }
-
- private ChangeContextImpl newChangeContext(
- ReviewDb db, Repository repo, RevWalk rw, Change.Id id) throws OrmException {
- Change c = newChanges.get(id);
- boolean isNew = c != null;
- if (isNew) {
- // New change: populate noteDbState.
- checkState(c.getNoteDbState() == null, "noteDbState should not be filled in by callers");
- if (notesMigration.changePrimaryStorage() == PrimaryStorage.NOTE_DB) {
- c.setNoteDbState(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
- }
- } else {
- // Existing change.
- c = ChangeNotes.readOneReviewDbChange(db, id);
- if (c == null) {
- // Not in ReviewDb, but new changes are created with default primary
- // storage as NOTE_DB, so we can assume that a missing change is
- // NoteDb primary. Pass a synthetic change into ChangeNotes.Factory,
- // which lets ChangeNotes take care of the existence check.
- //
- // TODO(dborowitz): This assumption is potentially risky, because
- // it means once we turn this option on and start creating changes
- // without writing anything to ReviewDb, we can't turn this option
- // back off without making those changes inaccessible. The problem
- // is we have no way of distinguishing a change that only exists in
- // NoteDb because it only ever existed in NoteDb, from a change that
- // only exists in NoteDb because it used to exist in ReviewDb and
- // deleting from ReviewDb succeeded but deleting from NoteDb failed.
- //
- // TODO(dborowitz): We actually still have that problem anyway. Maybe
- // we need a cutoff timestamp? Or maybe we need to start leaving
- // tombstones in ReviewDb?
- c = ChangeNotes.Factory.newNoteDbOnlyChange(project, id);
- }
- NoteDbChangeState.checkNotReadOnly(c, skewMs);
- }
- ChangeNotes notes = changeNotesFactory.createForBatchUpdate(c, !isNew);
- return new ChangeContextImpl(notes, new BatchUpdateReviewDb(db), repo, rw);
- }
-
- private NoteDbUpdateManager stageNoteDbUpdate(ChangeContextImpl ctx, boolean deleted)
- throws OrmException, IOException {
- logDebug("Staging NoteDb update");
- NoteDbUpdateManager updateManager =
- updateManagerFactory
- .create(ctx.getProject())
- .setChangeRepo(
- ctx.threadLocalRepo,
- ctx.threadLocalRevWalk,
- null,
- new ChainedReceiveCommands(ctx.threadLocalRepo));
- if (ctx.getUser().isIdentifiedUser()) {
- updateManager.setRefLogIdent(
- ctx.getUser().asIdentifiedUser().newRefLogIdent(ctx.getWhen(), tz));
- }
- for (ChangeUpdate u : ctx.updates.values()) {
- updateManager.add(u);
- }
-
- Change c = ctx.getChange();
- if (deleted) {
- updateManager.deleteChange(c.getId());
- }
- try {
- updateManager.stageAndApplyDelta(c);
- } catch (MismatchedStateException ex) {
- // Refused to apply update because NoteDb was out of sync, which can
- // only happen if ReviewDb is the primary storage for this change.
- //
- // Go ahead with this ReviewDb update; it's still out of sync, but this
- // is no worse than before, and it will eventually get rebuilt.
- logDebug("Ignoring MismatchedStateException while staging");
- }
-
- return updateManager;
- }
-
- private boolean isNewChange(Change.Id id) {
- return newChanges.containsKey(id);
- }
- }
-
- private static Iterable<Change> changesToUpdate(ChangeContextImpl ctx) {
- Change c = ctx.getChange();
- if (ctx.bumpLastUpdatedOn && c.getLastUpdatedOn().before(ctx.getWhen())) {
- c.setLastUpdatedOn(ctx.getWhen());
- }
- return Collections.singleton(c);
- }
-
- private void executePostOps() throws Exception {
- ContextImpl ctx = new ContextImpl();
- for (BatchUpdateOp op : ops.values()) {
- op.postUpdate(ctx);
- }
-
- for (RepoOnlyOp op : repoOnlyOps) {
- op.postUpdate(ctx);
- }
- }
-}
diff --git a/java/com/google/gerrit/sshd/commands/AdminQueryShell.java b/java/com/google/gerrit/sshd/commands/AdminQueryShell.java
deleted file mode 100644
index c520e79..0000000
--- a/java/com/google/gerrit/sshd/commands/AdminQueryShell.java
+++ /dev/null
@@ -1,61 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.sshd.commands;
-
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.extensions.annotations.RequiresCapability;
-import com.google.gerrit.extensions.restapi.AuthException;
-import com.google.gerrit.server.permissions.GlobalPermission;
-import com.google.gerrit.server.permissions.PermissionBackend;
-import com.google.gerrit.server.permissions.PermissionBackendException;
-import com.google.gerrit.sshd.AdminHighPriorityCommand;
-import com.google.gerrit.sshd.CommandMetaData;
-import com.google.gerrit.sshd.SshCommand;
-import com.google.inject.Inject;
-import org.kohsuke.args4j.Option;
-
-/** Opens a query processor. */
-@AdminHighPriorityCommand
-@RequiresCapability(GlobalCapability.ACCESS_DATABASE)
-@CommandMetaData(name = "gsql", description = "Administrative interface to active database")
-final class AdminQueryShell extends SshCommand {
- @Inject private PermissionBackend permissionBackend;
- @Inject private QueryShell.Factory factory;
-
- @Option(name = "--format", usage = "Set output format")
- private QueryShell.OutputFormat format = QueryShell.OutputFormat.PRETTY;
-
- @Option(name = "-c", metaVar = "SQL QUERY", usage = "Query to execute")
- private String query;
-
- @Override
- protected void run() throws Failure {
- try {
- permissionBackend.currentUser().check(GlobalPermission.ACCESS_DATABASE);
- } catch (AuthException err) {
- throw die(err.getMessage());
- } catch (PermissionBackendException e) {
- throw new Failure(1, "unavailable", e);
- }
-
- QueryShell shell = factory.create(in, out);
- shell.setOutputFormat(format);
- if (query != null) {
- shell.execute(query);
- } else {
- shell.run();
- }
- }
-}
diff --git a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
index 1c857e4..87b6f02 100644
--- a/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
+++ b/java/com/google/gerrit/sshd/commands/DefaultCommandModule.java
@@ -90,7 +90,6 @@
command(gerrit, CreateGroupCommand.class);
command(gerrit, CreateProjectCommand.class);
command(gerrit, SetHeadCommand.class);
- command(gerrit, AdminQueryShell.class);
if (slaveMode) {
command("git-receive-pack").to(ReceiveSlaveMode.class);
diff --git a/java/com/google/gerrit/testing/DisabledReviewDb.java b/java/com/google/gerrit/testing/DisabledReviewDb.java
index d06beb9..e90474b 100644
--- a/java/com/google/gerrit/testing/DisabledReviewDb.java
+++ b/java/com/google/gerrit/testing/DisabledReviewDb.java
@@ -20,7 +20,6 @@
import com.google.gerrit.reviewdb.server.PatchSetAccess;
import com.google.gerrit.reviewdb.server.PatchSetApprovalAccess;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.SchemaVersionAccess;
import com.google.gwtorm.server.Access;
import com.google.gwtorm.server.StatementExecutor;
@@ -65,11 +64,6 @@
}
@Override
- public SchemaVersionAccess schemaVersion() {
- throw new Disabled();
- }
-
- @Override
public ChangeAccess changes() {
throw new Disabled();
}
diff --git a/java/com/google/gerrit/testing/InMemoryDatabase.java b/java/com/google/gerrit/testing/InMemoryDatabase.java
index b489652..1a4b84e 100644
--- a/java/com/google/gerrit/testing/InMemoryDatabase.java
+++ b/java/com/google/gerrit/testing/InMemoryDatabase.java
@@ -14,60 +14,34 @@
package com.google.gerrit.testing;
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.pgm.init.index.elasticsearch.ElasticIndexModuleOnInit;
import com.google.gerrit.pgm.init.index.lucene.LuceneIndexModuleOnInit;
-import com.google.gerrit.reviewdb.client.CurrentSchemaVersion;
import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.config.AllProjectsName;
+import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.index.IndexModule;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
-import com.google.gerrit.server.schema.ReviewDbSchemaVersion;
-import com.google.gwtorm.jdbc.Database;
-import com.google.gwtorm.jdbc.SimpleDataSource;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
-import com.google.inject.Guice;
import com.google.inject.Inject;
import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.TypeLiteral;
import java.io.IOException;
-import java.sql.Connection;
-import java.sql.SQLException;
-import java.util.Properties;
-import javax.sql.DataSource;
import org.eclipse.jgit.errors.ConfigInvalidException;
+import org.eclipse.jgit.errors.RepositoryNotFoundException;
-/**
- * An in-memory test instance of {@link ReviewDb} database.
- *
- * <p>Test classes should create one instance of this class for each unique test database they want
- * to use. When the tests needing this instance are complete, ensure that {@link
- * #drop(InMemoryDatabase)} is called to free the resources so the JVM running the unit tests
- * doesn't run out of heap space.
- */
+/** Husk of an in-memory ReviewDb implementation. */
+// TODO(dborowitz): Inline callers to get their own darn schemaCreator.
public class InMemoryDatabase implements SchemaFactory<ReviewDb> {
- public static InMemoryDatabase newDatabase(LifecycleManager lifecycle) {
- Injector injector = Guice.createInjector(new InMemoryModule());
- lifecycle.add(injector);
- return injector.getInstance(InMemoryDatabase.class);
- }
-
- /** Drop the database from memory; does nothing if the instance was null. */
- public static void drop(InMemoryDatabase db) {
- if (db != null) {
- db.dbInstance.drop();
- }
- }
-
- private final ReviewDbSchemaCreator schemaCreator;
- private final Instance dbInstance;
-
- private boolean created;
+ private final GitRepositoryManager repoManager;
+ private final AllProjectsName allProjectsName;
+ private final SchemaCreator schemaCreator;
+ private final SchemaFactory<ReviewDb> schemaFactory;
@Inject
- InMemoryDatabase(Injector injector) throws OrmException {
+ InMemoryDatabase(Injector injector) {
Injector childInjector =
injector.createChildInjector(
new AbstractModule() {
@@ -85,110 +59,40 @@
}
}
});
- this.schemaCreator = childInjector.getInstance(ReviewDbSchemaCreator.class);
- Instance dbInstanceFromInjector = childInjector.getInstance(Instance.class);
- if (dbInstanceFromInjector != null) {
- this.dbInstance = dbInstanceFromInjector;
- this.created = true;
- } else {
- this.dbInstance = new Instance();
- }
+ this.repoManager = childInjector.getInstance(GitRepositoryManager.class);
+ this.allProjectsName = childInjector.getInstance(AllProjectsName.class);
+ this.schemaCreator = childInjector.getInstance(SchemaCreator.class);
+ this.schemaFactory =
+ childInjector.getInstance(Key.get(new TypeLiteral<SchemaFactory<ReviewDb>>() {}));
}
- InMemoryDatabase(ReviewDbSchemaCreator schemaCreator) throws OrmException {
+ InMemoryDatabase(
+ GitRepositoryManager repoManager,
+ AllProjectsName allProjectsName,
+ SchemaCreator schemaCreator,
+ SchemaFactory<ReviewDb> schemaFactory) {
+ this.repoManager = repoManager;
+ this.allProjectsName = allProjectsName;
this.schemaCreator = schemaCreator;
- this.dbInstance = new Instance();
- }
-
- public Instance getDbInstance() {
- return dbInstance;
- }
-
- public Database<ReviewDb> getDatabase() {
- return dbInstance.database;
+ this.schemaFactory = schemaFactory;
}
@Override
public ReviewDb open() throws OrmException {
- return getDatabase().open();
+ return schemaFactory.open();
}
/** Ensure the database schema has been created and initialized. */
public InMemoryDatabase create() throws OrmException {
- if (!created) {
- created = true;
- try (ReviewDb c = open()) {
- schemaCreator.create(c);
- } catch (IOException | ConfigInvalidException e) {
- throw new OrmException("Cannot create in-memory database", e);
+ try {
+ try {
+ repoManager.openRepository(allProjectsName).close();
+ } catch (RepositoryNotFoundException e) {
+ schemaCreator.create();
}
+ } catch (IOException | ConfigInvalidException e) {
+ throw new OrmException("Cannot create in-memory database", e);
}
return this;
}
-
- public CurrentSchemaVersion getSchemaVersion() throws OrmException {
- try (ReviewDb c = open()) {
- return c.schemaVersion().get(new CurrentSchemaVersion.Key());
- }
- }
-
- public void assertSchemaVersion() throws OrmException {
- assertThat(getSchemaVersion().versionNbr).isEqualTo(ReviewDbSchemaVersion.getBinaryVersion());
- }
-
- public static class Instance {
- private static int dbCnt;
-
- private Connection openHandle;
- private Database<ReviewDb> database;
- private boolean keepOpen;
-
- private static synchronized DataSource newDataSource() throws SQLException {
- final Properties p = new Properties();
- p.setProperty("driver", org.h2.Driver.class.getName());
- p.setProperty("url", "jdbc:h2:mem:Test_" + (++dbCnt));
- return new SimpleDataSource(p);
- }
-
- private Instance() throws OrmException {
- try {
- DataSource dataSource = newDataSource();
-
- // Open one connection. This will peg the database into memory
- // until someone calls drop on us, allowing subsequent connections
- // opened against the same URL to go to the same set of tables.
- //
- openHandle = dataSource.getConnection();
-
- // Build the access layer around the connection factory.
- //
- database = new Database<>(dataSource, ReviewDb.class);
-
- } catch (SQLException e) {
- throw new OrmException(e);
- }
- }
-
- public void setKeepOpen(boolean keepOpen) {
- this.keepOpen = keepOpen;
- }
-
- /** Drop this database from memory so it no longer exists. */
- public void drop() {
- if (keepOpen) {
- return;
- }
-
- if (openHandle != null) {
- try {
- openHandle.close();
- } catch (SQLException e) {
- System.err.println("WARNING: Cannot close database connection");
- e.printStackTrace(System.err);
- }
- openHandle = null;
- database = null;
- }
- }
- }
}
diff --git a/java/com/google/gerrit/testing/InMemoryH2Type.java b/java/com/google/gerrit/testing/InMemoryH2Type.java
deleted file mode 100644
index ae3bf36..0000000
--- a/java/com/google/gerrit/testing/InMemoryH2Type.java
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (C) 2012 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.testing;
-
-import com.google.gerrit.server.schema.BaseDataSourceType;
-
-public class InMemoryH2Type extends BaseDataSourceType {
-
- protected InMemoryH2Type() {
- super(null);
- }
-
- @Override
- public String getUrl() {
- // not used
- throw new UnsupportedOperationException();
- }
-}
diff --git a/java/com/google/gerrit/testing/InMemoryModule.java b/java/com/google/gerrit/testing/InMemoryModule.java
index fc17816..682e8c2 100644
--- a/java/com/google/gerrit/testing/InMemoryModule.java
+++ b/java/com/google/gerrit/testing/InMemoryModule.java
@@ -70,10 +70,9 @@
import com.google.gerrit.server.index.change.AllChangesIndexer;
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
import com.google.gerrit.server.index.group.AllGroupsIndexer;
+import com.google.gerrit.server.index.group.GroupIndexCollection;
import com.google.gerrit.server.index.group.GroupSchemaDefinitions;
import com.google.gerrit.server.mail.SignedTokenEmailTokenVerifier;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.GwtormChangeBundleReader;
import com.google.gerrit.server.notedb.MutableNotesMigration;
import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.patch.DiffExecutor;
@@ -81,16 +80,15 @@
import com.google.gerrit.server.plugins.ServerInformationImpl;
import com.google.gerrit.server.project.DefaultProjectNameLockManager;
import com.google.gerrit.server.restapi.RestApiModule;
-import com.google.gerrit.server.schema.DataSourceType;
import com.google.gerrit.server.schema.InMemoryAccountPatchReviewStore;
import com.google.gerrit.server.schema.NotesMigrationSchemaFactory;
import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreatorImpl;
import com.google.gerrit.server.securestore.DefaultSecureStore;
import com.google.gerrit.server.securestore.SecureStore;
import com.google.gerrit.server.ssh.NoSshKeyCache;
import com.google.gerrit.server.submit.LocalMergeSuperSetComputation;
-import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.SchemaFactory;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
@@ -189,15 +187,7 @@
bind(Path.class).annotatedWith(SitePath.class).toInstance(Paths.get("."));
bind(Config.class).annotatedWith(GerritServerConfig.class).toInstance(cfg);
bind(GerritOptions.class).toInstance(new GerritOptions(false, false, false));
- bind(PersonIdent.class)
- .annotatedWith(GerritPersonIdent.class)
- .toProvider(GerritPersonIdentProvider.class);
- bind(String.class)
- .annotatedWith(AnonymousCowardName.class)
- .toProvider(AnonymousCowardNameProvider.class);
- bind(AllProjectsName.class).toProvider(AllProjectsNameProvider.class);
- bind(AllUsersName.class).toProvider(AllUsersNameProvider.class);
bind(GitRepositoryManager.class).to(InMemoryRepositoryManager.class);
bind(InMemoryRepositoryManager.class).in(SINGLETON);
bind(TrackingFooters.class).toProvider(TrackingFootersProvider.class).in(SINGLETON);
@@ -206,8 +196,6 @@
bind(ListeningExecutorService.class)
.annotatedWith(ChangeUpdateExecutor.class)
.toInstance(MoreExecutors.newDirectExecutorService());
- bind(DataSourceType.class).to(InMemoryH2Type.class);
- bind(ChangeBundleReader.class).to(GwtormChangeBundleReader.class);
bind(SecureStore.class).to(DefaultSecureStore.class);
TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
@@ -215,6 +203,7 @@
bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
bind(Key.get(schemaFactory, ReviewDbFactory.class)).to(InMemoryDatabase.class);
+ install(new InMemorySchemaModule());
install(NoSshKeyCache.module());
install(new GerritInstanceNameModule());
install(
@@ -274,6 +263,41 @@
install(new DefaultProjectNameLockManager.Module());
}
+ /** Copy of ReviewDbSchemaModule with a slightly different server ID provider. */
+ // TODO(dborowitz): Better code sharing.
+ private class InMemorySchemaModule extends FactoryModule {
+ @Override
+ public void configure() {
+ bind(PersonIdent.class)
+ .annotatedWith(GerritPersonIdent.class)
+ .toProvider(GerritPersonIdentProvider.class);
+
+ bind(AllProjectsName.class).toProvider(AllProjectsNameProvider.class).in(SINGLETON);
+
+ bind(AllUsersName.class).toProvider(AllUsersNameProvider.class).in(SINGLETON);
+
+ bind(String.class)
+ .annotatedWith(AnonymousCowardName.class)
+ .toProvider(AnonymousCowardNameProvider.class);
+
+ bind(GroupIndexCollection.class);
+ bind(SchemaCreator.class).to(SchemaCreatorImpl.class);
+ }
+
+ @Provides
+ @Singleton
+ @GerritServerId
+ public String createServerId() {
+ String serverId =
+ cfg.getString(GerritServerIdProvider.SECTION, null, GerritServerIdProvider.KEY);
+ if (!Strings.isNullOrEmpty(serverId)) {
+ return serverId;
+ }
+
+ return "gerrit";
+ }
+ }
+
@Provides
@Singleton
@SendEmailExecutor
@@ -290,21 +314,12 @@
@Provides
@Singleton
- @GerritServerId
- public String createServerId() {
- String serverId =
- cfg.getString(GerritServerIdProvider.SECTION, null, GerritServerIdProvider.KEY);
- if (!Strings.isNullOrEmpty(serverId)) {
- return serverId;
- }
-
- return "gerrit";
- }
-
- @Provides
- @Singleton
- InMemoryDatabase getInMemoryDatabase(ReviewDbSchemaCreator schemaCreator) throws OrmException {
- return new InMemoryDatabase(schemaCreator);
+ InMemoryDatabase getInMemoryDatabase(
+ GitRepositoryManager repoManager,
+ AllProjectsName allProjectsName,
+ SchemaCreator schemaCreator,
+ SchemaFactory<ReviewDb> schemaFactory) {
+ return new InMemoryDatabase(repoManager, allProjectsName, schemaCreator, schemaFactory);
}
private Module luceneIndexModule() {
diff --git a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
index 02be071..c01a44a 100644
--- a/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
+++ b/java/com/google/gerrit/testing/InMemoryTestEnvironment.java
@@ -21,7 +21,7 @@
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.account.AccountManager;
import com.google.gerrit.server.account.AuthRequest;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gwtorm.server.SchemaFactory;
@@ -50,7 +50,7 @@
@Inject private AccountManager accountManager;
@Inject private IdentifiedUser.GenericFactory userFactory;
@Inject private SchemaFactory<ReviewDb> schemaFactory;
- @Inject private ReviewDbSchemaCreator schemaCreator;
+ @Inject private SchemaCreator schemaCreator;
@Inject private ThreadLocalRequestContext requestContext;
// Only for use in setting up/tearing down injector.
@Inject private InMemoryDatabase inMemoryDatabase;
@@ -117,9 +117,7 @@
lifecycle.add(injector);
lifecycle.start();
- try (ReviewDb underlyingDb = inMemoryDatabase.getDatabase().open()) {
- schemaCreator.create(underlyingDb);
- }
+ schemaCreator.create();
db = schemaFactory.open();
// The first user is added to the "Administrators" group. See AccountManager#create().
@@ -139,6 +137,5 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(inMemoryDatabase);
}
}
diff --git a/java/com/google/gerrit/testing/NoteDbChecker.java b/java/com/google/gerrit/testing/NoteDbChecker.java
deleted file mode 100644
index 1dc8ee2..0000000
--- a/java/com/google/gerrit/testing/NoteDbChecker.java
+++ /dev/null
@@ -1,225 +0,0 @@
-// Copyright (C) 2016 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.testing;
-
-import static com.google.common.truth.Truth.assertThat;
-import static java.util.Comparator.comparing;
-import static java.util.stream.Collectors.toList;
-
-import com.google.common.base.Joiner;
-import com.google.common.collect.ImmutableListMultimap;
-import com.google.common.collect.ListMultimap;
-import com.google.common.flogger.FluentLogger;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.MutableNotesMigration;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder;
-import com.google.gwtorm.client.IntKey;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.OrmRuntimeException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import com.google.inject.Singleton;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-import java.util.stream.Stream;
-import org.eclipse.jgit.errors.RepositoryNotFoundException;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.runner.Description;
-
-@Singleton
-public class NoteDbChecker {
- private static final FluentLogger logger = FluentLogger.forEnclosingClass();
-
- private final Provider<ReviewDb> dbProvider;
- private final GitRepositoryManager repoManager;
- private final MutableNotesMigration notesMigration;
- private final ChangeBundleReader bundleReader;
- private final ChangeNotes.Factory notesFactory;
- private final ChangeRebuilder changeRebuilder;
- private final CommentsUtil commentsUtil;
-
- @Inject
- NoteDbChecker(
- Provider<ReviewDb> dbProvider,
- GitRepositoryManager repoManager,
- MutableNotesMigration notesMigration,
- ChangeBundleReader bundleReader,
- ChangeNotes.Factory notesFactory,
- ChangeRebuilder changeRebuilder,
- CommentsUtil commentsUtil) {
- this.dbProvider = dbProvider;
- this.repoManager = repoManager;
- this.bundleReader = bundleReader;
- this.notesMigration = notesMigration;
- this.notesFactory = notesFactory;
- this.changeRebuilder = changeRebuilder;
- this.commentsUtil = commentsUtil;
- }
-
- public void rebuildAndCheckAllChanges() throws Exception {
- rebuildAndCheckChanges(
- getUnwrappedDb().changes().all().toList().stream().map(Change::getId),
- ImmutableListMultimap.of());
- }
-
- public void rebuildAndCheckChanges(Change.Id... changeIds) throws Exception {
- rebuildAndCheckChanges(Arrays.stream(changeIds), ImmutableListMultimap.of());
- }
-
- private void rebuildAndCheckChanges(
- Stream<Change.Id> changeIds, ListMultimap<Change.Id, String> expectedDiffs) throws Exception {
- ReviewDb db = getUnwrappedDb();
-
- List<ChangeBundle> allExpected = readExpected(changeIds);
-
- boolean oldWrite = notesMigration.rawWriteChangesSetting();
- boolean oldRead = notesMigration.readChanges();
- try {
- notesMigration.setWriteChanges(true);
- notesMigration.setReadChanges(true);
- List<String> msgs = new ArrayList<>();
- for (ChangeBundle expected : allExpected) {
- Change c = expected.getChange();
- try {
- changeRebuilder.rebuild(db, c.getId());
- } catch (RepositoryNotFoundException e) {
- msgs.add("Repository not found for change, cannot convert: " + c);
- }
- }
-
- checkActual(allExpected, expectedDiffs, msgs);
- } finally {
- notesMigration.setReadChanges(oldRead);
- notesMigration.setWriteChanges(oldWrite);
- }
- }
-
- public void checkChanges(Change.Id... changeIds) throws Exception {
- checkActual(
- readExpected(Arrays.stream(changeIds)), ImmutableListMultimap.of(), new ArrayList<>());
- }
-
- public void rebuildAndCheckChange(Change.Id changeId, String... expectedDiff) throws Exception {
- ImmutableListMultimap.Builder<Change.Id, String> b = ImmutableListMultimap.builder();
- b.putAll(changeId, Arrays.asList(expectedDiff));
- rebuildAndCheckChanges(Stream.of(changeId), b.build());
- }
-
- public void assertNoChangeRef(Project.NameKey project, Change.Id changeId) throws Exception {
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef(RefNames.changeMetaRef(changeId))).isNull();
- }
- }
-
- public void assertNoReviewDbChanges(Description desc) throws Exception {
- ReviewDb db = getUnwrappedDb();
- assertThat(db.changes().all().toList()).named("Changes in " + desc.getTestClass()).isEmpty();
- assertThat(db.changeMessages().all().toList())
- .named("ChangeMessages in " + desc.getTestClass())
- .isEmpty();
- assertThat(db.patchSets().all().toList())
- .named("PatchSets in " + desc.getTestClass())
- .isEmpty();
- assertThat(db.patchSetApprovals().all().toList())
- .named("PatchSetApprovals in " + desc.getTestClass())
- .isEmpty();
- assertThat(db.patchComments().all().toList())
- .named("PatchLineComments in " + desc.getTestClass())
- .isEmpty();
- }
-
- private List<ChangeBundle> readExpected(Stream<Change.Id> changeIds) throws Exception {
- boolean old = notesMigration.readChanges();
- try {
- notesMigration.setReadChanges(false);
- return changeIds
- .sorted(comparing(IntKey::get))
- .map(this::readBundleUnchecked)
- .collect(toList());
- } finally {
- notesMigration.setReadChanges(old);
- }
- }
-
- private ChangeBundle readBundleUnchecked(Change.Id id) {
- try {
- return bundleReader.fromReviewDb(getUnwrappedDb(), id);
- } catch (OrmException e) {
- throw new OrmRuntimeException(e);
- }
- }
-
- private void checkActual(
- List<ChangeBundle> allExpected,
- ListMultimap<Change.Id, String> expectedDiffs,
- List<String> msgs)
- throws Exception {
- ReviewDb db = getUnwrappedDb();
- boolean oldRead = notesMigration.readChanges();
- boolean oldWrite = notesMigration.rawWriteChangesSetting();
- try {
- notesMigration.setWriteChanges(true);
- notesMigration.setReadChanges(true);
- for (ChangeBundle expected : allExpected) {
- Change c = expected.getChange();
- ChangeBundle actual;
- try {
- actual =
- ChangeBundle.fromNotes(
- commentsUtil, notesFactory.create(db, c.getProject(), c.getId()));
- } catch (Throwable t) {
- String msg = "Error converting change: " + c;
- msgs.add(msg);
- logger.atSevere().withCause(t).log(msg);
- continue;
- }
- List<String> diff = expected.differencesFrom(actual);
- List<String> expectedDiff = expectedDiffs.get(c.getId());
- if (!diff.equals(expectedDiff)) {
- msgs.add("Differences between ReviewDb and NoteDb for " + c + ":");
- msgs.addAll(diff);
- if (!expectedDiff.isEmpty()) {
- msgs.add("Expected differences:");
- msgs.addAll(expectedDiff);
- }
- msgs.add("");
- } else {
- System.err.println("NoteDb conversion of change " + c.getId() + " successful");
- }
- }
- } finally {
- notesMigration.setReadChanges(oldRead);
- notesMigration.setWriteChanges(oldWrite);
- }
- if (!msgs.isEmpty()) {
- throw new AssertionError(Joiner.on('\n').join(msgs));
- }
- }
-
- private ReviewDb getUnwrappedDb() {
- ReviewDb db = dbProvider.get();
- return ReviewDbUtil.unwrapDb(db);
- }
-}
diff --git a/java/com/google/gerrit/testing/NoteDbMode.java b/java/com/google/gerrit/testing/NoteDbMode.java
index e46acc3..f901cce 100644
--- a/java/com/google/gerrit/testing/NoteDbMode.java
+++ b/java/com/google/gerrit/testing/NoteDbMode.java
@@ -35,13 +35,7 @@
PRIMARY(NotesMigrationState.READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY),
/** All change tables are entirely disabled, and code/meta ref updates are fused. */
- ON(NotesMigrationState.NOTE_DB),
-
- /**
- * Run tests with NoteDb disabled, then convert ReviewDb to NoteDb and check that the results
- * match.
- */
- CHECK(NotesMigrationState.REVIEW_DB);
+ ON(NotesMigrationState.NOTE_DB);
private static final String ENV_VAR = "GERRIT_NOTEDB";
private static final String SYS_PROP = "gerrit.notedb";
diff --git a/java/com/google/gerrit/testing/TestChanges.java b/java/com/google/gerrit/testing/TestChanges.java
index 8e752fa..0c87b38 100644
--- a/java/com/google/gerrit/testing/TestChanges.java
+++ b/java/com/google/gerrit/testing/TestChanges.java
@@ -30,7 +30,6 @@
import com.google.gerrit.server.notedb.AbstractChangeNotes;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NotesMigration;
import com.google.gerrit.server.util.time.TimeUtil;
import com.google.inject.Injector;
import java.util.TimeZone;
@@ -98,8 +97,7 @@
ChangeNotes notes = update.getNotes();
boolean hasPatchSets = notes.getPatchSets() != null && !notes.getPatchSets().isEmpty();
- NotesMigration migration = injector.getInstance(NotesMigration.class);
- if (hasPatchSets || !migration.readChanges()) {
+ if (hasPatchSets) {
return update;
}
diff --git a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
index 887035b..4086233 100644
--- a/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -123,7 +123,6 @@
import com.google.gerrit.server.git.meta.MetaDataUpdate;
import com.google.gerrit.server.index.account.AccountIndexer;
import com.google.gerrit.server.index.account.StalenessChecker;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
import com.google.gerrit.server.project.ProjectConfig;
import com.google.gerrit.server.project.RefPattern;
import com.google.gerrit.server.query.account.InternalAccountQuery;
@@ -468,7 +467,7 @@
RevCommit c = rw.parseCommit(ref.getObjectId());
long timestampDiffMs =
Math.abs(c.getCommitTime() * 1000L - getAccount(accountId).getRegisteredOn().getTime());
- assertThat(timestampDiffMs).isAtMost(ChangeRebuilderImpl.MAX_WINDOW_MS);
+ assertThat(timestampDiffMs).isAtMost(SECONDS.toMillis(1));
// Check the 'account.config' file.
try (TreeWalk tw = TreeWalk.forPath(or, AccountProperties.ACCOUNT_CONFIG, c.getTree())) {
@@ -2252,12 +2251,7 @@
externalIds,
metaDataUpdateInternalFactory,
new RetryHelper(
- cfg,
- retryMetrics,
- null,
- null,
- null,
- r -> r.withBlockStrategy(noSleepBlockStrategy)),
+ cfg, retryMetrics, null, r -> r.withBlockStrategy(noSleepBlockStrategy)),
extIdNotesFactory,
ident,
ident,
@@ -2310,8 +2304,6 @@
cfg,
retryMetrics,
null,
- null,
- null,
r ->
r.withStopStrategy(StopStrategies.stopAfterAttempt(status.size()))
.withBlockStrategy(noSleepBlockStrategy)),
@@ -2369,12 +2361,7 @@
externalIds,
metaDataUpdateInternalFactory,
new RetryHelper(
- cfg,
- retryMetrics,
- null,
- null,
- null,
- r -> r.withBlockStrategy(noSleepBlockStrategy)),
+ cfg, retryMetrics, null, r -> r.withBlockStrategy(noSleepBlockStrategy)),
extIdNotesFactory,
ident,
ident,
@@ -2440,12 +2427,7 @@
externalIds,
metaDataUpdateInternalFactory,
new RetryHelper(
- cfg,
- retryMetrics,
- null,
- null,
- null,
- r -> r.withBlockStrategy(noSleepBlockStrategy)),
+ cfg, retryMetrics, null, r -> r.withBlockStrategy(noSleepBlockStrategy)),
extIdNotesFactory,
ident,
ident,
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 5ca5b14..324f33b 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.assertPushOk;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_CONTENT;
@@ -40,7 +39,6 @@
import static com.google.gerrit.extensions.client.ReviewerState.REMOVED;
import static com.google.gerrit.extensions.client.ReviewerState.REVIEWER;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
-import static com.google.gerrit.reviewdb.server.ReviewDbUtil.unwrapDb;
import static com.google.gerrit.server.StarredChangesUtil.DEFAULT_LABEL;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.CHANGE_OWNER;
@@ -133,9 +131,7 @@
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.LabelId;
import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.ChangeMessagesUtil;
@@ -146,7 +142,6 @@
import com.google.gerrit.server.index.change.ChangeIndex;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.IndexedChangeQuery;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.restapi.change.PostReview;
@@ -162,7 +157,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
@@ -513,8 +507,6 @@
@Test
public void pendingReviewersInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
ConfigInput conf = new ConfigInput();
conf.enableReviewerByEmail = InheritableBoolean.TRUE;
gApi.projects().name(project.get()).config(conf);
@@ -854,16 +846,11 @@
List<Integer> reviewers =
result.get(ReviewerState.REVIEWER).stream().map(a -> a._accountId).collect(toList());
- if (notesMigration.readChanges()) {
- assertThat(result).containsKey(ReviewerState.CC);
- List<Integer> ccs =
- result.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
- assertThat(ccs).containsExactly(accountCreator.user2().id.get());
- assertThat(reviewers).containsExactly(user.id.get(), admin.id.get());
- } else {
- assertThat(reviewers)
- .containsExactly(user.id.get(), admin.id.get(), accountCreator.user2().id.get());
- }
+ assertThat(result).containsKey(ReviewerState.CC);
+ List<Integer> ccs =
+ result.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
+ assertThat(ccs).containsExactly(accountCreator.user2().id.get());
+ assertThat(reviewers).containsExactly(user.id.get(), admin.id.get());
}
@Test
@@ -929,17 +916,6 @@
assertThat(cr.all).hasSize(1);
assertThat(cr.all.get(0).value).isEqualTo(1);
- if (notesMigration.changePrimaryStorage() == PrimaryStorage.REVIEW_DB) {
- // Ensure record was actually copied under ReviewDb
- List<PatchSetApproval> psas =
- unwrapDb(db)
- .patchSetApprovals()
- .byPatchSet(new PatchSet.Id(new Change.Id(c2._number), 2))
- .toList();
- assertThat(psas).hasSize(1);
- assertThat(psas.get(0).getValue()).isEqualTo((short) 1);
- }
-
// Rebasing the second change again should fail
exception.expect(ResourceConflictException.class);
exception.expectMessage("Change is already up to date");
@@ -1711,8 +1687,6 @@
@Test
public void addReviewerThatIsInactiveEmailFallback() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
ConfigInput conf = new ConfigInput();
conf.enableReviewerByEmail = InheritableBoolean.TRUE;
gApi.projects().name(project.get()).config(conf);
@@ -1928,26 +1902,6 @@
}
@Test
- public void addReviewerWithNoteDbWhenDummyApprovalInReviewDbExists() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
- assume().that(notesMigration.changePrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
-
- PushOneCommit.Result r = createChange();
-
- // insert dummy approval in ReviewDb
- PatchSetApproval psa =
- new PatchSetApproval(
- new PatchSetApproval.Key(r.getPatchSetId(), user.id, new LabelId("Code-Review")),
- (short) 0,
- TimeUtil.nowTs());
- db.patchSetApprovals().insert(Collections.singleton(psa));
-
- AddReviewerInput in = new AddReviewerInput();
- in.reviewer = user.email;
- gApi.changes().id(r.getChangeId()).addReviewer(in);
- }
-
- @Test
public void addSelfAsReviewer() throws Exception {
TestTimeUtil.resetWithClockStep(1, SECONDS);
PushOneCommit.Result r = createChange();
@@ -2005,9 +1959,7 @@
in.reviewers = ImmutableList.of();
gApi.changes().id(r.getChangeId()).revision(r.getCommit().name()).review(in);
- // If we're not reading from NoteDb, then the CCed user will be returned in the REVIEWER state.
- assertThat(getReviewerState(r.getChangeId(), testAccount.id))
- .hasValue(notesMigration.readChanges() ? CC : REVIEWER);
+ assertThat(getReviewerState(r.getChangeId(), testAccount.id)).hasValue(CC);
}
@Test
@@ -2036,8 +1988,7 @@
.revision(r.getCommit().name())
.review(new ReviewInput().message("hi"));
c = gApi.changes().id(r.getChangeId()).get();
- ReviewerState state = notesMigration.readChanges() ? CC : REVIEWER;
- assertThat(c.reviewers.get(state).stream().map(ai -> ai._accountId).collect(toList()))
+ assertThat(c.reviewers.get(CC).stream().map(ai -> ai._accountId).collect(toList()))
.containsExactly(user.id.get());
}
@@ -2886,8 +2837,6 @@
@Test
public void noteDbCommitsOnPatchSetCreation() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
PushOneCommit.Result r = createChange();
pushFactory
.create(
@@ -3439,12 +3388,7 @@
gApi.changes().id(changeId).current().review(input);
Map<String, Short> votes = gApi.changes().id(changeId).current().reviewer(admin.email).votes();
- if (!notesMigration.readChanges()) {
- assertThat(votes.keySet()).containsExactly("Code-Review");
- assertThat(votes.values()).containsExactly((short) 0);
- } else {
- assertThat(votes).isEmpty();
- }
+ assertThat(votes).isEmpty();
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
index 18eb37a..85fbfa6 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupsIT.java
@@ -27,6 +27,7 @@
import static java.util.stream.Collectors.toList;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
import com.google.common.truth.Correspondence;
import com.google.common.util.concurrent.AtomicLongMap;
@@ -145,25 +146,6 @@
}
}
- // Creates a group, but with uniquified name.
- protected String createUniqueGroup() throws Exception {
- // TODO(hanwen): rewrite this test in terms of UUID. This requires redoing the assertion helpers
- // too.
- AccountGroup.UUID g = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
- return groupRef(g).getName();
- }
-
- protected String createGroup(String name, String owner) throws Exception {
- // TODO(hanwen): rewrite to use groupOperations. This requires passing the owner
- // group's UUID rathen than its name.
- name = name(name);
- GroupInput in = new GroupInput();
- in.name = name;
- in.ownerId = owner;
- gApi.groups().create(in);
- return name;
- }
-
@Override
protected ProjectResetter.Config resetProjects() {
// Don't reset All-Users since deleting users makes groups inconsistent (e.g. groups would
@@ -192,12 +174,14 @@
@Test
public void addRemoveMember() throws Exception {
- String g = createUniqueGroup();
- gApi.groups().id(g).addMembers("user");
- assertMembers(g, user);
+ AccountGroup.UUID group = groupOperations.newGroup().create();
- gApi.groups().id(g).removeMembers("user");
- assertNoMembers(g);
+ gApi.groups().id(group.get()).addMembers("user");
+ assertMembers(group.get(), user);
+
+ gApi.groups().id(group.get()).removeMembers("user");
+ ImmutableSet<Account.Id> members = groupOperations.group(group).get().members();
+ assertThat(members).isEmpty();
}
@Test
@@ -207,16 +191,15 @@
// Fill the cache for the observed account.
groupIncludeCache.getGroupsWithMember(accountId);
- String groupName = createUniqueGroup();
- AccountGroup.UUID groupUuid = new AccountGroup.UUID(gApi.groups().id(groupName).get().id);
+ AccountGroup.UUID groupUuid = groupOperations.newGroup().create();
- gApi.groups().id(groupName).addMembers(username);
+ gApi.groups().id(groupUuid.get()).addMembers(username);
Collection<AccountGroup.UUID> groupsWithMemberAfterAddition =
groupIncludeCache.getGroupsWithMember(accountId);
assertThat(groupsWithMemberAfterAddition).contains(groupUuid);
- gApi.groups().id(groupName).removeMembers(username);
+ gApi.groups().id(groupUuid.get()).removeMembers(username);
Collection<AccountGroup.UUID> groupsWithMemberAfterRemoval =
groupIncludeCache.getGroupsWithMember(accountId);
@@ -239,16 +222,16 @@
@Test
public void addMultipleMembers() throws Exception {
- String g = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String u1 = name("u1");
accountOperations.newAccount().username(u1).create();
String u2 = name("u2");
accountOperations.newAccount().username(u2).create();
- gApi.groups().id(g).addMembers(u1, u2);
+ gApi.groups().id(group.get()).addMembers(u1, u2);
- List<AccountInfo> members = gApi.groups().id(g).members();
+ List<AccountInfo> members = gApi.groups().id(group.get()).members();
assertThat(members)
.comparingElementsUsing(getAccountToUsernameCorrespondence())
.containsExactly(u1, u2);
@@ -256,13 +239,13 @@
@Test
public void membersWithAtSignInUsernameCanBeAdded() throws Exception {
- String g = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String usernameWithAt = name("u1@something");
accountOperations.newAccount().username(usernameWithAt).create();
- gApi.groups().id(g).addMembers(usernameWithAt);
+ gApi.groups().id(group.get()).addMembers(usernameWithAt);
- List<AccountInfo> members = gApi.groups().id(g).members();
+ List<AccountInfo> members = gApi.groups().id(group.get()).members();
assertThat(members)
.comparingElementsUsing(getAccountToUsernameCorrespondence())
.containsExactly(usernameWithAt);
@@ -270,7 +253,7 @@
@Test
public void membersWithAtSignInUsernameAreNotConfusedWithSimilarUsernames() throws Exception {
- String g = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String usernameWithAt = name("u1@something");
accountOperations.newAccount().username(usernameWithAt).create();
String usernameWithoutAt = name("u1something");
@@ -281,10 +264,10 @@
accountOperations.newAccount().username(usernameOnlySuffix).create();
gApi.groups()
- .id(g)
+ .id(group.get())
.addMembers(usernameWithAt, usernameWithoutAt, usernameOnlyPrefix, usernameOnlySuffix);
- List<AccountInfo> members = gApi.groups().id(g).members();
+ List<AccountInfo> members = gApi.groups().id(group.get()).members();
assertThat(members)
.comparingElementsUsing(getAccountToUsernameCorrespondence())
.containsExactly(usernameWithAt, usernameWithoutAt, usernameOnlyPrefix, usernameOnlySuffix);
@@ -292,49 +275,54 @@
@Test
public void includeRemoveGroup() throws Exception {
- String p = createUniqueGroup();
- String g = createUniqueGroup();
- gApi.groups().id(p).addGroups(g);
- assertIncludes(p, g);
+ AccountGroup.UUID parent = groupOperations.newGroup().create();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
+ gApi.groups().id(parent.get()).addGroups(group.get());
+ assertThat(groupOperations.group(parent).get().subgroups()).containsExactly(group);
- gApi.groups().id(p).removeGroups(g);
- assertNoIncludes(p);
+ gApi.groups().id(parent.get()).removeGroups(group.get());
+ assertThat(groupOperations.group(parent).get().subgroups()).isEmpty();
}
@Test
public void includeExternalGroup() throws Exception {
- String g = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String subgroupUuid = SystemGroupBackend.REGISTERED_USERS.get();
- gApi.groups().id(g).addGroups(subgroupUuid);
+ gApi.groups().id(group.get()).addGroups(subgroupUuid);
- List<GroupInfo> subgroups = gApi.groups().id(g).includedGroups();
+ List<GroupInfo> subgroups = gApi.groups().id(group.get()).includedGroups();
assertThat(subgroups).hasSize(1);
assertThat(subgroups.get(0).id).isEqualTo(subgroupUuid.replace(":", "%3A"));
assertThat(subgroups.get(0).name).isEqualTo("Registered Users");
assertThat(subgroups.get(0).groupId).isNull();
- List<? extends GroupAuditEventInfo> auditEvents = gApi.groups().id(g).auditLog();
+ List<? extends GroupAuditEventInfo> auditEvents = gApi.groups().id(group.get()).auditLog();
assertThat(auditEvents).hasSize(1);
assertSubgroupAuditEvent(auditEvents.get(0), Type.ADD_GROUP, admin.id, "Registered Users");
}
@Test
public void includeExistingGroup_OK() throws Exception {
- String p = createUniqueGroup();
- String g = createUniqueGroup();
- gApi.groups().id(p).addGroups(g);
- assertIncludes(p, g);
- gApi.groups().id(p).addGroups(g);
- assertIncludes(p, g);
+ AccountGroup.UUID parent = groupOperations.newGroup().create();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
+ groupOperations.group(parent).forUpdate().addSubgroup(group);
+
+ gApi.groups().id(parent.get()).addGroups(group.get());
+
+ ImmutableSet<AccountGroup.UUID> subgroups = groupOperations.group(parent).get().subgroups();
+ assertThat(subgroups).containsExactly(group);
}
@Test
public void addMultipleIncludes() throws Exception {
- String p = createUniqueGroup();
- String g1 = createUniqueGroup();
- String g2 = createUniqueGroup();
- gApi.groups().id(p).addGroups(g1, g2);
- assertIncludes(p, g1, g2);
+ AccountGroup.UUID parent = groupOperations.newGroup().create();
+ AccountGroup.UUID group1 = groupOperations.newGroup().create();
+ AccountGroup.UUID group2 = groupOperations.newGroup().create();
+
+ gApi.groups().id(parent.get()).addGroups(group1.get(), group2.get());
+
+ ImmutableSet<AccountGroup.UUID> subgroups = groupOperations.group(parent).get().subgroups();
+ assertThat(subgroups).containsExactly(group1, group2);
}
@Test
@@ -635,33 +623,39 @@
@Test
public void listEmptyGroupIncludes() throws Exception {
- String gx = createUniqueGroup();
- assertThat(gApi.groups().id(gx).includedGroups()).isEmpty();
+ AccountGroup.UUID gx = groupOperations.newGroup().create();
+ assertThat(gApi.groups().id(gx.get()).includedGroups()).isEmpty();
}
@Test
public void includeNonExistingGroup() throws Exception {
- String gx = createUniqueGroup();
+ AccountGroup.UUID gx = groupOperations.newGroup().create();
exception.expect(UnprocessableEntityException.class);
- gApi.groups().id(gx).addGroups("non-existing");
+ gApi.groups().id(gx.get()).addGroups("non-existing");
}
@Test
public void listNonEmptyGroupIncludes() throws Exception {
- String gx = createUniqueGroup();
- String gy = createUniqueGroup();
- String gz = createUniqueGroup();
- gApi.groups().id(gx).addGroups(gy);
- gApi.groups().id(gx).addGroups(gz);
- assertIncludes(gApi.groups().id(gx).includedGroups(), gy, gz);
+ AccountGroup.UUID gz = groupOperations.newGroup().create();
+ AccountGroup.UUID gy = groupOperations.newGroup().create();
+ AccountGroup.UUID gx = groupOperations.newGroup().subgroups(gy, gz).create();
+
+ List<GroupInfo> includes = gApi.groups().id(gx.get()).includedGroups();
+
+ String gyName = groupOperations.group(gy).get().name();
+ String gzName = groupOperations.group(gz).get().name();
+ assertIncludes(includes, gyName, gzName);
}
@Test
public void listOneIncludeMember() throws Exception {
- String gx = createUniqueGroup();
- String gy = createUniqueGroup();
- gApi.groups().id(gx).addGroups(gy);
- assertIncludes(gApi.groups().id(gx).includedGroups(), gy);
+ AccountGroup.UUID gy = groupOperations.newGroup().create();
+ AccountGroup.UUID gx = groupOperations.newGroup().subgroups(gy).create();
+
+ List<GroupInfo> includes = gApi.groups().id(gx.get()).includedGroups();
+
+ String gyName = groupOperations.group(gy).get().name();
+ assertIncludes(includes, gyName);
}
@Test
@@ -672,101 +666,101 @@
@Test
public void listEmptyGroupMembers() throws Exception {
- String group = createUniqueGroup();
- assertThat(gApi.groups().id(group).members()).isEmpty();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
+ assertThat(gApi.groups().id(group.get()).members()).isEmpty();
}
@Test
public void listNonEmptyGroupMembers() throws Exception {
- String group = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String user1 = name("user1");
accountOperations.newAccount().username(user1).create();
String user2 = name("user2");
accountOperations.newAccount().username(user2).create();
- gApi.groups().id(group).addMembers(user1, user2);
+ gApi.groups().id(group.get()).addMembers(user1, user2);
- assertMembers(gApi.groups().id(group).members(), user1, user2);
+ assertMembers(gApi.groups().id(group.get()).members(), user1, user2);
}
@Test
public void listOneGroupMember() throws Exception {
- String group = createUniqueGroup();
+ AccountGroup.UUID group = groupOperations.newGroup().create();
String user = name("user1");
accountOperations.newAccount().username(user).create();
- gApi.groups().id(group).addMembers(user);
+ gApi.groups().id(group.get()).addMembers(user);
- assertMembers(gApi.groups().id(group).members(), user);
+ assertMembers(gApi.groups().id(group.get()).members(), user);
}
@Test
public void listGroupMembersRecursively() throws Exception {
- String gx = createUniqueGroup();
+ AccountGroup.UUID gx = groupOperations.newGroup().create();
String ux = name("ux");
accountOperations.newAccount().username(ux).create();
- gApi.groups().id(gx).addMembers(ux);
+ gApi.groups().id(gx.get()).addMembers(ux);
- String gy = createUniqueGroup();
+ AccountGroup.UUID gy = groupOperations.newGroup().create();
String uy = name("uy");
accountOperations.newAccount().username(uy).create();
- gApi.groups().id(gy).addMembers(uy);
+ gApi.groups().id(gy.get()).addMembers(uy);
- String gz = createUniqueGroup();
+ AccountGroup.UUID gz = groupOperations.newGroup().create();
String uz = name("uz");
accountOperations.newAccount().username(uz).create();
- gApi.groups().id(gz).addMembers(uz);
+ gApi.groups().id(gz.get()).addMembers(uz);
- gApi.groups().id(gx).addGroups(gy);
- gApi.groups().id(gy).addGroups(gz);
- assertMembers(gApi.groups().id(gx).members(), ux);
- assertMembers(gApi.groups().id(gx).members(true), ux, uy, uz);
+ gApi.groups().id(gx.get()).addGroups(gy.get());
+ gApi.groups().id(gy.get()).addGroups(gz.get());
+ assertMembers(gApi.groups().id(gx.get()).members(), ux);
+ assertMembers(gApi.groups().id(gx.get()).members(true), ux, uy, uz);
}
@Test
public void usersSeeTheirDirectMembershipWhenListingMembersRecursively() throws Exception {
- String group = createUniqueGroup();
- gApi.groups().id(group).addMembers(user.username);
+ AccountGroup.UUID group = groupOperations.newGroup().create();
+ gApi.groups().id(group.get()).addMembers(user.username);
setApiUser(user);
- assertMembers(gApi.groups().id(group).members(true), user.fullName);
+ assertMembers(gApi.groups().id(group.get()).members(true), user.fullName);
}
@Test
public void usersDoNotSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
- String group1 = createUniqueGroup();
- String group2 = createUniqueGroup();
- gApi.groups().id(group1).addGroups(group2);
- gApi.groups().id(group2).addMembers(user.username);
+ AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
+ AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
+ gApi.groups().id(group1.get()).addGroups(group2.get());
+ gApi.groups().id(group2.get()).addMembers(user.username);
setApiUser(user);
- List<AccountInfo> listedMembers = gApi.groups().id(group1).members(true);
+ List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);
assertMembers(listedMembers);
}
@Test
public void adminsSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
- String ownerGroup = createGroup("ownerGroup", null);
- String group1 = createGroup("group1", ownerGroup);
- String group2 = createGroup("group2", ownerGroup);
- gApi.groups().id(group1).addGroups(group2);
- gApi.groups().id(group2).addMembers(admin.username);
+ AccountGroup.UUID ownerGroup = groupOperations.newGroup().create();
+ AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
+ AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
+ gApi.groups().id(group1.get()).addGroups(group2.get());
+ gApi.groups().id(group2.get()).addMembers(admin.username);
- List<AccountInfo> listedMembers = gApi.groups().id(group1).members(true);
+ List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);
assertMembers(listedMembers, admin.fullName);
}
@Test
public void ownersSeeTheirIndirectMembershipWhenListingMembersRecursively() throws Exception {
- String ownerGroup = createGroup("ownerGroup", null);
- String group1 = createGroup("group1", ownerGroup);
- String group2 = createGroup("group2", ownerGroup);
- gApi.groups().id(group1).addGroups(group2);
- gApi.groups().id(ownerGroup).addMembers(user.username);
- gApi.groups().id(group2).addMembers(user.username);
+ AccountGroup.UUID ownerGroup = groupOperations.newGroup().create();
+ AccountGroup.UUID group1 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
+ AccountGroup.UUID group2 = groupOperations.newGroup().ownerGroupUuid(ownerGroup).create();
+ gApi.groups().id(group1.get()).addGroups(group2.get());
+ gApi.groups().id(ownerGroup.get()).addMembers(user.username);
+ gApi.groups().id(group2.get()).addMembers(user.username);
setApiUser(user);
- List<AccountInfo> listedMembers = gApi.groups().id(group1).members(true);
+ List<AccountInfo> listedMembers = gApi.groups().id(group1.get()).members(true);
assertMembers(listedMembers, user.fullName);
}
@@ -789,18 +783,21 @@
@Test
public void getGroupsByOwner() throws Exception {
- String parent = createUniqueGroup();
- List<String> children =
- Arrays.asList(createGroup("test-child1", parent), createGroup("test-child2", parent));
+ AccountGroup.UUID parent = groupOperations.newGroup().ownerGroupUuid(adminGroupUuid()).create();
+ List<AccountGroup.UUID> children =
+ Arrays.asList(
+ groupOperations.newGroup().ownerGroupUuid(parent).create(),
+ groupOperations.newGroup().ownerGroupUuid(parent).create());
// By UUID
- List<GroupInfo> owned = gApi.groups().list().withOwnedBy(groupUuid(parent).get()).get();
- assertThat(owned.stream().map(g -> g.name).collect(toList()))
+ List<GroupInfo> owned = gApi.groups().list().withOwnedBy(parent.get()).get();
+ assertThat(owned.stream().map(g -> new AccountGroup.UUID(g.id)).collect(toList()))
.containsExactlyElementsIn(children);
// By name
- owned = gApi.groups().list().withOwnedBy(parent).get();
- assertThat(owned.stream().map(g -> g.name).collect(toList()))
+ String parentName = groupOperations.group(parent).get().name();
+ owned = gApi.groups().list().withOwnedBy(parentName).get();
+ assertThat(owned.stream().map(g -> new AccountGroup.UUID(g.id)).collect(toList()))
.containsExactlyElementsIn(children);
// By group that does not own any others
@@ -1495,24 +1492,12 @@
.inOrder();
}
- private void assertNoMembers(String group) throws Exception {
- assertThat(gApi.groups().id(group).members()).isEmpty();
- }
-
- private void assertIncludes(String group, String... expectedNames) throws Exception {
- assertIncludes(gApi.groups().id(group).includedGroups(), expectedNames);
- }
-
- private static void assertIncludes(Iterable<GroupInfo> includes, String... expectedNames) {
- Iterable<String> names = Iterables.transform(includes, i -> i.name);
+ private static void assertIncludes(List<GroupInfo> includes, String... expectedNames) {
+ List<String> names = includes.stream().map(i -> i.name).collect(toImmutableList());
assertThat(names).containsExactlyElementsIn(Arrays.asList(expectedNames));
assertThat(names).isOrdered();
}
- private void assertNoIncludes(String group) throws Exception {
- assertThat(gApi.groups().id(group).includedGroups()).isEmpty();
- }
-
private void assertBadRequest(ListRequest req) throws Exception {
try {
req.get();
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index bde042f..03ab0e1 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -795,16 +795,11 @@
assertThat(result).containsKey(ReviewerState.REVIEWER);
List<Integer> reviewers =
result.get(ReviewerState.REVIEWER).stream().map(a -> a._accountId).collect(toList());
- if (notesMigration.readChanges()) {
- assertThat(result).containsKey(ReviewerState.CC);
- List<Integer> ccs =
- result.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
- assertThat(ccs).containsExactly(user.id.get());
- assertThat(reviewers).containsExactly(admin.id.get(), accountCreator.admin2().id.get());
- } else {
- assertThat(reviewers)
- .containsExactly(user.id.get(), admin.id.get(), accountCreator.admin2().id.get());
- }
+ assertThat(result).containsKey(ReviewerState.CC);
+ List<Integer> ccs =
+ result.get(ReviewerState.CC).stream().map(a -> a._accountId).collect(toList());
+ assertThat(ccs).containsExactly(user.id.get());
+ assertThat(reviewers).containsExactly(admin.id.get(), accountCreator.admin2().id.get());
}
@Test
diff --git a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
index d713db6..c5251f7 100644
--- a/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/revision/RobotCommentsIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.api.revision;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
import static com.google.gerrit.extensions.common.testing.EditInfoSubject.assertThat;
import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
@@ -38,7 +37,6 @@
import com.google.gerrit.extensions.common.RobotCommentInfo;
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.extensions.restapi.BinaryResult;
-import com.google.gerrit.extensions.restapi.MethodNotAllowedException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
import com.google.gerrit.extensions.restapi.RestApiException;
@@ -85,8 +83,6 @@
@Test
public void retrievingRobotCommentsBeforeAddingAnyDoesNotRaiseAnException() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
Map<String, List<RobotCommentInfo>> robotComments =
gApi.changes().id(changeId).current().robotComments();
@@ -96,8 +92,6 @@
@Test
public void addedRobotCommentsCanBeRetrieved() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
RobotCommentInput in = createRobotCommentInput();
addRobotComment(changeId, in);
@@ -110,8 +104,6 @@
@Test
public void addedRobotCommentsCanBeRetrievedByChange() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
RobotCommentInput in = createRobotCommentInput();
addRobotComment(changeId, in);
@@ -133,8 +125,6 @@
@Test
public void robotCommentsCanBeRetrievedAsList() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
RobotCommentInput robotCommentInput = createRobotCommentInput();
addRobotComment(changeId, robotCommentInput);
@@ -148,8 +138,6 @@
@Test
public void specificRobotCommentCanBeRetrieved() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
RobotCommentInput robotCommentInput = createRobotCommentInput();
addRobotComment(changeId, robotCommentInput);
@@ -163,8 +151,6 @@
@Test
public void robotCommentWithoutOptionalFieldsCanBeAdded() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
RobotCommentInput in = createRobotCommentInputWithMandatoryFields();
addRobotComment(changeId, in);
@@ -176,8 +162,6 @@
@Test
public void hugeRobotCommentIsRejected() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
int defaultSizeLimit = 1024 * 1024;
int sizeOfRest = 451;
fixReplacementInfo.replacement = getStringFor(defaultSizeLimit - sizeOfRest + 1);
@@ -189,8 +173,6 @@
@Test
public void reasonablyLargeRobotCommentIsAccepted() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
int defaultSizeLimit = 1024 * 1024;
int sizeOfRest = 451;
fixReplacementInfo.replacement = getStringFor(defaultSizeLimit - sizeOfRest);
@@ -204,8 +186,6 @@
@Test
@GerritConfig(name = "change.robotCommentSizeLimit", value = "10k")
public void maximumAllowedSizeOfRobotCommentCanBeAdjusted() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
int sizeLimit = 10 * 1024;
fixReplacementInfo.replacement = getStringFor(sizeLimit);
@@ -217,8 +197,6 @@
@Test
@GerritConfig(name = "change.robotCommentSizeLimit", value = "0")
public void zeroForMaximumAllowedSizeOfRobotCommentRemovesRestriction() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
int defaultSizeLimit = 1024 * 1024;
fixReplacementInfo.replacement = getStringFor(defaultSizeLimit);
@@ -232,8 +210,6 @@
@GerritConfig(name = "change.robotCommentSizeLimit", value = "-1")
public void negativeValueForMaximumAllowedSizeOfRobotCommentRemovesRestriction()
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
int defaultSizeLimit = 1024 * 1024;
fixReplacementInfo.replacement = getStringFor(defaultSizeLimit);
@@ -245,8 +221,6 @@
@Test
public void addedFixSuggestionCanBeRetrieved() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -255,8 +229,6 @@
@Test
public void fixIdIsGeneratedForFixSuggestion() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -270,8 +242,6 @@
@Test
public void descriptionOfFixSuggestionIsAcceptedAsIs() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -284,8 +254,6 @@
@Test
public void descriptionOfFixSuggestionIsMandatory() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixSuggestionInfo.description = null;
exception.expect(BadRequestException.class);
@@ -298,8 +266,6 @@
@Test
public void addedFixReplacementCanBeRetrieved() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -312,8 +278,6 @@
@Test
public void fixReplacementsAreMandatory() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixSuggestionInfo.replacements = Collections.emptyList();
exception.expect(BadRequestException.class);
@@ -327,8 +291,6 @@
@Test
public void pathOfFixReplacementIsAcceptedAsIs() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -343,8 +305,6 @@
@Test
public void pathOfFixReplacementIsMandatory() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = null;
exception.expect(BadRequestException.class);
@@ -357,8 +317,6 @@
@Test
public void rangeOfFixReplacementIsAcceptedAsIs() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -373,8 +331,6 @@
@Test
public void rangeOfFixReplacementIsMandatory() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.range = null;
exception.expect(BadRequestException.class);
@@ -387,8 +343,6 @@
@Test
public void rangeOfFixReplacementNeedsToBeValid() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.range = createRange(13, 9, 5, 10);
exception.expect(BadRequestException.class);
exception.expectMessage("Range (13:9 - 5:10)");
@@ -398,8 +352,6 @@
@Test
public void rangesOfFixReplacementsOfSameFixSuggestionForSameFileMayNotOverlap()
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 1);
@@ -422,8 +374,6 @@
@Test
public void rangesOfFixReplacementsOfSameFixSuggestionForDifferentFileMayOverlap()
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 1);
@@ -447,8 +397,6 @@
@Test
public void rangesOfFixReplacementsOfDifferentFixSuggestionsForSameFileMayOverlap()
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 1);
@@ -472,8 +420,6 @@
@Test
public void fixReplacementsDoNotNeedToBeOrderedAccordingToRange() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
@@ -501,8 +447,6 @@
@Test
public void replacementStringOfFixReplacementIsAcceptedAsIs() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
addRobotComment(changeId, withFixRobotCommentInput);
List<RobotCommentInfo> robotCommentInfos = getRobotComments();
@@ -517,8 +461,6 @@
@Test
public void replacementStringOfFixReplacementIsMandatory() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.replacement = null;
exception.expect(BadRequestException.class);
@@ -532,8 +474,6 @@
@Test
public void fixWithinALineCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content";
fixReplacementInfo.range = createRange(3, 1, 3, 3);
@@ -557,8 +497,6 @@
@Test
public void fixSpanningMultipleLinesCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content\n5";
fixReplacementInfo.range = createRange(3, 2, 5, 3);
@@ -581,8 +519,6 @@
@Test
public void fixWithTwoCloseReplacementsOnSameFileCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
@@ -615,8 +551,6 @@
@Test
public void twoFixesOnSameFileCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
@@ -650,8 +584,6 @@
@Test
public void twoConflictingFixesOnSameFileCannotBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 1);
@@ -679,8 +611,6 @@
@Test
public void twoFixesOfSameRobotCommentCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
@@ -714,8 +644,6 @@
@Test
public void fixReferringToDifferentFileThanRobotCommentCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME2;
fixReplacementInfo.range = createRange(2, 0, 3, 0);
fixReplacementInfo.replacement = "Modified content\n";
@@ -736,8 +664,6 @@
@Test
public void fixInvolvingTwoFilesCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
FixReplacementInfo fixReplacementInfo1 = new FixReplacementInfo();
fixReplacementInfo1.path = FILE_NAME;
fixReplacementInfo1.range = createRange(2, 0, 3, 0);
@@ -775,8 +701,6 @@
@Test
public void fixReferringToNonExistentFileCannotBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = "a_non_existent_file.txt";
fixReplacementInfo.range = createRange(1, 0, 2, 0);
fixReplacementInfo.replacement = "Modified content\n";
@@ -792,8 +716,6 @@
@Test
public void fixOnPreviousPatchSetWithoutChangeEditCannotBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content";
fixReplacementInfo.range = createRange(3, 1, 3, 3);
@@ -815,8 +737,6 @@
@Test
public void fixOnPreviousPatchSetWithExistingChangeEditCanBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
// Create an empty change edit.
gApi.changes().id(changeId).edit().create();
@@ -849,8 +769,6 @@
@Test
public void fixOnCurrentPatchSetWithChangeEditOnPreviousPatchSetCannotBeApplied()
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
// Create an empty change edit.
gApi.changes().id(changeId).edit().create();
@@ -874,8 +792,6 @@
@Test
public void fixDoesNotModifyCommitMessageOfChangeEdit() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
String changeEditCommitMessage = "This is the commit message of the change edit.\n";
gApi.changes().id(changeId).edit().modifyCommitMessage(changeEditCommitMessage);
@@ -897,8 +813,6 @@
@Test
public void applyingFixTwiceIsIdempotent() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content";
fixReplacementInfo.range = createRange(3, 1, 3, 3);
@@ -922,8 +836,6 @@
@Test
public void nonExistentFixCannotBeApplied() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content";
fixReplacementInfo.range = createRange(3, 1, 3, 3);
@@ -941,8 +853,6 @@
@Test
public void applyingFixReturnsEditInfoForCreatedChangeEdit() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
fixReplacementInfo.path = FILE_NAME;
fixReplacementInfo.replacement = "Modified content";
fixReplacementInfo.range = createRange(3, 1, 3, 3);
@@ -964,8 +874,6 @@
@Test
public void applyingFixOnTopOfChangeEditReturnsEditInfoForUpdatedChangeEdit() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
gApi.changes().id(changeId).edit().create();
fixReplacementInfo.path = FILE_NAME;
@@ -989,7 +897,6 @@
@Test
public void createdChangeEditIsBasedOnCurrentPatchSet() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
String currentRevision = gApi.changes().id(changeId).get().currentRevision;
fixReplacementInfo.path = FILE_NAME;
@@ -1008,25 +915,7 @@
}
@Test
- public void robotCommentsNotSupportedWithoutNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
-
- RobotCommentInput in = createRobotCommentInput();
- ReviewInput reviewInput = new ReviewInput();
- Map<String, List<RobotCommentInput>> robotComments = new HashMap<>();
- robotComments.put(in.path, ImmutableList.of(in));
- reviewInput.robotComments = robotComments;
- reviewInput.message = "comment test";
-
- exception.expect(MethodNotAllowedException.class);
- exception.expectMessage("robot comments not supported");
- gApi.changes().id(changeId).current().review(reviewInput);
- }
-
- @Test
public void queryChangesWithCommentCounts() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
PushOneCommit.Result r1 = createChange();
PushOneCommit.Result r2 =
pushFactory
diff --git a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
index 7529ee3..5fdfe72 100644
--- a/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
+++ b/javatests/com/google/gerrit/acceptance/git/AbstractPushForReview.java
@@ -18,7 +18,6 @@
import static com.google.common.collect.ImmutableList.toImmutableList;
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.assertPushOk;
import static com.google.gerrit.acceptance.GitUtil.assertPushRejected;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
@@ -543,12 +542,7 @@
r.assertOkStatus();
assertThat(sender.getMessages()).hasSize(1);
Message m = sender.getMessages().get(0);
- if (notesMigration.readChanges()) {
- assertThat(m.rcpt()).containsExactly(user.emailAddress);
- } else {
- // CCs are considered reviewers in the storage layer and so get notified.
- assertThat(m.rcpt()).containsExactly(user.emailAddress, user2.emailAddress);
- }
+ assertThat(m.rcpt()).containsExactly(user.emailAddress);
sender.clear();
r = pushTo(pushSpec + ",notify=" + NotifyHandling.ALL);
@@ -639,23 +633,19 @@
PushOneCommit.Result r =
pushTo("refs/for/master%cc=non.existing.1@example.com,cc=non.existing.2@example.com");
- if (notesMigration.readChanges()) {
- r.assertOkStatus();
+ r.assertOkStatus();
- ChangeInfo ci = get(r.getChangeId(), DETAILED_LABELS);
- ImmutableList<AccountInfo> ccs =
- firstNonNull(ci.reviewers.get(ReviewerState.CC), ImmutableList.<AccountInfo>of())
- .stream()
- .sorted(comparing((AccountInfo a) -> a.email))
- .collect(toImmutableList());
- assertThat(ccs).hasSize(2);
- assertThat(ccs.get(0).email).isEqualTo("non.existing.1@example.com");
- assertThat(ccs.get(0)._accountId).isNull();
- assertThat(ccs.get(1).email).isEqualTo("non.existing.2@example.com");
- assertThat(ccs.get(1)._accountId).isNull();
- } else {
- r.assertErrorStatus("non.existing.1@example.com does not identify a registered user");
- }
+ ChangeInfo ci = get(r.getChangeId(), DETAILED_LABELS);
+ ImmutableList<AccountInfo> ccs =
+ firstNonNull(ci.reviewers.get(ReviewerState.CC), ImmutableList.<AccountInfo>of())
+ .stream()
+ .sorted(comparing((AccountInfo a) -> a.email))
+ .collect(toImmutableList());
+ assertThat(ccs).hasSize(2);
+ assertThat(ccs.get(0).email).isEqualTo("non.existing.1@example.com");
+ assertThat(ccs.get(0)._accountId).isNull();
+ assertThat(ccs.get(1).email).isEqualTo("non.existing.2@example.com");
+ assertThat(ccs.get(1)._accountId).isNull();
}
@Test
@@ -721,23 +711,19 @@
PushOneCommit.Result r =
pushTo("refs/for/master%r=non.existing.1@example.com,r=non.existing.2@example.com");
- if (notesMigration.readChanges()) {
- r.assertOkStatus();
+ r.assertOkStatus();
- ChangeInfo ci = get(r.getChangeId(), DETAILED_LABELS);
- ImmutableList<AccountInfo> reviewers =
- firstNonNull(ci.reviewers.get(ReviewerState.REVIEWER), ImmutableList.<AccountInfo>of())
- .stream()
- .sorted(comparing((AccountInfo a) -> a.email))
- .collect(toImmutableList());
- assertThat(reviewers).hasSize(2);
- assertThat(reviewers.get(0).email).isEqualTo("non.existing.1@example.com");
- assertThat(reviewers.get(0)._accountId).isNull();
- assertThat(reviewers.get(1).email).isEqualTo("non.existing.2@example.com");
- assertThat(reviewers.get(1)._accountId).isNull();
- } else {
- r.assertErrorStatus("non.existing.1@example.com does not identify a registered user");
- }
+ ChangeInfo ci = get(r.getChangeId(), DETAILED_LABELS);
+ ImmutableList<AccountInfo> reviewers =
+ firstNonNull(ci.reviewers.get(ReviewerState.REVIEWER), ImmutableList.<AccountInfo>of())
+ .stream()
+ .sorted(comparing((AccountInfo a) -> a.email))
+ .collect(toImmutableList());
+ assertThat(reviewers).hasSize(2);
+ assertThat(reviewers.get(0).email).isEqualTo("non.existing.1@example.com");
+ assertThat(reviewers.get(0)._accountId).isNull();
+ assertThat(reviewers.get(1).email).isEqualTo("non.existing.2@example.com");
+ assertThat(reviewers.get(1)._accountId).isNull();
}
@Test
@@ -1295,9 +1281,6 @@
@Test
public void pushForMasterWithHashtags() throws Exception {
- // Hashtags only work when reading from NoteDB is enabled
- assume().that(notesMigration.readChanges()).isTrue();
-
// specify a single hashtag as option
String hashtag1 = "tag1";
Set<String> expected = ImmutableSet.of(hashtag1);
@@ -1328,9 +1311,6 @@
@Test
public void pushForMasterWithMultipleHashtags() throws Exception {
- // Hashtags only work when reading from NoteDB is enabled
- assume().that(notesMigration.readChanges()).isTrue();
-
// specify multiple hashtags as options
String hashtag1 = "tag1";
String hashtag2 = "tag2";
@@ -1363,14 +1343,6 @@
}
@Test
- public void pushForMasterWithHashtagsNoteDbDisabled() throws Exception {
- // Push with hashtags should fail when reading from NoteDb is disabled.
- assume().that(notesMigration.readChanges()).isFalse();
- PushOneCommit.Result r = pushTo("refs/for/master%hashtag=tag1");
- r.assertErrorStatus("cannot add hashtags; noteDb is disabled");
- }
-
- @Test
public void pushCommitUsingSignedOffBy() throws Exception {
PushOneCommit push =
pushFactory.create(
diff --git a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
index e4d9f7c..d2fd331 100644
--- a/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/RefAdvertisementIT.java
@@ -49,18 +49,15 @@
import com.google.gerrit.server.config.AnonymousCowardName;
import com.google.gerrit.server.git.receive.ReceiveCommitsAdvertiseRefsHook;
import com.google.gerrit.server.notedb.ChangeNoteUtil;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.permissions.PermissionBackend;
import com.google.gerrit.server.permissions.PermissionBackend.RefFilterOptions;
import com.google.gerrit.server.project.testing.Util;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.testing.NoteDbMode;
-import com.google.gerrit.testing.TestChanges;
import com.google.inject.Inject;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.function.Predicate;
@@ -424,12 +421,6 @@
PatchSet.Id psId = new PatchSet.Id(c3.getId(), 2);
c.setCurrentPatchSet(psId, subject, c.getOriginalSubject());
- if (notesMigration.changePrimaryStorage() == PrimaryStorage.REVIEW_DB) {
- PatchSet ps = TestChanges.newPatchSet(psId, rev, admin.getId());
- db.patchSets().insert(Collections.singleton(ps));
- db.changes().update(Collections.singleton(c));
- }
-
if (notesMigration.commitChangeWrites()) {
PersonIdent committer = serverIdent.get();
PersonIdent author =
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
index 700b18b..cf22a0a 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -318,7 +318,7 @@
private PatchSetApproval getSubmitter(PatchSet.Id patchSetId) throws Exception {
ChangeNotes notes = notesFactory.createChecked(db, project, patchSetId.getParentKey()).load();
- return approvalsUtil.getSubmitter(db, notes, patchSetId);
+ return approvalsUtil.getSubmitter(notes, patchSetId);
}
private void assertSubmitApproval(PatchSet.Id patchSetId) throws Exception {
diff --git a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
index 82b9cd0..f72df99 100644
--- a/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
+++ b/javatests/com/google/gerrit/acceptance/git/SubmoduleSubscriptionsWholeTopicMergeIT.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.getChangeId;
import com.google.common.collect.ImmutableList;
@@ -800,8 +799,6 @@
@Test
public void retrySubmitAfterTornTopicOnLockFailure() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
-
Project.NameKey subKey1 = createProjectForPush(getSubmitType());
TestRepository<?> sub1 = cloneProject(subKey1);
Project.NameKey subKey2 = createProjectForPush(getSubmitType());
diff --git a/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java b/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java
deleted file mode 100644
index 1bb23fb..0000000
--- a/javatests/com/google/gerrit/acceptance/pgm/StandaloneNoteDbMigrationIT.java
+++ /dev/null
@@ -1,363 +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.pgm;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
-import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.acceptance.StandaloneSiteTest;
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.common.ChangeInput;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.LocalDiskRepositoryManager;
-import com.google.gerrit.server.index.GerritIndexStatus;
-import com.google.gerrit.server.index.change.ChangeIndexCollection;
-import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbChangeState.RefState;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.testing.NoteDbMode;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Key;
-import com.google.inject.TypeLiteral;
-import java.io.File;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.stream.Stream;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.lib.StoredConfig;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.junit.Before;
-import org.junit.Test;
-
-/**
- * Tests for NoteDb migrations where the entry point is through a program, {@code
- * migrate-to-note-db} or {@code daemon}.
- *
- * <p><strong>Note:</strong> These tests are very slow due to the repeated daemon startup. Prefer
- * adding tests to {@link com.google.gerrit.acceptance.server.notedb.OnlineNoteDbMigrationIT} if
- * possible.
- */
-@NoHttpd
-public class StandaloneNoteDbMigrationIT extends StandaloneSiteTest {
- private StoredConfig gerritConfig;
- private StoredConfig noteDbConfig;
-
- private Project.NameKey project;
- private Change.Id changeId;
-
- @Before
- public void setUp() throws Exception {
- assume().that(NoteDbMode.get()).isEqualTo(NoteDbMode.OFF);
- gerritConfig = new FileBasedConfig(sitePaths.gerrit_config.toFile(), FS.detect());
- // Unlike in the running server, for tests, we don't stack notedb.config on gerrit.config.
- noteDbConfig = new FileBasedConfig(sitePaths.notedb_config.toFile(), FS.detect());
-
- // Set gc.pruneExpire=now so GC prunes all unreachable objects from All-Users, which allows us
- // to reliably test that it behaves as expected.
- Path cfgPath = sitePaths.site_path.resolve("git").resolve("All-Users.git").resolve("config");
- assertWithMessage("Expected All-Users config at %s", cfgPath)
- .that(Files.isRegularFile(cfgPath))
- .isTrue();
- FileBasedConfig cfg = new FileBasedConfig(cfgPath.toFile(), FS.detect());
- cfg.setString("gc", null, "pruneExpire", "now");
- cfg.save();
- }
-
- @Test
- public void rebuildOneChangeTrialMode() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoAutoMigrateConfig(noteDbConfig);
- assertNotesMigrationState(NotesMigrationState.REVIEW_DB);
- setUpOneChange();
-
- migrate("--trial");
- assertNotesMigrationState(NotesMigrationState.READ_WRITE_NO_SEQUENCE);
-
- try (ServerContext ctx = startServer()) {
- GitRepositoryManager repoManager = ctx.getInjector().getInstance(GitRepositoryManager.class);
- ObjectId metaId;
- try (Repository repo = repoManager.openRepository(project)) {
- Ref ref = repo.exactRef(RefNames.changeMetaRef(changeId));
- assertThat(ref).isNotNull();
- metaId = ref.getObjectId();
- }
-
- try (ReviewDb db = openUnderlyingReviewDb(ctx)) {
- Change c = db.changes().get(changeId);
- assertThat(c).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.getRefState()).hasValue(RefState.create(metaId, ImmutableMap.of()));
- }
- }
- }
-
- @Test
- public void migrateOneChange() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoAutoMigrateConfig(noteDbConfig);
- assertNotesMigrationState(NotesMigrationState.REVIEW_DB);
- setUpOneChange();
-
- migrate();
- assertNotesMigrationState(NotesMigrationState.NOTE_DB);
-
- File allUsersDir;
- try (ServerContext ctx = startServer()) {
- GitRepositoryManager repoManager = ctx.getInjector().getInstance(GitRepositoryManager.class);
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef(RefNames.changeMetaRef(changeId))).isNotNull();
- }
- assertThat(repoManager).isInstanceOf(LocalDiskRepositoryManager.class);
- try (Repository repo =
- repoManager.openRepository(ctx.getInjector().getInstance(AllUsersName.class))) {
- allUsersDir = repo.getDirectory();
- }
-
- try (ReviewDb db = openUnderlyingReviewDb(ctx)) {
- Change c = db.changes().get(changeId);
- assertThat(c).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.NOTE_DB);
- assertThat(state.getRefState()).isEmpty();
-
- ChangeInput in = new ChangeInput(project.get(), "master", "NoteDb-only change");
- in.newBranch = true;
- GerritApi gApi = ctx.getInjector().getInstance(GerritApi.class);
- Change.Id id2 = new Change.Id(gApi.changes().create(in).info()._number);
- assertThat(db.changes().get(id2)).isNull();
- }
- }
- assertNoAutoMigrateConfig(gerritConfig);
- assertAutoMigrateConfig(noteDbConfig, false);
-
- try (FileRepository repo = new FileRepository(allUsersDir)) {
- try (Stream<Path> paths = Files.walk(repo.getObjectsDirectory().toPath())) {
- assertThat(paths.filter(p -> !p.toString().contains("pack") && Files.isRegularFile(p)))
- .named("loose object files in All-Users")
- .isEmpty();
- }
- assertThat(repo.getObjectDatabase().getPacks()).named("packfiles in All-Users").hasSize(1);
- }
- }
-
- @Test
- public void migrationWithReindex() throws Exception {
- assertNotesMigrationState(NotesMigrationState.REVIEW_DB);
- setUpOneChange();
-
- int version = ChangeSchemaDefinitions.INSTANCE.getLatest().getVersion();
- GerritIndexStatus status = new GerritIndexStatus(sitePaths);
- assertThat(status.getReady(ChangeSchemaDefinitions.NAME, version)).isTrue();
- status.setReady(ChangeSchemaDefinitions.NAME, version, false);
- status.save();
- assertServerStartupFails();
-
- migrate();
- assertNotesMigrationState(NotesMigrationState.NOTE_DB);
-
- status = new GerritIndexStatus(sitePaths);
- assertThat(status.getReady(ChangeSchemaDefinitions.NAME, version)).isTrue();
- }
-
- @Test
- public void onlineMigrationViaDaemon() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoAutoMigrateConfig(noteDbConfig);
-
- testOnlineMigration(u -> startServer(u.module(), "--migrate-to-note-db", "true"));
-
- assertNoAutoMigrateConfig(gerritConfig);
- assertAutoMigrateConfig(noteDbConfig, false);
- }
-
- @Test
- public void onlineMigrationViaConfig() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoAutoMigrateConfig(noteDbConfig);
-
- testOnlineMigration(
- u -> {
- gerritConfig.setBoolean("noteDb", "changes", "autoMigrate", true);
- gerritConfig.save();
- return startServer(u.module());
- });
-
- // Auto-migration is turned off in notedb.config, which takes precedence, but is still on in
- // gerrit.config. This means Puppet can continue overwriting gerrit.config without turning
- // auto-migration back on.
- assertAutoMigrateConfig(gerritConfig, true);
- assertAutoMigrateConfig(noteDbConfig, false);
- }
-
- @Test
- public void onlineMigrationTrialModeViaFlag() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoTrialConfig(gerritConfig);
-
- assertNoAutoMigrateConfig(noteDbConfig);
- assertNoTrialConfig(noteDbConfig);
-
- testOnlineMigration(
- u -> startServer(u.module(), "--migrate-to-note-db", "--trial"),
- NotesMigrationState.READ_WRITE_NO_SEQUENCE);
-
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoTrialConfig(gerritConfig);
-
- assertAutoMigrateConfig(noteDbConfig, true);
- assertTrialConfig(noteDbConfig, true);
- }
-
- @Test
- public void onlineMigrationTrialModeViaConfig() throws Exception {
- assertNoAutoMigrateConfig(gerritConfig);
- assertNoTrialConfig(gerritConfig);
-
- assertNoAutoMigrateConfig(noteDbConfig);
- assertNoTrialConfig(noteDbConfig);
-
- testOnlineMigration(
- u -> {
- gerritConfig.setBoolean("noteDb", "changes", "autoMigrate", true);
- gerritConfig.setBoolean("noteDb", "changes", "trial", true);
- gerritConfig.save();
- return startServer(u.module());
- },
- NotesMigrationState.READ_WRITE_NO_SEQUENCE);
-
- assertAutoMigrateConfig(gerritConfig, true);
- assertTrialConfig(gerritConfig, true);
-
- assertAutoMigrateConfig(noteDbConfig, true);
- assertTrialConfig(noteDbConfig, true);
- }
-
- @FunctionalInterface
- private interface StartServerWithMigration {
- ServerContext start(IndexUpgradeController u) throws Exception;
- }
-
- private void testOnlineMigration(StartServerWithMigration start) throws Exception {
- testOnlineMigration(start, NotesMigrationState.NOTE_DB);
- }
-
- private void testOnlineMigration(
- StartServerWithMigration start, NotesMigrationState expectedEndState) throws Exception {
- assertNotesMigrationState(NotesMigrationState.REVIEW_DB);
- int prevVersion = ChangeSchemaDefinitions.INSTANCE.getPrevious().getVersion();
- int currVersion = ChangeSchemaDefinitions.INSTANCE.getLatest().getVersion();
-
- // Before storing any changes, switch back to the previous version.
- GerritIndexStatus status = new GerritIndexStatus(sitePaths);
- status.setReady(ChangeSchemaDefinitions.NAME, currVersion, false);
- status.setReady(ChangeSchemaDefinitions.NAME, prevVersion, true);
- status.save();
-
- setOnlineUpgradeConfig(false);
- setUpOneChange();
- setOnlineUpgradeConfig(true);
-
- IndexUpgradeController u = new IndexUpgradeController(1);
- try (ServerContext ctx = start.start(u)) {
- ChangeIndexCollection indexes = ctx.getInjector().getInstance(ChangeIndexCollection.class);
- assertThat(indexes.getSearchIndex().getSchema().getVersion()).isEqualTo(prevVersion);
-
- // Index schema upgrades happen after NoteDb migration, so waiting for those to complete
- // should be sufficient.
- u.runUpgrades();
-
- assertThat(indexes.getSearchIndex().getSchema().getVersion()).isEqualTo(currVersion);
- assertNotesMigrationState(expectedEndState);
- }
- }
-
- private void setUpOneChange() throws Exception {
- project = new Project.NameKey("project");
- try (ServerContext ctx = startServer()) {
- GerritApi gApi = ctx.getInjector().getInstance(GerritApi.class);
- gApi.projects().create("project");
-
- ChangeInput in = new ChangeInput(project.get(), "master", "Test change");
- in.newBranch = true;
- changeId = new Change.Id(gApi.changes().create(in).info()._number);
- }
- }
-
- private void migrate(String... additionalArgs) throws Exception {
- runGerrit(
- ImmutableList.of(
- "migrate-to-note-db", "-d", sitePaths.site_path.toString(), "--show-stack-trace"),
- ImmutableList.copyOf(additionalArgs));
- }
-
- private void assertNotesMigrationState(NotesMigrationState expected) throws Exception {
- noteDbConfig.load();
- assertThat(NotesMigrationState.forConfig(noteDbConfig)).hasValue(expected);
- }
-
- private ReviewDb openUnderlyingReviewDb(ServerContext ctx) throws Exception {
- return ctx.getInjector()
- .getInstance(Key.get(new TypeLiteral<SchemaFactory<ReviewDb>>() {}, ReviewDbFactory.class))
- .open();
- }
-
- private static void assertNoAutoMigrateConfig(StoredConfig cfg) throws Exception {
- cfg.load();
- assertThat(cfg.getString("noteDb", "changes", "autoMigrate")).isNull();
- }
-
- private static void assertAutoMigrateConfig(StoredConfig cfg, boolean expected) throws Exception {
- cfg.load();
- assertThat(cfg.getString("noteDb", "changes", "autoMigrate")).isNotNull();
- assertThat(cfg.getBoolean("noteDb", "changes", "autoMigrate", false)).isEqualTo(expected);
- }
-
- private static void assertNoTrialConfig(StoredConfig cfg) throws Exception {
- cfg.load();
- assertThat(cfg.getString("noteDb", "changes", "trial")).isNull();
- }
-
- private static void assertTrialConfig(StoredConfig cfg, boolean expected) throws Exception {
- cfg.load();
- assertThat(cfg.getString("noteDb", "changes", "trial")).isNotNull();
- assertThat(cfg.getBoolean("noteDb", "changes", "trial", false)).isEqualTo(expected);
- }
-
- private void setOnlineUpgradeConfig(boolean enable) throws Exception {
- gerritConfig.load();
- gerritConfig.setBoolean("index", null, "onlineUpgrade", enable);
- gerritConfig.save();
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
index 65c95f8..dd26347 100644
--- a/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/account/ImpersonationIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.account;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -116,7 +115,7 @@
assertThat(psa.getRealAccountId()).isEqualTo(admin.id);
ChangeData cd = r.getChange();
- ChangeMessage m = Iterables.getLast(cmUtil.byChange(db, cd.notes()));
+ ChangeMessage m = Iterables.getLast(cmUtil.byChange(cd.notes()));
assertThat(m.getMessage()).endsWith(in.message);
assertThat(m.getAuthor()).isEqualTo(user.id);
assertThat(m.getRealAuthor()).isEqualTo(admin.id);
@@ -191,7 +190,6 @@
@Test
public void voteOnBehalfOfWithCommentWritingJson() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
testVoteOnBehalfOfWithComment();
}
@@ -218,7 +216,7 @@
assertThat(psa.getRealAccountId()).isEqualTo(admin.id);
ChangeData cd = r.getChange();
- Comment c = Iterables.getOnlyElement(commentsUtil.publishedByChange(db, cd.notes()));
+ Comment c = Iterables.getOnlyElement(commentsUtil.publishedByChange(cd.notes()));
assertThat(c.message).isEqualTo(ci.message);
assertThat(c.author.getId()).isEqualTo(user.id);
assertThat(c.getRealAuthor().getId()).isEqualTo(admin.id);
@@ -226,7 +224,6 @@
@Test
public void voteOnBehalfOfWithRobotComment() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
allowCodeReviewOnBehalfOf();
PushOneCommit.Result r = createChange();
@@ -342,7 +339,7 @@
ChangeData cd = r.getChange();
assertThat(cd.change().getStatus()).isEqualTo(Change.Status.MERGED);
PatchSetApproval submitter =
- approvalsUtil.getSubmitter(db, cd.notes(), cd.change().currentPatchSetId());
+ approvalsUtil.getSubmitter(cd.notes(), cd.change().currentPatchSetId());
assertThat(submitter.getAccountId()).isEqualTo(admin2.id);
assertThat(submitter.getRealAccountId()).isEqualTo(admin.id);
}
@@ -520,7 +517,7 @@
assertThat(psa.getRealAccountId()).isEqualTo(admin.id); // not user2
ChangeData cd = r.getChange();
- ChangeMessage m = Iterables.getLast(cmUtil.byChange(db, cd.notes()));
+ ChangeMessage m = Iterables.getLast(cmUtil.byChange(cd.notes()));
assertThat(m.getMessage()).endsWith(in.message);
assertThat(m.getAuthor()).isEqualTo(user.id);
assertThat(m.getRealAuthor()).isEqualTo(admin.id); // not user2
diff --git a/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
index 628b63f..db5dfab 100644
--- a/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/binding/ChangesRestApiBindingsIT.java
@@ -14,7 +14,6 @@
package com.google.gerrit.acceptance.rest.binding;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.rest.util.RestCall.Method.GET;
import static com.google.gerrit.extensions.common.testing.RobotCommentInfoSubject.assertThatList;
import static java.util.stream.Collectors.toList;
@@ -113,14 +112,6 @@
RestCall.delete("/changes/%s"));
/**
- * Change REST endpoints to be tested with NoteDb, each URL contains a placeholder for the change
- * identifier.
- */
- private static final ImmutableList<RestCall> CHANGE_ENDPOINTS_NOTEDB =
- ImmutableList.of(
- RestCall.post("/changes/%s/hashtags"), RestCall.post("/changes/%s/rebuild.notedb"));
-
- /**
* Reviewer REST endpoints to be tested, each URL contains placeholders for the change identifier
* and the reviewer identifier.
*/
@@ -285,14 +276,6 @@
}
@Test
- public void changeEndpointsNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
- String changeId = createChange().getChangeId();
- RestApiCallHelper.execute(adminRestSession, CHANGE_ENDPOINTS_NOTEDB, changeId);
- }
-
- @Test
public void reviewerEndpoints() throws Exception {
String changeId = createChange().getChangeId();
@@ -394,8 +377,6 @@
@Test
public void robotCommentEndpoints() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
String changeId = createChange().getChangeId();
RobotCommentInput robotCommentInput = new RobotCommentInput();
@@ -421,8 +402,6 @@
@Test
public void fixEndpoints() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
String changeId = createChange("Subject", FILENAME, "content").getChangeId();
RobotCommentInput robotCommentInput = new RobotCommentInput();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index bab4c1d..095bd96 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -905,8 +905,6 @@
@Test
public void retrySubmitSingleChangeOnLockFailure() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
-
PushOneCommit.Result change = createChange();
String id = change.getChangeId();
approve(id);
@@ -932,7 +930,6 @@
@Test
public void retrySubmitAfterTornTopicOnLockFailure() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
assume().that(isSubmitWholeTopicEnabled()).isTrue();
String topic = "test-topic";
@@ -1281,7 +1278,7 @@
Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
ChangeNotes cn = notesFactory.createChecked(db, c);
PatchSetApproval submitter =
- approvalsUtil.getSubmitter(db, cn, new PatchSet.Id(cn.getChangeId(), psId));
+ approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNotNull();
assertThat(submitter.isLegacySubmit()).isTrue();
assertThat(submitter.getAccountId()).isEqualTo(user.getId());
@@ -1291,7 +1288,7 @@
Change c = getOnlyElement(queryProvider.get().byKeyPrefix(changeId)).change();
ChangeNotes cn = notesFactory.createChecked(db, c);
PatchSetApproval submitter =
- approvalsUtil.getSubmitter(db, cn, new PatchSet.Id(cn.getChangeId(), psId));
+ approvalsUtil.getSubmitter(cn, new PatchSet.Id(cn.getChangeId(), psId));
assertThat(submitter).isNull();
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
index 29a81ca..fecb6c5 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
@@ -17,21 +17,10 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.TruthJUnit.assume;
-import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestProjectInput;
-import com.google.gerrit.extensions.api.changes.SubmitInput;
-import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.InheritableBoolean;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.change.TestSubmitInput;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Test;
public abstract class AbstractSubmitByMerge extends AbstractSubmit {
@@ -124,58 +113,4 @@
assertThat(head.getParent(0)).isEqualTo(change1.getCommit());
assertThat(head.getParent(1)).isEqualTo(change2.getCommit());
}
-
- @Test
- public void repairChangeStateAfterFailure() throws Exception {
- // In NoteDb-only mode, repo and meta updates are atomic (at least in InMemoryRepository).
- assume().that(notesMigration.disableChangeReviewDb()).isFalse();
-
- RevCommit initialHead = getRemoteHead();
- PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
- submit(change.getChangeId());
- RevCommit afterChange1Head = getRemoteHead();
-
- testRepo.reset(initialHead);
- PushOneCommit.Result change2 = createChange("Change 2", "b.txt", "other content");
- Change.Id id2 = change2.getChange().getId();
- TestSubmitInput failInput = new TestSubmitInput();
- failInput.failAfterRefUpdates = true;
- submit(
- change2.getChangeId(),
- failInput,
- ResourceConflictException.class,
- "Failing after ref updates");
-
- // Bad: ref advanced but change wasn't updated.
- PatchSet.Id psId1 = new PatchSet.Id(id2, 1);
- ChangeInfo info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.NEW);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
-
- RevCommit tip;
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
- ObjectId rev1 = repo.exactRef(psId1.toRefName()).getObjectId();
- assertThat(rev1).isNotNull();
-
- tip = rw.parseCommit(repo.exactRef("refs/heads/master").getObjectId());
- assertThat(tip.getParentCount()).isEqualTo(2);
- assertThat(tip.getParent(0)).isEqualTo(afterChange1Head);
- assertThat(tip.getParent(1)).isEqualTo(change2.getCommit());
- }
-
- submit(change2.getChangeId(), new SubmitInput(), null, null);
-
- // Change status and patch set entities were updated, and branch tip stayed
- // the same.
- info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.MERGED);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
- assertThat(Iterables.getLast(info.messages).message)
- .isEqualTo("Change has been successfully merged by Administrator");
-
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(tip);
- }
- }
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
index 0a92cfb..e8e896d 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AbstractSubmitByRebase.java
@@ -15,13 +15,11 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.getChangeId;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.TestAccount;
import com.google.gerrit.acceptance.TestProjectInput;
@@ -30,12 +28,8 @@
import com.google.gerrit.extensions.client.InheritableBoolean;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.server.change.TestSubmitInput;
import com.google.gerrit.server.project.testing.Util;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Repository;
@@ -242,80 +236,6 @@
assertChangeMergedEvents(change.getChangeId(), headAfterFirstSubmit.name());
}
- @Test
- public void repairChangeStateAfterFailure() throws Exception {
- // In NoteDb-only mode, repo and meta updates are atomic (at least in InMemoryRepository).
- assume().that(notesMigration.disableChangeReviewDb()).isFalse();
-
- RevCommit initialHead = getRemoteHead();
- PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
- submit(change.getChangeId());
-
- RevCommit headAfterFirstSubmit = getRemoteHead();
- testRepo.reset(initialHead);
- PushOneCommit.Result change2 = createChange("Change 2", "b.txt", "other content");
- Change.Id id2 = change2.getChange().getId();
- TestSubmitInput failInput = new TestSubmitInput();
- failInput.failAfterRefUpdates = true;
- submit(
- change2.getChangeId(),
- failInput,
- ResourceConflictException.class,
- "Failing after ref updates");
- RevCommit headAfterFailedSubmit = getRemoteHead();
-
- // Bad: ref advanced but change wasn't updated.
- PatchSet.Id psId1 = new PatchSet.Id(id2, 1);
- PatchSet.Id psId2 = new PatchSet.Id(id2, 2);
- ChangeInfo info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.NEW);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
- assertThat(getPatchSet(psId2)).isNull();
-
- ObjectId rev2;
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
- ObjectId rev1 = repo.exactRef(psId1.toRefName()).getObjectId();
- assertThat(rev1).isNotNull();
-
- rev2 = repo.exactRef(psId2.toRefName()).getObjectId();
- assertThat(rev2).isNotNull();
- assertThat(rev2).isNotEqualTo(rev1);
- assertThat(rw.parseCommit(rev2).getParent(0)).isEqualTo(headAfterFirstSubmit);
-
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev2);
- }
-
- submit(change2.getChangeId());
- RevCommit headAfterSecondSubmit = getRemoteHead();
- assertThat(headAfterSecondSubmit).isEqualTo(headAfterFailedSubmit);
-
- // Change status and patch set entities were updated, and branch tip stayed
- // the same.
- info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.MERGED);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(2);
- PatchSet ps2 = getPatchSet(psId2);
- assertThat(ps2).isNotNull();
- assertThat(ps2.getRevision().get()).isEqualTo(rev2.name());
- assertThat(Iterables.getLast(info.messages).message)
- .isEqualTo(
- "Change has been successfully rebased and submitted as "
- + rev2.name()
- + " by Administrator");
-
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev2);
- }
-
- assertRefUpdatedEvents(initialHead, headAfterFirstSubmit);
- assertChangeMergedEvents(
- change.getChangeId(),
- headAfterFirstSubmit.name(),
- change2.getChangeId(),
- headAfterSecondSubmit.name());
- }
-
protected RevCommit parse(ObjectId id) throws Exception {
try (Repository repo = repoManager.openRepository(project);
RevWalk rw = new RevWalk(repo)) {
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/AssigneeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/AssigneeIT.java
index 69035f2..c925d88 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/AssigneeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/AssigneeIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -79,7 +78,6 @@
@Test
public void getPastAssignees() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
setAssignee(r, user.email);
setAssignee(r, admin.email);
@@ -92,14 +90,7 @@
@Test
public void assigneeAddedAsReviewer() throws Exception {
- ReviewerState state;
- // Assignee is added as CC, if back-end is reviewDb (that does not support
- // CC) CC is stored as REVIEWER
- if (notesMigration.readChanges()) {
- state = ReviewerState.CC;
- } else {
- state = ReviewerState.REVIEWER;
- }
+ ReviewerState state = ReviewerState.CC;
PushOneCommit.Result r = createChange();
Iterable<AccountInfo> reviewers = getReviewers(r, state);
assertThat(reviewers).isNull();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java
index 790b884..48cb050 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeMessagesIT.java
@@ -251,10 +251,7 @@
List<ChangeMessageInfo> messagesBeforeDeletion = gApi.changes().id(changeNum).messages();
List<CommentInfo> commentsBefore = getChangeSortedComments(changeNum);
- List<RevCommit> commitsBefore = new ArrayList<>();
- if (notesMigration.readChanges()) {
- commitsBefore = getChangeMetaCommitsInReverseOrder(new Change.Id(changeNum));
- }
+ List<RevCommit> commitsBefore = getChangeMetaCommitsInReverseOrder(new Change.Id(changeNum));
String id = messagesBeforeDeletion.get(deletedMessageIndex).id;
DeleteChangeMessageInput input = new DeleteChangeMessageInput(reason);
@@ -271,11 +268,9 @@
List<ChangeInfo> changes = gApi.changes().query("message removed").get();
assertThat(changes.stream().map(c -> c._number).collect(toSet())).contains(changeNum);
- // Verifies states of commits if NoteDb is on.
- if (notesMigration.readChanges()) {
- assertMetaCommitsAfterDeletion(
- commitsBefore, changeNum, deletedMessageIndex, deletedBy, reason);
- }
+ // Verifies states of commits.
+ assertMetaCommitsAfterDeletion(
+ commitsBefore, changeNum, deletedMessageIndex, deletedBy, reason);
}
private void assertMessagesAfterDeletion(
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
index dc71c1f..2a397e4 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersByEmailIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import com.google.common.collect.ImmutableList;
@@ -52,7 +51,6 @@
@Test
public void addByEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -72,7 +70,6 @@
@Test
public void addByEmailAndById() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo byEmail = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
AccountInfo byId = new AccountInfo(user.id.get());
@@ -98,7 +95,6 @@
@Test
public void listReviewersByEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -126,7 +122,6 @@
@Test
public void removeByEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -146,7 +141,6 @@
@Test
public void convertFromCCToReviewer() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
PushOneCommit.Result r = createChange();
@@ -168,7 +162,6 @@
@Test
public void addedReviewersGetNotified() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -188,7 +181,6 @@
@Test
public void removingReviewerTriggersNotification() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -221,7 +213,6 @@
@Test
public void reviewerAndCCReceiveRegularNotification() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -244,8 +235,6 @@
@Test
public void reviewerAndCCReceiveSameEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
PushOneCommit.Result r = createChange();
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
for (int i = 0; i < 10; i++) {
@@ -270,8 +259,6 @@
@Test
public void addingMultipleReviewersAndCCsAtOnceSendsOnlyOneEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
PushOneCommit.Result r = createChange();
ReviewInput reviewInput = new ReviewInput();
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -288,7 +275,6 @@
@Test
public void rejectMissingEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerResult result = gApi.changes().id(r.getChangeId()).addReviewer("");
@@ -298,7 +284,6 @@
@Test
public void rejectMalformedEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerResult result = gApi.changes().id(r.getChangeId()).addReviewer("Foo Bar <foo.bar@");
@@ -308,8 +293,6 @@
@Test
public void rejectWhenFeatureIsDisabled() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
ConfigInput conf = new ConfigInput();
conf.enableReviewerByEmail = InheritableBoolean.FALSE;
gApi.projects().name(project.get()).config(conf);
@@ -326,7 +309,6 @@
@Test
public void reviewersByEmailAreServedFromIndex() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
AccountInfo acc = new AccountInfo("Foo Bar", "foo.bar@gerritcodereview.com");
for (ReviewerState state : ImmutableList.of(ReviewerState.CC, ReviewerState.REVIEWER)) {
@@ -351,7 +333,6 @@
@Test
public void addExistingReviewerByEmailShortCircuits() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerInput input = new AddReviewerInput();
@@ -369,7 +350,6 @@
@Test
public void addExistingCcByEmailShortCircuits() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerInput input = new AddReviewerInput();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
index 6a9a27c..069607a 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/ChangeReviewersIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.DETAILED_LABELS;
import static com.google.gerrit.extensions.client.ReviewerState.CC;
import static com.google.gerrit.extensions.client.ReviewerState.REMOVED;
@@ -134,31 +133,18 @@
assertThat(result.confirm).isNull();
assertThat(result.error).isNull();
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertThat(result.reviewers).isNull();
- assertThat(result.ccs).hasSize(1);
- AccountInfo ai = result.ccs.get(0);
- assertThat(ai._accountId).isEqualTo(user.id.get());
- assertReviewers(c, CC, user);
- } else {
- assertThat(result.ccs).isNull();
- assertThat(result.reviewers).hasSize(1);
- AccountInfo ai = result.reviewers.get(0);
- assertThat(ai._accountId).isEqualTo(user.id.get());
- assertReviewers(c, REVIEWER, user);
- }
+ assertThat(result.reviewers).isNull();
+ assertThat(result.ccs).hasSize(1);
+ AccountInfo ai = result.ccs.get(0);
+ assertThat(ai._accountId).isEqualTo(user.id.get());
+ assertReviewers(c, CC, user);
// Verify email was sent to CCed account.
List<Message> messages = sender.getMessages();
assertThat(messages).hasSize(1);
Message m = messages.get(0);
assertThat(m.rcpt()).containsExactly(user.emailAddress);
- if (notesMigration.readChanges()) {
- assertThat(m.body()).contains(admin.fullName + " has uploaded this change for review.");
- } else {
- assertThat(m.body()).contains("Hello " + user.fullName + ",\n");
- assertThat(m.body()).contains("I'd like you to do a code review.");
- }
+ assertThat(m.body()).contains(admin.fullName + " has uploaded this change for review.");
}
@Test
@@ -185,18 +171,9 @@
assertThat(result.input).isEqualTo(in.reviewer);
assertThat(result.confirm).isNull();
assertThat(result.error).isNull();
- if (notesMigration.readChanges()) {
- assertThat(result.reviewers).isNull();
- } else {
- assertThat(result.ccs).isNull();
- }
+ assertThat(result.reviewers).isNull();
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertReviewers(c, CC, firstUsers);
- } else {
- assertReviewers(c, REVIEWER, firstUsers);
- assertReviewers(c, CC);
- }
+ assertReviewers(c, CC, firstUsers);
// Verify emails were sent to each of the group's accounts.
List<Message> messages = sender.getMessages();
@@ -222,19 +199,10 @@
assertThat(result.confirm).isNull();
assertThat(result.error).isNull();
c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertThat(result.ccs).hasSize(3);
- assertThat(result.reviewers).isNull();
- assertReviewers(c, REVIEWER, reviewer);
- assertReviewers(c, CC, users);
- } else {
- assertThat(result.ccs).isNull();
- assertThat(result.reviewers).hasSize(3);
- List<TestAccount> expectedUsers = new ArrayList<>(users.size() + 2);
- expectedUsers.addAll(users);
- expectedUsers.add(reviewer);
- assertReviewers(c, REVIEWER, expectedUsers);
- }
+ assertThat(result.ccs).hasSize(3);
+ assertThat(result.reviewers).isNull();
+ assertReviewers(c, REVIEWER, reviewer);
+ assertReviewers(c, CC, users);
messages = sender.getMessages();
assertThat(messages).hasSize(1);
@@ -243,11 +211,6 @@
for (int i = 0; i < 3; i++) {
expectedAddresses.add(users.get(users.size() - i - 1).emailAddress);
}
- if (!notesMigration.readChanges()) {
- for (int i = 0; i < 3; i++) {
- expectedAddresses.add(users.get(i).emailAddress);
- }
- }
expectedAddresses.add(reviewer.emailAddress);
assertThat(m.rcpt()).containsExactlyElementsIn(expectedAddresses);
}
@@ -261,13 +224,8 @@
in.state = CC;
addReviewer(changeId, in);
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertReviewers(c, REVIEWER);
- assertReviewers(c, CC, user);
- } else {
- assertReviewers(c, REVIEWER, user);
- assertReviewers(c, CC);
- }
+ assertReviewers(c, REVIEWER);
+ assertReviewers(c, CC, user);
in.state = REVIEWER;
addReviewer(changeId, in);
@@ -293,15 +251,8 @@
// Verify user is added to CC list.
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertReviewers(c, REVIEWER);
- assertReviewers(c, CC, user);
- } else {
- // If we aren't reading from NoteDb, the user will appear as a
- // reviewer.
- assertReviewers(c, REVIEWER, user);
- assertReviewers(c, CC);
- }
+ assertReviewers(c, REVIEWER);
+ assertReviewers(c, CC, user);
}
@Test
@@ -350,26 +301,13 @@
// Verify reviewer state.
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertReviewers(c, REVIEWER);
- assertReviewers(c, CC, user);
- // Verify no approvals were added.
- assertThat(c.labels).isNotNull();
- LabelInfo label = c.labels.get("Code-Review");
- assertThat(label).isNotNull();
- assertThat(label.all).isNull();
- } else {
- // When approvals are stored in ReviewDb, we still create a label for
- // the reviewing user, and force them into the REVIEWER state.
- assertReviewers(c, REVIEWER, user);
- assertReviewers(c, CC);
- LabelInfo label = c.labels.get("Code-Review");
- assertThat(label).isNotNull();
- assertThat(label.all).isNotNull();
- assertThat(label.all).hasSize(1);
- ApprovalInfo approval = label.all.get(0);
- assertThat(approval._accountId).isEqualTo(user.getId().get());
- }
+ assertReviewers(c, REVIEWER);
+ assertReviewers(c, CC, user);
+ // Verify no approvals were added.
+ assertThat(c.labels).isNotNull();
+ LabelInfo label = c.labels.get("Code-Review");
+ assertThat(label).isNotNull();
+ assertThat(label.all).isNull();
}
@Test
@@ -449,14 +387,8 @@
// Verify reviewer and CC were added. If not in NoteDb read mode, both
// parties will be returned as CCed.
ChangeInfo c = gApi.changes().id(r.getChangeId()).get();
- if (notesMigration.readChanges()) {
- assertReviewers(c, REVIEWER, admin, user);
- assertReviewers(c, CC, observer);
- } else {
- // In legacy mode, everyone should be a reviewer.
- assertReviewers(c, REVIEWER, admin, user, observer);
- assertReviewers(c, CC);
- }
+ assertReviewers(c, REVIEWER, admin, user);
+ assertReviewers(c, CC, observer);
// Verify emails were sent to added reviewers.
List<Message> messages = sender.getMessages();
@@ -549,23 +481,12 @@
c = gApi.changes().id(r.getChangeId()).get();
assertThat(c.messages).hasSize(2);
- if (notesMigration.readChanges()) {
- assertReviewers(c, REVIEWER, admin, user);
- assertReviewers(c, CC, users.subList(0, mediumGroupSize));
- } else {
- // If not in NoteDb mode, then everyone is a REVIEWER.
- List<TestAccount> expected = users.subList(0, mediumGroupSize);
- expected.add(admin);
- expected.add(user);
- assertReviewers(c, REVIEWER, expected);
- assertReviewers(c, CC);
- }
+ assertReviewers(c, REVIEWER, admin, user);
+ assertReviewers(c, CC, users.subList(0, mediumGroupSize));
}
@Test
public void noteDbAddReviewerToReviewerChangeInfo() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
PushOneCommit.Result r = createChange();
String changeId = r.getChangeId();
AddReviewerInput in = new AddReviewerInput();
@@ -645,9 +566,6 @@
assertThat(reviewerResult.reviewers).hasSize(1);
// Repeat the above for CCs
- if (!notesMigration.readChanges()) {
- return;
- }
r = createChange();
input = ReviewInput.approve().reviewer(group1, CC, false).reviewer(group2, CC, false);
result = review(r.getChangeId(), r.getCommit().name(), input);
@@ -792,7 +710,6 @@
@Test
public void addExistingReviewerShortCircuits() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerInput input = new AddReviewerInput();
@@ -809,7 +726,6 @@
@Test
public void addExistingCcShortCircuits() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result r = createChange();
AddReviewerInput input = new AddReviewerInput();
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
index 9218336..28252e5 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/CreateChangeIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.common.data.Permission.READ;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -276,8 +275,6 @@
@Test
public void noteDbCommit() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
ChangeInfo c = assertCreateSucceeds(newChangeInput(ChangeStatus.NEW));
try (Repository repo = repoManager.openRepository(project);
RevWalk rw = new RevWalk(repo)) {
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/HashtagsIT.java b/javatests/com/google/gerrit/acceptance/rest/change/HashtagsIT.java
index 864f08d..47ec0d2 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/HashtagsIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/HashtagsIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
import static java.util.Objects.requireNonNull;
import static java.util.concurrent.TimeUnit.SECONDS;
@@ -33,17 +32,11 @@
import com.google.gerrit.extensions.restapi.BadRequestException;
import com.google.gerrit.testing.TestTimeUtil;
import org.junit.AfterClass;
-import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
@NoHttpd
public class HashtagsIT extends AbstractDaemonTest {
- @Before
- public void before() {
- assume().that(notesMigration.readChanges()).isTrue();
- }
-
@BeforeClass
public static void setTimeForTesting() {
TestTimeUtil.resetWithClockStep(1, SECONDS);
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java b/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
index 936feed..c2d3817 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/PrivateByDefaultIT.java
@@ -130,7 +130,7 @@
public void pushDraftsWithPrivateByDefaultAndDisablePrivateChangesTrue() throws Exception {
setPrivateByDefault(project2, InheritableBoolean.TRUE);
- RevCommit initialHead = getRemoteHead();
+ RevCommit initialHead = getRemoteHead(project2, "master");
TestRepository<InMemoryRepository> testRepo = cloneProject(project2);
PushOneCommit.Result result =
pushFactory.create(db, admin.getIdent(), testRepo).to("refs/for/master%draft");
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
index 8160d9a..8a81d6d 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.CURRENT_REVISION;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
@@ -31,19 +30,13 @@
import com.google.gerrit.extensions.common.ChangeInfo;
import com.google.gerrit.extensions.registration.DynamicSet;
import com.google.gerrit.extensions.registration.RegistrationHandle;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Branch;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.change.TestSubmitInput;
import com.google.gerrit.server.git.ChangeMessageModifier;
import com.google.gerrit.server.submit.CommitMergeStatus;
import com.google.inject.Inject;
import java.util.List;
import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.junit.Test;
public class SubmitByCherryPickIT extends AbstractSubmit {
@@ -389,76 +382,4 @@
change2.getChangeId(),
headAfterFirstSubmit.name());
}
-
- @Test
- public void repairChangeStateAfterFailure() throws Exception {
- // In NoteDb-only mode, repo and meta updates are atomic (at least in InMemoryRepository).
- assume().that(notesMigration.disableChangeReviewDb()).isFalse();
-
- RevCommit initialHead = getRemoteHead();
- PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
- submit(change.getChangeId());
-
- RevCommit headAfterFirstSubmit = getRemoteHead();
- testRepo.reset(initialHead);
- PushOneCommit.Result change2 = createChange("Change 2", "b.txt", "other content");
- Change.Id id2 = change2.getChange().getId();
- TestSubmitInput failInput = new TestSubmitInput();
- failInput.failAfterRefUpdates = true;
- submit(
- change2.getChangeId(),
- failInput,
- ResourceConflictException.class,
- "Failing after ref updates");
- RevCommit headAfterFailedSubmit = getRemoteHead();
-
- // Bad: ref advanced but change wasn't updated.
- PatchSet.Id psId1 = new PatchSet.Id(id2, 1);
- PatchSet.Id psId2 = new PatchSet.Id(id2, 2);
- ChangeInfo info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.NEW);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
- assertThat(getPatchSet(psId2)).isNull();
-
- ObjectId rev2;
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
- ObjectId rev1 = repo.exactRef(psId1.toRefName()).getObjectId();
- assertThat(rev1).isNotNull();
-
- rev2 = repo.exactRef(psId2.toRefName()).getObjectId();
- assertThat(rev2).isNotNull();
- assertThat(rev2).isNotEqualTo(rev1);
- assertThat(rw.parseCommit(rev2).getParent(0)).isEqualTo(headAfterFirstSubmit);
-
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev2);
- }
-
- submit(change2.getChangeId());
-
- // Change status and patch set entities were updated, and branch tip stayed
- // the same.
- RevCommit headAfterSecondSubmit = getRemoteHead();
- assertThat(headAfterSecondSubmit).isEqualTo(headAfterFailedSubmit);
- info = gApi.changes().id(id2.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.MERGED);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(2);
- PatchSet ps2 = getPatchSet(psId2);
- assertThat(ps2).isNotNull();
- assertThat(ps2.getRevision().get()).isEqualTo(rev2.name());
- assertThat(Iterables.getLast(info.messages).message)
- .isEqualTo(
- "Change has been successfully cherry-picked as " + rev2.name() + " by Administrator");
-
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev2);
- }
-
- assertRefUpdatedEvents(initialHead, headAfterFirstSubmit);
- assertChangeMergedEvents(
- change.getChangeId(),
- headAfterFirstSubmit.name(),
- change2.getChangeId(),
- headAfterSecondSubmit.name());
- }
}
diff --git a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
index ea8b98a..ccb684c 100644
--- a/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
+++ b/javatests/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
@@ -15,26 +15,16 @@
package com.google.gerrit.acceptance.rest.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.GitUtil.pushHead;
-import com.google.common.collect.Iterables;
import com.google.gerrit.acceptance.GitUtil;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.extensions.client.ChangeStatus;
import com.google.gerrit.extensions.client.SubmitType;
import com.google.gerrit.extensions.common.ActionInfo;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.restapi.ResourceConflictException;
import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.change.TestSubmitInput;
import java.util.Map;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
import org.eclipse.jgit.transport.PushResult;
import org.junit.Test;
@@ -146,52 +136,6 @@
}
@Test
- public void repairChangeStateAfterFailure() throws Exception {
- // In NoteDb-only mode, repo and meta updates are atomic (at least in InMemoryRepository).
- assume().that(notesMigration.disableChangeReviewDb()).isFalse();
-
- PushOneCommit.Result change = createChange("Change 1", "a.txt", "content");
- Change.Id id = change.getChange().getId();
- TestSubmitInput failInput = new TestSubmitInput();
- failInput.failAfterRefUpdates = true;
- submit(
- change.getChangeId(),
- failInput,
- ResourceConflictException.class,
- "Failing after ref updates");
-
- // Bad: ref advanced but change wasn't updated.
- PatchSet.Id psId = new PatchSet.Id(id, 1);
- ChangeInfo info = gApi.changes().id(id.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.NEW);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
-
- ObjectId rev;
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
- rev = repo.exactRef(psId.toRefName()).getObjectId();
- assertThat(rev).isNotNull();
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev);
- }
-
- submit(change.getChangeId());
-
- // Change status was updated, and branch tip stayed the same.
- info = gApi.changes().id(id.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.MERGED);
- assertThat(info.revisions.get(info.currentRevision)._number).isEqualTo(1);
- assertThat(Iterables.getLast(info.messages).message)
- .isEqualTo("Change has been successfully merged by Administrator");
-
- try (Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(rev);
- }
-
- assertRefUpdatedEvents();
- assertChangeMergedEvents(change.getChangeId(), getRemoteHead().name());
- }
-
- @Test
public void submitSameCommitsAsInExperimentalBranch() throws Exception {
RevCommit initialHead = getRemoteHead();
diff --git a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
index 0d40a1c..a352baa 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/CommentsIT.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.acceptance.PushOneCommit.FILE_NAME;
import static com.google.gerrit.acceptance.PushOneCommit.SUBJECT;
import static java.util.stream.Collectors.groupingBy;
@@ -946,7 +945,6 @@
@Test
public void jsonCommentHasLegacyFormatFalse() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
PushOneCommit.Result result = createChange();
Change.Id changeId = result.getChange().getId();
addComment(result.getChangeId(), "comment");
diff --git a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
index 2af90a8..e377a86 100644
--- a/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/change/ConsistencyCheckerIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.server.change;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.common.ProblemInfo.Status.FIXED;
import static com.google.gerrit.extensions.common.ProblemInfo.Status.FIX_FAILED;
import static com.google.gerrit.testing.TestChanges.newPatchSet;
@@ -35,7 +34,6 @@
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
@@ -52,8 +50,6 @@
import com.google.gerrit.server.update.ChangeContext;
import com.google.gerrit.server.update.RepoContext;
import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.NoteDbMode;
import com.google.gerrit.testing.TestChanges;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
@@ -97,11 +93,6 @@
private ConsistencyChecker checker;
private TestRepository<InMemoryRepository> serverSideTestRepo;
- private void assumeNoteDbDisabled() {
- assume().that(notesMigration.readChanges()).isFalse();
- assume().that(NoteDbMode.get()).isNotEqualTo(NoteDbMode.CHECK);
- }
-
@Before
public void setUp() throws Exception {
serverSideTestRepo =
@@ -134,38 +125,6 @@
assertProblems(notes, null, problem("Missing change owner: " + owner.getId()));
}
- @Test
- public void missingRepo() throws Exception {
- // NoteDb can't have a change without a repo.
- assumeNoteDbDisabled();
-
- ChangeNotes notes = insertChange();
- Project.NameKey name = notes.getProjectName();
- ((InMemoryRepositoryManager) repoManager).deleteRepository(name);
- assertThat(checker.check(notes, null).problems())
- .containsExactly(problem("Destination repository not found: " + name));
- }
-
- @Test
- public void invalidRevision() throws Exception {
- // NoteDb always parses the revision when inserting a patch set, so we can't
- // create an invalid patch set.
- assumeNoteDbDisabled();
-
- ChangeNotes notes = insertChange();
- PatchSet ps =
- newPatchSet(
- notes.getChange().currentPatchSetId(),
- "fooooooooooooooooooooooooooooooooooooooo",
- adminId);
- db.patchSets().update(singleton(ps));
-
- assertProblems(
- notes,
- null,
- problem("Invalid revision on patch set 1: fooooooooooooooooooooooooooooooooooooooo"));
- }
-
// No test for ref existing but object missing; InMemoryRepository won't let
// us do such a thing.
@@ -282,17 +241,10 @@
public void onlyPatchSetObjectMissingWithFix() throws Exception {
Change c = TestChanges.newChange(project, admin.getId(), sequences.nextChangeId());
- // Set review started, mimicking Schema_153, so tests pass with NoteDbMode.CHECK.
- c.setReviewStarted(true);
-
PatchSet.Id psId = c.currentPatchSetId();
String rev = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
PatchSet ps = newPatchSet(psId, rev, adminId);
- if (notesMigration.changePrimaryStorage() == PrimaryStorage.REVIEW_DB) {
- db.changes().insert(singleton(c));
- db.patchSets().insert(singleton(ps));
- }
addNoteDbCommit(
c.getId(),
"Create change\n"
@@ -331,16 +283,6 @@
}
@Test
- public void currentPatchSetMissing() throws Exception {
- // NoteDb can't create a change without a patch set.
- assumeNoteDbDisabled();
-
- ChangeNotes notes = insertChange();
- db.patchSets().deleteKeys(singleton(notes.getChange().currentPatchSetId()));
- assertProblems(notes, null, problem("Current patch set 1 not found"));
- }
-
- @Test
public void duplicatePatchSetRevisions() throws Exception {
ChangeNotes notes = insertChange();
PatchSet ps1 = psUtil.current(db, notes);
diff --git a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
index 209d0a2..35d9e88 100644
--- a/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/mail/ChangeNotificationsIT.java
@@ -14,7 +14,6 @@
package com.google.gerrit.acceptance.server.mail;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.api.changes.NotifyHandling.ALL;
import static com.google.gerrit.extensions.api.changes.NotifyHandling.NONE;
import static com.google.gerrit.extensions.api.changes.NotifyHandling.OWNER;
@@ -255,31 +254,7 @@
* AddReviewerSender tests.
*/
- private void addReviewerToReviewableChangeInReviewDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
- addReviewer(adder, sc.changeId, sc.owner, reviewer.email);
- assertThat(sender)
- .sent("newchange", sc)
- .to(reviewer)
- .cc(sc.reviewer, sc.ccer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .noOneElse();
- }
-
- @Test
- public void addReviewerToReviewableChangeInReviewDbSingly() throws Exception {
- addReviewerToReviewableChangeInReviewDb(singly());
- }
-
- @Test
- public void addReviewerToReviewableChangeInReviewDbBatch() throws Exception {
- addReviewerToReviewableChangeInReviewDb(batch());
- }
-
- private void addReviewerToReviewableChangeInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToReviewableChange(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email);
@@ -293,17 +268,16 @@
}
@Test
- public void addReviewerToReviewableChangeInNoteDbSingly() throws Exception {
- addReviewerToReviewableChangeInNoteDb(singly());
+ public void addReviewerToReviewableChangeSingly() throws Exception {
+ addReviewerToReviewableChange(singly());
}
@Test
- public void addReviewerToReviewableChangeInNoteDbBatch() throws Exception {
- addReviewerToReviewableChangeInNoteDb(batch());
+ public void addReviewerToReviewableChangeBatch() throws Exception {
+ addReviewerToReviewableChange(batch());
}
- private void addReviewerToReviewableChangeByOwnerCcingSelfInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToReviewableChangeByOwnerCcingSelf(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email, CC_ON_OWN_COMMENTS, null);
@@ -317,17 +291,16 @@
}
@Test
- public void addReviewerToReviewableChangeByOwnerCcingSelfInNoteDbSingly() throws Exception {
- addReviewerToReviewableChangeByOwnerCcingSelfInNoteDb(singly());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfSingly() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelf(singly());
}
@Test
- public void addReviewerToReviewableChangeByOwnerCcingSelfInNoteDbBatch() throws Exception {
- addReviewerToReviewableChangeByOwnerCcingSelfInNoteDb(batch());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfBatch() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelf(batch());
}
- private void addReviewerToReviewableChangeByOtherInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToReviewableChangeByOther(Adder adder) throws Exception {
TestAccount other = accountCreator.create("other", "other@example.com", "other");
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
@@ -342,17 +315,16 @@
}
@Test
- public void addReviewerToReviewableChangeByOtherInNoteDbSingly() throws Exception {
- addReviewerToReviewableChangeByOtherInNoteDb(singly());
+ public void addReviewerToReviewableChangeByOtherSingly() throws Exception {
+ addReviewerToReviewableChangeByOther(singly());
}
@Test
- public void addReviewerToReviewableChangeByOtherInNoteDbBatch() throws Exception {
- addReviewerToReviewableChangeByOtherInNoteDb(batch());
+ public void addReviewerToReviewableChangeByOtherBatch() throws Exception {
+ addReviewerToReviewableChangeByOther(batch());
}
- private void addReviewerToReviewableChangeByOtherCcingSelfInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToReviewableChangeByOtherCcingSelf(Adder adder) throws Exception {
TestAccount other = accountCreator.create("other", "other@example.com", "other");
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
@@ -367,35 +339,16 @@
}
@Test
- public void addReviewerToReviewableChangeByOtherCcingSelfInNoteDbSingly() throws Exception {
- addReviewerToReviewableChangeByOtherCcingSelfInNoteDb(singly());
+ public void addReviewerToReviewableChangeByOtherCcingSelfSingly() throws Exception {
+ addReviewerToReviewableChangeByOtherCcingSelf(singly());
}
@Test
- public void addReviewerToReviewableChangeByOtherCcingSelfInNoteDbBatch() throws Exception {
- addReviewerToReviewableChangeByOtherCcingSelfInNoteDb(batch());
+ public void addReviewerToReviewableChangeByOtherCcingSelfBatch() throws Exception {
+ addReviewerToReviewableChangeByOtherCcingSelf(batch());
}
- private void addReviewerByEmailToReviewableChangeInReviewDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- String email = "addedbyemail@example.com";
- StagedChange sc = stageReviewableChange();
- addReviewer(adder, sc.changeId, sc.owner, email);
- assertThat(sender).notSent();
- }
-
- @Test
- public void addReviewerByEmailToReviewableChangeInReviewDbSingly() throws Exception {
- addReviewerByEmailToReviewableChangeInReviewDb(singly());
- }
-
- @Test
- public void addReviewerByEmailToReviewableChangeInReviewDbBatch() throws Exception {
- addReviewerByEmailToReviewableChangeInReviewDb(batch());
- }
-
- private void addReviewerByEmailToReviewableChangeInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerByEmailToReviewableChange(Adder adder) throws Exception {
String email = "addedbyemail@example.com";
StagedChange sc = stageReviewableChange();
addReviewer(adder, sc.changeId, sc.owner, email);
@@ -409,13 +362,13 @@
}
@Test
- public void addReviewerByEmailToReviewableChangeInNoteDbSingly() throws Exception {
- addReviewerByEmailToReviewableChangeInNoteDb(singly());
+ public void addReviewerByEmailToReviewableChangeSingly() throws Exception {
+ addReviewerByEmailToReviewableChange(singly());
}
@Test
- public void addReviewerByEmailToReviewableChangeInNoteDbBatch() throws Exception {
- addReviewerByEmailToReviewableChangeInNoteDb(batch());
+ public void addReviewerByEmailToReviewableChangeBatch() throws Exception {
+ addReviewerByEmailToReviewableChange(batch());
}
private void addReviewerToWipChange(Adder adder) throws Exception {
@@ -452,8 +405,7 @@
addReviewerToReviewableWipChange(batch());
}
- private void addReviewerToWipChangeInNoteDbNotifyAll(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToWipChangeNotifyAll(Adder adder) throws Exception {
StagedChange sc = stageWipChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email, NotifyHandling.ALL);
@@ -467,41 +419,16 @@
}
@Test
- public void addReviewerToWipChangeInNoteDbNotifyAllSingly() throws Exception {
- addReviewerToWipChangeInNoteDbNotifyAll(singly());
+ public void addReviewerToWipChangeNotifyAllSingly() throws Exception {
+ addReviewerToWipChangeNotifyAll(singly());
}
@Test
- public void addReviewerToWipChangeInNoteDbNotifyAllBatch() throws Exception {
- addReviewerToWipChangeInNoteDbNotifyAll(batch());
+ public void addReviewerToWipChangeNotifyAllBatch() throws Exception {
+ addReviewerToWipChangeNotifyAll(batch());
}
- private void addReviewerToWipChangeInReviewDbNotifyAll(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
- addReviewer(adder, sc.changeId, sc.owner, reviewer.email, NotifyHandling.ALL);
- assertThat(sender)
- .sent("newchange", sc)
- .to(reviewer)
- .cc(sc.reviewer, sc.ccer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .noOneElse();
- }
-
- @Test
- public void addReviewerToWipChangeInReviewDbNotifyAllSingly() throws Exception {
- addReviewerToWipChangeInReviewDbNotifyAll(singly());
- }
-
- @Test
- public void addReviewerToWipChangeInReviewDbNotifyAllBatch() throws Exception {
- addReviewerToWipChangeInReviewDbNotifyAll(batch());
- }
-
- private void addReviewerToReviewableChangeInNoteDbNotifyOwnerReviewers(Adder adder)
- throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addReviewerToReviewableChangeNotifyOwnerReviewers(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email, OWNER_REVIEWERS);
@@ -515,18 +442,17 @@
}
@Test
- public void addReviewerToReviewableChangeInNoteDbNotifyOwnerReviewersSingly() throws Exception {
- addReviewerToReviewableChangeInNoteDbNotifyOwnerReviewers(singly());
+ public void addReviewerToReviewableChangeNotifyOwnerReviewersSingly() throws Exception {
+ addReviewerToReviewableChangeNotifyOwnerReviewers(singly());
}
@Test
- public void addReviewerToReviewableChangeInNoteDbNotifyOwnerReviewersBatch() throws Exception {
- addReviewerToReviewableChangeInNoteDbNotifyOwnerReviewers(batch());
+ public void addReviewerToReviewableChangeNotifyOwnerReviewersBatch() throws Exception {
+ addReviewerToReviewableChangeNotifyOwnerReviewers(batch());
}
- private void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyOwner(Adder adder)
+ private void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(Adder adder)
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email, CC_ON_OWN_COMMENTS, OWNER);
@@ -534,20 +460,17 @@
}
@Test
- public void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyOwnerSingly()
- throws Exception {
- addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyOwner(singly());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwnerSingly() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(singly());
}
@Test
- public void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyOwnerBatch()
- throws Exception {
- addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyOwner(batch());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwnerBatch() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelfNotifyOwner(batch());
}
- private void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyNone(Adder adder)
+ private void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(Adder adder)
throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
StagedChange sc = stageReviewableChange();
TestAccount reviewer = accountCreator.create("added", "added@example.com", "added");
addReviewer(adder, sc.changeId, sc.owner, reviewer.email, CC_ON_OWN_COMMENTS, NONE);
@@ -555,19 +478,16 @@
}
@Test
- public void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyNoneSingly()
- throws Exception {
- addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyNone(singly());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNoneSingly() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(singly());
}
@Test
- public void addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyNoneBatch()
- throws Exception {
- addReviewerToReviewableChangeInNoteDbByOwnerCcingSelfNotifyNone(batch());
+ public void addReviewerToReviewableChangeByOwnerCcingSelfNotifyNoneBatch() throws Exception {
+ addReviewerToReviewableChangeByOwnerCcingSelfNotifyNone(batch());
}
- private void addNonUserReviewerByEmailInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addNonUserReviewerByEmail(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
addReviewer(adder, sc.changeId, sc.owner, "nonexistent@example.com");
assertThat(sender)
@@ -579,17 +499,16 @@
}
@Test
- public void addNonUserReviewerByEmailInNoteDbSingly() throws Exception {
- addNonUserReviewerByEmailInNoteDb(singly(ReviewerState.REVIEWER));
+ public void addNonUserReviewerByEmailSingly() throws Exception {
+ addNonUserReviewerByEmail(singly(ReviewerState.REVIEWER));
}
@Test
- public void addNonUserReviewerByEmailInNoteDbBatch() throws Exception {
- addNonUserReviewerByEmailInNoteDb(batch(ReviewerState.REVIEWER));
+ public void addNonUserReviewerByEmailBatch() throws Exception {
+ addNonUserReviewerByEmail(batch(ReviewerState.REVIEWER));
}
- private void addNonUserCcByEmailInNoteDb(Adder adder) throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ private void addNonUserCcByEmail(Adder adder) throws Exception {
StagedChange sc = stageReviewableChange();
addReviewer(adder, sc.changeId, sc.owner, "nonexistent@example.com");
assertThat(sender)
@@ -601,13 +520,13 @@
}
@Test
- public void addNonUserCcByEmailInNoteDbSingly() throws Exception {
- addNonUserCcByEmailInNoteDb(singly(ReviewerState.CC));
+ public void addNonUserCcByEmailSingly() throws Exception {
+ addNonUserCcByEmail(singly(ReviewerState.CC));
}
@Test
- public void addNonUserCcByEmailInNoteDbBatch() throws Exception {
- addNonUserCcByEmailInNoteDb(batch(ReviewerState.CC));
+ public void addNonUserCcByEmailBatch() throws Exception {
+ addNonUserCcByEmail(batch(ReviewerState.CC));
}
private interface Adder {
@@ -923,8 +842,7 @@
}
@Test
- public void addReviewerOnWipChangeAndStartReviewInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void addReviewerOnWipChangeAndStartReview() throws Exception {
StagedChange sc = stageWipChange();
ReviewInput in = ReviewInput.noScore().reviewer(other.email).setWorkInProgress(false);
gApi.changes().id(sc.changeId).revision("current").review(in);
@@ -946,28 +864,6 @@
}
@Test
- public void addReviewerOnWipChangeAndStartReviewInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- ReviewInput in = ReviewInput.noScore().reviewer(other.email).setWorkInProgress(false);
- gApi.changes().id(sc.changeId).revision("current").review(in);
- assertThat(sender)
- .sent("comment", sc)
- .cc(sc.reviewer, sc.ccer, other)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .bcc(sc.starrer)
- .bcc(ALL_COMMENTS)
- .noOneElse();
- assertThat(sender)
- .sent("newchange", sc)
- .to(other)
- .cc(sc.reviewer, sc.ccer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .noOneElse();
- assertThat(sender).notSent();
- }
-
- @Test
public void startReviewMessageNotRepeated() throws Exception {
// TODO(logan): Remove this test check once PolyGerrit workaround is rolled back.
StagedChange sc = stageWipChange();
@@ -1094,18 +990,12 @@
users -> ImmutableList.of("r=" + users.reviewer.username, "cc=" + users.ccer.username));
FakeEmailSenderSubject subject =
assertThat(sender).sent("newchange", spc).to(spc.reviewer, spc.watchingProjectOwner);
- if (notesMigration.readChanges()) {
- subject.cc(spc.ccer);
- } else {
- // CCs are considered reviewers in the storage layer.
- subject.to(spc.ccer);
- }
+ subject.cc(spc.ccer);
subject.bcc(NEW_CHANGES, NEW_PATCHSETS).noOneElse();
}
@Test
- public void createReviewableChangeWithReviewersAndCcsByEmailInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void createReviewableChangeWithReviewersAndCcsByEmail() throws Exception {
StagedPreChange spc =
stagePreChange(
"refs/for/master",
@@ -1290,8 +1180,7 @@
}
@Test
- public void deleteReviewerByEmailFromWipChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void deleteReviewerByEmailFromWipChange() throws Exception {
StagedChange sc = stageWipChangeWithExtraReviewer();
gApi.changes().id(sc.changeId).reviewer(sc.reviewerByEmail).remove();
assertThat(sender).notSent();
@@ -1650,8 +1539,7 @@
*/
@Test
- public void newPatchSetByOwnerOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetByOwnerOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master", sc.owner);
assertThat(sender)
@@ -1665,21 +1553,7 @@
}
@Test
- public void newPatchSetByOwnerOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- pushTo(sc, "refs/for/master", sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void newPatchSetByOtherOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetByOtherOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master", other);
assertThat(sender)
@@ -1694,22 +1568,7 @@
}
@Test
- public void newPatchSetByOtherOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- pushTo(sc, "refs/for/master", other);
- assertThat(sender)
- .sent("newpatchset", sc)
- .notTo(sc.owner) // TODO(logan): This email shouldn't come from the owner.
- .to(sc.reviewer, sc.ccer, other)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetByOtherOnReviewableChangeOwnerSelfCc() throws Exception {
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master", other, EmailStrategy.CC_ON_OWN_COMMENTS);
assertThat(sender)
@@ -1724,22 +1583,7 @@
}
@Test
- public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- pushTo(sc, "refs/for/master", other, EmailStrategy.CC_ON_OWN_COMMENTS);
- assertThat(sender)
- .sent("newpatchset", sc)
- .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner.
- .to(sc.reviewer, sc.ccer, other)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void newPatchSetByOtherOnReviewableChangeNotifyOwnerReviewersInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetByOtherOnReviewableChangeNotifyOwnerReviewers() throws Exception {
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other);
assertThat(sender)
@@ -1753,23 +1597,8 @@
}
@Test
- public void newPatchSetByOtherOnReviewableChangeNotifyOwnerReviewersInReviewDb()
+ public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewers()
throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other);
- assertThat(sender)
- .sent("newpatchset", sc)
- .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner.
- .to(sc.reviewer, sc.ccer)
- .to(other)
- .noOneElse();
- }
-
- @Test
- public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewersInNoteDb()
- throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other, EmailStrategy.CC_ON_OWN_COMMENTS);
assertThat(sender)
@@ -1783,20 +1612,6 @@
}
@Test
- public void newPatchSetByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewersInReviewDb()
- throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- pushTo(sc, "refs/for/master%notify=OWNER_REVIEWERS", other, EmailStrategy.CC_ON_OWN_COMMENTS);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .to(other)
- .notTo(sc.owner) // TODO(logan): This shouldn't be sent *from* the owner.
- .noOneElse();
- }
-
- @Test
public void newPatchSetByOtherOnReviewableChangeNotifyOwner() throws Exception {
StagedChange sc = stageReviewableChange();
pushTo(sc, "refs/for/master%notify=OWNER", other);
@@ -1843,8 +1658,7 @@
}
@Test
- public void newPatchSetOnWipChangeNotifyAllInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetOnWipChangeNotifyAll() throws Exception {
StagedChange sc = stageWipChange();
pushTo(sc, "refs/for/master%wip,notify=ALL", sc.owner);
assertThat(sender)
@@ -1858,21 +1672,7 @@
}
@Test
- public void newPatchSetOnWipChangeNotifyAllInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- pushTo(sc, "refs/for/master%wip,notify=ALL", sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void newPatchSetOnWipChangeToReadyInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetOnWipChangeToReady() throws Exception {
StagedChange sc = stageWipChange();
pushTo(sc, "refs/for/master%ready", sc.owner);
assertThat(sender)
@@ -1886,19 +1686,6 @@
}
@Test
- public void newPatchSetOnWipChangeToReadyInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- pushTo(sc, "refs/for/master%ready", sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
public void newPatchSetOnReviewableWipChange() throws Exception {
StagedChange sc = stageReviewableWipChange();
pushTo(sc, "refs/for/master%wip", sc.owner);
@@ -1906,8 +1693,7 @@
}
@Test
- public void newPatchSetOnReviewableChangeAddingReviewerInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetOnReviewableChangeAddingReviewer() throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount newReviewer = sc.testAccount("newReviewer");
pushTo(sc, "refs/for/master%r=" + newReviewer.username, sc.owner);
@@ -1923,22 +1709,6 @@
}
@Test
- public void newPatchSetOnReviewableChangeAddingReviewerInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- TestAccount newReviewer = sc.testAccount("newReviewer");
- pushTo(sc, "refs/for/master%r=" + newReviewer.username, sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer, newReviewer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- assertThat(sender).notSent();
- }
-
- @Test
public void newPatchSetOnWipChangeAddingReviewer() throws Exception {
StagedChange sc = stageWipChange();
TestAccount newReviewer = sc.testAccount("newReviewer");
@@ -1947,8 +1717,7 @@
}
@Test
- public void newPatchSetOnWipChangeAddingReviewerNotifyAllInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetOnWipChangeAddingReviewerNotifyAll() throws Exception {
StagedChange sc = stageWipChange();
TestAccount newReviewer = sc.testAccount("newReviewer");
pushTo(sc, "refs/for/master%notify=ALL,r=" + newReviewer.username, sc.owner);
@@ -1964,24 +1733,7 @@
}
@Test
- public void newPatchSetOnWipChangeAddingReviewerNotifyAllInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- TestAccount newReviewer = sc.testAccount("newReviewer");
- pushTo(sc, "refs/for/master%notify=ALL,r=" + newReviewer.username, sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer, newReviewer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- assertThat(sender).notSent();
- }
-
- @Test
- public void newPatchSetOnWipChangeSettingReadyInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void newPatchSetOnWipChangeSettingReady() throws Exception {
StagedChange sc = stageWipChange();
pushTo(sc, "refs/for/master%ready", sc.owner);
assertThat(sender)
@@ -1995,21 +1747,6 @@
assertThat(sender).notSent();
}
- @Test
- public void newPatchSetOnWipChangeSettingReadyInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- pushTo(sc, "refs/for/master%ready", sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .cc(sc.reviewerByEmail, sc.ccerByEmail)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- assertThat(sender).notSent();
- }
-
private void pushTo(StagedChange sc, String ref, TestAccount by) throws Exception {
pushTo(sc, ref, by, ENABLED);
}
@@ -2021,8 +1758,7 @@
}
@Test
- public void editCommitMessageEditByOwnerOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void editCommitMessageEditByOwnerOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, sc.owner);
assertThat(sender)
@@ -2036,21 +1772,7 @@
}
@Test
- public void editCommitMessageEditByOwnerOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- editCommitMessage(sc, sc.owner);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void editCommitMessageEditByOtherOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void editCommitMessageEditByOtherOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, other);
assertThat(sender)
@@ -2064,21 +1786,7 @@
}
@Test
- public void editCommitMessageEditByOtherOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- editCommitMessage(sc, other);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.owner, sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCc() throws Exception {
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, other, CC_ON_OWN_COMMENTS);
assertThat(sender)
@@ -2092,22 +1800,7 @@
}
@Test
- public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- editCommitMessage(sc, other, CC_ON_OWN_COMMENTS);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.owner, sc.reviewer, sc.ccer, other)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
- @Test
- public void editCommitMessageByOtherOnReviewableChangeNotifyOwnerReviewersInNoteDb()
- throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void editCommitMessageByOtherOnReviewableChangeNotifyOwnerReviewers() throws Exception {
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, other, OWNER_REVIEWERS);
assertThat(sender)
@@ -2119,18 +1812,8 @@
}
@Test
- public void editCommitMessageByOtherOnReviewableChangeNotifyOwnerReviewersInReviewDb()
+ public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewers()
throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- editCommitMessage(sc, other, OWNER_REVIEWERS);
- assertThat(sender).sent("newpatchset", sc).to(sc.owner, sc.reviewer, sc.ccer).noOneElse();
- }
-
- @Test
- public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewersInNoteDb()
- throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, other, OWNER_REVIEWERS, CC_ON_OWN_COMMENTS);
assertThat(sender)
@@ -2142,19 +1825,6 @@
}
@Test
- public void editCommitMessageByOtherOnReviewableChangeOwnerSelfCcNotifyOwnerReviewersInReviewDb()
- throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- editCommitMessage(sc, other, OWNER_REVIEWERS, CC_ON_OWN_COMMENTS);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.owner, sc.reviewer, sc.ccer)
- .cc(other)
- .noOneElse();
- }
-
- @Test
public void editCommitMessageByOtherOnReviewableChangeNotifyOwner() throws Exception {
StagedChange sc = stageReviewableChange();
editCommitMessage(sc, other, OWNER);
@@ -2204,8 +1874,7 @@
}
@Test
- public void editCommitMessageOnWipChangeNotifyAllInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void editCommitMessageOnWipChangeNotifyAll() throws Exception {
StagedChange sc = stageWipChange();
editCommitMessage(sc, sc.owner, ALL);
assertThat(sender)
@@ -2218,19 +1887,6 @@
.noOneElse();
}
- @Test
- public void editCommitMessageOnWipChangeNotifyAllInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageWipChange();
- editCommitMessage(sc, sc.owner, ALL);
- assertThat(sender)
- .sent("newpatchset", sc)
- .to(sc.reviewer, sc.ccer)
- .bcc(sc.starrer)
- .bcc(NEW_PATCHSETS)
- .noOneElse();
- }
-
private void editCommitMessage(StagedChange sc, TestAccount by) throws Exception {
editCommitMessage(sc, by, null, ENABLED);
}
@@ -2357,31 +2013,7 @@
*/
@Test
- public void revertChangeByOwnerInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageChange();
- revert(sc, sc.owner);
-
- // email for the newly created revert change
- assertThat(sender)
- .sent("newchange", sc)
- .to(sc.reviewer, sc.ccer, sc.watchingProjectOwner, admin)
- .bcc(NEW_CHANGES, NEW_PATCHSETS)
- .noOneElse();
-
- // email for the change that is reverted
- assertThat(sender)
- .sent("revert", sc)
- .cc(sc.reviewer, sc.ccer, admin)
- .cc(sc.reviewerByEmail)
- .bcc(sc.starrer)
- .bcc(ALL_COMMENTS)
- .noOneElse();
- }
-
- @Test
- public void revertChangeByOwnerInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void revertChangeByOwner() throws Exception {
StagedChange sc = stageChange();
revert(sc, sc.owner);
@@ -2404,33 +2036,7 @@
}
@Test
- public void revertChangeByOwnerCcingSelfInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageChange();
- revert(sc, sc.owner, CC_ON_OWN_COMMENTS);
-
- // email for the newly created revert change
- assertThat(sender)
- .sent("newchange", sc)
- .to(sc.reviewer, sc.ccer, sc.watchingProjectOwner, admin)
- .cc(sc.owner)
- .bcc(NEW_CHANGES, NEW_PATCHSETS)
- .noOneElse();
-
- // email for the change that is reverted
- assertThat(sender)
- .sent("revert", sc)
- .to(sc.owner)
- .cc(sc.reviewer, sc.ccer, admin)
- .cc(sc.reviewerByEmail)
- .bcc(sc.starrer)
- .bcc(ALL_COMMENTS)
- .noOneElse();
- }
-
- @Test
- public void revertChangeByOwnerCcingSelfInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void revertChangeByOwnerCcingSelf() throws Exception {
StagedChange sc = stageChange();
revert(sc, sc.owner, CC_ON_OWN_COMMENTS);
@@ -2454,32 +2060,7 @@
}
@Test
- public void revertChangeByOtherInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageChange();
- revert(sc, other);
-
- // email for the newly created revert change
- assertThat(sender)
- .sent("newchange", sc)
- .to(sc.owner, sc.reviewer, sc.ccer, sc.watchingProjectOwner, admin)
- .bcc(NEW_CHANGES, NEW_PATCHSETS)
- .noOneElse();
-
- // email for the change that is reverted
- assertThat(sender)
- .sent("revert", sc)
- .to(sc.owner)
- .cc(sc.reviewer, sc.ccer, admin)
- .cc(sc.reviewerByEmail)
- .bcc(sc.starrer)
- .bcc(ALL_COMMENTS)
- .noOneElse();
- }
-
- @Test
- public void revertChangeByOtherInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void revertChangeByOther() throws Exception {
StagedChange sc = stageChange();
revert(sc, other);
@@ -2503,33 +2084,7 @@
}
@Test
- public void revertChangeByOtherCcingSelfInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageChange();
- revert(sc, other, CC_ON_OWN_COMMENTS);
-
- // email for the newly created revert change
- assertThat(sender)
- .sent("newchange", sc)
- .to(sc.owner, sc.reviewer, sc.ccer, sc.watchingProjectOwner, admin)
- .cc(other)
- .bcc(NEW_CHANGES, NEW_PATCHSETS)
- .noOneElse();
-
- // email for the change that is reverted
- assertThat(sender)
- .sent("revert", sc)
- .to(sc.owner)
- .cc(other, sc.reviewer, sc.ccer, admin)
- .cc(sc.reviewerByEmail)
- .bcc(sc.starrer)
- .bcc(ALL_COMMENTS)
- .noOneElse();
- }
-
- @Test
- public void revertChangeByOtherCcingSelfInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void revertChangeByOtherCcingSelf() throws Exception {
StagedChange sc = stageChange();
revert(sc, other, CC_ON_OWN_COMMENTS);
@@ -2623,8 +2178,7 @@
}
@Test
- public void setAssigneeToSelfOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void setAssigneeToSelfOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
assign(sc, sc.owner, sc.owner);
assertThat(sender)
@@ -2634,14 +2188,6 @@
}
@Test
- public void setAssigneeToSelfOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- assign(sc, sc.owner, sc.owner);
- assertThat(sender).notSent();
- }
-
- @Test
public void changeAssigneeOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
TestAccount other = accountCreator.create("other", "other@example.com", "other");
@@ -2656,8 +2202,7 @@
}
@Test
- public void changeAssigneeToSelfOnReviewableChangeInNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void changeAssigneeToSelfOnReviewableChange() throws Exception {
StagedChange sc = stageReviewableChange();
assign(sc, sc.owner, sc.assignee);
sender.clear();
@@ -2669,16 +2214,6 @@
}
@Test
- public void changeAssigneeToSelfOnReviewableChangeInReviewDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- StagedChange sc = stageReviewableChange();
- assign(sc, sc.owner, sc.assignee);
- sender.clear();
- assign(sc, sc.owner, sc.owner);
- assertThat(sender).notSent();
- }
-
- @Test
public void setAssigneeOnReviewableWipChange() throws Exception {
StagedChange sc = stageReviewableWipChange();
assign(sc, sc.owner, sc.assignee);
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
deleted file mode 100644
index 29f1b7d..0000000
--- a/javatests/com/google/gerrit/acceptance/server/notedb/ChangeRebuilderIT.java
+++ /dev/null
@@ -1,1598 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assert_;
-import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
-import static com.google.gerrit.reviewdb.client.RefNames.refsDraftComments;
-import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.concurrent.TimeUnit.DAYS;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.stream.Collectors.joining;
-import static java.util.stream.Collectors.toList;
-import static org.eclipse.jgit.lib.Constants.OBJ_BLOB;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Ordering;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.AcceptanceTestRequestScope;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.acceptance.TestAccount;
-import com.google.gerrit.common.data.GlobalCapability;
-import com.google.gerrit.extensions.api.changes.DraftInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
-import com.google.gerrit.extensions.client.Side;
-import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.extensions.common.Input;
-import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.ChangeUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.change.RevisionResource;
-import com.google.gerrit.server.git.RepoRefCache;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbUpdateManager;
-import com.google.gerrit.server.notedb.TestChangeRebuilderWrapper;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilder.NoPatchSetsException;
-import com.google.gerrit.server.patch.PatchListCache;
-import com.google.gerrit.server.patch.PatchListNotAvailableException;
-import com.google.gerrit.server.patch.PatchSetInfoFactory;
-import com.google.gerrit.server.patch.PatchSetInfoNotAvailableException;
-import com.google.gerrit.server.project.testing.Util;
-import com.google.gerrit.server.query.change.ChangeData;
-import com.google.gerrit.server.restapi.change.PostReview;
-import com.google.gerrit.server.restapi.change.Rebuild;
-import com.google.gerrit.server.update.BatchUpdate;
-import com.google.gerrit.server.update.BatchUpdateOp;
-import com.google.gerrit.server.update.ChangeContext;
-import com.google.gerrit.server.update.UpdateException;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.ConfigSuite;
-import com.google.gerrit.testing.NoteDbChecker;
-import com.google.gerrit.testing.NoteDbMode;
-import com.google.gerrit.testing.TestChanges;
-import com.google.gerrit.testing.TestTimeUtil;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.OrmRuntimeException;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.Timestamp;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
-import org.apache.http.Header;
-import org.apache.http.message.BasicHeader;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ChangeRebuilderIT extends AbstractDaemonTest {
- @ConfigSuite.Default
- public static Config defaultConfig() {
- Config cfg = new Config();
- cfg.setBoolean("noteDb", null, "testRebuilderWrapper", true);
-
- // Disable async reindex-if-stale check after index update. This avoids
- // unintentional auto-rebuilding of the change in NoteDb during the read
- // path of the reindex-if-stale check. For the purposes of this test, we
- // want precise control over when auto-rebuilding happens.
- cfg.setBoolean("index", null, "autoReindexIfStale", false);
-
- // setNotesMigration tries to keep IDs in sync between ReviewDb and NoteDb, which is behavior
- // unique to this test. This gets prohibitively slow if we use the default sequence gap.
- cfg.setInt("noteDb", "changes", "initialSequenceGap", 0);
-
- return cfg;
- }
-
- @Inject private NoteDbChecker checker;
-
- @Inject private Rebuild rebuildHandler;
-
- @Inject private Provider<ReviewDb> dbProvider;
-
- @Inject private CommentsUtil commentsUtil;
-
- @Inject private Provider<PostReview> postReview;
-
- @Inject private TestChangeRebuilderWrapper rebuilderWrapper;
-
- @Inject private Sequences seq;
-
- @Inject private ChangeBundleReader bundleReader;
-
- @Inject private PatchSetInfoFactory patchSetInfoFactory;
-
- @Inject private PatchListCache patchListCache;
-
- @Before
- public void setUp() throws Exception {
- assume().that(NoteDbMode.get()).isEqualTo(NoteDbMode.OFF);
- TestTimeUtil.resetWithClockStep(1, SECONDS);
- setNotesMigration(false, false);
- }
-
- @After
- public void tearDown() {
- TestTimeUtil.useSystemTime();
- }
-
- @SuppressWarnings("deprecation")
- private void setNotesMigration(boolean writeChanges, boolean readChanges) throws Exception {
- notesMigration.setWriteChanges(writeChanges);
- notesMigration.setReadChanges(readChanges);
- db = atrScope.reopenDb().getReviewDbProvider().get();
-
- if (notesMigration.readChangeSequence()) {
- // Copy next ReviewDb ID to NoteDb.
- seq.getChangeIdRepoSequence().set(db.nextChangeId());
- } else {
- // Copy next NoteDb ID to ReviewDb.
- while (db.nextChangeId() < seq.getChangeIdRepoSequence().next()) {}
- }
- }
-
- @Test
- public void changeFields() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- gApi.changes().id(id.get()).topic(name("a-topic"));
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void patchSets() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- amendChange(r.getChangeId());
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void publishedComment() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putComment(user, id, 1, "comment", null);
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void publishedCommentAndReply() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putComment(user, id, 1, "comment", null);
- Map<String, List<CommentInfo>> comments = getPublishedComments(id);
- String parentUuid = comments.get("a.txt").get(0).id;
- putComment(user, id, 1, "comment", parentUuid);
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void patchSetWithNullGroups() throws Exception {
- Timestamp ts = TimeUtil.nowTs();
- Change c = TestChanges.newChange(project, user.getId(), seq.nextChangeId());
- c.setCreatedOn(ts);
- c.setLastUpdatedOn(ts);
- c.setReviewStarted(true);
- PatchSet ps =
- TestChanges.newPatchSet(
- c.currentPatchSetId(), "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef", user.getId());
- ps.setCreatedOn(ts);
- db.changes().insert(Collections.singleton(c));
- db.patchSets().insert(Collections.singleton(ps));
-
- assertThat(ps.getGroups()).isEmpty();
- checker.rebuildAndCheckChanges(c.getId());
- }
-
- @Test
- public void draftComment() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment", null);
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void draftAndPublishedComment() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "draft comment", null);
- putComment(user, id, 1, "published comment", null);
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void publishDraftComment() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "draft comment", null);
- publishDrafts(user, id);
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void nullAccountId() throws Exception {
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId = r.getPatchSetId();
- Change.Id id = psId.getParentKey();
-
- // Events need to be otherwise identical for the account ID to be compared.
- ChangeMessage msg1 = insertMessage(id, psId, user.getId(), TimeUtil.nowTs(), "message 1");
- insertMessage(id, psId, null, msg1.getWrittenOn(), "message 2");
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void nullPatchSetId() throws Exception {
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId1 = r.getPatchSetId();
- Change.Id id = psId1.getParentKey();
-
- // Events need to be otherwise identical for the PatchSet.ID to be compared.
- ChangeMessage msg1 = insertMessage(id, null, user.getId(), TimeUtil.nowTs(), "message 1");
- insertMessage(id, null, user.getId(), msg1.getWrittenOn(), "message 2");
-
- PatchSet.Id psId2 = amendChange(r.getChangeId()).getPatchSetId();
-
- ChangeMessage msg3 = insertMessage(id, null, user.getId(), TimeUtil.nowTs(), "message 3");
- insertMessage(id, null, user.getId(), msg3.getWrittenOn(), "message 4");
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
-
- ChangeNotes notes = notesFactory.create(db, project, id);
- Map<String, PatchSet.Id> psIds = new HashMap<>();
- for (ChangeMessage msg : notes.getChangeMessages()) {
- PatchSet.Id psId = msg.getPatchSetId();
- assertThat(psId).named("patchset for " + msg).isNotNull();
- psIds.put(msg.getMessage(), psId);
- }
- // Patch set IDs were replaced during conversion process.
- assertThat(psIds).containsEntry("message 1", psId1);
- assertThat(psIds).containsEntry("message 2", psId1);
- assertThat(psIds).containsEntry("message 3", psId2);
- assertThat(psIds).containsEntry("message 4", psId2);
- }
-
- @Test
- public void noWriteToNewRef() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- checker.assertNoChangeRef(project, id);
-
- setNotesMigration(true, false);
- gApi.changes().id(id.get()).topic(name("a-topic"));
-
- // First write doesn't create the ref, but rebuilding works.
- checker.assertNoChangeRef(project, id);
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isNull();
- checker.rebuildAndCheckChanges(id);
-
- // Now that there is a ref, writes are "turned on" for this change, and
- // NoteDb stays up to date without explicit rebuilding.
- gApi.changes().id(id.get()).topic(name("new-topic"));
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isNotNull();
- checker.checkChanges(id);
- }
-
- @Test
- public void restApiNotFoundWhenNoteDbDisabled() throws Exception {
- PushOneCommit.Result r = createChange();
- exception.expect(ResourceNotFoundException.class);
- rebuildHandler.apply(parseChangeResource(r.getChangeId()), new Input());
- }
-
- @Test
- public void rebuildViaRestApi() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- setNotesMigration(true, false);
-
- checker.assertNoChangeRef(project, id);
- rebuildHandler.apply(parseChangeResource(r.getChangeId()), new Input());
- checker.checkChanges(id);
- }
-
- @Test
- public void writeToNewRefForNewChange() throws Exception {
- PushOneCommit.Result r1 = createChange();
- Change.Id id1 = r1.getPatchSetId().getParentKey();
-
- setNotesMigration(true, false);
- gApi.changes().id(id1.get()).topic(name("a-topic"));
- PushOneCommit.Result r2 = createChange();
- Change.Id id2 = r2.getPatchSetId().getParentKey();
-
- // Second change was created after NoteDb writes were turned on, so it was
- // allowed to write to a new ref.
- checker.checkChanges(id2);
-
- // First change was created before NoteDb writes were turned on, so its meta
- // ref doesn't exist until a manual rebuild.
- checker.assertNoChangeRef(project, id1);
- checker.rebuildAndCheckChanges(id1);
- }
-
- @Test
- public void noteDbChangeState() throws Exception {
- setNotesMigration(true, true);
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
-
- ObjectId changeMetaId = getMetaRef(project, changeMetaRef(id));
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState()).isEqualTo(changeMetaId.name());
-
- putDraft(user, id, 1, "comment by user", null);
- ObjectId userDraftsId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
- .isEqualTo(changeMetaId.name() + "," + user.getId() + "=" + userDraftsId.name());
-
- putDraft(admin, id, 2, "comment by admin", null);
- ObjectId adminDraftsId = getMetaRef(allUsers, refsDraftComments(id, admin.getId()));
- assertThat(admin.getId().get()).isLessThan(user.getId().get());
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
- .isEqualTo(
- changeMetaId.name()
- + ","
- + admin.getId()
- + "="
- + adminDraftsId.name()
- + ","
- + user.getId()
- + "="
- + userDraftsId.name());
-
- putDraft(admin, id, 2, "revised comment by admin", null);
- adminDraftsId = getMetaRef(allUsers, refsDraftComments(id, admin.getId()));
- assertThat(getUnwrappedDb().changes().get(id).getNoteDbState())
- .isEqualTo(
- changeMetaId.name()
- + ","
- + admin.getId()
- + "="
- + adminDraftsId.name()
- + ","
- + user.getId()
- + "="
- + userDraftsId.name());
- }
-
- @Test
- public void rebuildAutomaticallyWhenChangeOutOfDate() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
-
- // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
- setNotesMigration(false, false);
- gApi.changes().id(id.get()).topic(name("a-topic"));
- setInvalidNoteDbState(id);
- assertChangeUpToDate(false, id);
-
- // On next NoteDb read, the change is transparently rebuilt.
- setNotesMigration(true, true);
- assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
- assertChangeUpToDate(true, id);
-
- // Check that the bundles are equal.
- ChangeBundle actual =
- ChangeBundle.fromNotes(commentsUtil, notesFactory.create(dbProvider.get(), project, id));
- ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- assertThat(actual.differencesFrom(expected)).isEmpty();
- }
-
- @Test
- public void rebuildAutomaticallyWithinBatchUpdate() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- final Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
-
- // Update ReviewDb and NoteDb, then revert the corresponding NoteDb change
- // to simulate it failing.
- NoteDbChangeState oldState = NoteDbChangeState.parse(getUnwrappedDb().changes().get(id));
- String topic = name("a-topic");
- gApi.changes().id(id.get()).topic(topic);
- try (Repository repo = repoManager.openRepository(project)) {
- new TestRepository<>(repo).update(RefNames.changeMetaRef(id), oldState.getChangeMetaId());
- }
- assertChangeUpToDate(false, id);
-
- // Next NoteDb read comes inside the transaction started by BatchUpdate. In
- // reality this could be caused by a failed update happening between when
- // the change is parsed by ChangesCollection and when the BatchUpdate
- // executes. We simulate it here by using BatchUpdate directly and not going
- // through an API handler.
- final String msg = "message from BatchUpdate";
- try (BatchUpdate bu =
- batchUpdateFactory.create(
- db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs())) {
- bu.addOp(
- id,
- new BatchUpdateOp() {
- @Override
- public boolean updateChange(ChangeContext ctx) throws OrmException {
- PatchSet.Id psId = ctx.getChange().currentPatchSetId();
- ChangeMessage cm =
- new ChangeMessage(
- new ChangeMessage.Key(id, ChangeUtil.messageUuid()),
- ctx.getAccountId(),
- ctx.getWhen(),
- psId);
- cm.setMessage(msg);
- ctx.getDb().changeMessages().insert(Collections.singleton(cm));
- ctx.getUpdate(psId).setChangeMessage(msg);
- return true;
- }
- });
- try {
- bu.execute();
- fail("expected update to fail");
- } catch (UpdateException e) {
- assertThat(e.getMessage()).contains("cannot copy ChangeNotesState");
- }
- }
-
- // TODO(dborowitz): Re-enable these assertions once we fix auto-rebuilding
- // in the BatchUpdate path.
- // As an implementation detail, change wasn't actually rebuilt inside the
- // BatchUpdate transaction, but it was rebuilt during read for the
- // subsequent reindex. Thus it's impossible to actually observe an
- // out-of-date state in the caller.
- // assertChangeUpToDate(true, id);
-
- // Check that the bundles are equal.
- // ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
- // ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
- // ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- // assertThat(actual.differencesFrom(expected)).isEmpty();
- // assertThat(
- // Iterables.transform(
- // notes.getChangeMessages(),
- // ChangeMessage::getMessage))
- // .contains(msg);
- // assertThat(actual.getChange().getTopic()).isEqualTo(topic);
- }
-
- @Test
- public void rebuildIgnoresErrorIfChangeIsUpToDateAfter() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
-
- // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
- setNotesMigration(false, false);
- gApi.changes().id(id.get()).topic(name("a-topic"));
- setInvalidNoteDbState(id);
- assertChangeUpToDate(false, id);
-
- // Force the next rebuild attempt to fail but also rebuild the change in the
- // background.
- rebuilderWrapper.stealNextUpdate();
- setNotesMigration(true, true);
- assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
- assertChangeUpToDate(true, id);
-
- // Check that the bundles are equal.
- ChangeBundle actual =
- ChangeBundle.fromNotes(commentsUtil, notesFactory.create(dbProvider.get(), project, id));
- ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- assertThat(actual.differencesFrom(expected)).isEmpty();
- }
-
- @Test
- public void rebuildReturnsCorrectResultEvenIfSavingToNoteDbFailed() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
- ObjectId oldMetaId = getMetaRef(project, changeMetaRef(id));
-
- // Make a ReviewDb change behind NoteDb's back.
- setNotesMigration(false, false);
- gApi.changes().id(id.get()).topic(name("a-topic"));
- setInvalidNoteDbState(id);
- assertChangeUpToDate(false, id);
- assertThat(getMetaRef(project, changeMetaRef(id))).isEqualTo(oldMetaId);
-
- // Force the next rebuild attempt to fail.
- rebuilderWrapper.failNextUpdate();
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
-
- // Not up to date, but the actual returned state matches anyway.
- assertChangeUpToDate(false, id);
- assertThat(getMetaRef(project, changeMetaRef(id))).isEqualTo(oldMetaId);
- ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
- ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- assertThat(actual.differencesFrom(expected)).isEmpty();
- assertChangeUpToDate(false, id);
-
- // Another rebuild attempt succeeds
- notesFactory.create(dbProvider.get(), project, id);
- assertThat(getMetaRef(project, changeMetaRef(id))).isNotEqualTo(oldMetaId);
- assertChangeUpToDate(true, id);
- }
-
- @Test
- public void rebuildReturnsDraftResultWhenRebuildingInChangeNotesFails() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment by user", null);
- assertChangeUpToDate(true, id);
-
- ObjectId oldMetaId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));
-
- // Add a draft behind NoteDb's back.
- setNotesMigration(false, false);
- putDraft(user, id, 1, "second comment by user", null);
- setInvalidNoteDbState(id);
- assertDraftsUpToDate(false, id, user);
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);
-
- // Force the next rebuild attempt to fail (in ChangeNotes).
- rebuilderWrapper.failNextUpdate();
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
- notes.getDraftComments(user.getId());
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);
-
- // Not up to date, but the actual returned state matches anyway.
- assertDraftsUpToDate(false, id, user);
- ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
- ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- assertThat(actual.differencesFrom(expected)).isEmpty();
-
- // Another rebuild attempt succeeds
- notesFactory.create(dbProvider.get(), project, id);
- assertChangeUpToDate(true, id);
- assertDraftsUpToDate(true, id, user);
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isNotEqualTo(oldMetaId);
- }
-
- @Test
- public void rebuildReturnsDraftResultWhenRebuildingInDraftCommentNotesFails() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment by user", null);
- assertChangeUpToDate(true, id);
-
- ObjectId oldMetaId = getMetaRef(allUsers, refsDraftComments(id, user.getId()));
-
- // Add a draft behind NoteDb's back.
- setNotesMigration(false, false);
- putDraft(user, id, 1, "second comment by user", null);
-
- ReviewDb db = getUnwrappedDb();
- Change c = db.changes().get(id);
- // Leave change meta ID alone so DraftCommentNotes does the rebuild.
- ObjectId badSha = ObjectId.fromString("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- NoteDbChangeState bogusState =
- new NoteDbChangeState(
- id,
- PrimaryStorage.REVIEW_DB,
- Optional.of(
- NoteDbChangeState.RefState.create(
- NoteDbChangeState.parse(c).getChangeMetaId(),
- ImmutableMap.of(user.getId(), badSha))),
- Optional.empty());
- c.setNoteDbState(bogusState.toString());
- db.changes().update(Collections.singleton(c));
-
- assertDraftsUpToDate(false, id, user);
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);
-
- // Force the next rebuild attempt to fail (in DraftCommentNotes).
- rebuilderWrapper.failNextUpdate();
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
- notes.getDraftComments(user.getId());
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isEqualTo(oldMetaId);
-
- // Not up to date, but the actual returned state matches anyway.
- assertChangeUpToDate(true, id);
- assertDraftsUpToDate(false, id, user);
- ChangeBundle actual = ChangeBundle.fromNotes(commentsUtil, notes);
- ChangeBundle expected = bundleReader.fromReviewDb(getUnwrappedDb(), id);
- assertThat(actual.differencesFrom(expected)).isEmpty();
-
- // Another rebuild attempt succeeds
- notesFactory.create(dbProvider.get(), project, id).getDraftComments(user.getId());
- assertChangeUpToDate(true, id);
- assertDraftsUpToDate(true, id, user);
- assertThat(getMetaRef(allUsers, refsDraftComments(id, user.getId()))).isNotEqualTo(oldMetaId);
- }
-
- @Test
- public void rebuildAutomaticallyWhenDraftsOutOfDate() throws Exception {
- setNotesMigration(true, true);
- setApiUser(user);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment", null);
- assertDraftsUpToDate(true, id, user);
-
- // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
- setNotesMigration(false, false);
- putDraft(user, id, 1, "comment", null);
- setInvalidNoteDbState(id);
- assertDraftsUpToDate(false, id, user);
-
- // On next NoteDb read, the drafts are transparently rebuilt.
- setNotesMigration(true, true);
- assertThat(gApi.changes().id(id.get()).current().drafts()).containsKey(PushOneCommit.FILE_NAME);
- assertDraftsUpToDate(true, id, user);
- }
-
- @Test
- public void pushCert() throws Exception {
- // We don't have the code in our test harness to do signed pushes, so just
- // use a hard-coded cert. This cert was actually generated by C git 2.2.0
- // (albeit not for sending to Gerrit).
- String cert =
- "certificate version 0.1\n"
- + "pusher Dave Borowitz <dborowitz@google.com> 1433954361 -0700\n"
- + "pushee git://localhost/repo.git\n"
- + "nonce 1433954361-bde756572d665bba81d8\n"
- + "\n"
- + "0000000000000000000000000000000000000000"
- + "b981a177396fb47345b7df3e4d3f854c6bea7"
- + "s/heads/master\n"
- + "-----BEGIN PGP SIGNATURE-----\n"
- + "Version: GnuPG v1\n"
- + "\n"
- + "iQEcBAABAgAGBQJVeGg5AAoJEPfTicJkUdPkUggH/RKAeI9/i/LduuiqrL/SSdIa\n"
- + "9tYaSqJKLbXz63M/AW4Sp+4u+dVCQvnAt/a35CVEnpZz6hN4Kn/tiswOWVJf4CO7\n"
- + "htNubGs5ZMwvD6sLYqKAnrM3WxV/2TbbjzjZW6Jkidz3jz/WRT4SmjGYiEO7aA+V\n"
- + "4ZdIS9f7sW5VsHHYlNThCA7vH8Uu48bUovFXyQlPTX0pToSgrWV3JnTxDNxfn3iG\n"
- + "IL0zTY/qwVCdXgFownLcs6J050xrrBWIKqfcWr3u4D2aCLyR0v+S/KArr7ulZygY\n"
- + "+SOklImn8TAZiNxhWtA6ens66IiammUkZYFv7SSzoPLFZT4dC84SmGPWgf94NoQ=\n"
- + "=XFeC\n"
- + "-----END PGP SIGNATURE-----\n";
-
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId = r.getPatchSetId();
- Change.Id id = psId.getParentKey();
-
- PatchSet ps = db.patchSets().get(psId);
- ps.setPushCertificate(cert);
- db.patchSets().update(Collections.singleton(ps));
- indexer.index(db, project, id);
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void emptyTopic() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- Change c = db.changes().get(id);
- assertThat(c.getTopic()).isNull();
- c.setTopic("");
- db.changes().update(Collections.singleton(c));
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
-
- // Rebuild and check was successful, but NoteDb doesn't support storing an
- // empty topic, so it comes out as null.
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getChange().getTopic()).isNull();
- }
-
- @Test
- public void commentBeforeFirstPatchSet() throws Exception {
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId = r.getPatchSetId();
- Change.Id id = psId.getParentKey();
-
- Change c = db.changes().get(id);
- c.setCreatedOn(new Timestamp(c.getCreatedOn().getTime() - 5000));
- db.changes().update(Collections.singleton(c));
- indexer.index(db, project, id);
-
- ReviewInput rin = new ReviewInput();
- rin.message = "comment";
-
- Timestamp ts = new Timestamp(c.getCreatedOn().getTime() + 2000);
- assertThat(ts).isGreaterThan(c.getCreatedOn());
- assertThat(ts).isLessThan(db.patchSets().get(psId).getCreatedOn());
- RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
- postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void commentPredatingChangeBySomeoneOtherThanOwner() throws Exception {
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId = r.getPatchSetId();
- Change.Id id = psId.getParentKey();
- Change c = db.changes().get(id);
-
- ReviewInput rin = new ReviewInput();
- rin.message = "comment";
-
- Timestamp ts = new Timestamp(c.getCreatedOn().getTime() - 10000);
- RevisionResource revRsrc = parseCurrentRevisionResource(r.getChangeId());
- setApiUser(user);
- postReview.get().apply(batchUpdateFactory, revRsrc, rin, ts);
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void noteDbUsesOriginalSubjectFromPatchSetAndIgnoresChangeField() throws Exception {
- PushOneCommit.Result r = createChange();
- String orig = r.getChange().change().getSubject();
- r =
- pushFactory
- .create(
- db,
- admin.getIdent(),
- testRepo,
- orig + " v2",
- PushOneCommit.FILE_NAME,
- "new contents",
- r.getChangeId())
- .to("refs/for/master");
- r.assertOkStatus();
-
- PatchSet.Id psId = r.getPatchSetId();
- Change.Id id = psId.getParentKey();
- Change c = db.changes().get(id);
-
- c.setCurrentPatchSet(psId, c.getSubject(), "Bogus original subject");
- db.changes().update(Collections.singleton(c));
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(db, project, id);
- Change nc = notes.getChange();
- assertThat(nc.getSubject()).isEqualTo(c.getSubject());
- assertThat(nc.getSubject()).isEqualTo(orig + " v2");
- assertThat(nc.getOriginalSubject()).isNotEqualTo(c.getOriginalSubject());
- assertThat(nc.getOriginalSubject()).isEqualTo(orig);
- }
-
- @Test
- public void ignorePatchLineCommentsOnPatchSet0() throws Exception {
- PushOneCommit.Result r = createChange();
- Change change = r.getChange().change();
- Change.Id id = change.getId();
-
- PatchLineComment comment =
- new PatchLineComment(
- new PatchLineComment.Key(
- new Patch.Key(new PatchSet.Id(id, 0), PushOneCommit.FILE_NAME), "uuid"),
- 0,
- user.getId(),
- null,
- TimeUtil.nowTs());
- comment.setSide((short) 1);
- comment.setMessage("message");
- comment.setStatus(PatchLineComment.Status.PUBLISHED);
- db.patchComments().insert(Collections.singleton(comment));
- indexer.index(db, change.getProject(), id);
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getComments()).isEmpty();
- }
-
- @Test
- public void leadingSpacesInSubject() throws Exception {
- String subj = " " + PushOneCommit.SUBJECT;
- PushOneCommit push =
- pushFactory.create(
- db,
- admin.getIdent(),
- testRepo,
- subj,
- PushOneCommit.FILE_NAME,
- PushOneCommit.FILE_CONTENT);
- PushOneCommit.Result r = push.to("refs/for/master");
- r.assertOkStatus();
- Change change = r.getChange().change();
- assertThat(change.getSubject()).isEqualTo(subj);
- Change.Id id = r.getPatchSetId().getParentKey();
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getChange().getSubject()).isNotEqualTo(subj);
- assertThat(notes.getChange().getSubject()).isEqualTo(PushOneCommit.SUBJECT);
- }
-
- @Test
- public void allTimestampsExceptUpdatedAreEqualDueToBadMigration() throws Exception {
- // https://bugs.chromium.org/p/gerrit/issues/detail?id=7397
- PushOneCommit.Result r = createChange();
- Change c = r.getChange().change();
- Change.Id id = c.getId();
- Timestamp ts = TimeUtil.nowTs();
- Timestamp origUpdated = c.getLastUpdatedOn();
-
- c.setCreatedOn(ts);
- assertThat(c.getCreatedOn()).isGreaterThan(c.getLastUpdatedOn());
- db.changes().update(Collections.singleton(c));
-
- List<ChangeMessage> cm = db.changeMessages().byChange(id).toList();
- cm.forEach(m -> m.setWrittenOn(ts));
- db.changeMessages().update(cm);
-
- List<PatchSet> ps = db.patchSets().byChange(id).toList();
- ps.forEach(p -> p.setCreatedOn(ts));
- db.patchSets().update(ps);
-
- List<PatchSetApproval> psa = db.patchSetApprovals().byChange(id).toList();
- psa.forEach(p -> p.setGranted(ts));
- db.patchSetApprovals().update(psa);
-
- List<PatchLineComment> plc = db.patchComments().byChange(id).toList();
- plc.forEach(p -> p.setWrittenOn(ts));
- db.patchComments().update(plc);
-
- checker.rebuildAndCheckChanges(id);
-
- setNotesMigration(true, true);
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getChange().getCreatedOn()).isEqualTo(origUpdated);
- assertThat(notes.getChange().getLastUpdatedOn()).isAtLeast(origUpdated);
- assertThat(notes.getPatchSets().get(new PatchSet.Id(id, 1)).getCreatedOn())
- .isEqualTo(origUpdated);
- }
-
- @Test
- public void createWithAutoRebuildingDisabled() throws Exception {
- ReviewDb oldDb = db;
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- ChangeNotes oldNotes = notesFactory.create(db, project, id);
-
- // Make a ReviewDb change behind NoteDb's back.
- Change c = oldDb.changes().get(id);
- assertThat(c.getTopic()).isNull();
- String topic = name("a-topic");
- c.setTopic(topic);
- oldDb.changes().update(Collections.singleton(c));
-
- c = oldDb.changes().get(c.getId());
- ChangeNotes newNotes = notesFactory.createWithAutoRebuildingDisabled(c, null);
- assertThat(newNotes.getChange().getTopic()).isNotEqualTo(topic);
- assertThat(newNotes.getChange().getTopic()).isEqualTo(oldNotes.getChange().getTopic());
- }
-
- @Test
- public void rebuildDeletesOldDraftRefs() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment", null);
-
- Account.Id otherAccountId = new Account.Id(user.getId().get() + 1234);
- String otherDraftRef = refsDraftComments(id, otherAccountId);
-
- try (Repository repo = repoManager.openRepository(allUsers);
- ObjectInserter ins = repo.newObjectInserter()) {
- ObjectId sha = ins.insert(OBJ_BLOB, "garbage data".getBytes(UTF_8));
- ins.flush();
- RefUpdate ru = repo.updateRef(otherDraftRef);
- ru.setExpectedOldObjectId(ObjectId.zeroId());
- ru.setNewObjectId(sha);
- assertThat(ru.update()).isEqualTo(RefUpdate.Result.NEW);
- }
-
- checker.rebuildAndCheckChanges(id);
-
- try (Repository repo = repoManager.openRepository(allUsers)) {
- assertThat(repo.exactRef(otherDraftRef)).isNull();
- }
- }
-
- @Test
- public void failWhenWritesDisabled() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
- assertThat(gApi.changes().id(id.get()).info().topic).isNull();
-
- // Turning off writes causes failure.
- setNotesMigration(false, true);
- try {
- gApi.changes().id(id.get()).topic(name("a-topic"));
- fail("Expected write to fail");
- } catch (RestApiException e) {
- assertChangesReadOnly(e);
- }
-
- // Update was not written.
- assertThat(gApi.changes().id(id.get()).info().topic).isNull();
- assertChangeUpToDate(true, id);
- }
-
- @Test
- public void rebuildWhenWritesDisabledWorksButDoesNotWrite() throws Exception {
- setNotesMigration(true, true);
-
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- assertChangeUpToDate(true, id);
-
- // Make a ReviewDb change behind NoteDb's back and ensure it's detected.
- setNotesMigration(false, false);
- gApi.changes().id(id.get()).topic(name("a-topic"));
- setInvalidNoteDbState(id);
- assertChangeUpToDate(false, id);
-
- // On next NoteDb read, change is rebuilt in-memory but not stored.
- setNotesMigration(false, true);
- assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
- assertChangeUpToDate(false, id);
-
- // Attempting to write directly causes failure.
- try {
- gApi.changes().id(id.get()).topic(name("other-topic"));
- fail("Expected write to fail");
- } catch (RestApiException e) {
- assertChangesReadOnly(e);
- }
-
- // Update was not written.
- assertThat(gApi.changes().id(id.get()).info().topic).isEqualTo(name("a-topic"));
- assertChangeUpToDate(false, id);
- }
-
- @Test
- public void rebuildChangeWithNoPatchSets() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- db.changes().beginTransaction(id);
- try {
- db.patchSets().delete(db.patchSets().byChange(id));
- db.commit();
- } finally {
- db.rollback();
- }
-
- try {
- checker.rebuildAndCheckChanges(id);
- assert_().fail("expected NoPatchSetsException");
- } catch (NoPatchSetsException e) {
- // Expected.
- }
-
- Change c = db.changes().get(id);
- assertThat(c.getNoteDbState()).isNull();
- checker.assertNoChangeRef(project, id);
- }
-
- @Test
- public void rebuildChangeWithNoEntitiesOtherThanChange() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- db.changes().beginTransaction(id);
- try {
- db.changeMessages().delete(db.changeMessages().byChange(id));
- db.patchSets().delete(db.patchSets().byChange(id));
- db.patchSetApprovals().delete(db.patchSetApprovals().byChange(id));
- db.patchComments().delete(db.patchComments().byChange(id));
- db.commit();
- } finally {
- db.rollback();
- }
-
- try {
- checker.rebuildAndCheckChanges(id);
- assert_().fail("expected NoPatchSetsException");
- } catch (NoPatchSetsException e) {
- // Expected.
- }
-
- Change c = db.changes().get(id);
- assertThat(c.getNoteDbState()).isNull();
- checker.assertNoChangeRef(project, id);
- }
-
- @Test
- public void rebuildEntitiesCreatedByImpersonation() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- PatchSet.Id psId = new PatchSet.Id(id, 1);
- String prefix = "/changes/" + id + "/revisions/current/";
-
- // For each of the entities that have a real user field, create one entity
- // without impersonation and one with.
- CommentInput ci = new CommentInput();
- ci.path = Patch.COMMIT_MSG;
- ci.side = Side.REVISION;
- ci.line = 1;
- ci.message = "comment without impersonation";
- ReviewInput ri = new ReviewInput();
- ri.label("Code-Review", -1);
- ri.message = "message without impersonation";
- ri.drafts = DraftHandling.KEEP;
- ri.comments = ImmutableMap.of(ci.path, ImmutableList.of(ci));
- userRestSession.post(prefix + "review", ri).assertOK();
-
- DraftInput di = new DraftInput();
- di.path = Patch.COMMIT_MSG;
- di.side = Side.REVISION;
- di.line = 1;
- di.message = "draft without impersonation";
- userRestSession.put(prefix + "drafts", di).assertCreated();
-
- allowRunAs();
- try {
- Header runAs = new BasicHeader("X-Gerrit-RunAs", user.id.toString());
- ci.message = "comment with impersonation";
- ri.message = "message with impersonation";
- ri.label("Code-Review", 1);
- adminRestSession.postWithHeader(prefix + "review", runAs, ri).assertOK();
-
- di.message = "draft with impersonation";
- adminRestSession.putWithHeader(prefix + "drafts", runAs, di).assertCreated();
- } finally {
- removeRunAs();
- }
-
- List<ChangeMessage> msgs =
- Ordering.natural()
- .onResultOf(ChangeMessage::getWrittenOn)
- .sortedCopy(db.changeMessages().byChange(id));
- assertThat(msgs).hasSize(3);
- assertThat(msgs.get(1).getMessage()).endsWith("message without impersonation");
- assertThat(msgs.get(1).getAuthor()).isEqualTo(user.id);
- assertThat(msgs.get(1).getRealAuthor()).isEqualTo(user.id);
- assertThat(msgs.get(2).getMessage()).endsWith("message with impersonation");
- assertThat(msgs.get(2).getAuthor()).isEqualTo(user.id);
- assertThat(msgs.get(2).getRealAuthor()).isEqualTo(admin.id);
-
- List<PatchSetApproval> psas = db.patchSetApprovals().byChange(id).toList();
- assertThat(psas).hasSize(1);
- assertThat(psas.get(0).getLabel()).isEqualTo("Code-Review");
- assertThat(psas.get(0).getValue()).isEqualTo(1);
- assertThat(psas.get(0).getAccountId()).isEqualTo(user.id);
- assertThat(psas.get(0).getRealAccountId()).isEqualTo(admin.id);
-
- Ordering<PatchLineComment> commentOrder =
- Ordering.natural().onResultOf(PatchLineComment::getWrittenOn);
- List<PatchLineComment> drafts =
- commentOrder.sortedCopy(db.patchComments().draftByPatchSetAuthor(psId, user.id));
- assertThat(drafts).hasSize(2);
- assertThat(drafts.get(0).getMessage()).isEqualTo("draft without impersonation");
- assertThat(drafts.get(0).getAuthor()).isEqualTo(user.id);
- assertThat(drafts.get(0).getRealAuthor()).isEqualTo(user.id);
- assertThat(drafts.get(1).getMessage()).isEqualTo("draft with impersonation");
- assertThat(drafts.get(1).getAuthor()).isEqualTo(user.id);
- assertThat(drafts.get(1).getRealAuthor()).isEqualTo(admin.id);
-
- List<PatchLineComment> pub =
- commentOrder.sortedCopy(db.patchComments().publishedByPatchSet(psId));
- assertThat(pub).hasSize(2);
- assertThat(pub.get(0).getMessage()).isEqualTo("comment without impersonation");
- assertThat(pub.get(0).getAuthor()).isEqualTo(user.id);
- assertThat(pub.get(0).getRealAuthor()).isEqualTo(user.id);
- assertThat(pub.get(1).getMessage()).isEqualTo("comment with impersonation");
- assertThat(pub.get(1).getAuthor()).isEqualTo(user.id);
- assertThat(pub.get(1).getRealAuthor()).isEqualTo(admin.id);
- }
-
- @Test
- public void laterEventsDependingOnEarlierPatchSetDontIntefereWithOtherPatchSets()
- throws Exception {
- PushOneCommit.Result r1 = createChange();
- ChangeData cd = r1.getChange();
- Change.Id id = cd.getId();
- amendChange(cd.change().getKey().get());
- TestTimeUtil.incrementClock(90, TimeUnit.DAYS);
-
- ReviewInput rin = ReviewInput.approve();
- rin.message = "Some very late message on PS1";
- gApi.changes().id(id.get()).revision(1).review(rin);
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void ignoreChangeMessageBeyondCurrentPatchSet() throws Exception {
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId1 = r.getPatchSetId();
- Change.Id id = psId1.getParentKey();
- gApi.changes().id(id.get()).current().review(ReviewInput.recommend());
-
- r = amendChange(r.getChangeId());
- PatchSet.Id psId2 = r.getPatchSetId();
-
- assertThat(db.patchSets().byChange(id)).hasSize(2);
- assertThat(db.changeMessages().byPatchSet(psId2)).hasSize(1);
- db.patchSets().deleteKeys(Collections.singleton(psId2));
-
- checker.rebuildAndCheckChanges(psId2.getParentKey());
- setNotesMigration(true, true);
-
- ChangeData cd = changeDataFactory.create(db, project, id);
- assertThat(cd.change().currentPatchSetId()).isEqualTo(psId1);
- assertThat(cd.patchSets().stream().map(PatchSet::getId).collect(toList()))
- .containsExactly(psId1);
- PatchSet ps = cd.currentPatchSet();
- assertThat(ps).isNotNull();
- assertThat(ps.getId()).isEqualTo(psId1);
- }
-
- @Test
- public void highestNumberedPatchSetIsNotCurrent() throws Exception {
- PushOneCommit.Result r1 = createChange();
- PatchSet.Id psId1 = r1.getPatchSetId();
- Change.Id id = psId1.getParentKey();
- PushOneCommit.Result r2 = amendChange(r1.getChangeId());
- PatchSet.Id psId2 = r2.getPatchSetId();
-
- try (BatchUpdate bu =
- batchUpdateFactory.create(
- db, project, identifiedUserFactory.create(user.getId()), TimeUtil.nowTs())) {
- bu.addOp(
- id,
- new BatchUpdateOp() {
- @Override
- public boolean updateChange(ChangeContext ctx)
- throws PatchSetInfoNotAvailableException {
- ctx.getChange()
- .setCurrentPatchSet(patchSetInfoFactory.get(ctx.getDb(), ctx.getNotes(), psId1));
- return true;
- }
- });
- bu.execute();
- }
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(psUtil.byChangeAsMap(db, notes).keySet()).containsExactly(psId1, psId2);
- assertThat(notes.getChange().currentPatchSetId()).isEqualTo(psId1);
-
- assertThat(db.changes().get(id).currentPatchSetId()).isEqualTo(psId1);
-
- checker.rebuildAndCheckChanges(id);
- setNotesMigration(true, true);
-
- notes = notesFactory.create(db, project, id);
- assertThat(psUtil.byChangeAsMap(db, notes).keySet()).containsExactly(psId1, psId2);
- assertThat(notes.getChange().currentPatchSetId()).isEqualTo(psId1);
- }
-
- @Test
- public void resolveCommentsInheritsValueFromParentWhenUnspecified() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getPatchSetId().getParentKey();
- putDraft(user, id, 1, "comment", true);
- putDraft(user, id, 1, "newComment", null);
-
- Map<String, List<CommentInfo>> comments = gApi.changes().id(id.get()).current().drafts();
- for (List<CommentInfo> cList : comments.values()) {
- for (CommentInfo ci : cList) {
- assertThat(ci.unresolved).isTrue();
- }
- }
- }
-
- @Test
- public void rebuilderRespectsReadOnlyInNoteDbChangeState() throws Exception {
- TestTimeUtil.resetWithClockStep(1, SECONDS);
- PushOneCommit.Result r = createChange();
- PatchSet.Id psId1 = r.getPatchSetId();
- Change.Id id = psId1.getParentKey();
-
- checker.rebuildAndCheckChanges(id);
- setNotesMigration(true, true);
-
- ReviewDb db = getUnwrappedDb();
- Change c = db.changes().get(id);
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- Timestamp until = new Timestamp(TimeUtil.nowMs() + MILLISECONDS.convert(1, DAYS));
- state = state.withReadOnlyUntil(until);
- c.setNoteDbState(state.toString());
- db.changes().update(Collections.singleton(c));
-
- try {
- rebuilderWrapper.rebuild(db, id);
- fail("expected rebuild to fail");
- } catch (OrmRuntimeException e) {
- assertThat(e.getMessage()).contains("read-only until");
- }
-
- TestTimeUtil.setClock(new Timestamp(until.getTime() + MILLISECONDS.convert(1, SECONDS)));
- rebuilderWrapper.rebuild(db, id);
- }
-
- @Test
- public void commitWithCrLineEndings() throws Exception {
- PushOneCommit.Result r =
- createChange("Subject\r\rBody\r", PushOneCommit.FILE_NAME, PushOneCommit.FILE_CONTENT);
- Change c = r.getChange().change();
-
- // This assertion demonstrates an arguable bug in JGit's commit subject
- // parsing, and shows how this kind of data might have gotten into
- // ReviewDb. If that bug ever gets fixed upstream, this assert may start
- // failing. If that happens, this test can be rewritten to directly set the
- // subject field in ReviewDb.
- assertThat(c.getSubject()).isEqualTo("Subject\r\rBody");
-
- checker.rebuildAndCheckChanges(c.getId());
- }
-
- @Test
- public void patchSetsOutOfOrder() throws Exception {
- String id = createChange().getChangeId();
- amendChange(id);
- PushOneCommit.Result r = amendChange(id);
-
- ChangeData cd = r.getChange();
- PatchSet.Id psId3 = cd.change().currentPatchSetId();
- assertThat(psId3.get()).isEqualTo(3);
-
- PatchSet ps1 = db.patchSets().get(new PatchSet.Id(cd.getId(), 1));
- PatchSet ps3 = db.patchSets().get(psId3);
- assertThat(ps1.getCreatedOn()).isLessThan(ps3.getCreatedOn());
-
- // Simulate an old Gerrit bug by setting the created timestamp of the latest
- // patch set ID to the timestamp of PS1.
- ps3.setCreatedOn(ps1.getCreatedOn());
- db.patchSets().update(Collections.singleton(ps3));
-
- checker.rebuildAndCheckChanges(cd.getId());
-
- setNotesMigration(true, true);
- cd = changeDataFactory.create(db, project, cd.getId());
- assertThat(cd.change().currentPatchSetId()).isEqualTo(psId3);
-
- List<PatchSet> patchSets = ImmutableList.copyOf(cd.patchSets());
- assertThat(patchSets).hasSize(3);
-
- PatchSet newPs1 = patchSets.get(0);
- assertThat(newPs1.getId()).isEqualTo(ps1.getId());
- assertThat(newPs1.getCreatedOn()).isEqualTo(ps1.getCreatedOn());
-
- PatchSet newPs2 = patchSets.get(1);
- assertThat(newPs2.getCreatedOn()).isGreaterThan(newPs1.getCreatedOn());
-
- PatchSet newPs3 = patchSets.get(2);
- assertThat(newPs3.getId()).isEqualTo(ps3.getId());
- // Migrated with a newer timestamp than the original, to preserve ordering.
- assertThat(newPs3.getCreatedOn()).isAtLeast(newPs2.getCreatedOn());
- assertThat(newPs3.getCreatedOn()).isGreaterThan(ps1.getCreatedOn());
- }
-
- @Test
- public void ignoreNoteDbStateWithNoCorrespondingRefWhenWritesAndReadsDisabled() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- ReviewDb db = getUnwrappedDb();
- Change c = db.changes().get(id);
- c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- db.changes().update(Collections.singleton(c));
- c = db.changes().get(id);
-
- String refName = RefNames.changeMetaRef(id);
- assertThat(getMetaRef(project, refName)).isNull();
-
- ChangeNotes notes = notesFactory.create(dbProvider.get(), project, id);
- assertThat(notes.getChange().getRowVersion()).isEqualTo(c.getRowVersion());
-
- notes = notesFactory.createChecked(dbProvider.get(), project, id);
- assertThat(notes.getChange().getRowVersion()).isEqualTo(c.getRowVersion());
-
- assertThat(getMetaRef(project, refName)).isNull();
- }
-
- @Test
- public void autoRebuildMissingRefWriteOnly() throws Exception {
- setNotesMigration(true, false);
- testAutoRebuildMissingRef();
- }
-
- @Test
- public void autoRebuildMissingRefReadWrite() throws Exception {
- setNotesMigration(true, true);
- testAutoRebuildMissingRef();
- }
-
- private void testAutoRebuildMissingRef() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- assertChangeUpToDate(true, id);
- notesFactory.createChecked(db, project, id);
-
- try (Repository repo = repoManager.openRepository(project)) {
- RefUpdate ru = repo.updateRef(RefNames.changeMetaRef(id));
- ru.setForceUpdate(true);
- assertThat(ru.delete()).isEqualTo(RefUpdate.Result.FORCED);
- }
- assertChangeUpToDate(false, id);
-
- notesFactory.createChecked(db, project, id);
- assertChangeUpToDate(true, id);
- }
-
- @Test
- public void missingPatchSetCommitOkForCommentsNotOnParentSide() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- putDraft(user, id, 1, "draft comment", null, Side.REVISION);
- putComment(user, id, 1, "published comment", null, Side.REVISION);
-
- ReviewDb db = getUnwrappedDb();
- PatchSet ps = db.patchSets().get(new PatchSet.Id(id, 1));
- ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- db.patchSets().update(Collections.singleton(ps));
-
- try {
- patchListCache.getOldId(db.changes().get(id), ps, null);
- assert_().fail("Expected PatchListNotAvailableException");
- } catch (PatchListNotAvailableException e) {
- // Expected.
- }
-
- checker.rebuildAndCheckChanges(id);
- }
-
- @Test
- public void missingPatchSetCommitOmitsCommentsOnParentSide() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- CommentInfo draftInfo = putDraft(user, id, 1, "draft comment", null, Side.PARENT);
- putComment(user, id, 1, "published comment", null, Side.PARENT);
- CommentInfo commentInfo =
- gApi.changes()
- .id(id.get())
- .comments()
- .values()
- .stream()
- .flatMap(List::stream)
- .findFirst()
- .get();
-
- ReviewDb db = getUnwrappedDb();
- PatchSet ps = db.patchSets().get(new PatchSet.Id(id, 1));
- ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- db.patchSets().update(Collections.singleton(ps));
-
- try {
- patchListCache.getOldId(db.changes().get(id), ps, null);
- assert_().fail("Expected PatchListNotAvailableException");
- } catch (PatchListNotAvailableException e) {
- // Expected.
- }
-
- checker.rebuildAndCheckChange(
- id,
- Stream.of(draftInfo.id, commentInfo.id)
- .sorted()
- .map(c -> id + ",1," + PushOneCommit.FILE_NAME + "," + c)
- .collect(
- joining(", ", "PatchLineComment.Key sets differ: [", "] only in A; [] only in B")));
- }
-
- private void assertChangesReadOnly(RestApiException e) throws Exception {
- Throwable cause = e.getCause();
- assertThat(cause).isInstanceOf(UpdateException.class);
- assertThat(cause.getCause()).isInstanceOf(OrmException.class);
- assertThat(cause.getCause()).hasMessageThat().isEqualTo(NoteDbUpdateManager.CHANGES_READ_ONLY);
- }
-
- private void setInvalidNoteDbState(Change.Id id) throws Exception {
- ReviewDb db = getUnwrappedDb();
- Change c = db.changes().get(id);
- // In reality we would have NoteDb writes enabled, which would write a real
- // state into this field. For tests however, we turn NoteDb writes off, so
- // just use a dummy state to force ChangeNotes to view the notes as
- // out-of-date.
- c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- db.changes().update(Collections.singleton(c));
- }
-
- private void assertChangeUpToDate(boolean expected, Change.Id id) throws Exception {
- try (Repository repo = repoManager.openRepository(project)) {
- Change c = getUnwrappedDb().changes().get(id);
- assertThat(c).isNotNull();
- assertThat(c.getNoteDbState()).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.isChangeUpToDate(new RepoRefCache(repo))).isEqualTo(expected);
- }
- }
-
- private void assertDraftsUpToDate(boolean expected, Change.Id changeId, TestAccount account)
- throws Exception {
- try (Repository repo = repoManager.openRepository(allUsers)) {
- Change c = getUnwrappedDb().changes().get(changeId);
- assertThat(c).isNotNull();
- assertThat(c.getNoteDbState()).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state.areDraftsUpToDate(new RepoRefCache(repo), account.getId()))
- .isEqualTo(expected);
- }
- }
-
- private ObjectId getMetaRef(Project.NameKey p, String name) throws Exception {
- try (Repository repo = repoManager.openRepository(p)) {
- Ref ref = repo.exactRef(name);
- return ref != null ? ref.getObjectId() : null;
- }
- }
-
- private CommentInfo putDraft(
- TestAccount account, Change.Id id, int line, String msg, Boolean unresolved)
- throws Exception {
- return putDraft(account, id, line, msg, unresolved, Side.REVISION);
- }
-
- private CommentInfo putDraft(
- TestAccount account, Change.Id id, int line, String msg, Boolean unresolved, Side side)
- throws Exception {
- DraftInput in = new DraftInput();
- in.side = side;
- in.line = line;
- in.message = msg;
- in.path = PushOneCommit.FILE_NAME;
- in.unresolved = unresolved;
- AcceptanceTestRequestScope.Context old = setApiUser(account);
- try {
- return gApi.changes().id(id.get()).current().createDraft(in).get();
- } finally {
- atrScope.set(old);
- }
- }
-
- private void putComment(TestAccount account, Change.Id id, int line, String msg, String inReplyTo)
- throws Exception {
- putComment(account, id, line, msg, inReplyTo, Side.REVISION);
- }
-
- private void putComment(
- TestAccount account, Change.Id id, int line, String msg, String inReplyTo, Side side)
- throws Exception {
- CommentInput in = new CommentInput();
- in.side = side;
- in.line = line;
- in.message = msg;
- in.inReplyTo = inReplyTo;
- ReviewInput rin = new ReviewInput();
- rin.comments = new HashMap<>();
- rin.comments.put(PushOneCommit.FILE_NAME, ImmutableList.of(in));
- rin.drafts = ReviewInput.DraftHandling.KEEP;
- AcceptanceTestRequestScope.Context old = setApiUser(account);
- try {
- gApi.changes().id(id.get()).current().review(rin);
- } finally {
- atrScope.set(old);
- }
- }
-
- private void publishDrafts(TestAccount account, Change.Id id) throws Exception {
- ReviewInput rin = new ReviewInput();
- rin.drafts = ReviewInput.DraftHandling.PUBLISH_ALL_REVISIONS;
- AcceptanceTestRequestScope.Context old = setApiUser(account);
- try {
- gApi.changes().id(id.get()).current().review(rin);
- } finally {
- atrScope.set(old);
- }
- }
-
- private ChangeMessage insertMessage(
- Change.Id id, PatchSet.Id psId, Account.Id author, Timestamp ts, String message)
- throws Exception {
- ChangeMessage msg =
- new ChangeMessage(new ChangeMessage.Key(id, ChangeUtil.messageUuid()), author, ts, psId);
- msg.setMessage(message);
- db.changeMessages().insert(Collections.singleton(msg));
-
- Change c = db.changes().get(id);
- if (ts.compareTo(c.getLastUpdatedOn()) > 0) {
- c.setLastUpdatedOn(ts);
- db.changes().update(Collections.singleton(c));
- }
-
- return msg;
- }
-
- private ReviewDb getUnwrappedDb() {
- ReviewDb db = dbProvider.get();
- return ReviewDbUtil.unwrapDb(db);
- }
-
- private void allowRunAs() throws Exception {
- try (ProjectConfigUpdate u = updateProject(allProjects)) {
- Util.allow(
- u.getConfig(),
- GlobalCapability.RUN_AS,
- systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
- u.save();
- }
- }
-
- private void removeRunAs() throws Exception {
- try (ProjectConfigUpdate u = updateProject(allProjects)) {
- Util.remove(
- u.getConfig(),
- GlobalCapability.RUN_AS,
- systemGroupBackend.getGroup(REGISTERED_USERS).getUUID());
- u.save();
- }
- }
-
- private Map<String, List<CommentInfo>> getPublishedComments(Change.Id id) throws Exception {
- return gApi.changes().id(id.get()).current().comments();
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
index 8d6fecd..5047b73 100644
--- a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbOnlyIT.java
@@ -16,7 +16,6 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.extensions.client.ListChangesOption.MESSAGES;
import static java.util.stream.Collectors.toList;
@@ -56,7 +55,6 @@
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.revwalk.RevSort;
import org.eclipse.jgit.revwalk.RevWalk;
-import org.junit.Before;
import org.junit.Test;
public class NoteDbOnlyIT extends AbstractDaemonTest {
@@ -70,14 +68,8 @@
@Inject private RetryHelper retryHelper;
- @Before
- public void setUp() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
- }
-
@Test
public void updateChangeFailureRollsBackRefUpdate() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
PushOneCommit.Result r = createChange();
Change.Id id = r.getChange().getId();
@@ -149,7 +141,6 @@
@Test
public void retryOnLockFailureWithAtomicUpdates() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
PushOneCommit.Result r = createChange();
Change.Id id = r.getChange().getId();
String master = "refs/heads/master";
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java
deleted file mode 100644
index 26d5461..0000000
--- a/javatests/com/google/gerrit/acceptance/server/notedb/NoteDbPrimaryIT.java
+++ /dev/null
@@ -1,524 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage.REVIEW_DB;
-import static com.google.gerrit.server.notedb.NoteDbUtil.formatTime;
-import static java.util.concurrent.TimeUnit.DAYS;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static java.util.stream.Collectors.toList;
-
-import com.github.rholder.retry.Retryer;
-import com.github.rholder.retry.RetryerBuilder;
-import com.github.rholder.retry.StopStrategies;
-import com.google.common.base.Throwables;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.Iterables;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.extensions.api.changes.DraftInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput;
-import com.google.gerrit.extensions.api.changes.ReviewInput.CommentInput;
-import com.google.gerrit.extensions.client.ChangeStatus;
-import com.google.gerrit.extensions.common.ApprovalInfo;
-import com.google.gerrit.extensions.common.ChangeInfo;
-import com.google.gerrit.extensions.common.CommentInfo;
-import com.google.gerrit.extensions.restapi.RestApiException;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
-import com.google.gerrit.server.ChangeMessagesUtil;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.InternalUser;
-import com.google.gerrit.server.git.RepoRefCache;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.PrimaryStorageMigrator;
-import com.google.gerrit.server.notedb.TestChangeRebuilderWrapper;
-import com.google.gerrit.server.update.RetryHelper;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.ConfigSuite;
-import com.google.gerrit.testing.NoteDbMode;
-import com.google.gerrit.testing.TestTimeUtil;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.OrmRuntimeException;
-import com.google.inject.Inject;
-import com.google.inject.util.Providers;
-import java.sql.Timestamp;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.List;
-import java.util.Optional;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevCommit;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-@NoHttpd
-public class NoteDbPrimaryIT extends AbstractDaemonTest {
- @ConfigSuite.Default
- public static Config defaultConfig() {
- Config cfg = new Config();
- cfg.setString("notedb", null, "concurrentWriterTimeout", "0s");
- cfg.setString("notedb", null, "primaryStorageMigrationTimeout", "1d");
- cfg.setBoolean("noteDb", null, "testRebuilderWrapper", true);
- return cfg;
- }
-
- @Inject private ChangeBundleReader bundleReader;
- @Inject private CommentsUtil commentsUtil;
- @Inject private TestChangeRebuilderWrapper rebuilderWrapper;
- @Inject private ChangeNotes.Factory changeNotesFactory;
- @Inject private ChangeUpdate.Factory updateFactory;
- @Inject private InternalUser.Factory internalUserFactory;
- @Inject private RetryHelper retryHelper;
-
- private PrimaryStorageMigrator migrator;
-
- @Before
- public void setUp() throws Exception {
- assume().that(NoteDbMode.get()).isEqualTo(NoteDbMode.READ_WRITE);
- db = ReviewDbUtil.unwrapDb(db);
- TestTimeUtil.resetWithClockStep(1, SECONDS);
- migrator = newMigrator(null);
- }
-
- private PrimaryStorageMigrator newMigrator(
- @Nullable Retryer<NoteDbChangeState> ensureRebuiltRetryer) {
- return new PrimaryStorageMigrator(
- cfg,
- Providers.of(db),
- repoManager,
- allUsers,
- rebuilderWrapper,
- ensureRebuiltRetryer,
- changeNotesFactory,
- queryProvider,
- updateFactory,
- internalUserFactory,
- retryHelper);
- }
-
- @After
- public void tearDown() {
- TestTimeUtil.useSystemTime();
- }
-
- @Test
- public void updateChange() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
- gApi.changes().id(id.get()).current().submit();
-
- ChangeInfo info = gApi.changes().id(id.get()).get();
- assertThat(info.status).isEqualTo(ChangeStatus.MERGED);
- ApprovalInfo approval = Iterables.getOnlyElement(info.labels.get("Code-Review").all);
- assertThat(approval._accountId).isEqualTo(admin.id.get());
- assertThat(approval.value).isEqualTo(2);
- assertThat(info.messages).hasSize(3);
- assertThat(Iterables.getLast(info.messages).message)
- .isEqualTo("Change has been successfully merged by " + admin.fullName);
-
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getChange().getStatus()).isEqualTo(Change.Status.MERGED);
- assertThat(notes.getChange().getNoteDbState())
- .isEqualTo(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
-
- // Writes weren't reflected in ReviewDb.
- assertThat(db.changes().get(id).getStatus()).isEqualTo(Change.Status.NEW);
- assertThat(db.patchSetApprovals().byChange(id)).isEmpty();
- assertThat(db.changeMessages().byChange(id)).hasSize(1);
- }
-
- @Test
- public void deleteDraftComment() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
-
- DraftInput din = new DraftInput();
- din.path = PushOneCommit.FILE_NAME;
- din.line = 1;
- din.message = "A comment";
- gApi.changes().id(id.get()).current().createDraft(din);
-
- CommentInfo di =
- Iterables.getOnlyElement(
- gApi.changes().id(id.get()).current().drafts().get(PushOneCommit.FILE_NAME));
- assertThat(di.message).isEqualTo(din.message);
-
- assertThat(db.patchComments().draftByChangeFileAuthor(id, din.path, admin.id)).isEmpty();
-
- gApi.changes().id(id.get()).current().draft(di.id).delete();
- assertThat(gApi.changes().id(id.get()).current().drafts()).isEmpty();
- }
-
- @Test
- public void deleteVote() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
- List<ApprovalInfo> approvals = gApi.changes().id(id.get()).get().labels.get("Code-Review").all;
- assertThat(approvals).hasSize(1);
- assertThat(approvals.get(0).value).isEqualTo(2);
-
- gApi.changes().id(id.get()).reviewer(admin.id.toString()).deleteVote("Code-Review");
-
- approvals = gApi.changes().id(id.get()).get().labels.get("Code-Review").all;
- assertThat(approvals).hasSize(1);
- assertThat(approvals.get(0).value).isEqualTo(0);
- }
-
- @Test
- public void deleteVoteViaReview() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
- List<ApprovalInfo> approvals = gApi.changes().id(id.get()).get().labels.get("Code-Review").all;
- assertThat(approvals).hasSize(1);
- assertThat(approvals.get(0).value).isEqualTo(2);
-
- gApi.changes().id(id.get()).current().review(ReviewInput.noScore());
-
- approvals = gApi.changes().id(id.get()).get().labels.get("Code-Review").all;
- assertThat(approvals).hasSize(1);
- assertThat(approvals.get(0).value).isEqualTo(0);
- }
-
- @Test
- public void deleteReviewer() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).addReviewer(user.id.toString());
- assertThat(getReviewers(id)).containsExactly(user.id);
- gApi.changes().id(id.get()).reviewer(user.id.toString()).remove();
- assertThat(getReviewers(id)).isEmpty();
- }
-
- @Test
- public void readOnlyReviewDb() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- testReadOnly(id);
- }
-
- @Test
- public void readOnlyNoteDb() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- setNoteDbPrimary(id);
- testReadOnly(id);
- }
-
- private void testReadOnly(Change.Id id) throws Exception {
- Timestamp before = TimeUtil.nowTs();
- Timestamp until = new Timestamp(before.getTime() + 1000 * 3600);
-
- // Set read-only.
- Change c = db.changes().get(id);
- assertThat(c).named("change " + id).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- state = state.withReadOnlyUntil(until);
- c.setNoteDbState(state.toString());
- db.changes().update(Collections.singleton(c));
-
- assertThat(gApi.changes().id(id.get()).get().subject).isEqualTo(PushOneCommit.SUBJECT);
- assertThat(gApi.changes().id(id.get()).get().topic).isNull();
- try {
- gApi.changes().id(id.get()).topic("a-topic");
- fail("expected read-only exception");
- } catch (RestApiException e) {
- Optional<Throwable> oe =
- Throwables.getCausalChain(e)
- .stream()
- .filter(x -> x instanceof OrmRuntimeException)
- .findFirst();
- assertThat(oe).named("OrmRuntimeException in causal chain of " + e).isPresent();
- assertThat(oe.get().getMessage()).contains("read-only");
- }
- assertThat(gApi.changes().id(id.get()).get().topic).isNull();
-
- TestTimeUtil.setClock(new Timestamp(until.getTime() + 1000));
- assertThat(gApi.changes().id(id.get()).get().subject).isEqualTo(PushOneCommit.SUBJECT);
- gApi.changes().id(id.get()).topic("a-topic");
- assertThat(gApi.changes().id(id.get()).get().topic).isEqualTo("a-topic");
- }
-
- @Test
- public void migrateToNoteDb() throws Exception {
- testMigrateToNoteDb(createChange().getChange().getId());
- }
-
- @Test
- public void migrateToNoteDbWithRebuildingFirst() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- Change c = db.changes().get(id);
- c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- db.changes().update(Collections.singleton(c));
- testMigrateToNoteDb(id);
- }
-
- private void testMigrateToNoteDb(Change.Id id) throws Exception {
- assertThat(PrimaryStorage.of(db.changes().get(id))).isEqualTo(PrimaryStorage.REVIEW_DB);
- migrator.migrateToNoteDbPrimary(id);
- assertNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).topic("a-topic");
- assertThat(gApi.changes().id(id.get()).get().topic).isEqualTo("a-topic");
- assertThat(db.changes().get(id).getTopic()).isNull();
- }
-
- @Test
- public void migrateToNoteDbFailsRebuildingOnceAndRetries() throws Exception {
- Change.Id id = createChange().getChange().getId();
-
- Change c = db.changes().get(id);
- c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- db.changes().update(Collections.singleton(c));
- rebuilderWrapper.failNextUpdate();
-
- migrator =
- newMigrator(
- RetryerBuilder.<NoteDbChangeState>newBuilder()
- .retryIfException()
- .withStopStrategy(StopStrategies.neverStop())
- .build());
- migrator.migrateToNoteDbPrimary(id);
- assertNoteDbPrimary(id);
- }
-
- @Test
- public void migrateToNoteDbFailsRebuildingAndStops() throws Exception {
- Change.Id id = createChange().getChange().getId();
-
- Change c = db.changes().get(id);
- c.setNoteDbState("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef");
- db.changes().update(Collections.singleton(c));
- rebuilderWrapper.failNextUpdate();
-
- migrator =
- newMigrator(
- RetryerBuilder.<NoteDbChangeState>newBuilder()
- .retryIfException()
- .withStopStrategy(StopStrategies.stopAfterAttempt(1))
- .build());
- exception.expect(OrmException.class);
- exception.expectMessage("Retrying failed");
- migrator.migrateToNoteDbPrimary(id);
- }
-
- @Test
- public void migrateToNoteDbMissingOldState() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- Change c = db.changes().get(id);
- c.setNoteDbState(null);
- db.changes().update(Collections.singleton(c));
-
- exception.expect(PrimaryStorageMigrator.NoNoteDbStateException.class);
- exception.expectMessage("no note_db_state");
- migrator.migrateToNoteDbPrimary(id);
- }
-
- @Test
- public void migrateToNoteDbLeaseExpires() throws Exception {
- TestTimeUtil.resetWithClockStep(2, DAYS);
- exception.expect(OrmRuntimeException.class);
- exception.expectMessage("read-only lease");
- migrator.migrateToNoteDbPrimary(createChange().getChange().getId());
- }
-
- @Test
- public void migrateToNoteDbAlreadyReadOnly() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- Change c = db.changes().get(id);
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- Timestamp until = new Timestamp(TimeUtil.nowMs() + MILLISECONDS.convert(1, DAYS));
- state = state.withReadOnlyUntil(until);
- c.setNoteDbState(state.toString());
- db.changes().update(Collections.singleton(c));
-
- exception.expect(OrmRuntimeException.class);
- exception.expectMessage("read-only until " + until);
- migrator.migrateToNoteDbPrimary(id);
- }
-
- @Test
- public void migrateToNoteDbAlreadyMigrated() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- assertThat(PrimaryStorage.of(db.changes().get(id))).isEqualTo(PrimaryStorage.REVIEW_DB);
- migrator.migrateToNoteDbPrimary(id);
- assertNoteDbPrimary(id);
-
- migrator.migrateToNoteDbPrimary(id);
- assertNoteDbPrimary(id);
- }
-
- @Test
- public void rebuildReviewDb() throws Exception {
- Change c = createChange().getChange().change();
- Change.Id id = c.getId();
-
- CommentInput cin = new CommentInput();
- cin.line = 1;
- cin.message = "Published comment";
- ReviewInput rin = ReviewInput.approve();
- rin.comments = ImmutableMap.of(PushOneCommit.FILE_NAME, ImmutableList.of(cin));
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
-
- DraftInput din = new DraftInput();
- din.path = PushOneCommit.FILE_NAME;
- din.line = 1;
- din.message = "Draft comment";
- gApi.changes().id(id.get()).current().createDraft(din);
- gApi.changes().id(id.get()).current().review(ReviewInput.approve());
- gApi.changes().id(id.get()).current().createDraft(din);
-
- assertThat(db.changeMessages().byChange(id)).isNotEmpty();
- assertThat(db.patchSets().byChange(id)).isNotEmpty();
- assertThat(db.patchSetApprovals().byChange(id)).isNotEmpty();
- assertThat(db.patchComments().byChange(id)).isNotEmpty();
-
- ChangeBundle noteDbBundle =
- ChangeBundle.fromNotes(commentsUtil, notesFactory.create(db, project, id));
-
- setNoteDbPrimary(id);
-
- db.changeMessages().delete(db.changeMessages().byChange(id));
- db.patchSets().delete(db.patchSets().byChange(id));
- db.patchSetApprovals().delete(db.patchSetApprovals().byChange(id));
- db.patchComments().delete(db.patchComments().byChange(id));
- ChangeMessage bogusMessage =
- ChangeMessagesUtil.newMessage(
- c.currentPatchSetId(),
- identifiedUserFactory.create(admin.getId()),
- TimeUtil.nowTs(),
- "some message",
- null);
- db.changeMessages().insert(Collections.singleton(bogusMessage));
-
- rebuilderWrapper.rebuildReviewDb(db, project, id);
-
- assertThat(db.changeMessages().byChange(id)).isNotEmpty();
- assertThat(db.patchSets().byChange(id)).isNotEmpty();
- assertThat(db.patchSetApprovals().byChange(id)).isNotEmpty();
- assertThat(db.patchComments().byChange(id)).isNotEmpty();
-
- ChangeBundle reviewDbBundle = bundleReader.fromReviewDb(ReviewDbUtil.unwrapDb(db), id);
- assertThat(reviewDbBundle.differencesFrom(noteDbBundle)).isEmpty();
- }
-
- @Test
- public void migrateBackToReviewDbPrimary() throws Exception {
- Change c = createChange().getChange().change();
- Change.Id id = c.getId();
-
- migrator.migrateToNoteDbPrimary(id);
- assertNoteDbPrimary(id);
-
- gApi.changes().id(id.get()).topic("new-topic");
- assertThat(gApi.changes().id(id.get()).topic()).isEqualTo("new-topic");
- assertThat(db.changes().get(id).getTopic()).isNotEqualTo("new-topic");
-
- migrator.migrateToReviewDbPrimary(id, null);
- ObjectId metaId;
- try (Repository repo = repoManager.openRepository(c.getProject());
- RevWalk rw = new RevWalk(repo)) {
- metaId = repo.exactRef(RefNames.changeMetaRef(id)).getObjectId();
- RevCommit commit = rw.parseCommit(metaId);
- rw.parseBody(commit);
- assertThat(commit.getFullMessage())
- .contains("Read-only-until: " + formatTime(serverIdent.get(), new Timestamp(0)));
- }
- NoteDbChangeState state = NoteDbChangeState.parse(db.changes().get(id));
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.getChangeMetaId()).isEqualTo(metaId);
- assertThat(gApi.changes().id(id.get()).topic()).isEqualTo("new-topic");
- assertThat(db.changes().get(id).getTopic()).isEqualTo("new-topic");
-
- ChangeNotes notes = notesFactory.create(db, project, id);
- assertThat(notes.getRevision()).isEqualTo(metaId); // No rebuilding, change was up to date.
- assertThat(notes.getReadOnlyUntil()).isNotNull();
-
- gApi.changes().id(id.get()).topic("reviewdb-topic");
- assertThat(db.changes().get(id).getTopic()).isEqualTo("reviewdb-topic");
- }
-
- private void setNoteDbPrimary(Change.Id id) throws Exception {
- Change c = db.changes().get(id);
- assertThat(c).named("change " + id).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state.getPrimaryStorage()).named("storage of " + id).isEqualTo(REVIEW_DB);
-
- try (Repository changeRepo = repoManager.openRepository(c.getProject());
- Repository allUsersRepo = repoManager.openRepository(allUsers)) {
- assertThat(state.isUpToDate(new RepoRefCache(changeRepo), new RepoRefCache(allUsersRepo)))
- .named("change " + id + " up to date")
- .isTrue();
- }
-
- c.setNoteDbState(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
- db.changes().update(Collections.singleton(c));
- }
-
- private void assertNoteDbPrimary(Change.Id id) throws Exception {
- assertThat(PrimaryStorage.of(db.changes().get(id))).isEqualTo(PrimaryStorage.NOTE_DB);
- }
-
- private List<Account.Id> getReviewers(Change.Id id) throws Exception {
- return gApi.changes()
- .id(id.get())
- .get()
- .reviewers
- .values()
- .stream()
- .flatMap(Collection::stream)
- .map(a -> new Account.Id(a._accountId))
- .collect(toList());
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java b/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java
deleted file mode 100644
index 6f226c8..0000000
--- a/javatests/com/google/gerrit/acceptance/server/notedb/OnlineNoteDbMigrationIT.java
+++ /dev/null
@@ -1,629 +0,0 @@
-// Copyright (C) 2017 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.notedb;
-
-import static com.google.common.collect.ImmutableSortedSet.toImmutableSortedSet;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
-import static com.google.gerrit.server.notedb.NoteDbChangeState.NOTE_DB_PRIMARY_STATE;
-import static com.google.gerrit.server.notedb.NotesMigrationState.NOTE_DB;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_NO_SEQUENCE;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY;
-import static com.google.gerrit.server.notedb.NotesMigrationState.READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY;
-import static com.google.gerrit.server.notedb.NotesMigrationState.REVIEW_DB;
-import static com.google.gerrit.server.notedb.NotesMigrationState.WRITE;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Comparator.naturalOrder;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.expectLastCall;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSortedSet;
-import com.google.gerrit.acceptance.AbstractDaemonTest;
-import com.google.gerrit.acceptance.GerritConfig;
-import com.google.gerrit.acceptance.NoHttpd;
-import com.google.gerrit.acceptance.PushOneCommit;
-import com.google.gerrit.acceptance.Sandboxed;
-import com.google.gerrit.acceptance.UseLocalDisk;
-import com.google.gerrit.acceptance.testsuite.project.ProjectOperations;
-import com.google.gerrit.extensions.registration.DynamicSet;
-import com.google.gerrit.extensions.registration.RegistrationHandle;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.CommentsUtil;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.notedb.ChangeBundle;
-import com.google.gerrit.server.notedb.ChangeBundleReader;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
-import com.google.gerrit.server.notedb.NoteDbChangeState.RefState;
-import com.google.gerrit.server.notedb.NotesMigrationState;
-import com.google.gerrit.server.notedb.rebuild.MigrationException;
-import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
-import com.google.gerrit.server.notedb.rebuild.NotesMigrationStateListener;
-import com.google.gerrit.server.schema.ReviewDbFactory;
-import com.google.gerrit.testing.ConfigSuite;
-import com.google.gerrit.testing.NoteDbMode;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Stream;
-import org.eclipse.jgit.internal.storage.file.FileRepository;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.Constants;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectLoader;
-import org.eclipse.jgit.lib.ObjectReader;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.RefUpdate;
-import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-@Sandboxed
-@UseLocalDisk
-@NoHttpd
-public class OnlineNoteDbMigrationIT extends AbstractDaemonTest {
- private static final String INVALID_STATE = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
- @Inject private ProjectOperations projectOperations;
-
- @ConfigSuite.Default
- public static Config defaultConfig() {
- Config cfg = new Config();
- cfg.setInt("noteDb", "changes", "sequenceBatchSize", 10);
- cfg.setInt("noteDb", "changes", "initialSequenceGap", 500);
- return cfg;
- }
-
- // Tests in this class are generally interested in the actual ReviewDb contents, but the shifting
- // migration state may result in various kinds of wrappers showing up unexpectedly.
- @Inject @ReviewDbFactory private SchemaFactory<ReviewDb> schemaFactory;
-
- @Inject private ChangeBundleReader changeBundleReader;
- @Inject private CommentsUtil commentsUtil;
- @Inject private DynamicSet<NotesMigrationStateListener> listeners;
- @Inject private Provider<NoteDbMigrator.Builder> migratorBuilderProvider;
- @Inject private Sequences sequences;
- @Inject private SitePaths sitePaths;
-
- private FileBasedConfig noteDbConfig;
- private List<RegistrationHandle> addedListeners;
-
- @Before
- public void setUp() throws Exception {
- assume().that(NoteDbMode.get()).isEqualTo(NoteDbMode.OFF);
- // Unlike in the running server, for tests, we don't stack notedb.config on gerrit.config.
- noteDbConfig = new FileBasedConfig(sitePaths.notedb_config.toFile(), FS.detect());
- assertNotesMigrationState(REVIEW_DB, false, false);
- addedListeners = new ArrayList<>();
- }
-
- @After
- public void tearDown() throws Exception {
- if (addedListeners != null) {
- addedListeners.forEach(RegistrationHandle::remove);
- addedListeners = null;
- }
- }
-
- @Test
- public void preconditionsFail() throws Exception {
- List<Change.Id> cs = ImmutableList.of(new Change.Id(1));
- List<Project.NameKey> ps = ImmutableList.of(new Project.NameKey("p"));
- assertMigrationException(
- "Cannot rebuild without noteDb.changes.write=true", b -> b, NoteDbMigrator::rebuild);
- assertMigrationException(
- "Cannot set both changes and projects", b -> b.setChanges(cs).setProjects(ps), m -> {});
- assertMigrationException(
- "Cannot set changes or projects during full migration",
- b -> b.setChanges(cs),
- NoteDbMigrator::migrate);
- assertMigrationException(
- "Cannot set changes or projects during full migration",
- b -> b.setProjects(ps),
- NoteDbMigrator::migrate);
-
- setNotesMigrationState(READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY);
- assertMigrationException(
- "Migration has already progressed past the endpoint of the \"trial mode\" state",
- b -> b.setTrialMode(true),
- NoteDbMigrator::migrate);
-
- setNotesMigrationState(READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY);
- assertMigrationException(
- "Cannot force rebuild changes; NoteDb is already the primary storage for some changes",
- b -> b.setForceRebuild(true),
- NoteDbMigrator::migrate);
- }
-
- @Test
- @GerritConfig(name = "noteDb.changes.initialSequenceGap", value = "-7")
- public void initialSequenceGapMustBeNonNegative() throws Exception {
- setNotesMigrationState(READ_WRITE_NO_SEQUENCE);
- assertMigrationException("Sequence gap must be non-negative: -7", b -> b, m -> {});
- }
-
- @Test
- public void rebuildOneChangeTrialModeAndForceRebuild() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- migrate(b -> b.setTrialMode(true));
- assertNotesMigrationState(READ_WRITE_NO_SEQUENCE, false, true);
-
- ObjectId oldMetaId;
- try (Repository repo = repoManager.openRepository(project);
- ReviewDb db = schemaFactory.open()) {
- Ref ref = repo.exactRef(RefNames.changeMetaRef(id));
- assertThat(ref).isNotNull();
- oldMetaId = ref.getObjectId();
-
- Change c = db.changes().get(id);
- assertThat(c).isNotNull();
- NoteDbChangeState state = NoteDbChangeState.parse(c);
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.getRefState()).hasValue(RefState.create(oldMetaId, ImmutableMap.of()));
-
- // Force change to be out of date, and change topic so it will get rebuilt as something other
- // than oldMetaId.
- c.setNoteDbState(INVALID_STATE);
- c.setTopic(name("a-new-topic"));
- db.changes().update(ImmutableList.of(c));
- }
-
- migrate(b -> b.setTrialMode(true));
- assertNotesMigrationState(READ_WRITE_NO_SEQUENCE, false, true);
-
- try (Repository repo = repoManager.openRepository(project);
- ReviewDb db = schemaFactory.open()) {
- // Change is out of date, but was not rebuilt without forceRebuild.
- assertThat(repo.exactRef(RefNames.changeMetaRef(id)).getObjectId()).isEqualTo(oldMetaId);
- Change c = db.changes().get(id);
- assertThat(c.getNoteDbState()).isEqualTo(INVALID_STATE);
- }
-
- migrate(b -> b.setTrialMode(true).setForceRebuild(true));
- assertNotesMigrationState(READ_WRITE_NO_SEQUENCE, false, true);
-
- try (Repository repo = repoManager.openRepository(project);
- ReviewDb db = schemaFactory.open()) {
- Ref ref = repo.exactRef(RefNames.changeMetaRef(id));
- assertThat(ref).isNotNull();
- ObjectId newMetaId = ref.getObjectId();
- assertThat(newMetaId).isNotEqualTo(oldMetaId);
-
- NoteDbChangeState state = NoteDbChangeState.parse(db.changes().get(id));
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.getRefState()).hasValue(RefState.create(newMetaId, ImmutableMap.of()));
- }
- }
-
- @Test
- public void autoMigrateTrialMode() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- migrate(b -> b.setAutoMigrate(true).setTrialMode(true).setStopAtStateForTesting(WRITE));
- assertNotesMigrationState(WRITE, true, true);
-
- migrate(b -> b);
- // autoMigrate is still enabled so that we can continue the migration by only unsetting trial.
- assertNotesMigrationState(READ_WRITE_NO_SEQUENCE, true, true);
-
- ObjectId metaId;
- try (Repository repo = repoManager.openRepository(project);
- ReviewDb db = schemaFactory.open()) {
- Ref ref = repo.exactRef(RefNames.changeMetaRef(id));
- assertThat(ref).isNotNull();
- metaId = ref.getObjectId();
- NoteDbChangeState state = NoteDbChangeState.parse(db.changes().get(id));
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- assertThat(state.getRefState()).hasValue(RefState.create(metaId, ImmutableMap.of()));
- }
-
- // Unset trial mode and the next migration runs to completion.
- noteDbConfig.load();
- NoteDbMigrator.setTrialMode(noteDbConfig, false);
- noteDbConfig.save();
-
- migrate(b -> b);
- assertNotesMigrationState(NOTE_DB, false, false);
-
- try (Repository repo = repoManager.openRepository(project);
- ReviewDb db = schemaFactory.open()) {
- Ref ref = repo.exactRef(RefNames.changeMetaRef(id));
- assertThat(ref).isNotNull();
- assertThat(ref.getObjectId()).isEqualTo(metaId);
- NoteDbChangeState state = NoteDbChangeState.parse(db.changes().get(id));
- assertThat(state).isNotNull();
- assertThat(state.getPrimaryStorage()).isEqualTo(PrimaryStorage.NOTE_DB);
- }
- }
-
- @Test
- public void rebuildSubsetOfChanges() throws Exception {
- setNotesMigrationState(WRITE);
-
- PushOneCommit.Result r1 = createChange();
- PushOneCommit.Result r2 = createChange();
- Change.Id id1 = r1.getChange().getId();
- Change.Id id2 = r2.getChange().getId();
-
- try (ReviewDb db = schemaFactory.open()) {
- Change c1 = db.changes().get(id1);
- c1.setNoteDbState(INVALID_STATE);
- Change c2 = db.changes().get(id2);
- c2.setNoteDbState(INVALID_STATE);
- db.changes().update(ImmutableList.of(c1, c2));
- }
-
- migrate(b -> b.setChanges(ImmutableList.of(id2)), NoteDbMigrator::rebuild);
-
- try (ReviewDb db = schemaFactory.open()) {
- NoteDbChangeState s1 = NoteDbChangeState.parse(db.changes().get(id1));
- assertThat(s1.getChangeMetaId().name()).isEqualTo(INVALID_STATE);
-
- NoteDbChangeState s2 = NoteDbChangeState.parse(db.changes().get(id2));
- assertThat(s2.getChangeMetaId().name()).isNotEqualTo(INVALID_STATE);
- }
- }
-
- @Test
- public void rebuildSubsetOfProjects() throws Exception {
- setNotesMigrationState(WRITE);
-
- Project.NameKey p2 = projectOperations.newProject().create();
- TestRepository<?> tr2 = cloneProject(p2, admin);
-
- PushOneCommit.Result r1 = createChange();
- PushOneCommit.Result r2 = pushFactory.create(db, admin.getIdent(), tr2).to("refs/for/master");
- Change.Id id1 = r1.getChange().getId();
- Change.Id id2 = r2.getChange().getId();
-
- String invalidState = "deadbeefdeadbeefdeadbeefdeadbeefdeadbeef";
- try (ReviewDb db = schemaFactory.open()) {
- Change c1 = db.changes().get(id1);
- c1.setNoteDbState(invalidState);
- Change c2 = db.changes().get(id2);
- c2.setNoteDbState(invalidState);
- db.changes().update(ImmutableList.of(c1, c2));
- }
-
- migrate(b -> b.setProjects(ImmutableList.of(p2)), NoteDbMigrator::rebuild);
-
- try (ReviewDb db = schemaFactory.open()) {
- NoteDbChangeState s1 = NoteDbChangeState.parse(db.changes().get(id1));
- assertThat(s1.getChangeMetaId().name()).isEqualTo(invalidState);
-
- NoteDbChangeState s2 = NoteDbChangeState.parse(db.changes().get(id2));
- assertThat(s2.getChangeMetaId().name()).isNotEqualTo(invalidState);
- }
- }
-
- @Test
- public void enableSequencesNoGap() throws Exception {
- testEnableSequences(0, 3, "13");
- }
-
- @Test
- public void enableSequencesWithGap() throws Exception {
- testEnableSequences(-1, 502, "512");
- }
-
- private void testEnableSequences(int builderOption, int expectedFirstId, String expectedRefValue)
- throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
- assertThat(id.get()).isEqualTo(1);
-
- migrate(
- b ->
- b.setSequenceGap(builderOption)
- .setStopAtStateForTesting(READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY));
-
- assertThat(sequences.nextChangeId()).isEqualTo(expectedFirstId);
- assertThat(sequences.nextChangeId()).isEqualTo(expectedFirstId + 1);
-
- try (Repository repo = repoManager.openRepository(allProjects);
- ObjectReader reader = repo.newObjectReader()) {
- Ref ref = repo.exactRef("refs/sequences/changes");
- assertThat(ref).isNotNull();
- ObjectLoader loader = reader.open(ref.getObjectId());
- assertThat(loader.getType()).isEqualTo(Constants.OBJ_BLOB);
- // Acquired a block of 10 to serve the first nextChangeId call after migration.
- assertThat(new String(loader.getCachedBytes(), UTF_8)).isEqualTo(expectedRefValue);
- }
-
- try (ReviewDb db = schemaFactory.open()) {
- // Underlying, unused ReviewDb is still on its own sequence.
- @SuppressWarnings("deprecation")
- int nextFromReviewDb = db.nextChangeId();
- assertThat(nextFromReviewDb).isEqualTo(3);
- }
- }
-
- @Test
- public void fullMigrationSameThread() throws Exception {
- testFullMigration(1);
- }
-
- @Test
- public void fullMigrationMultipleThreads() throws Exception {
- testFullMigration(2);
- }
-
- private void testFullMigration(int threads) throws Exception {
- PushOneCommit.Result r1 = createChange();
- PushOneCommit.Result r2 = createChange();
- Change.Id id1 = r1.getChange().getId();
- Change.Id id2 = r2.getChange().getId();
-
- Set<String> objectFiles = getObjectFiles(project);
- assertThat(objectFiles).isNotEmpty();
-
- migrate(b -> b.setThreads(threads));
-
- assertNotesMigrationState(NOTE_DB, false, false);
- assertThat(sequences.nextChangeId()).isEqualTo(503);
- assertThat(getObjectFiles(project)).containsExactlyElementsIn(objectFiles);
-
- ObjectId oldMetaId = null;
- int rowVersion = 0;
- try (ReviewDb db = schemaFactory.open();
- Repository repo = repoManager.openRepository(project)) {
- for (Change.Id id : ImmutableList.of(id1, id2)) {
- String refName = RefNames.changeMetaRef(id);
- Ref ref = repo.exactRef(refName);
- assertThat(ref).named(refName).isNotNull();
-
- Change c = db.changes().get(id);
- assertThat(c.getTopic()).named("topic of change %s", id).isNull();
- NoteDbChangeState s = NoteDbChangeState.parse(c);
- assertThat(s.getPrimaryStorage())
- .named("primary storage of change %s", id)
- .isEqualTo(PrimaryStorage.NOTE_DB);
- assertThat(s.getRefState()).named("ref state of change %s").isEmpty();
-
- if (id.equals(id1)) {
- oldMetaId = ref.getObjectId();
- rowVersion = c.getRowVersion();
- }
- }
- }
-
- // Do not open a new context, to simulate races with other threads that opened a context earlier
- // in the migration process; this needs to work.
- gApi.changes().id(id1.get()).topic(name("a-topic"));
-
- // Of course, it should also work with a new context.
- resetCurrentApiUser();
- gApi.changes().id(id1.get()).topic(name("another-topic"));
-
- try (ReviewDb db = schemaFactory.open();
- Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef(RefNames.changeMetaRef(id1)).getObjectId()).isNotEqualTo(oldMetaId);
-
- Change c = db.changes().get(id1);
- assertThat(c.getTopic()).isNull();
- assertThat(c.getRowVersion()).isEqualTo(rowVersion);
- }
- }
-
- @Test
- public void fullMigrationOneChangeWithNoPatchSets() throws Exception {
- PushOneCommit.Result r1 = createChange();
- PushOneCommit.Result r2 = createChange();
- Change.Id id1 = r1.getChange().getId();
- Change.Id id2 = r2.getChange().getId();
-
- db.changes().beginTransaction(id2);
- try {
- db.patchSets().delete(db.patchSets().byChange(id2));
- db.commit();
- } finally {
- db.rollback();
- }
-
- migrate(b -> b);
- assertNotesMigrationState(NOTE_DB, false, false);
-
- try (ReviewDb db = schemaFactory.open();
- Repository repo = repoManager.openRepository(project)) {
- assertThat(repo.exactRef(RefNames.changeMetaRef(id1))).isNotNull();
- assertThat(db.changes().get(id1).getNoteDbState()).isEqualTo(NOTE_DB_PRIMARY_STATE);
-
- // A change with no patch sets is so corrupt that it is completely skipped by the migration
- // process.
- assertThat(repo.exactRef(RefNames.changeMetaRef(id2))).isNull();
- assertThat(db.changes().get(id2).getNoteDbState()).isNull();
- }
- }
-
- @Test
- public void fullMigrationMissingPatchSetRefs() throws Exception {
- PushOneCommit.Result r = createChange();
- Change.Id id = r.getChange().getId();
-
- try (Repository repo = repoManager.openRepository(project)) {
- RefUpdate u = repo.updateRef(new PatchSet.Id(id, 1).toRefName());
- u.setForceUpdate(true);
- assertThat(u.delete()).isEqualTo(RefUpdate.Result.FORCED);
- }
-
- ChangeBundle reviewDbBundle;
- try (ReviewDb db = schemaFactory.open()) {
- reviewDbBundle = changeBundleReader.fromReviewDb(db, id);
- }
-
- migrate(b -> b);
- assertNotesMigrationState(NOTE_DB, false, false);
-
- try (ReviewDb db = schemaFactory.open();
- Repository repo = repoManager.openRepository(project)) {
- // Change migrated successfully even though it was missing patch set refs.
- assertThat(repo.exactRef(RefNames.changeMetaRef(id))).isNotNull();
- assertThat(db.changes().get(id).getNoteDbState()).isEqualTo(NOTE_DB_PRIMARY_STATE);
-
- ChangeBundle noteDbBundle =
- ChangeBundle.fromNotes(commentsUtil, notesFactory.createChecked(db, project, id));
- assertThat(noteDbBundle.differencesFrom(reviewDbBundle)).isEmpty();
- }
- }
-
- @Test
- public void autoMigrationConfig() throws Exception {
- createChange();
-
- migrate(b -> b.setStopAtStateForTesting(WRITE));
- assertNotesMigrationState(WRITE, false, false);
-
- migrate(b -> b.setAutoMigrate(true).setStopAtStateForTesting(READ_WRITE_NO_SEQUENCE));
- assertNotesMigrationState(READ_WRITE_NO_SEQUENCE, true, false);
-
- migrate(b -> b);
- assertNotesMigrationState(NOTE_DB, false, false);
- }
-
- @Test
- public void notesMigrationStateListener() throws Exception {
- NotesMigrationStateListener listener = createStrictMock(NotesMigrationStateListener.class);
- listener.preStateChange(REVIEW_DB, WRITE);
- expectLastCall();
- listener.preStateChange(WRITE, READ_WRITE_NO_SEQUENCE);
- expectLastCall();
- listener.preStateChange(READ_WRITE_NO_SEQUENCE, READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY);
- expectLastCall();
- listener.preStateChange(
- READ_WRITE_WITH_SEQUENCE_REVIEW_DB_PRIMARY, READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY);
- listener.preStateChange(READ_WRITE_WITH_SEQUENCE_NOTE_DB_PRIMARY, NOTE_DB);
- expectLastCall();
- replay(listener);
- addListener(listener);
-
- createChange();
- migrate(b -> b);
- assertNotesMigrationState(NOTE_DB, false, false);
- verify(listener);
- }
-
- @Test
- public void notesMigrationStateListenerFails() throws Exception {
- NotesMigrationStateListener listener = createStrictMock(NotesMigrationStateListener.class);
- listener.preStateChange(REVIEW_DB, WRITE);
- expectLastCall();
- listener.preStateChange(WRITE, READ_WRITE_NO_SEQUENCE);
- IOException listenerException = new IOException("Listener failed");
- expectLastCall().andThrow(listenerException);
- replay(listener);
- addListener(listener);
-
- createChange();
- try {
- migrate(b -> b);
- fail("expected IOException");
- } catch (IOException e) {
- assertThat(e).isSameAs(listenerException);
- }
- assertNotesMigrationState(WRITE, false, false);
- verify(listener);
- }
-
- private void assertNotesMigrationState(
- NotesMigrationState expected, boolean autoMigrate, boolean trialMode) throws Exception {
- assertThat(NotesMigrationState.forNotesMigration(notesMigration)).hasValue(expected);
- noteDbConfig.load();
- assertThat(NotesMigrationState.forConfig(noteDbConfig)).hasValue(expected);
- assertThat(NoteDbMigrator.getAutoMigrate(noteDbConfig))
- .named("noteDb.changes.autoMigrate")
- .isEqualTo(autoMigrate);
- assertThat(NoteDbMigrator.getTrialMode(noteDbConfig))
- .named("noteDb.changes.trial")
- .isEqualTo(trialMode);
- }
-
- private void setNotesMigrationState(NotesMigrationState state) throws Exception {
- noteDbConfig.load();
- state.setConfigValues(noteDbConfig);
- noteDbConfig.save();
- notesMigration.setFrom(state);
- }
-
- @FunctionalInterface
- interface PrepareBuilder {
- NoteDbMigrator.Builder prepare(NoteDbMigrator.Builder b) throws Exception;
- }
-
- @FunctionalInterface
- interface RunMigration {
- void run(NoteDbMigrator m) throws Exception;
- }
-
- private void migrate(PrepareBuilder b) throws Exception {
- migrate(b, NoteDbMigrator::migrate);
- }
-
- private void migrate(PrepareBuilder b, RunMigration m) throws Exception {
- try (NoteDbMigrator migrator = b.prepare(migratorBuilderProvider.get()).build()) {
- m.run(migrator);
- }
- }
-
- private void assertMigrationException(
- String expectMessageContains, PrepareBuilder b, RunMigration m) throws Exception {
- try {
- migrate(b, m);
- fail("expected MigrationException");
- } catch (MigrationException e) {
- assertThat(e).hasMessageThat().contains(expectMessageContains);
- }
- }
-
- private void addListener(NotesMigrationStateListener listener) {
- addedListeners.add(listeners.add("gerrit", listener));
- }
-
- private ImmutableSortedSet<String> getObjectFiles(Project.NameKey project) throws Exception {
- try (Repository repo = repoManager.openRepository(project);
- Stream<Path> paths =
- Files.walk(((FileRepository) repo).getObjectDatabase().getDirectory().toPath())) {
- return paths
- .filter(path -> !Files.isDirectory(path))
- .map(Path::toString)
- .filter(name -> !name.endsWith(".pack") && !name.endsWith(".idx"))
- .collect(toImmutableSortedSet(naturalOrder()));
- }
- }
-}
diff --git a/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java b/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
index 8abb59d..04303ea 100644
--- a/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
+++ b/javatests/com/google/gerrit/acceptance/server/project/ReflogIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.server.project;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -40,7 +39,6 @@
public class ReflogIT extends AbstractDaemonTest {
@Test
public void guessRestApiInReflog() throws Exception {
- assume().that(notesMigration.disableChangeReviewDb()).isTrue();
PushOneCommit.Result r = createChange();
Change.Id id = r.getChange().getId();
diff --git a/javatests/com/google/gerrit/acceptance/ssh/SshCommandsIT.java b/javatests/com/google/gerrit/acceptance/ssh/SshCommandsIT.java
index eb79c18..4e9c4a4 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/SshCommandsIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/SshCommandsIT.java
@@ -17,7 +17,6 @@
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.server.group.SystemGroupBackend.REGISTERED_USERS;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableMap;
@@ -27,7 +26,6 @@
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.Sandboxed;
import com.google.gerrit.acceptance.UseSsh;
-import com.google.gerrit.common.data.GlobalCapability;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -64,7 +62,6 @@
"create-branch",
"create-group",
"create-project",
- "gsql",
"index",
"query",
"receive-pack",
@@ -113,9 +110,6 @@
@Test
@Sandboxed
public void sshCommandCanBeExecuted() throws Exception {
- // Access Database capability is required to run the "gerrit gsql" command
- allowGlobalCapabilities(REGISTERED_USERS, GlobalCapability.ACCESS_DATABASE);
-
testCommandExecution(MASTER_COMMANDS);
restartAsSlave();
diff --git a/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java b/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
index 93fc769..03b7143 100644
--- a/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
+++ b/javatests/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
@@ -15,7 +15,6 @@
package com.google.gerrit.acceptance.ssh;
import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
import com.google.common.base.Splitter;
import com.google.gerrit.acceptance.AbstractDaemonTest;
@@ -23,7 +22,6 @@
import com.google.gerrit.acceptance.NoHttpd;
import com.google.gerrit.acceptance.PushOneCommit;
import com.google.gerrit.acceptance.UseSsh;
-import com.google.gerrit.testing.NoteDbMode;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
@@ -34,20 +32,12 @@
import org.eclipse.jgit.transport.PacketLineIn;
import org.eclipse.jgit.transport.PacketLineOut;
import org.eclipse.jgit.util.IO;
-import org.junit.Before;
import org.junit.Test;
@NoHttpd
@UseSsh
public class UploadArchiveIT extends AbstractDaemonTest {
- @Before
- public void setUp() {
- // There is some Guice request scoping problem preventing this test from
- // passing in CHECK mode.
- assume().that(NoteDbMode.get()).isNotEqualTo(NoteDbMode.CHECK);
- }
-
@Test
@GerritConfig(name = "download.archive", value = "off")
public void archiveFeatureOff() throws Exception {
diff --git a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
index 14fe4de..19ea44b 100644
--- a/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
+++ b/javatests/com/google/gerrit/elasticsearch/ElasticContainer.java
@@ -45,7 +45,7 @@
case V6_4:
return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.4.3";
case V6_5:
- return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.5.1";
+ return "docker.elastic.co/elasticsearch/elasticsearch-oss:6.5.2";
case V7_0:
return "docker.elastic.co/elasticsearch/elasticsearch-oss:7.0.0-alpha1";
}
diff --git a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
index b90ccf7c..d5add7d 100644
--- a/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
+++ b/javatests/com/google/gerrit/gpg/GerritPublicKeyCheckerTest.java
@@ -41,7 +41,7 @@
import com.google.gerrit.server.account.AccountsUpdate;
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.account.externalids.ExternalId;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.testing.GerritBaseTests;
@@ -81,7 +81,7 @@
@Inject private InMemoryDatabase schemaFactory;
- @Inject private ReviewDbSchemaCreator schemaCreator;
+ @Inject private SchemaCreator schemaCreator;
@Inject private ThreadLocalRequestContext requestContext;
@@ -112,7 +112,7 @@
lifecycle.start();
db = schemaFactory.open();
- schemaCreator.create(db);
+ schemaCreator.create();
userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
// Note: does not match any key in TestKeys.
accountsUpdateProvider
@@ -162,7 +162,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java b/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
deleted file mode 100644
index 159ff0d..0000000
--- a/javatests/com/google/gerrit/pgm/init/UpgradeFrom2_0_xTest.java
+++ /dev/null
@@ -1,115 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.pgm.init;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.easymock.EasyMock.createStrictMock;
-import static org.easymock.EasyMock.eq;
-import static org.easymock.EasyMock.expect;
-import static org.easymock.EasyMock.replay;
-import static org.easymock.EasyMock.verify;
-import static org.junit.Assert.assertEquals;
-import static org.junit.Assert.assertFalse;
-import static org.junit.Assert.assertNull;
-import static org.junit.Assert.assertTrue;
-
-import com.google.common.io.ByteStreams;
-import com.google.gerrit.common.FileUtil;
-import com.google.gerrit.pgm.init.api.ConsoleUI;
-import com.google.gerrit.pgm.init.api.InitFlags;
-import com.google.gerrit.pgm.init.api.Section;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.securestore.testing.InMemorySecureStore;
-import com.google.gerrit.testing.GerritBaseTests;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.Collections;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.storage.file.FileBasedConfig;
-import org.eclipse.jgit.util.FS;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-public class UpgradeFrom2_0_xTest extends GerritBaseTests {
- @Rule public TemporaryFolder folder = new TemporaryFolder();
-
- @Test
- public void upgrade() throws IOException, ConfigInvalidException {
- final Path p = folder.newFolder().toPath();
- final SitePaths site = new SitePaths(p);
- assertTrue(site.isNew);
- FileUtil.mkdirsOrDie(site.etc_dir, "Failed to create");
-
- for (String n : UpgradeFrom2_0_x.etcFiles) {
- Files.write(p.resolve(n), ("# " + n + "\n").getBytes(UTF_8));
- }
-
- FileBasedConfig old = new FileBasedConfig(p.resolve("gerrit.config").toFile(), FS.DETECTED);
-
- old.setString("ldap", null, "username", "ldap.user");
- old.setString("ldap", null, "password", "ldap.s3kr3t");
-
- old.setString("sendemail", null, "smtpUser", "email.user");
- old.setString("sendemail", null, "smtpPass", "email.s3kr3t");
- old.save();
-
- final InMemorySecureStore secureStore = new InMemorySecureStore();
- final InitFlags flags =
- new InitFlags(site, secureStore, Collections.<String>emptyList(), false);
- final ConsoleUI ui = createStrictMock(ConsoleUI.class);
- Section.Factory sections =
- new Section.Factory() {
- @Override
- public Section get(String name, String subsection) {
- return new Section(flags, site, secureStore, ui, name, subsection);
- }
- };
-
- expect(ui.yesno(eq(true), eq("Upgrade '%s'"), eq(p.toAbsolutePath().normalize())))
- .andReturn(true);
- replay(ui);
-
- UpgradeFrom2_0_x u = new UpgradeFrom2_0_x(site, flags, ui, sections);
- assertTrue(u.isNeedUpgrade());
- u.run();
- assertFalse(u.isNeedUpgrade());
- verify(ui);
-
- for (String n : UpgradeFrom2_0_x.etcFiles) {
- if ("gerrit.config".equals(n) || "secure.config".equals(n)) {
- continue;
- }
- try (InputStream in = Files.newInputStream(site.etc_dir.resolve(n))) {
- assertEquals("# " + n + "\n", new String(ByteStreams.toByteArray(in), UTF_8));
- }
- }
-
- FileBasedConfig cfg = new FileBasedConfig(site.gerrit_config.toFile(), FS.DETECTED);
- cfg.load();
-
- assertEquals("email.user", cfg.getString("sendemail", null, "smtpUser"));
- assertNull(cfg.getString("sendemail", null, "smtpPass"));
- assertEquals("email.s3kr3t", secureStore.get("sendemail", null, "smtpPass"));
-
- assertEquals("ldap.user", cfg.getString("ldap", null, "username"));
- assertNull(cfg.getString("ldap", null, "password"));
- assertEquals("ldap.s3kr3t", secureStore.get("ldap", null, "password"));
-
- u.run();
- }
-}
diff --git a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
index fe980f9..cc15b1b 100644
--- a/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
+++ b/javatests/com/google/gerrit/server/change/LabelNormalizerTest.java
@@ -44,7 +44,7 @@
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.server.util.time.TimeUtil;
@@ -72,7 +72,7 @@
@Inject private LabelNormalizer norm;
@Inject private MetaDataUpdate.User metaDataUpdateFactory;
@Inject private ProjectCache projectCache;
- @Inject private ReviewDbSchemaCreator schemaCreator;
+ @Inject private SchemaCreator schemaCreator;
@Inject protected ThreadLocalRequestContext requestContext;
@Inject private ChangeNotes.Factory changeNotesFactory;
@Inject private ProjectConfig.Factory projectConfigFactory;
@@ -94,7 +94,7 @@
lifecycle.start();
db = schemaFactory.open();
- schemaCreator.create(db);
+ schemaCreator.create();
userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
user = userFactory.create(userId);
@@ -148,7 +148,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
index d00f96b..ed4aacb 100644
--- a/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/AbstractChangeNotesTest.java
@@ -137,7 +137,7 @@
install(new GitModule());
install(new DefaultUrlFormatter.Module());
- install(NoteDbModule.forTest(testConfig));
+ install(NoteDbModule.forTest());
bind(AllUsersName.class).toProvider(AllUsersNameProvider.class);
bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
bind(GitRepositoryManager.class).toInstance(repoManager);
@@ -172,11 +172,6 @@
() -> {
throw new UnsupportedOperationException();
});
- bind(ChangeBundleReader.class)
- .toInstance(
- (db, id) -> {
- throw new UnsupportedOperationException();
- });
}
});
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeBundleTest.java b/javatests/com/google/gerrit/server/notedb/ChangeBundleTest.java
deleted file mode 100644
index fc2a272..0000000
--- a/javatests/com/google/gerrit/server/notedb/ChangeBundleTest.java
+++ /dev/null
@@ -1,1976 +0,0 @@
-// Copyright (C) 2016 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.notedb;
-
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.gerrit.server.notedb.ChangeBundle.Source.NOTE_DB;
-import static com.google.gerrit.server.notedb.ChangeBundle.Source.REVIEW_DB;
-import static com.google.gerrit.server.notedb.ReviewerStateInternal.CC;
-import static com.google.gerrit.server.notedb.ReviewerStateInternal.REVIEWER;
-import static com.google.gerrit.server.util.time.TimeUtil.truncateToSecond;
-import static java.util.concurrent.TimeUnit.MILLISECONDS;
-import static java.util.concurrent.TimeUnit.SECONDS;
-
-import com.google.common.collect.HashBasedTable;
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Table;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.ChangeMessage;
-import com.google.gerrit.reviewdb.client.LabelId;
-import com.google.gerrit.reviewdb.client.Patch;
-import com.google.gerrit.reviewdb.client.PatchLineComment;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.reviewdb.client.PatchSetApproval;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.client.RevId;
-import com.google.gerrit.server.ReviewerSet;
-import com.google.gerrit.server.notedb.rebuild.ChangeRebuilderImpl;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.TestChanges;
-import com.google.gerrit.testing.TestTimeUtil;
-import com.google.gwtorm.protobuf.CodecFactory;
-import com.google.gwtorm.protobuf.ProtobufCodec;
-import java.sql.Timestamp;
-import java.time.LocalDate;
-import java.time.Month;
-import java.time.ZoneId;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.TimeZone;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ChangeBundleTest extends GerritBaseTests {
- private static final ProtobufCodec<Change> CHANGE_CODEC = CodecFactory.encoder(Change.class);
- private static final ProtobufCodec<ChangeMessage> CHANGE_MESSAGE_CODEC =
- CodecFactory.encoder(ChangeMessage.class);
- private static final ProtobufCodec<PatchSet> PATCH_SET_CODEC =
- CodecFactory.encoder(PatchSet.class);
- private static final ProtobufCodec<PatchSetApproval> PATCH_SET_APPROVAL_CODEC =
- CodecFactory.encoder(PatchSetApproval.class);
- private static final ProtobufCodec<PatchLineComment> PATCH_LINE_COMMENT_CODEC =
- CodecFactory.encoder(PatchLineComment.class);
- private static final String TIMEZONE_ID = "US/Eastern";
-
- private String systemTimeZoneProperty;
- private TimeZone systemTimeZone;
-
- private Project.NameKey project;
- private Account.Id accountId;
-
- @Before
- public void setUp() {
- systemTimeZoneProperty = System.setProperty("user.timezone", TIMEZONE_ID);
- systemTimeZone = TimeZone.getDefault();
- TimeZone.setDefault(TimeZone.getTimeZone(TIMEZONE_ID));
- long maxMs = ChangeRebuilderImpl.MAX_WINDOW_MS;
- assertThat(maxMs).isGreaterThan(1000L);
- TestTimeUtil.resetWithClockStep(maxMs * 2, MILLISECONDS);
- project = new Project.NameKey("project");
- accountId = new Account.Id(100);
- }
-
- @After
- public void tearDown() {
- TestTimeUtil.useSystemTime();
- System.setProperty("user.timezone", systemTimeZoneProperty);
- TimeZone.setDefault(systemTimeZone);
- }
-
- private void superWindowResolution() {
- TestTimeUtil.setClockStep(ChangeRebuilderImpl.MAX_WINDOW_MS * 2, MILLISECONDS);
- TimeUtil.nowTs();
- }
-
- private void subWindowResolution() {
- TestTimeUtil.setClockStep(1, SECONDS);
- TimeUtil.nowTs();
- }
-
- @Test
- public void diffChangesDifferentIds() throws Exception {
- Change c1 = TestChanges.newChange(project, accountId);
- int id1 = c1.getId().get();
- Change c2 = TestChanges.newChange(project, accountId);
- int id2 = c2.getId().get();
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertDiffs(
- b1,
- b2,
- "changeId differs for Changes: {" + id1 + "} != {" + id2 + "}",
- "createdOn differs for Changes: {2009-09-30 17:00:00.0} != {2009-09-30 17:00:06.0}",
- "effective last updated time differs for Changes:"
- + " {2009-09-30 17:00:00.0} != {2009-09-30 17:00:06.0}");
- }
-
- @Test
- public void diffChangesSameId() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertNoDiffs(b1, b2);
-
- c2.setTopic("topic");
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": {null} != {topic}");
- }
-
- @Test
- public void diffChangesMixedSourcesAllowsSlop() throws Exception {
- subWindowResolution();
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- c2.setCreatedOn(TimeUtil.nowTs());
- c2.setLastUpdatedOn(TimeUtil.nowTs());
-
- // Both are ReviewDb, exact timestamp match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for Change.Id "
- + c1.getId()
- + ":"
- + " {2009-09-30 17:00:01.0} != {2009-09-30 17:00:02.0}",
- "effective last updated time differs for Change.Id "
- + c1.getId()
- + ":"
- + " {2009-09-30 17:00:01.0} != {2009-09-30 17:00:03.0}");
-
- // One NoteDb, slop is allowed.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // But not too much slop.
- superWindowResolution();
- Change c3 = clone(c1);
- c3.setLastUpdatedOn(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- ChangeBundle b3 =
- new ChangeBundle(
- c3, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- String msg =
- "effective last updated time differs for Change.Id "
- + c1.getId()
- + " in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:01.0} != {2009-09-30 17:00:10.0}";
- assertDiffs(b1, b3, msg);
- assertDiffs(b3, b1, msg);
- }
-
- @Test
- public void diffChangesIgnoresOriginalSubjectInReviewDb() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- c1.setCurrentPatchSet(c1.currentPatchSetId(), "Subject", "Original A");
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(c2.currentPatchSetId(), c1.getSubject(), "Original B");
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "originalSubject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Original A} != {Original B}");
-
- // Both NoteDb, exact match required.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "originalSubject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Original A} != {Original B}");
-
- // One ReviewDb, one NoteDb, original subject is ignored.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesSanitizesSubjectsBeforeComparison() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- c1.setCurrentPatchSet(c1.currentPatchSetId(), "Subject\r\rbody", "Original");
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(c2.currentPatchSetId(), "Subject body", "Original");
-
- // Both ReviewDb, exact match required
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Subject\r\rbody} != {Subject body}");
-
- // Both NoteDb, exact match required (although it should be impossible to
- // create a NoteDb change with '\r' in the subject).
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Subject\r\rbody} != {Subject body}");
-
- // One ReviewDb, one NoteDb, '\r' is normalized to ' '.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesConsidersEmptyReviewDbTopicEquivalentToNullInNoteDb() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- c1.setTopic("");
- Change c2 = clone(c1);
- c2.setTopic(null);
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": {} != {null}");
-
- // Topic ignored if ReviewDb is empty and NoteDb is null.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
-
- // Exact match still required if NoteDb has empty value (not realistic).
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": {} != {null}");
-
- // Null is not equal to a non-empty string.
- Change c3 = clone(c1);
- c3.setTopic("topic");
- b1 =
- new ChangeBundle(
- c3, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": {topic} != {null}");
-
- // Null is equal to a string that is all whitespace.
- Change c4 = clone(c1);
- c4.setTopic(" ");
- b1 =
- new ChangeBundle(
- c4, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesIgnoresLeadingAndTrailingWhitespaceInReviewDbTopics() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- c1.setTopic(" abc ");
- Change c2 = clone(c1);
- c2.setTopic("abc");
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": { abc } != {abc}");
-
- // Leading whitespace in ReviewDb topic is ignored.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // Must match except for the leading/trailing whitespace.
- Change c3 = clone(c1);
- c3.setTopic("cba");
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c3, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(b1, b2, "topic differs for Change.Id " + c1.getId() + ": { abc } != {cba}");
- }
-
- @Test
- public void diffChangesTakesMaxEntityTimestampFromReviewDb() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- PatchSet ps = new PatchSet(c1.currentPatchSetId());
- ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps.setUploader(accountId);
- ps.setCreatedOn(TimeUtil.nowTs());
- PatchSetApproval a =
- new PatchSetApproval(
- new PatchSetApproval.Key(c1.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
-
- Change c2 = clone(c1);
- c2.setLastUpdatedOn(a.getGranted());
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(ps), approvals(a), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(ps), approvals(a), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "effective last updated time differs for Change.Id "
- + c1.getId()
- + ":"
- + " {2009-09-30 17:00:00.0} != {2009-09-30 17:00:12.0}");
-
- // NoteDb allows latest timestamp from all entities in bundle.
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(ps), approvals(a), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- }
-
- @Test
- public void diffChangesIgnoresChangeTimestampIfAnyOtherEntitiesExist() {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- PatchSet ps = new PatchSet(c1.currentPatchSetId());
- ps.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps.setUploader(accountId);
- ps.setCreatedOn(TimeUtil.nowTs());
- PatchSetApproval a =
- new PatchSetApproval(
- new PatchSetApproval.Key(c1.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
- c1.setLastUpdatedOn(a.getGranted());
-
- Change c2 = clone(c1);
- c2.setLastUpdatedOn(TimeUtil.nowTs());
-
- // ReviewDb has later lastUpdatedOn timestamp than NoteDb, allowed since
- // NoteDb matches the latest timestamp of a non-Change entity.
- ChangeBundle b1 =
- new ChangeBundle(
- c2, messages(), patchSets(ps), approvals(a), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c1, messages(), patchSets(ps), approvals(a), comments(), reviewers(), NOTE_DB);
- assertThat(b1.getChange().getLastUpdatedOn()).isGreaterThan(b2.getChange().getLastUpdatedOn());
- assertNoDiffs(b1, b2);
-
- // Timestamps must actually match if Change is the only entity.
- b1 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "effective last updated time differs for Change.Id "
- + c1.getId()
- + " in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:12.0} != {2009-09-30 17:00:18.0}");
- }
-
- @Test
- public void diffChangesAllowsReviewDbSubjectToBePrefixOfNoteDbSubject() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(
- c1.currentPatchSetId(), c1.getSubject().substring(0, 10), c1.getOriginalSubject());
- assertThat(c2.getSubject()).isNotEqualTo(c1.getSubject());
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id " + c1.getId() + ": {Change subject} != {Change sub}");
-
- // ReviewDb has shorter subject, allowed.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
-
- // NoteDb has shorter subject, not allowed.
- b1 =
- new ChangeBundle(
- c1, messages(), latest(c1), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(c2, messages(), latest(c2), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id " + c1.getId() + ": {Change subject} != {Change sub}");
- }
-
- @Test
- public void diffChangesTrimsLeadingSpacesFromReviewDbComparingToNoteDb() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(c1.currentPatchSetId(), " " + c1.getSubject(), c1.getOriginalSubject());
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Change subject} != { Change subject}");
-
- // ReviewDb is missing leading spaces, allowed.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesDoesntTrimLeadingNonSpaceWhitespaceFromSubject() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(c1.currentPatchSetId(), "\t" + c1.getSubject(), c1.getOriginalSubject());
-
- // Both ReviewDb.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Change subject} != {\tChange subject}");
-
- // One NoteDb.
- b1 =
- new ChangeBundle(c1, messages(), latest(c1), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), latest(c2), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Change subject} != {\tChange subject}");
- assertDiffs(
- b2,
- b1,
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {\tChange subject} != {Change subject}");
- }
-
- @Test
- public void diffChangesHandlesBuggyJGitSubjectExtraction() throws Exception {
- Change c1 = TestChanges.newChange(project, accountId);
- String buggySubject = "Subject\r \r Rest of message.";
- c1.setCurrentPatchSet(c1.currentPatchSetId(), buggySubject, buggySubject);
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(c2.currentPatchSetId(), "Subject", "Subject");
-
- // Both ReviewDb.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "originalSubject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Subject\r \r Rest of message.} != {Subject}",
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Subject\r \r Rest of message.} != {Subject}");
-
- // NoteDb has correct subject without "\r ".
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesIgnoresInvalidCurrentPatchSetIdInReviewDb() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- Change c2 = clone(c1);
- c2.setCurrentPatchSet(
- new PatchSet.Id(c2.getId(), 0), "Unrelated subject", c2.getOriginalSubject());
-
- // Both ReviewDb.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "currentPatchSetId differs for Change.Id " + c1.getId() + ": {1} != {0}",
- "subject differs for Change.Id "
- + c1.getId()
- + ":"
- + " {Change subject} != {Unrelated subject}");
-
- // One NoteDb.
- //
- // This is based on a real corrupt change where all patch sets were deleted
- // but the Change entity stuck around, resulting in a currentPatchSetId of 0
- // after converting to NoteDb.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangesAllowsCreatedToMatchLastUpdated() throws Exception {
- Change c1 = TestChanges.newChange(new Project.NameKey("project"), new Account.Id(100));
- c1.setCreatedOn(TimeUtil.nowTs());
- assertThat(c1.getCreatedOn()).isGreaterThan(c1.getLastUpdatedOn());
- Change c2 = clone(c1);
- c2.setCreatedOn(c2.getLastUpdatedOn());
-
- // Both ReviewDb.
- ChangeBundle b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for Change.Id "
- + c1.getId()
- + ": {2009-09-30 17:00:06.0} != {2009-09-30 17:00:00.0}");
-
- // One NoteDb.
- b1 =
- new ChangeBundle(
- c1, messages(), patchSets(), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c2, messages(), patchSets(), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffChangeMessageKeySets() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- ChangeMessage cm2 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid2"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertDiffs(
- b1,
- b2,
- "ChangeMessage.Key sets differ:"
- + " ["
- + id
- + ",uuid1] only in A; ["
- + id
- + ",uuid2] only in B");
- }
-
- @Test
- public void diffChangeMessages() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 1");
- ChangeMessage cm2 = clone(cm1);
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertNoDiffs(b1, b2);
-
- cm2.setMessage("message 2");
- assertDiffs(
- b1,
- b2,
- "message differs for ChangeMessage.Key "
- + c.getId()
- + ",uuid:"
- + " {message 1} != {message 2}");
- }
-
- @Test
- public void diffChangeMessagesIgnoresUuids() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 1");
- ChangeMessage cm2 = clone(cm1);
- cm2.getKey().set("uuid2");
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- // Both are ReviewDb, exact UUID match is required.
- assertDiffs(
- b1,
- b2,
- "ChangeMessage.Key sets differ:"
- + " ["
- + id
- + ",uuid1] only in A; ["
- + id
- + ",uuid2] only in B");
-
- // One NoteDb, UUIDs are ignored.
- b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- }
-
- @Test
- public void diffChangeMessagesWithDifferentCounts() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 1");
- ChangeMessage cm2 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid2"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 2");
-
- // Both ReviewDb: Uses same keySet diff as other types.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1, cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1, b2, "ChangeMessage.Key sets differ: [" + id + ",uuid2] only in A; [] only in B");
-
- // One NoteDb: UUIDs in keys can't be used for comparison, just diff counts.
- b1 =
- new ChangeBundle(
- c, messages(cm1, cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(b1, b2, "ChangeMessages differ for Change.Id " + id + "\nOnly in A:\n " + cm2);
- assertDiffs(b2, b1, "ChangeMessages differ for Change.Id " + id + "\nOnly in B:\n " + cm2);
- }
-
- @Test
- public void diffChangeMessagesMixedSourcesWithDifferences() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 1");
- ChangeMessage cm2 = clone(cm1);
- cm2.setMessage("message 2");
- ChangeMessage cm3 = clone(cm1);
- cm3.getKey().set("uuid2"); // Differs only in UUID.
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1, cm3), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2, cm3), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- // Implementation happens to pair up cm1 in b1 with cm3 in b2 because it
- // depends on iteration order and doesn't care about UUIDs. The important
- // thing is that there's some diff.
- assertDiffs(
- b1,
- b2,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm3
- + "\n"
- + "Only in B:\n "
- + cm2);
- assertDiffs(
- b2,
- b1,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm2
- + "\n"
- + "Only in B:\n "
- + cm3);
- }
-
- @Test
- public void diffChangeMessagesMixedSourcesAllowsSlop() throws Exception {
- subWindowResolution();
- Change c = TestChanges.newChange(project, accountId);
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- ChangeMessage cm2 = clone(cm1);
- cm2.setWrittenOn(TimeUtil.nowTs());
-
- // Both are ReviewDb, exact timestamp match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "writtenOn differs for ChangeMessage.Key "
- + c.getId()
- + ",uuid1:"
- + " {2009-09-30 17:00:02.0} != {2009-09-30 17:00:03.0}");
-
- // One NoteDb, slop is allowed.
- b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // But not too much slop.
- superWindowResolution();
- ChangeMessage cm3 = clone(cm1);
- cm3.setWrittenOn(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- ChangeBundle b3 =
- new ChangeBundle(
- c, messages(cm3), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- int id = c.getId().get();
- assertDiffs(
- b1,
- b3,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm1
- + "\n"
- + "Only in B:\n "
- + cm3);
- assertDiffs(
- b3,
- b1,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm3
- + "\n"
- + "Only in B:\n "
- + cm1);
- }
-
- @Test
- public void diffChangeMessagesAllowsNullPatchSetIdFromReviewDb() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- cm1.setMessage("message 1");
- ChangeMessage cm2 = clone(cm1);
- cm2.setPatchSetId(null);
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
-
- // Both are ReviewDb, exact patch set ID match is required.
- assertDiffs(
- b1,
- b2,
- "patchset differs for ChangeMessage.Key "
- + c.getId()
- + ",uuid:"
- + " {"
- + id
- + ",1} != {null}");
-
- // Null patch set ID on ReviewDb is ignored.
- b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
-
- // Null patch set ID on NoteDb is not ignored (but is not realistic).
- b1 =
- new ChangeBundle(
- c, messages(cm1), latest(c), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(cm2), latest(c), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm1
- + "\n"
- + "Only in B:\n "
- + cm2);
- assertDiffs(
- b2,
- b1,
- "ChangeMessages differ for Change.Id "
- + id
- + "\n"
- + "Only in A:\n "
- + cm2
- + "\n"
- + "Only in B:\n "
- + cm1);
- }
-
- @Test
- public void diffPatchSetIdSets() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- TestChanges.incrementPatchSet(c);
-
- PatchSet ps1 = new PatchSet(new PatchSet.Id(c.getId(), 1));
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(TimeUtil.nowTs());
- PatchSet ps2 = new PatchSet(new PatchSet.Id(c.getId(), 2));
- ps2.setRevision(new RevId("badc0feebadc0feebadc0feebadc0feebadc0fee"));
- ps2.setUploader(accountId);
- ps2.setCreatedOn(TimeUtil.nowTs());
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps1, ps2), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertDiffs(b1, b2, "PatchSet.Id sets differ: [] only in A; [" + c.getId() + ",1] only in B");
- }
-
- @Test
- public void diffPatchSets() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- PatchSet ps1 = new PatchSet(c.currentPatchSetId());
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(TimeUtil.nowTs());
- PatchSet ps2 = clone(ps1);
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
-
- assertNoDiffs(b1, b2);
-
- ps2.setRevision(new RevId("badc0feebadc0feebadc0feebadc0feebadc0fee"));
- assertDiffs(
- b1,
- b2,
- "revision differs for PatchSet.Id "
- + c.getId()
- + ",1:"
- + " {RevId{deadbeefdeadbeefdeadbeefdeadbeefdeadbeef}}"
- + " != {RevId{badc0feebadc0feebadc0feebadc0feebadc0fee}}");
- }
-
- @Test
- public void diffPatchSetsMixedSourcesAllowsSlop() throws Exception {
- subWindowResolution();
- Change c = TestChanges.newChange(project, accountId);
- PatchSet ps1 = new PatchSet(c.currentPatchSetId());
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(truncateToSecond(TimeUtil.nowTs()));
- PatchSet ps2 = clone(ps1);
- ps2.setCreatedOn(TimeUtil.nowTs());
-
- // Both are ReviewDb, exact timestamp match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",1:"
- + " {2009-09-30 17:00:02.0} != {2009-09-30 17:00:03.0}");
-
- // One NoteDb, slop is allowed.
- b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
-
- // But not too much slop.
- superWindowResolution();
- PatchSet ps3 = clone(ps1);
- ps3.setCreatedOn(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), NOTE_DB);
- ChangeBundle b3 =
- new ChangeBundle(
- c, messages(), patchSets(ps3), approvals(), comments(), reviewers(), REVIEW_DB);
- String msg =
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",1 in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:02.0} != {2009-09-30 17:00:10.0}";
- assertDiffs(b1, b3, msg);
- assertDiffs(b3, b1, msg);
- }
-
- @Test
- public void diffPatchSetsIgnoresTrailingNewlinesInPushCertificate() throws Exception {
- subWindowResolution();
- Change c = TestChanges.newChange(project, accountId);
- PatchSet ps1 = new PatchSet(c.currentPatchSetId());
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(truncateToSecond(TimeUtil.nowTs()));
- ps1.setPushCertificate("some cert");
- PatchSet ps2 = clone(ps1);
- ps2.setPushCertificate(ps2.getPushCertificate() + "\n\n");
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), NOTE_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffPatchSetsGreaterThanCurrent() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
-
- PatchSet ps1 = new PatchSet(new PatchSet.Id(c.getId(), 1));
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(TimeUtil.nowTs());
- PatchSet ps2 = new PatchSet(new PatchSet.Id(c.getId(), 2));
- ps2.setRevision(new RevId("badc0feebadc0feebadc0feebadc0feebadc0fee"));
- ps2.setUploader(accountId);
- ps2.setCreatedOn(TimeUtil.nowTs());
- assertThat(ps2.getId().get()).isGreaterThan(c.currentPatchSetId().get());
-
- ChangeMessage cm1 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid1"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
- ChangeMessage cm2 =
- new ChangeMessage(
- new ChangeMessage.Key(c.getId(), "uuid2"),
- accountId,
- TimeUtil.nowTs(),
- c.currentPatchSetId());
-
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(ps1.getId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
- PatchSetApproval a2 =
- new PatchSetApproval(
- new PatchSetApproval.Key(ps2.getId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
-
- // Both ReviewDb.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(cm1), patchSets(ps1), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c,
- messages(cm1, cm2),
- patchSets(ps1, ps2),
- approvals(a1, a2),
- comments(),
- reviewers(),
- REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "ChangeMessage.Key sets differ: [] only in A; [" + cm2.getKey() + "] only in B",
- "PatchSet.Id sets differ: [] only in A; [" + ps2.getId() + "] only in B",
- "PatchSetApproval.Key sets differ: [] only in A; [" + a2.getKey() + "] only in B");
-
- // One NoteDb.
- b1 =
- new ChangeBundle(
- c, messages(cm1), patchSets(ps1), approvals(a1), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c,
- messages(cm1, cm2),
- patchSets(ps1, ps2),
- approvals(a1, a2),
- comments(),
- reviewers(),
- REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "ChangeMessages differ for Change.Id " + c.getId() + "\nOnly in B:\n " + cm2,
- "PatchSet.Id sets differ: [] only in A; [" + ps2.getId() + "] only in B",
- "PatchSetApproval.Key sets differ: [] only in A; [" + a2.getKey() + "] only in B");
-
- // Both NoteDb.
- b1 =
- new ChangeBundle(
- c, messages(cm1), patchSets(ps1), approvals(a1), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c,
- messages(cm1, cm2),
- patchSets(ps1, ps2),
- approvals(a1, a2),
- comments(),
- reviewers(),
- NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "ChangeMessages differ for Change.Id " + c.getId() + "\nOnly in B:\n " + cm2,
- "PatchSet.Id sets differ: [] only in A; [" + ps2.getId() + "] only in B",
- "PatchSetApproval.Key sets differ: [] only in A; [" + a2.getKey() + "] only in B");
- }
-
- @Test
- public void diffPatchSetsIgnoresLeadingAndTrailingWhitespaceInReviewDbDescriptions()
- throws Exception {
- Change c = TestChanges.newChange(project, accountId);
-
- PatchSet ps1 = new PatchSet(new PatchSet.Id(c.getId(), 1));
- ps1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- ps1.setUploader(accountId);
- ps1.setCreatedOn(TimeUtil.nowTs());
- ps1.setDescription(" abc ");
- PatchSet ps2 = clone(ps1);
- ps2.setDescription("abc");
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1, b2, "description differs for PatchSet.Id " + ps1.getId() + ": { abc } != {abc}");
-
- // Whitespace in ReviewDb description is ignored.
- b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps2), approvals(), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // Must match except for the leading/trailing whitespace.
- PatchSet ps3 = clone(ps1);
- ps3.setDescription("cba");
- b1 =
- new ChangeBundle(
- c, messages(), patchSets(ps1), approvals(), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(
- c, messages(), patchSets(ps3), approvals(), comments(), reviewers(), NOTE_DB);
- assertDiffs(
- b1, b2, "description differs for PatchSet.Id " + ps1.getId() + ": { abc } != {cba}");
- }
-
- @Test
- public void diffPatchSetsIgnoresCreatedOnWhenReviewDbIsNonMonotonic() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
-
- Timestamp beforePs1 = TimeUtil.nowTs();
-
- PatchSet goodPs1 = new PatchSet(new PatchSet.Id(c.getId(), 1));
- goodPs1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- goodPs1.setUploader(accountId);
- goodPs1.setCreatedOn(TimeUtil.nowTs());
- PatchSet goodPs2 = new PatchSet(new PatchSet.Id(c.getId(), 2));
- goodPs2.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- goodPs2.setUploader(accountId);
- goodPs2.setCreatedOn(TimeUtil.nowTs());
- assertThat(goodPs2.getCreatedOn()).isGreaterThan(goodPs1.getCreatedOn());
-
- PatchSet badPs2 = clone(goodPs2);
- badPs2.setCreatedOn(beforePs1);
- assertThat(badPs2.getCreatedOn()).isLessThan(goodPs1.getCreatedOn());
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, goodPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, badPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for PatchSet.Id "
- + badPs2.getId()
- + ":"
- + " {2009-09-30 17:00:18.0} != {2009-09-30 17:00:06.0}");
-
- // Non-monotonic in ReviewDb but monotonic in NoteDb, timestamps are
- // ignored, including for ps1.
- PatchSet badPs1 = clone(goodPs1);
- badPs1.setCreatedOn(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(badPs1, badPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- b2 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, goodPs2),
- approvals(),
- comments(),
- reviewers(),
- NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // Non-monotonic in NoteDb but monotonic in ReviewDb, timestamps are not
- // ignored.
- b1 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, goodPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- b2 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(badPs1, badPs2),
- approvals(),
- comments(),
- reviewers(),
- NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for PatchSet.Id "
- + badPs1.getId()
- + " in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:24.0} != {2009-09-30 17:00:12.0}",
- "createdOn differs for PatchSet.Id "
- + badPs2.getId()
- + " in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:06.0} != {2009-09-30 17:00:18.0}");
- }
-
- @Test
- public void diffPatchSetsAllowsFirstPatchSetCreatedOnToMatchChangeCreatedOn() {
- Change c = TestChanges.newChange(project, accountId);
- c.setLastUpdatedOn(TimeUtil.nowTs());
-
- PatchSet goodPs1 = new PatchSet(new PatchSet.Id(c.getId(), 1));
- goodPs1.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- goodPs1.setUploader(accountId);
- goodPs1.setCreatedOn(TimeUtil.nowTs());
- assertThat(goodPs1.getCreatedOn()).isGreaterThan(c.getCreatedOn());
-
- PatchSet ps1AtCreatedOn = clone(goodPs1);
- ps1AtCreatedOn.setCreatedOn(c.getCreatedOn());
-
- PatchSet goodPs2 = new PatchSet(new PatchSet.Id(c.getId(), 2));
- goodPs2.setRevision(new RevId("deadbeefdeadbeefdeadbeefdeadbeefdeadbeef"));
- goodPs2.setUploader(accountId);
- goodPs2.setCreatedOn(TimeUtil.nowTs());
-
- PatchSet ps2AtCreatedOn = clone(goodPs2);
- ps2AtCreatedOn.setCreatedOn(c.getCreatedOn());
-
- // Both ReviewDb, exact match required.
- ChangeBundle b1 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, goodPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(ps1AtCreatedOn, ps2AtCreatedOn),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",1: {2009-09-30 17:00:12.0} != {2009-09-30 17:00:00.0}",
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",2: {2009-09-30 17:00:18.0} != {2009-09-30 17:00:00.0}");
-
- // One ReviewDb, PS1 is allowed to match change createdOn, but PS2 isn't.
- b1 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(goodPs1, goodPs2),
- approvals(),
- comments(),
- reviewers(),
- REVIEW_DB);
- b2 =
- new ChangeBundle(
- c,
- messages(),
- patchSets(ps1AtCreatedOn, ps2AtCreatedOn),
- approvals(),
- comments(),
- reviewers(),
- NOTE_DB);
- assertDiffs(
- b1,
- b2,
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",2 in NoteDb vs. ReviewDb: {2009-09-30 17:00:00.0} != {2009-09-30 17:00:18.0}");
- assertDiffs(
- b2,
- b1,
- "createdOn differs for PatchSet.Id "
- + c.getId()
- + ",2 in NoteDb vs. ReviewDb: {2009-09-30 17:00:00.0} != {2009-09-30 17:00:18.0}");
- }
-
- @Test
- public void diffPatchSetApprovalKeySets() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
- PatchSetApproval a2 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Verified")),
- (short) 1,
- TimeUtil.nowTs());
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
-
- assertDiffs(
- b1,
- b2,
- "PatchSetApproval.Key sets differ:"
- + " ["
- + id
- + "%2C1,100,Code-Review] only in A;"
- + " ["
- + id
- + "%2C1,100,Verified] only in B");
- }
-
- @Test
- public void diffPatchSetApprovals() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- TimeUtil.nowTs());
- PatchSetApproval a2 = clone(a1);
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
-
- assertNoDiffs(b1, b2);
-
- a2.setValue((short) -1);
- assertDiffs(
- b1,
- b2,
- "value differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review: {1} != {-1}");
- }
-
- @Test
- public void diffPatchSetApprovalsMixedSourcesAllowsSlop() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- subWindowResolution();
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- truncateToSecond(TimeUtil.nowTs()));
- PatchSetApproval a2 = clone(a1);
- a2.setGranted(TimeUtil.nowTs());
-
- // Both are ReviewDb, exact timestamp match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "granted differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review:"
- + " {2009-09-30 17:00:07.0} != {2009-09-30 17:00:08.0}");
-
- // One NoteDb, slop is allowed.
- b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(a1), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
-
- // But not too much slop.
- superWindowResolution();
- PatchSetApproval a3 = clone(a1);
- a3.setGranted(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(a1), comments(), reviewers(), NOTE_DB);
- ChangeBundle b3 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a3), comments(), reviewers(), REVIEW_DB);
- String msg =
- "granted differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:07.0} != {2009-09-30 17:00:15.0}";
- assertDiffs(b1, b3, msg);
- assertDiffs(b3, b1, msg);
- }
-
- @Test
- public void diffPatchSetApprovalsAllowsTruncatedTimestampInNoteDb() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 1,
- c.getCreatedOn());
- PatchSetApproval a2 = clone(a1);
- a2.setGranted(
- new Timestamp(
- LocalDate.of(1900, Month.JANUARY, 1)
- .atStartOfDay()
- .atZone(ZoneId.of(TIMEZONE_ID))
- .toInstant()
- .toEpochMilli()));
-
- // Both are ReviewDb, exact match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "granted differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review:"
- + " {2009-09-30 17:00:00.0} != {1900-01-01 00:00:00.0}");
-
- // Truncating NoteDb timestamp is allowed.
- b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(a1), comments(), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
- }
-
- @Test
- public void diffPatchSetApprovalsIgnoresPostSubmitBitOnZeroVote() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- c.setStatus(Change.Status.MERGED);
- PatchSetApproval a1 =
- new PatchSetApproval(
- new PatchSetApproval.Key(c.currentPatchSetId(), accountId, new LabelId("Code-Review")),
- (short) 0,
- TimeUtil.nowTs());
- a1.setPostSubmit(false);
- PatchSetApproval a2 = clone(a1);
- a2.setPostSubmit(true);
-
- // Both are ReviewDb, exact match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a2), comments(), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "postSubmit differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review:"
- + " {false} != {true}");
-
- // One NoteDb, postSubmit is ignored.
- b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(a1), comments(), reviewers(), REVIEW_DB);
- b2 =
- new ChangeBundle(c, messages(), latest(c), approvals(a2), comments(), reviewers(), NOTE_DB);
- assertNoDiffs(b1, b2);
- assertNoDiffs(b2, b1);
-
- // postSubmit is not ignored if vote isn't 0.
- a1.setValue((short) 1);
- a2.setValue((short) 1);
- assertDiffs(
- b1,
- b2,
- "postSubmit differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review:"
- + " {false} != {true}");
- assertDiffs(
- b2,
- b1,
- "postSubmit differs for PatchSetApproval.Key "
- + c.getId()
- + "%2C1,100,Code-Review:"
- + " {true} != {false}");
- }
-
- @Test
- public void diffReviewers() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- Timestamp now = TimeUtil.nowTs();
- ReviewerSet r1 = reviewers(REVIEWER, new Account.Id(1), now);
- ReviewerSet r2 = reviewers(REVIEWER, new Account.Id(2), now);
-
- ChangeBundle b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(), r1, REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(), r2, REVIEW_DB);
- assertNoDiffs(b1, b1);
- assertNoDiffs(b2, b2);
- assertDiffs(b1, b2, "reviewer sets differ: [1] only in A; [2] only in B");
- }
-
- @Test
- public void diffReviewersIgnoresStateAndTimestamp() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- ReviewerSet r1 = reviewers(REVIEWER, new Account.Id(1), TimeUtil.nowTs());
- ReviewerSet r2 = reviewers(CC, new Account.Id(1), TimeUtil.nowTs());
-
- ChangeBundle b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(), r1, REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(), r2, REVIEW_DB);
- assertNoDiffs(b1, b1);
- assertNoDiffs(b2, b2);
- }
-
- @Test
- public void diffPatchLineCommentKeySets() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- int id = c.getId().get();
- PatchLineComment c1 =
- new PatchLineComment(
- new PatchLineComment.Key(new Patch.Key(c.currentPatchSetId(), "filename1"), "uuid1"),
- 5,
- accountId,
- null,
- TimeUtil.nowTs());
- PatchLineComment c2 =
- new PatchLineComment(
- new PatchLineComment.Key(new Patch.Key(c.currentPatchSetId(), "filename2"), "uuid2"),
- 5,
- accountId,
- null,
- TimeUtil.nowTs());
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c1), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c2), reviewers(), REVIEW_DB);
-
- assertDiffs(
- b1,
- b2,
- "PatchLineComment.Key sets differ:"
- + " ["
- + id
- + ",1,filename1,uuid1] only in A;"
- + " ["
- + id
- + ",1,filename2,uuid2] only in B");
- }
-
- @Test
- public void diffPatchLineComments() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- PatchLineComment c1 =
- new PatchLineComment(
- new PatchLineComment.Key(new Patch.Key(c.currentPatchSetId(), "filename"), "uuid"),
- 5,
- accountId,
- null,
- TimeUtil.nowTs());
- PatchLineComment c2 = clone(c1);
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c1), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c2), reviewers(), REVIEW_DB);
-
- assertNoDiffs(b1, b2);
-
- c2.setStatus(PatchLineComment.Status.PUBLISHED);
- assertDiffs(
- b1,
- b2,
- "status differs for PatchLineComment.Key " + c.getId() + ",1,filename,uuid: {d} != {P}");
- }
-
- @Test
- public void diffPatchLineCommentsMixedSourcesAllowsSlop() throws Exception {
- subWindowResolution();
- Change c = TestChanges.newChange(project, accountId);
- PatchLineComment c1 =
- new PatchLineComment(
- new PatchLineComment.Key(new Patch.Key(c.currentPatchSetId(), "filename"), "uuid"),
- 5,
- accountId,
- null,
- truncateToSecond(TimeUtil.nowTs()));
- PatchLineComment c2 = clone(c1);
- c2.setWrittenOn(TimeUtil.nowTs());
-
- // Both are ReviewDb, exact timestamp match is required.
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c1), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c2), reviewers(), REVIEW_DB);
- assertDiffs(
- b1,
- b2,
- "writtenOn differs for PatchLineComment.Key "
- + c.getId()
- + ",1,filename,uuid:"
- + " {2009-09-30 17:00:02.0} != {2009-09-30 17:00:03.0}");
-
- // One NoteDb, slop is allowed.
- b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(c1), reviewers(), NOTE_DB);
- b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c2), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
-
- // But not too much slop.
- superWindowResolution();
- PatchLineComment c3 = clone(c1);
- c3.setWrittenOn(TimeUtil.nowTs());
- b1 =
- new ChangeBundle(c, messages(), latest(c), approvals(), comments(c1), reviewers(), NOTE_DB);
- ChangeBundle b3 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c3), reviewers(), REVIEW_DB);
- String msg =
- "writtenOn differs for PatchLineComment.Key "
- + c.getId()
- + ",1,filename,uuid in NoteDb vs. ReviewDb:"
- + " {2009-09-30 17:00:02.0} != {2009-09-30 17:00:10.0}";
- assertDiffs(b1, b3, msg);
- assertDiffs(b3, b1, msg);
- }
-
- @Test
- public void diffPatchLineCommentsIgnoresCommentsOnInvalidPatchSet() throws Exception {
- Change c = TestChanges.newChange(project, accountId);
- PatchLineComment c1 =
- new PatchLineComment(
- new PatchLineComment.Key(new Patch.Key(c.currentPatchSetId(), "filename1"), "uuid1"),
- 5,
- accountId,
- null,
- TimeUtil.nowTs());
- PatchLineComment c2 =
- new PatchLineComment(
- new PatchLineComment.Key(
- new Patch.Key(new PatchSet.Id(c.getId(), 0), "filename2"), "uuid2"),
- 5,
- accountId,
- null,
- TimeUtil.nowTs());
-
- ChangeBundle b1 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c1, c2), reviewers(), REVIEW_DB);
- ChangeBundle b2 =
- new ChangeBundle(
- c, messages(), latest(c), approvals(), comments(c1), reviewers(), REVIEW_DB);
- assertNoDiffs(b1, b2);
- }
-
- private static void assertNoDiffs(ChangeBundle a, ChangeBundle b) {
- assertThat(a.differencesFrom(b)).isEmpty();
- assertThat(b.differencesFrom(a)).isEmpty();
- }
-
- private static void assertDiffs(ChangeBundle a, ChangeBundle b, String first, String... rest) {
- List<String> actual = a.differencesFrom(b);
- if (actual.size() == 1 && rest.length == 0) {
- // This error message is much easier to read.
- assertThat(actual.get(0)).isEqualTo(first);
- } else {
- List<String> expected = new ArrayList<>(1 + rest.length);
- expected.add(first);
- Collections.addAll(expected, rest);
- assertThat(actual).containsExactlyElementsIn(expected).inOrder();
- }
- assertThat(a).isNotEqualTo(b);
- }
-
- private static List<ChangeMessage> messages(ChangeMessage... ents) {
- return Arrays.asList(ents);
- }
-
- private static List<PatchSet> patchSets(PatchSet... ents) {
- return Arrays.asList(ents);
- }
-
- private static List<PatchSet> latest(Change c) {
- PatchSet ps = new PatchSet(c.currentPatchSetId());
- ps.setCreatedOn(c.getLastUpdatedOn());
- return ImmutableList.of(ps);
- }
-
- private static List<PatchSetApproval> approvals(PatchSetApproval... ents) {
- return Arrays.asList(ents);
- }
-
- private static ReviewerSet reviewers(Object... ents) {
- checkArgument(ents.length % 3 == 0);
- Table<ReviewerStateInternal, Account.Id, Timestamp> t = HashBasedTable.create();
- for (int i = 0; i < ents.length; i += 3) {
- t.put((ReviewerStateInternal) ents[i], (Account.Id) ents[i + 1], (Timestamp) ents[i + 2]);
- }
- return ReviewerSet.fromTable(t);
- }
-
- private static List<PatchLineComment> comments(PatchLineComment... ents) {
- return Arrays.asList(ents);
- }
-
- private static Change clone(Change ent) {
- return clone(CHANGE_CODEC, ent);
- }
-
- private static ChangeMessage clone(ChangeMessage ent) {
- return clone(CHANGE_MESSAGE_CODEC, ent);
- }
-
- private static PatchSet clone(PatchSet ent) {
- return clone(PATCH_SET_CODEC, ent);
- }
-
- private static PatchSetApproval clone(PatchSetApproval ent) {
- return clone(PATCH_SET_APPROVAL_CODEC, ent);
- }
-
- private static PatchLineComment clone(PatchLineComment ent) {
- return clone(PATCH_LINE_COMMENT_CODEC, ent);
- }
-
- private static <T> T clone(ProtobufCodec<T> codec, T obj) {
- return codec.decode(codec.encodeToByteArray(obj));
- }
-}
diff --git a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
index 549f5db..e274cdf 100644
--- a/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
+++ b/javatests/com/google/gerrit/server/notedb/ChangeNotesTest.java
@@ -2605,7 +2605,7 @@
}
// Looking at drafts directly shows the zombie comment.
- DraftCommentNotes draftNotes = draftNotesFactory.create(c, otherUserId);
+ DraftCommentNotes draftNotes = draftNotesFactory.create(c.getId(), otherUserId);
assertThat(draftNotes.load().getComments().get(rev1)).containsExactly(comment1, comment2);
// Zombie comment is filtered out of drafts via ChangeNotes.
diff --git a/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java b/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
index b9027bc..fbec5e6 100644
--- a/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
+++ b/javatests/com/google/gerrit/server/notedb/CommentJsonMigratorTest.java
@@ -38,6 +38,7 @@
import com.google.gerrit.testing.TestChanges;
import com.google.inject.Inject;
import java.io.ByteArrayOutputStream;
+import java.util.Collection;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import org.eclipse.jgit.junit.TestRepository;
@@ -185,7 +186,6 @@
// Comments at each commit all have JSON format.
ImmutableList<RevCommit> newLog = log(project, RefNames.changeMetaRef(c.getId()));
- assertLogEqualExceptTrees(newLog, oldLog);
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(0))).isEmpty();
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(1))).isEmpty();
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(2)))
@@ -297,7 +297,6 @@
// Comments at each commit all have JSON format.
ImmutableList<RevCommit> newOwnerLog =
log(allUsers, RefNames.refsDraftComments(c.getId(), changeOwner.getAccountId()));
- assertLogEqualExceptTrees(newOwnerLog, oldOwnerLog);
assertThat(getLegacyFormatMapForDraftComments(notes, newOwnerLog.get(0)))
.containsExactly(ownerCommentPs1.key, false);
assertThat(getLegacyFormatMapForDraftComments(notes, newOwnerLog.get(1)))
@@ -305,7 +304,6 @@
ImmutableList<RevCommit> newOtherLog =
log(allUsers, RefNames.refsDraftComments(c.getId(), otherUser.getAccountId()));
- assertLogEqualExceptTrees(newOtherLog, oldOtherLog);
assertThat(getLegacyFormatMapForDraftComments(notes, newOtherLog.get(0)))
.containsExactly(otherCommentPs1.key, false);
}
@@ -392,7 +390,6 @@
// Comments at each commit all have JSON format.
ImmutableList<RevCommit> newLog = log(project, RefNames.changeMetaRef(c.getId()));
- assertLogEqualExceptTrees(newLog, oldLog);
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(0))).isEmpty();
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(1))).isEmpty();
assertThat(getLegacyFormatMapForPublishedComments(notes, newLog.get(2))).isEmpty();
@@ -491,17 +488,35 @@
}
private ImmutableList<RevCommit> log(Project.NameKey project, String refName) throws Exception {
- try (Repository repo = repoManager.openRepository(project);
- RevWalk rw = new RevWalk(repo)) {
+ try (Repository repo = repoManager.openRepository(project)) {
+ return log(repo, refName);
+ }
+ }
+
+ private ImmutableList<RevCommit> log(Repository repo, String refName) throws Exception {
+ try (RevWalk rw = new RevWalk(repo)) {
rw.sort(RevSort.TOPO);
rw.sort(RevSort.REVERSE);
Ref ref = repo.exactRef(refName);
- checkArgument(ref != null, "missing ref: %s", refName);
+ if (ref == null) {
+ return ImmutableList.of();
+ }
rw.markStart(rw.parseCommit(ref.getObjectId()));
return ImmutableList.copyOf(rw);
}
}
+ private ImmutableListMultimap<String, RevCommit> logAll(
+ Project.NameKey project, Collection<Ref> refs) throws Exception {
+ ImmutableListMultimap.Builder<String, RevCommit> logs = ImmutableListMultimap.builder();
+ try (Repository repo = repoManager.openRepository(project)) {
+ for (Ref r : refs) {
+ logs.putAll(r.getName(), log(repo, r.getName()));
+ }
+ }
+ return logs.build();
+ }
+
private static void assertLogEqualExceptTrees(
ImmutableList<RevCommit> actualLog, ImmutableList<RevCommit> expectedLog) {
assertThat(actualLog).hasSize(expectedLog.size());
@@ -522,9 +537,61 @@
}
private void assertNoDifferences(ChangeNotes actual, ChangeNotes expected) throws Exception {
- assertThat(
- ChangeBundle.fromNotes(commentsUtil, actual)
- .differencesFrom(ChangeBundle.fromNotes(commentsUtil, expected)))
- .isEmpty();
+ checkArgument(
+ actual.getChangeId().equals(expected.getChangeId()),
+ "must be same change: %s != %s",
+ actual.getChangeId(),
+ expected.getChangeId());
+
+ // Parsed comment representations are equal.
+ // TODO(dborowitz): Comparing collections directly would be much easier, but Comment doesn't
+ // have a proper equals; switch to that when the issues with
+ // https://gerrit-review.googlesource.com/c/gerrit/+/207013 are resolved.
+ assertCommentsEqual(commentsUtil.draftByChange(actual), commentsUtil.draftByChange(expected));
+ assertCommentsEqual(
+ commentsUtil.publishedByChange(actual), commentsUtil.publishedByChange(expected));
+
+ // Change metadata is equal.
+ assertLogEqualExceptTrees(
+ log(project, actual.getRefName()), log(project, expected.getRefName()));
+
+ // Logs of all draft refs are equal.
+ ImmutableListMultimap<String, RevCommit> actualDraftLogs =
+ logAll(allUsersName, commentsUtil.getDraftRefs(actual.getChangeId()));
+ ImmutableListMultimap<String, RevCommit> expectedDraftLogs =
+ logAll(allUsersName, commentsUtil.getDraftRefs(expected.getChangeId()));
+ assertThat(actualDraftLogs.keySet())
+ .named("draft ref names")
+ .containsExactlyElementsIn(expectedDraftLogs.keySet());
+ for (String refName : actualDraftLogs.keySet()) {
+ assertLogEqualExceptTrees(actualDraftLogs.get(refName), actualDraftLogs.get(refName));
+ }
+ }
+
+ private static void assertCommentsEqual(List<Comment> actualList, List<Comment> expectedList) {
+ ImmutableMap<Comment.Key, Comment> actualMap = byKey(actualList);
+ ImmutableMap<Comment.Key, Comment> expectedMap = byKey(expectedList);
+ assertThat(actualMap.keySet()).isEqualTo(expectedMap.keySet());
+ for (Comment.Key key : actualMap.keySet()) {
+ Comment actual = actualMap.get(key);
+ Comment expected = expectedMap.get(key);
+ assertThat(actual.key).isEqualTo(expected.key);
+ assertThat(actual.lineNbr).isEqualTo(expected.lineNbr);
+ assertThat(actual.author).isEqualTo(expected.author);
+ assertThat(actual.getRealAuthor()).isEqualTo(expected.getRealAuthor());
+ assertThat(actual.writtenOn).isEqualTo(expected.writtenOn);
+ assertThat(actual.side).isEqualTo(expected.side);
+ assertThat(actual.message).isEqualTo(expected.message);
+ assertThat(actual.parentUuid).isEqualTo(expected.parentUuid);
+ assertThat(actual.range).isEqualTo(expected.range);
+ assertThat(actual.tag).isEqualTo(expected.tag);
+ assertThat(actual.revId).isEqualTo(expected.revId);
+ assertThat(actual.serverId).isEqualTo(expected.serverId);
+ assertThat(actual.unresolved).isEqualTo(expected.unresolved);
+ }
+ }
+
+ private static ImmutableMap<Comment.Key, Comment> byKey(List<Comment> comments) {
+ return comments.stream().collect(toImmutableMap(c -> c.key, c -> c));
}
}
diff --git a/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java b/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java
deleted file mode 100644
index 7fb9d82..0000000
--- a/javatests/com/google/gerrit/server/notedb/rebuild/EventSorterTest.java
+++ /dev/null
@@ -1,232 +0,0 @@
-// Copyright (C) 2016 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.notedb.rebuild;
-
-import static com.google.common.truth.Truth.assertThat;
-import static java.util.stream.Collectors.toList;
-import static org.junit.Assert.fail;
-
-import com.google.common.collect.Collections2;
-import com.google.common.collect.Lists;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-import com.google.gerrit.server.notedb.ChangeUpdate;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.TestTimeUtil;
-import java.sql.Timestamp;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.concurrent.TimeUnit;
-import java.util.stream.Stream;
-import org.junit.Before;
-import org.junit.Test;
-
-public class EventSorterTest extends GerritBaseTests {
- private class TestEvent extends Event {
- protected TestEvent(Timestamp when) {
- super(
- new PatchSet.Id(new Change.Id(1), 1),
- new Account.Id(1000),
- new Account.Id(1000),
- when,
- changeCreatedOn,
- null);
- }
-
- @Override
- boolean uniquePerUpdate() {
- return false;
- }
-
- @Override
- void apply(ChangeUpdate update) {
- throw new UnsupportedOperationException();
- }
-
- @SuppressWarnings("deprecation")
- @Override
- public String toString() {
- return "E{" + when.getSeconds() + '}';
- }
- }
-
- private Timestamp changeCreatedOn;
-
- @Before
- public void setUp() {
- TestTimeUtil.resetWithClockStep(10, TimeUnit.SECONDS);
- changeCreatedOn = TimeUtil.nowTs();
- }
-
- @Test
- public void naturalSort() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
- Event e3 = new TestEvent(TimeUtil.nowTs());
-
- for (List<Event> events : Collections2.permutations(events(e1, e2, e3))) {
- assertSorted(events, events(e1, e2, e3));
- }
- }
-
- @Test
- public void topoSortOneDep() {
- List<Event> es;
-
- // Input list is 0,1,2
-
- // 0 depends on 1 => 1,0,2
- es = threeEventsOneDep(0, 1);
- assertSorted(es, events(es, 1, 0, 2));
-
- // 1 depends on 0 => 0,1,2
- es = threeEventsOneDep(1, 0);
- assertSorted(es, events(es, 0, 1, 2));
-
- // 0 depends on 2 => 1,2,0
- es = threeEventsOneDep(0, 2);
- assertSorted(es, events(es, 1, 2, 0));
-
- // 2 depends on 0 => 0,1,2
- es = threeEventsOneDep(2, 0);
- assertSorted(es, events(es, 0, 1, 2));
-
- // 1 depends on 2 => 0,2,1
- es = threeEventsOneDep(1, 2);
- assertSorted(es, events(es, 0, 2, 1));
-
- // 2 depends on 1 => 0,1,2
- es = threeEventsOneDep(2, 1);
- assertSorted(es, events(es, 0, 1, 2));
- }
-
- private List<Event> threeEventsOneDep(int depFromIdx, int depOnIdx) {
- List<Event> events =
- Lists.newArrayList(
- new TestEvent(TimeUtil.nowTs()),
- new TestEvent(TimeUtil.nowTs()),
- new TestEvent(TimeUtil.nowTs()));
- events.get(depFromIdx).addDep(events.get(depOnIdx));
- return events;
- }
-
- @Test
- public void lastEventDependsOnFirstEvent() {
- List<Event> events = new ArrayList<>();
- for (int i = 0; i < 20; i++) {
- events.add(new TestEvent(TimeUtil.nowTs()));
- }
- events.get(events.size() - 1).addDep(events.get(0));
- assertSorted(events, events);
- }
-
- @Test
- public void firstEventDependsOnLastEvent() {
- List<Event> events = new ArrayList<>();
- for (int i = 0; i < 20; i++) {
- events.add(new TestEvent(TimeUtil.nowTs()));
- }
- events.get(0).addDep(events.get(events.size() - 1));
-
- List<Event> expected = new ArrayList<>();
- expected.addAll(events.subList(1, events.size()));
- expected.add(events.get(0));
- assertSorted(events, expected);
- }
-
- @Test
- public void topoSortChainOfDeps() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
- Event e3 = new TestEvent(TimeUtil.nowTs());
- Event e4 = new TestEvent(TimeUtil.nowTs());
- e1.addDep(e2);
- e2.addDep(e3);
- e3.addDep(e4);
-
- assertSorted(events(e1, e2, e3, e4), events(e4, e3, e2, e1));
- }
-
- @Test
- public void topoSortMultipleDeps() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
- Event e3 = new TestEvent(TimeUtil.nowTs());
- Event e4 = new TestEvent(TimeUtil.nowTs());
- e1.addDep(e2);
- e1.addDep(e4);
- e2.addDep(e3);
-
- // Processing 3 pops 2, processing 4 pops 1.
- assertSorted(events(e2, e3, e1, e4), events(e3, e2, e4, e1));
- }
-
- @Test
- public void topoSortMultipleDepsPreservesNaturalOrder() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
- Event e3 = new TestEvent(TimeUtil.nowTs());
- Event e4 = new TestEvent(TimeUtil.nowTs());
- e1.addDep(e4);
- e2.addDep(e4);
- e3.addDep(e4);
-
- // Processing 4 pops 1, 2, 3 in natural order.
- assertSorted(events(e4, e3, e2, e1), events(e4, e1, e2, e3));
- }
-
- @Test
- public void topoSortCycle() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
-
- // Implementation is not really defined, but infinite looping would be bad.
- // According to current implementation details, 2 pops 1, 1 pops 2 which was
- // already seen.
- assertSorted(events(e2, e1), events(e1, e2));
- }
-
- @Test
- public void topoSortDepNotInInputList() {
- Event e1 = new TestEvent(TimeUtil.nowTs());
- Event e2 = new TestEvent(TimeUtil.nowTs());
- Event e3 = new TestEvent(TimeUtil.nowTs());
- e1.addDep(e3);
-
- List<Event> events = events(e2, e1);
- try {
- new EventSorter(events).sort();
- fail("expected IllegalArgumentException");
- } catch (IllegalArgumentException e) {
- // Expected.
- }
- }
-
- private static List<Event> events(Event... es) {
- return Lists.newArrayList(es);
- }
-
- private static List<Event> events(List<Event> in, Integer... indexes) {
- return Stream.of(indexes).map(in::get).collect(toList());
- }
-
- private static void assertSorted(List<Event> unsorted, List<Event> expected) {
- List<Event> actual = new ArrayList<>(unsorted);
- new EventSorter(actual).sort();
- assertThat(actual).named("sorted" + unsorted).isEqualTo(expected);
- }
-}
diff --git a/javatests/com/google/gerrit/server/permissions/RefControlTest.java b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
index c467312..bd0316c 100644
--- a/javatests/com/google/gerrit/server/permissions/RefControlTest.java
+++ b/javatests/com/google/gerrit/server/permissions/RefControlTest.java
@@ -63,7 +63,7 @@
import com.google.gerrit.server.project.ProjectState;
import com.google.gerrit.server.project.RefPattern;
import com.google.gerrit.server.project.testing.Util;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.testing.GerritBaseTests;
@@ -200,7 +200,7 @@
@Inject private PermissionBackend permissionBackend;
@Inject private CapabilityCollection.Factory capabilityCollectionFactory;
- @Inject private ReviewDbSchemaCreator schemaCreator;
+ @Inject private SchemaCreator schemaCreator;
@Inject private SingleVersionListener singleVersionListener;
@Inject private InMemoryDatabase schemaFactory;
@Inject private ThreadLocalRequestContext requestContext;
@@ -289,7 +289,7 @@
db = schemaFactory.open();
singleVersionListener.start();
try {
- schemaCreator.create(db);
+ schemaCreator.create();
} finally {
singleVersionListener.stop();
}
@@ -329,7 +329,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
index 26cc3f8..b0d0849 100644
--- a/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
+++ b/javatests/com/google/gerrit/server/query/account/AbstractQueryAccountsTest.java
@@ -74,7 +74,7 @@
import com.google.gerrit.server.index.account.AccountIndex;
import com.google.gerrit.server.index.account.AccountIndexCollection;
import com.google.gerrit.server.index.account.AccountIndexer;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
@@ -120,7 +120,7 @@
@Inject protected InMemoryDatabase schemaFactory;
- @Inject protected ReviewDbSchemaCreator schemaCreator;
+ @Inject protected SchemaCreator schemaCreator;
@Inject protected ThreadLocalRequestContext requestContext;
@@ -165,7 +165,7 @@
protected void setUpDatabase() throws Exception {
db = schemaFactory.open();
- schemaCreator.create(db);
+ schemaCreator.create();
Account.Id adminId = createAccount("admin", "Administrator", "admin@example.com", true);
admin = userFactory.create(adminId);
@@ -214,7 +214,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
index 0ea5241..e87942c 100644
--- a/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
+++ b/javatests/com/google/gerrit/server/query/change/AbstractQueryChangesTest.java
@@ -52,7 +52,6 @@
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.ReviewInput;
import com.google.gerrit.extensions.api.changes.ReviewInput.DraftHandling;
-import com.google.gerrit.extensions.api.changes.ReviewInput.RobotCommentInput;
import com.google.gerrit.extensions.api.changes.StarsInput;
import com.google.gerrit.extensions.api.groups.GroupInput;
import com.google.gerrit.extensions.api.projects.ConfigInput;
@@ -69,7 +68,6 @@
import com.google.gerrit.extensions.restapi.RestApiException;
import com.google.gerrit.index.FieldDef;
import com.google.gerrit.index.IndexConfig;
-import com.google.gerrit.index.QueryOptions;
import com.google.gerrit.index.Schema;
import com.google.gerrit.lifecycle.LifecycleManager;
import com.google.gerrit.reviewdb.client.Account;
@@ -81,7 +79,6 @@
import com.google.gerrit.reviewdb.client.Project;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbUtil;
import com.google.gerrit.server.CurrentUser;
import com.google.gerrit.server.IdentifiedUser;
import com.google.gerrit.server.PatchSetUtil;
@@ -102,21 +99,16 @@
import com.google.gerrit.server.index.change.ChangeField;
import com.google.gerrit.server.index.change.ChangeIndexCollection;
import com.google.gerrit.server.index.change.ChangeIndexer;
-import com.google.gerrit.server.index.change.IndexedChangeQuery;
-import com.google.gerrit.server.index.change.StalenessChecker;
import com.google.gerrit.server.notedb.ChangeNotes;
-import com.google.gerrit.server.notedb.NoteDbChangeState;
-import com.google.gerrit.server.notedb.NoteDbChangeState.PrimaryStorage;
import com.google.gerrit.server.project.ProjectCache;
import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.update.BatchUpdate;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.DisabledReviewDb;
import com.google.gerrit.testing.GerritServerTests;
import com.google.gerrit.testing.InMemoryDatabase;
import com.google.gerrit.testing.InMemoryRepositoryManager;
@@ -131,13 +123,11 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
-import java.util.Optional;
import java.util.concurrent.TimeUnit;
import org.eclipse.jgit.junit.TestRepository;
import org.eclipse.jgit.lib.ObjectId;
@@ -177,7 +167,7 @@
@Inject protected PatchSetUtil psUtil;
@Inject protected ChangeNotes.Factory changeNotesFactory;
@Inject protected Provider<ChangeQueryProcessor> queryProcessorProvider;
- @Inject protected ReviewDbSchemaCreator schemaCreator;
+ @Inject protected SchemaCreator schemaCreator;
@Inject protected SchemaFactory<ReviewDb> schemaFactory;
@Inject protected Sequences seq;
@Inject protected ThreadLocalRequestContext requestContext;
@@ -185,7 +175,6 @@
@Inject protected MetaDataUpdate.Server metaDataUpdateFactory;
@Inject protected IdentifiedUser.GenericFactory identifiedUserFactory;
- // Only for use in setting up/tearing down injector; other users should use schemaFactory.
@Inject private InMemoryDatabase inMemoryDatabase;
protected Injector injector;
@@ -234,9 +223,7 @@
protected void initAfterLifecycleStart() throws Exception {}
protected void setUpDatabase() throws Exception {
- try (ReviewDb underlyingDb = inMemoryDatabase.getDatabase().open()) {
- schemaCreator.create(underlyingDb);
- }
+ schemaCreator.create();
db = schemaFactory.open();
userId = accountManager.authenticate(AuthRequest.forUser("user")).getAccountId();
@@ -279,7 +266,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(inMemoryDatabase);
}
@Before
@@ -577,7 +563,6 @@
@Test
public void restorePendingReviewers() throws Exception {
assume().that(getSchemaVersion()).isAtLeast(44);
- assume().that(notesMigration.readChanges()).isTrue();
Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get());
@@ -1604,8 +1589,7 @@
}
@Test
- public void byHashtagWithNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
+ public void byHashtag() throws Exception {
List<Change> changes = setUpHashtagChanges();
assertQuery("hashtag:foo", changes.get(1), changes.get(0));
assertQuery("hashtag:bar", changes.get(1));
@@ -1617,35 +1601,6 @@
}
@Test
- public void byHashtagWithoutNoteDb() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
-
- notesMigration.setWriteChanges(true);
- notesMigration.setReadChanges(true);
- db.close();
- db = schemaFactory.open();
- List<Change> changes;
- try {
- changes = setUpHashtagChanges();
- notesMigration.setWriteChanges(false);
- notesMigration.setReadChanges(false);
- } finally {
- db.close();
- }
- db = schemaFactory.open();
- for (Change c : changes) {
- indexer.index(db, c); // Reindex without hashtag field.
- }
- assertQuery("hashtag:foo");
- assertQuery("hashtag:bar");
- assertQuery("hashtag:\" bar \"");
- assertQuery("hashtag:\"a tag\"");
- assertQuery("hashtag:\" a tag \"");
- assertQuery("hashtag:#foo");
- assertQuery("hashtag:\"# #foo\"");
- }
-
- @Test
public void byDefault() throws Exception {
TestRepository<Repo> repo = createProject("repo");
@@ -1776,8 +1731,6 @@
@Test
public void byDraftByExcludesZombieDrafts() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get());
Change change = insert(repo, newChange(repo));
@@ -1809,18 +1762,6 @@
allUsers.update(draftsRef.getName(), draftsRef.getObjectId());
assertThat(allUsers.getRepository().exactRef(draftsRef.getName())).isNotNull();
- if (PrimaryStorage.of(change) == PrimaryStorage.REVIEW_DB
- && !notesMigration.disableChangeReviewDb()) {
- // Record draft ref in noteDbState as well.
- ReviewDb db = ReviewDbUtil.unwrapDb(this.db);
- change = db.changes().get(id);
- NoteDbChangeState.applyDelta(
- change,
- NoteDbChangeState.Delta.create(
- id, Optional.empty(), ImmutableMap.of(userId, draftsRef.getObjectId())));
- db.changes().update(Collections.singleton(change));
- }
-
indexer.index(db, project, id);
assertQuery("draftby:" + userId);
}
@@ -2035,17 +1976,10 @@
assertQuery("reviewer:self", change3);
requestContext.setContext(newRequestContext(user1));
- if (notesMigration.readChanges()) {
- assertQuery("reviewer:" + user1, change1);
- assertQuery("cc:" + user1, change2);
- assertQuery("is:cc", change2);
- assertQuery("cc:self", change2);
- } else {
- assertQuery("reviewer:" + user1, change2, change1);
- assertQuery("cc:" + user1);
- assertQuery("is:cc");
- assertQuery("cc:self");
- }
+ assertQuery("reviewer:" + user1, change1);
+ assertQuery("cc:" + user1, change2);
+ assertQuery("is:cc", change2);
+ assertQuery("cc:self", change2);
}
@Test
@@ -2108,36 +2042,19 @@
.collect(toList());
assertThat(members).contains(user2.toString());
- if (notesMigration.readChanges()) {
- // CC and REVIEWER are separate in NoteDB
- assertQuery("reviewerin:\"Registered Users\"", change2, change1);
- assertQuery("reviewerin:" + group, change2);
- } else {
- // CC and REVIEWER are the same in ReviewDb
- assertQuery("reviewerin:\"Registered Users\"", change3, change2, change1);
- assertQuery("reviewerin:" + group, change3, change2);
- }
+ assertQuery("reviewerin:\"Registered Users\"", change2, change1);
+ assertQuery("reviewerin:" + group, change2);
gApi.changes().id(change2.getId().get()).current().review(ReviewInput.approve());
gApi.changes().id(change2.getId().get()).current().submit();
- if (notesMigration.readChanges()) {
- // CC and REVIEWER are separate in NoteDB
- assertQuery("reviewerin:" + group, change2);
- assertQuery("project:repo reviewerin:" + group, change2);
- assertQuery("status:merged reviewerin:" + group, change2);
- } else {
- // CC and REVIEWER are the same in ReviewDb
- assertQuery("reviewerin:" + group, change2, change3);
- assertQuery("project:repo reviewerin:" + group, change2, change3);
- assertQuery("status:merged reviewerin:" + group, change2);
- }
+ assertQuery("reviewerin:" + group, change2);
+ assertQuery("project:repo reviewerin:" + group, change2);
+ assertQuery("status:merged reviewerin:" + group, change2);
}
@Test
public void reviewerAndCcByEmail() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get());
ConfigInput conf = new ConfigInput();
@@ -2184,8 +2101,6 @@
@Test
public void reviewerAndCcByEmailWithQueryForDifferentUser() throws Exception {
- assume().that(notesMigration.readChanges()).isTrue();
-
Project.NameKey project = new Project.NameKey("repo");
TestRepository<Repo> repo = createProject(project.get());
ConfigInput conf = new ConfigInput();
@@ -2358,71 +2273,6 @@
}
@Test
- public void prepopulatedFields() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- db = new DisabledReviewDb();
- requestContext.setContext(newRequestContext(userId));
- // Use QueryProcessor directly instead of API so we get ChangeDatas back.
- List<ChangeData> cds =
- queryProcessorProvider
- .get()
- .query(queryBuilder.parse(change.getId().toString()))
- .entities();
- assertThat(cds).hasSize(1);
-
- ChangeData cd = cds.get(0);
- cd.change();
- cd.patchSets();
- cd.currentApprovals();
- cd.changedLines();
- cd.reviewedBy();
- cd.reviewers();
- cd.unresolvedCommentCount();
-
- if (getSchemaVersion() < 51) {
- assertMissingField(ChangeField.TOTAL_COMMENT_COUNT);
- } else {
- cd.totalCommentCount();
- }
-
- // TODO(dborowitz): Swap out GitRepositoryManager somehow? Will probably be
- // necessary for NoteDb anyway.
- cd.isMergeable();
-
- exception.expect(DisabledReviewDb.Disabled.class);
- cd.messages();
- }
-
- @Test
- public void prepopulateOnlyRequestedFields() throws Exception {
- assume().that(notesMigration.readChanges()).isFalse();
- TestRepository<Repo> repo = createProject("repo");
- Change change = insert(repo, newChange(repo));
-
- db = new DisabledReviewDb();
- requestContext.setContext(newRequestContext(userId));
- // Use QueryProcessor directly instead of API so we get ChangeDatas back.
- List<ChangeData> cds =
- queryProcessorProvider
- .get()
- .setRequestedFields(
- ImmutableSet.of(ChangeField.PATCH_SET.getName(), ChangeField.CHANGE.getName()))
- .query(queryBuilder.parse(change.getId().toString()))
- .entities();
- assertThat(cds).hasSize(1);
-
- ChangeData cd = cds.get(0);
- cd.change();
- cd.patchSets();
-
- exception.expect(DisabledReviewDb.Disabled.class);
- cd.currentApprovals();
- }
-
- @Test
public void reindexIfStale() throws Exception {
Account.Id user = createAccount("user");
Project.NameKey project = new Project.NameKey("repo");
@@ -2450,93 +2300,6 @@
}
@Test
- public void refStateFields() throws Exception {
- // This test method manages primary storage manually.
- assume().that(notesMigration.changePrimaryStorage()).isEqualTo(PrimaryStorage.REVIEW_DB);
- Account.Id user = createAccount("user");
- Project.NameKey project = new Project.NameKey("repo");
- TestRepository<Repo> repo = createProject(project.get());
- String path = "file";
- RevCommit commit = repo.parseBody(repo.commit().message("one").add(path, "contents").create());
- Change change = insert(repo, newChangeForCommit(repo, commit));
- Change.Id id = change.getId();
- int c = id.get();
- String changeId = change.getKey().get();
- requestContext.setContext(newRequestContext(user));
-
- // Ensure one of each type of supported ref is present for the change. If
- // any more refs are added, update this test to reflect them.
-
- // Edit
- gApi.changes().id(changeId).edit().create();
-
- // Star
- gApi.accounts().self().starChange(change.getId().toString());
-
- if (notesMigration.readChanges()) {
- // Robot comment.
- ReviewInput rin = new ReviewInput();
- RobotCommentInput rcin = new RobotCommentInput();
- rcin.robotId = "happyRobot";
- rcin.robotRunId = "1";
- rcin.line = 1;
- rcin.message = "nit: trailing whitespace";
- rcin.path = path;
- rin.robotComments = ImmutableMap.of(path, ImmutableList.of(rcin));
- gApi.changes().id(c).current().review(rin);
- }
-
- // Draft.
- DraftInput din = new DraftInput();
- din.path = path;
- din.line = 1;
- din.message = "draft";
- gApi.changes().id(c).current().createDraft(din);
-
- if (notesMigration.readChanges()) {
- // Force NoteDb primary.
- change = ReviewDbUtil.unwrapDb(db).changes().get(id);
- change.setNoteDbState(NoteDbChangeState.NOTE_DB_PRIMARY_STATE);
- ReviewDbUtil.unwrapDb(db).changes().update(Collections.singleton(change));
- indexer.index(db, change);
- }
-
- QueryOptions opts =
- IndexedChangeQuery.createOptions(indexConfig, 0, 1, StalenessChecker.FIELDS);
- ChangeData cd = indexes.getSearchIndex().get(id, opts).get();
-
- String cs = RefNames.shard(c);
- int u = user.get();
- String us = RefNames.shard(u);
-
- List<String> expectedStates =
- Lists.newArrayList(
- "repo:refs/users/" + us + "/edit-" + c + "/1",
- "All-Users:refs/starred-changes/" + cs + "/" + u);
- if (notesMigration.readChanges()) {
- expectedStates.add("repo:refs/changes/" + cs + "/meta");
- expectedStates.add("repo:refs/changes/" + cs + "/robot-comments");
- expectedStates.add("All-Users:refs/draft-comments/" + cs + "/" + u);
- }
- assertThat(
- cd.getRefStates()
- .stream()
- .map(String::new)
- // Omit SHA-1, we're just concerned with the project/ref names.
- .map(s -> s.substring(0, s.lastIndexOf(':')))
- .collect(toList()))
- .containsExactlyElementsIn(expectedStates);
-
- List<String> expectedPatterns = Lists.newArrayList("repo:refs/users/*/edit-" + c + "/*");
- expectedPatterns.add("All-Users:refs/starred-changes/" + cs + "/*");
- if (notesMigration.readChanges()) {
- expectedPatterns.add("All-Users:refs/draft-comments/" + cs + "/*");
- }
- assertThat(cd.getRefStatePatterns().stream().map(String::new).collect(toList()))
- .containsExactlyElementsIn(expectedPatterns);
- }
-
- @Test
public void watched() throws Exception {
TestRepository<Repo> repo = createProject("repo");
ChangeInserter ins1 = newChangeWithStatus(repo, Change.Status.NEW);
diff --git a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
index 7e4a0a4..2906409 100644
--- a/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
+++ b/javatests/com/google/gerrit/server/query/group/AbstractQueryGroupsTest.java
@@ -52,7 +52,7 @@
import com.google.gerrit.server.index.group.GroupField;
import com.google.gerrit.server.index.group.GroupIndex;
import com.google.gerrit.server.index.group.GroupIndexCollection;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
@@ -91,7 +91,7 @@
@Inject protected InMemoryDatabase schemaFactory;
- @Inject protected ReviewDbSchemaCreator schemaCreator;
+ @Inject protected SchemaCreator schemaCreator;
@Inject protected ThreadLocalRequestContext requestContext;
@@ -134,7 +134,7 @@
protected void setUpDatabase() throws Exception {
db = schemaFactory.open();
- schemaCreator.create(db);
+ schemaCreator.create();
Account.Id userId =
createAccountOutsideRequestContext("user", "User", "user@example.com", true);
@@ -186,7 +186,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
index 3219dfd..4750353 100644
--- a/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
+++ b/javatests/com/google/gerrit/server/query/project/AbstractQueryProjectsTest.java
@@ -50,7 +50,7 @@
import com.google.gerrit.server.account.AuthRequest;
import com.google.gerrit.server.config.AllProjectsName;
import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.schema.ReviewDbSchemaCreator;
+import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.ManualRequestContext;
import com.google.gerrit.server.util.OneOffRequestContext;
import com.google.gerrit.server.util.RequestContext;
@@ -88,7 +88,7 @@
@Inject protected InMemoryDatabase schemaFactory;
- @Inject protected ReviewDbSchemaCreator schemaCreator;
+ @Inject protected SchemaCreator schemaCreator;
@Inject protected ThreadLocalRequestContext requestContext;
@@ -125,7 +125,7 @@
protected void setUpDatabase() throws Exception {
db = schemaFactory.open();
- schemaCreator.create(db);
+ schemaCreator.create();
Account.Id userId = createAccount("user", "User", "user@example.com", true);
user = userFactory.create(userId);
@@ -174,7 +174,6 @@
if (db != null) {
db.close();
}
- InMemoryDatabase.drop(schemaFactory);
}
@Test
diff --git a/javatests/com/google/gerrit/server/schema/GroupBundleTest.java b/javatests/com/google/gerrit/server/schema/GroupBundleTest.java
deleted file mode 100644
index c1de3a3..0000000
--- a/javatests/com/google/gerrit/server/schema/GroupBundleTest.java
+++ /dev/null
@@ -1,146 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.AccountGroupById;
-import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
-import com.google.gerrit.reviewdb.client.AccountGroupMember;
-import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
-import com.google.gerrit.server.schema.GroupBundle.Source;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.TestTimeUtil;
-import java.sql.Timestamp;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class GroupBundleTest extends GerritBaseTests {
- // This class just contains sanity checks that GroupBundle#compare correctly compares all parts of
- // the bundle. Most other test coverage should come via the slightly more realistic
- // GroupRebuilderTest.
-
- private static final String TIMEZONE_ID = "US/Eastern";
-
- private String systemTimeZoneProperty;
- private TimeZone systemTimeZone;
- private Timestamp ts;
-
- @Before
- public void setUp() {
- systemTimeZoneProperty = System.setProperty("user.timezone", TIMEZONE_ID);
- systemTimeZone = TimeZone.getDefault();
- TimeZone.setDefault(TimeZone.getTimeZone(TIMEZONE_ID));
- TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
- ts = TimeUtil.nowTs();
- }
-
- @After
- public void tearDown() {
- TestTimeUtil.useSystemTime();
- System.setProperty("user.timezone", systemTimeZoneProperty);
- TimeZone.setDefault(systemTimeZone);
- }
-
- @Test
- public void compareNonEqual() throws Exception {
- GroupBundle reviewDbBundle = newBundle().source(Source.REVIEW_DB).build();
- AccountGroup g2 = new AccountGroup(reviewDbBundle.group());
- g2.setDescription("Hello!");
- GroupBundle noteDbBundle = GroupBundle.builder().source(Source.NOTE_DB).group(g2).build();
- assertThat(GroupBundle.compareWithAudits(reviewDbBundle, noteDbBundle))
- .containsExactly(
- "AccountGroups differ\n"
- + ("ReviewDb: AccountGroup{name=group, groupId=1, description=null,"
- + " visibleToAll=false, groupUUID=group-1, ownerGroupUUID=group-1,"
- + " createdOn=2009-09-30 17:00:00.0}\n")
- + ("NoteDb : AccountGroup{name=group, groupId=1, description=Hello!,"
- + " visibleToAll=false, groupUUID=group-1, ownerGroupUUID=group-1,"
- + " createdOn=2009-09-30 17:00:00.0}"),
- "AccountGroupMembers differ\n"
- + "ReviewDb: [AccountGroupMember{key=1000,1}]\n"
- + "NoteDb : []",
- "AccountGroupMemberAudits differ\n"
- + ("ReviewDb: [AccountGroupMemberAudit{key=Key{groupId=1, accountId=1000,"
- + " addedOn=2009-09-30 17:00:00.0}, addedBy=2000, removedBy=null,"
- + " removedOn=null}]\n")
- + "NoteDb : []",
- "AccountGroupByIds differ\n"
- + "ReviewDb: [AccountGroupById{key=1,subgroup}]\n"
- + "NoteDb : []",
- "AccountGroupByIdAudits differ\n"
- + ("ReviewDb: [AccountGroupByIdAud{key=Key{groupId=1, includeUUID=subgroup,"
- + " addedOn=2009-09-30 17:00:00.0}, addedBy=3000, removedBy=null,"
- + " removedOn=null}]\n")
- + "NoteDb : []");
- }
-
- @Test
- public void compareIgnoreAudits() throws Exception {
- GroupBundle reviewDbBundle = newBundle().source(Source.REVIEW_DB).build();
- AccountGroup group = new AccountGroup(reviewDbBundle.group());
-
- AccountGroupMember member =
- new AccountGroupMember(new AccountGroupMember.Key(new Account.Id(1), group.getId()));
- AccountGroupMemberAudit memberAudit =
- new AccountGroupMemberAudit(member, new Account.Id(2), ts);
- AccountGroupById byId =
- new AccountGroupById(
- new AccountGroupById.Key(group.getId(), new AccountGroup.UUID("subgroup-2")));
- AccountGroupByIdAud byIdAudit = new AccountGroupByIdAud(byId, new Account.Id(3), ts);
-
- GroupBundle noteDbBundle =
- newBundle().source(Source.NOTE_DB).memberAudit(memberAudit).byIdAudit(byIdAudit).build();
-
- assertThat(GroupBundle.compareWithAudits(reviewDbBundle, noteDbBundle)).isNotEmpty();
- assertThat(GroupBundle.compareWithoutAudits(reviewDbBundle, noteDbBundle)).isEmpty();
- }
-
- @Test
- public void compareEqual() throws Exception {
- GroupBundle reviewDbBundle = newBundle().source(Source.REVIEW_DB).build();
- GroupBundle noteDbBundle = newBundle().source(Source.NOTE_DB).build();
- assertThat(GroupBundle.compareWithAudits(reviewDbBundle, noteDbBundle)).isEmpty();
- }
-
- private GroupBundle.Builder newBundle() {
- AccountGroup group =
- new AccountGroup(
- new AccountGroup.NameKey("group"),
- new AccountGroup.Id(1),
- new AccountGroup.UUID("group-1"),
- ts);
- AccountGroupMember member =
- new AccountGroupMember(new AccountGroupMember.Key(new Account.Id(1000), group.getId()));
- AccountGroupMemberAudit memberAudit =
- new AccountGroupMemberAudit(member, new Account.Id(2000), ts);
- AccountGroupById byId =
- new AccountGroupById(
- new AccountGroupById.Key(group.getId(), new AccountGroup.UUID("subgroup")));
- AccountGroupByIdAud byIdAudit = new AccountGroupByIdAud(byId, new Account.Id(3000), ts);
- return GroupBundle.builder()
- .group(group)
- .members(member)
- .memberAudit(memberAudit)
- .byId(byId)
- .byIdAudit(byIdAudit);
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java b/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
deleted file mode 100644
index 6a8a55a..0000000
--- a/javatests/com/google/gerrit/server/schema/GroupRebuilderTest.java
+++ /dev/null
@@ -1,747 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.collect.ImmutableList.toImmutableList;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assert_;
-import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.assertThat;
-import static com.google.gerrit.reviewdb.client.RefNames.REFS_GROUPNAMES;
-
-import com.google.common.collect.ImmutableList;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.GroupDescription;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.extensions.common.CommitInfo;
-import com.google.gerrit.git.RefUpdateUtil;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.AccountGroupById;
-import com.google.gerrit.reviewdb.client.AccountGroupByIdAud;
-import com.google.gerrit.reviewdb.client.AccountGroupMember;
-import com.google.gerrit.reviewdb.client.AccountGroupMemberAudit;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AllUsersNameProvider;
-import com.google.gerrit.server.group.db.AuditLogFormatter;
-import com.google.gerrit.server.group.db.AuditLogReader;
-import com.google.gerrit.server.group.db.GroupNameNotes;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.GitTestUtil;
-import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.TestTimeUtil;
-import com.google.gwtorm.server.OrmDuplicateKeyException;
-import java.sql.Timestamp;
-import java.util.Optional;
-import java.util.TimeZone;
-import java.util.concurrent.TimeUnit;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.stream.IntStream;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.ObjectInserter;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class GroupRebuilderTest extends GerritBaseTests {
- private static final TimeZone TZ = TimeZone.getTimeZone("America/Los_Angeles");
- private static final String SERVER_ID = "server-id";
- private static final String SERVER_NAME = "Gerrit Server";
- private static final String SERVER_EMAIL = "noreply@gerritcodereview.com";
-
- private AtomicInteger idCounter;
- private AllUsersName allUsersName;
- private Repository repo;
- private GroupRebuilder rebuilder;
- private GroupBundle.Factory bundleFactory;
-
- @Before
- public void setUp() throws Exception {
- TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
- idCounter = new AtomicInteger();
- allUsersName = new AllUsersName(AllUsersNameProvider.DEFAULT);
- repo = new InMemoryRepositoryManager().createRepository(allUsersName);
- rebuilder =
- new GroupRebuilder(
- GroupRebuilderTest.newPersonIdent(),
- allUsersName,
- // Note that the expected name/email values in tests are not necessarily realistic,
- // since they use these trivial name/email functions.
- getAuditLogFormatter());
- bundleFactory = new GroupBundle.Factory(new AuditLogReader(SERVER_ID, allUsersName));
- }
-
- @After
- public void tearDown() {
- TestTimeUtil.useSystemTime();
- }
-
- @Test
- public void minimalGroupFields() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(1);
- assertCommit(log.get(0), "Create group", SERVER_NAME, SERVER_EMAIL);
- assertThat(logGroupNames()).isEmpty();
- }
-
- @Test
- public void allGroupFields() throws Exception {
- AccountGroup g = newGroup("a");
- g.setDescription("Description");
- g.setOwnerGroupUUID(new AccountGroup.UUID("owner"));
- g.setVisibleToAll(true);
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(1);
- assertServerCommit(log.get(0), "Create group");
- }
-
- @Test
- public void emptyGroupName() throws Exception {
- AccountGroup g = newGroup("");
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
-
- GroupBundle noteDbBundle = reload(g);
- assertMigratedCleanly(noteDbBundle, b);
- assertThat(noteDbBundle.group().getName()).isEmpty();
- }
-
- @Test
- public void nullGroupDescription() throws Exception {
- AccountGroup g = newGroup("a");
- g.setDescription(null);
- assertThat(g.getDescription()).isNull();
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
-
- GroupBundle noteDbBundle = reload(g);
- assertMigratedCleanly(noteDbBundle, b);
- assertThat(noteDbBundle.group().getDescription()).isNull();
- }
-
- @Test
- public void emptyGroupDescription() throws Exception {
- AccountGroup g = newGroup("a");
- g.setDescription("");
- assertThat(g.getDescription()).isEmpty();
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
-
- GroupBundle noteDbBundle = reload(g);
- assertMigratedCleanly(noteDbBundle, b);
- assertThat(noteDbBundle.group().getDescription()).isNull();
- }
-
- @Test
- public void membersAndSubgroups() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1), member(g, 2))
- .byId(byId(g, "x"), byId(g, "y"))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(2);
- assertServerCommit(log.get(0), "Create group");
- assertServerCommit(
- log.get(1),
- "Update group\n"
- + "\n"
- + "Add-group: Group x <x>\n"
- + "Add-group: Group y <y>\n"
- + "Add: Account 1 <1@server-id>\n"
- + "Add: Account 2 <2@server-id>");
- }
-
- @Test
- public void memberAudit() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp t1 = TimeUtil.nowTs();
- Timestamp t2 = TimeUtil.nowTs();
- Timestamp t3 = TimeUtil.nowTs();
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1))
- .memberAudit(addMember(g, 1, 8, t2), addAndRemoveMember(g, 2, 8, t1, 9, t3))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(4);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(3), "Update group\n\nRemove: Account 2 <2@server-id>", "Account 9", "9@server-id");
- }
-
- @Test
- public void memberAuditLegacyRemoved() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 2))
- .memberAudit(
- addAndLegacyRemoveMember(g, 1, 8, TimeUtil.nowTs()),
- addMember(g, 2, 8, TimeUtil.nowTs()))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(4);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 8", "8@server-id");
- }
-
- @Test
- public void unauditedMembershipsAddedAtEnd() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1), member(g, 2), member(g, 3))
- .memberAudit(addMember(g, 1, 8, TimeUtil.nowTs()))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(3);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertServerCommit(
- log.get(2), "Update group\n\nAdd: Account 2 <2@server-id>\nAdd: Account 3 <3@server-id>");
- }
-
- @Test
- public void byIdAudit() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp t1 = TimeUtil.nowTs();
- Timestamp t2 = TimeUtil.nowTs();
- Timestamp t3 = TimeUtil.nowTs();
- GroupBundle b =
- builder()
- .group(g)
- .byId(byId(g, "x"))
- .byIdAudit(addById(g, "x", 8, t2), addAndRemoveById(g, "y", 8, t1, 9, t3))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(4);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(log.get(1), "Update group\n\nAdd-group: Group y <y>", "Account 8", "8@server-id");
- assertCommit(log.get(2), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
- assertCommit(
- log.get(3), "Update group\n\nRemove-group: Group y <y>", "Account 9", "9@server-id");
- }
-
- @Test
- public void unauditedByIdAddedAtEnd() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b =
- builder()
- .group(g)
- .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
- .byIdAudit(addById(g, "x", 8, TimeUtil.nowTs()))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(3);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
- assertServerCommit(
- log.get(2), "Update group\n\nAdd-group: Group y <y>\nAdd-group: Group z <z>");
- }
-
- @Test
- public void auditsAtSameTimestampBrokenDownByType() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp ts = TimeUtil.nowTs();
- int user = 8;
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1), member(g, 2))
- .memberAudit(
- addMember(g, 1, user, ts),
- addMember(g, 2, user, ts),
- addAndRemoveMember(g, 3, user, ts, user, ts))
- .byId(byId(g, "x"), byId(g, "y"))
- .byIdAudit(
- addById(g, "x", user, ts),
- addById(g, "y", user, ts),
- addAndRemoveById(g, "z", user, ts, user, ts))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(5);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1),
- "Update group\n"
- + "\n"
- + "Add: Account 1 <1@server-id>\n"
- + "Add: Account 2 <2@server-id>\n"
- + "Add: Account 3 <3@server-id>",
- "Account 8",
- "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nRemove: Account 3 <3@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(3),
- "Update group\n"
- + "\n"
- + "Add-group: Group x <x>\n"
- + "Add-group: Group y <y>\n"
- + "Add-group: Group z <z>",
- "Account 8",
- "8@server-id");
- assertCommit(
- log.get(4), "Update group\n\nRemove-group: Group z <z>", "Account 8", "8@server-id");
- }
-
- @Test
- public void auditsAtSameTimestampBrokenDownByUserAndType() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp ts = TimeUtil.nowTs();
- int user1 = 8;
- int user2 = 9;
-
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1), member(g, 2), member(g, 3))
- .memberAudit(
- addMember(g, 1, user1, ts), addMember(g, 2, user2, ts), addMember(g, 3, user1, ts))
- .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
- .byIdAudit(
- addById(g, "x", user1, ts), addById(g, "y", user2, ts), addById(g, "z", user1, ts))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(5);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1),
- "Update group\n" + "\n" + "Add: Account 1 <1@server-id>\n" + "Add: Account 3 <3@server-id>",
- "Account 8",
- "8@server-id");
- assertCommit(
- log.get(2),
- "Update group\n\nAdd-group: Group x <x>\nAdd-group: Group z <z>",
- "Account 8",
- "8@server-id");
- assertCommit(
- log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 9", "9@server-id");
- assertCommit(log.get(4), "Update group\n\nAdd-group: Group y <y>", "Account 9", "9@server-id");
- }
-
- @Test
- public void fixupCommitPostDatesAllAuditEventsEvenIfAuditEventsAreInTheFuture() throws Exception {
- AccountGroup g = newGroup("a");
- IntStream.range(0, 20).forEach(i -> TimeUtil.nowTs());
- Timestamp future = TimeUtil.nowTs();
- TestTimeUtil.resetWithClockStep(1, TimeUnit.SECONDS);
-
- GroupBundle b =
- builder()
- .group(g)
- .byId(byId(g, "x"), byId(g, "y"), byId(g, "z"))
- .byIdAudit(addById(g, "x", 8, future))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(3);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
- assertServerCommit(
- log.get(2), "Update group\n\nAdd-group: Group y <y>\nAdd-group: Group z <z>");
-
- assertThat(log.stream().map(c -> c.committer.date).collect(toImmutableList()))
- .named("%s", log)
- .isOrdered();
- assertThat(TimeUtil.nowTs()).isLessThan(future);
- }
-
- @Test
- public void redundantMemberAuditsAreIgnored() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp t1 = TimeUtil.nowTs();
- Timestamp t2 = TimeUtil.nowTs();
- Timestamp t3 = TimeUtil.nowTs();
- Timestamp t4 = TimeUtil.nowTs();
- Timestamp t5 = TimeUtil.nowTs();
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 2))
- .memberAudit(
- addMember(g, 1, 8, t1),
- addMember(g, 1, 8, t1),
- addMember(g, 1, 8, t3),
- addMember(g, 1, 9, t4),
- addAndRemoveMember(g, 1, 8, t2, 9, t5),
- addAndLegacyRemoveMember(g, 2, 9, t3),
- addMember(g, 2, 8, t1),
- addMember(g, 2, 9, t4),
- addMember(g, 1, 8, t5))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(5);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1),
- "Update group\n\nAdd: Account 1 <1@server-id>\nAdd: Account 2 <2@server-id>",
- "Account 8",
- "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nRemove: Account 2 <2@server-id>", "Account 9", "9@server-id");
- assertCommit(
- log.get(3), "Update group\n\nAdd: Account 2 <2@server-id>", "Account 9", "9@server-id");
- assertCommit(
- log.get(4), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 9", "9@server-id");
- }
-
- @Test
- public void additionsAndRemovalsWithinSameSecondCanBeMigrated() throws Exception {
- TestTimeUtil.resetWithClockStep(1, TimeUnit.MILLISECONDS);
- AccountGroup g = newGroup("a");
- Timestamp t1 = TimeUtil.nowTs();
- Timestamp t2 = TimeUtil.nowTs();
- Timestamp t3 = TimeUtil.nowTs();
- Timestamp t4 = TimeUtil.nowTs();
- Timestamp t5 = TimeUtil.nowTs();
- GroupBundle b =
- builder()
- .group(g)
- .members(member(g, 1))
- .memberAudit(
- addAndLegacyRemoveMember(g, 1, 8, t1),
- addMember(g, 1, 10, t2),
- addAndRemoveMember(g, 1, 8, t3, 9, t4),
- addMember(g, 1, 8, t5))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(6);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(
- log.get(1), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 8", "8@server-id");
- assertCommit(
- log.get(3), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 10", "10@server-id");
- assertCommit(
- log.get(4), "Update group\n\nRemove: Account 1 <1@server-id>", "Account 9", "9@server-id");
- assertCommit(
- log.get(5), "Update group\n\nAdd: Account 1 <1@server-id>", "Account 8", "8@server-id");
- }
-
- @Test
- public void redundantByIdAuditsAreIgnored() throws Exception {
- AccountGroup g = newGroup("a");
- Timestamp t1 = TimeUtil.nowTs();
- Timestamp t2 = TimeUtil.nowTs();
- Timestamp t3 = TimeUtil.nowTs();
- Timestamp t4 = TimeUtil.nowTs();
- Timestamp t5 = TimeUtil.nowTs();
- GroupBundle b =
- builder()
- .group(g)
- .byId()
- .byIdAudit(
- addById(g, "x", 8, t1),
- addById(g, "x", 8, t3),
- addById(g, "x", 9, t4),
- addAndRemoveById(g, "x", 8, t2, 9, t5))
- .build();
-
- rebuilder.rebuild(repo, b, null);
-
- assertMigratedCleanly(reload(g), b);
- ImmutableList<CommitInfo> log = log(g);
- assertThat(log).hasSize(3);
- assertServerCommit(log.get(0), "Create group");
- assertCommit(log.get(1), "Update group\n\nAdd-group: Group x <x>", "Account 8", "8@server-id");
- assertCommit(
- log.get(2), "Update group\n\nRemove-group: Group x <x>", "Account 9", "9@server-id");
- }
-
- @Test
- public void combineWithBatchGroupNameNotes() throws Exception {
- AccountGroup g1 = newGroup("a");
- AccountGroup g2 = newGroup("b");
- GroupReference gr1 = new GroupReference(g1.getGroupUUID(), g1.getName());
- GroupReference gr2 = new GroupReference(g2.getGroupUUID(), g2.getName());
-
- GroupBundle b1 = builder().group(g1).build();
- GroupBundle b2 = builder().group(g2).build();
-
- BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
-
- rebuilder.rebuild(repo, b1, bru);
- rebuilder.rebuild(repo, b2, bru);
- try (ObjectInserter inserter = repo.newObjectInserter()) {
- ImmutableList<GroupReference> refs = ImmutableList.of(gr1, gr2);
- GroupNameNotes.updateAllGroups(repo, inserter, bru, refs, newPersonIdent());
- inserter.flush();
- }
-
- assertThat(log(g1)).isEmpty();
- assertThat(log(g2)).isEmpty();
- assertThat(logGroupNames()).isEmpty();
-
- RefUpdateUtil.executeChecked(bru, repo);
-
- assertThat(log(g1)).hasSize(1);
- assertThat(log(g2)).hasSize(1);
- assertThat(logGroupNames()).hasSize(1);
- assertMigratedCleanly(reload(g1), b1);
- assertMigratedCleanly(reload(g2), b2);
-
- assertThat(GroupNameNotes.loadAllGroups(repo)).containsExactly(gr1, gr2);
- }
-
- @Test
- public void groupNamesWithLeadingAndTrailingWhitespace() throws Exception {
- for (String leading : ImmutableList.of("", " ", " ")) {
- for (String trailing : ImmutableList.of("", " ", " ")) {
- AccountGroup g = newGroup(leading + "a" + trailing);
- GroupBundle b = builder().group(g).build();
- rebuilder.rebuild(repo, b, null);
- assertMigratedCleanly(reload(g), b);
- }
- }
- }
-
- @Test
- public void disallowExisting() throws Exception {
- AccountGroup g = newGroup("a");
- GroupBundle b = builder().group(g).build();
-
- rebuilder.rebuild(repo, b, null);
- assertMigratedCleanly(reload(g), b);
- String refName = RefNames.refsGroups(g.getGroupUUID());
- ObjectId oldId = repo.exactRef(refName).getObjectId();
-
- try {
- rebuilder.rebuild(repo, b, null);
- assert_().fail("expected OrmDuplicateKeyException");
- } catch (OrmDuplicateKeyException e) {
- // Expected.
- }
-
- assertThat(repo.exactRef(refName).getObjectId()).isEqualTo(oldId);
- }
-
- private GroupBundle reload(AccountGroup g) throws Exception {
- return bundleFactory.fromNoteDb(allUsersName, repo, g.getGroupUUID());
- }
-
- private void assertMigratedCleanly(GroupBundle noteDbBundle, GroupBundle expectedReviewDbBundle) {
- assertThat(GroupBundle.compareWithAudits(expectedReviewDbBundle, noteDbBundle)).isEmpty();
- }
-
- private AccountGroup newGroup(String name) {
- int id = idCounter.incrementAndGet();
- return new AccountGroup(
- new AccountGroup.NameKey(name),
- new AccountGroup.Id(id),
- new AccountGroup.UUID(name.trim() + "-" + id),
- TimeUtil.nowTs());
- }
-
- private AccountGroupMember member(AccountGroup g, int accountId) {
- return new AccountGroupMember(new AccountGroupMember.Key(new Account.Id(accountId), g.getId()));
- }
-
- private AccountGroupMemberAudit addMember(
- AccountGroup g, int accountId, int adder, Timestamp addedOn) {
- return new AccountGroupMemberAudit(member(g, accountId), new Account.Id(adder), addedOn);
- }
-
- private AccountGroupMemberAudit addAndLegacyRemoveMember(
- AccountGroup g, int accountId, int adder, Timestamp addedOn) {
- AccountGroupMemberAudit a = addMember(g, accountId, adder, addedOn);
- a.removedLegacy();
- return a;
- }
-
- private AccountGroupMemberAudit addAndRemoveMember(
- AccountGroup g,
- int accountId,
- int adder,
- Timestamp addedOn,
- int removedBy,
- Timestamp removedOn) {
- AccountGroupMemberAudit a = addMember(g, accountId, adder, addedOn);
- a.removed(new Account.Id(removedBy), removedOn);
- return a;
- }
-
- private AccountGroupByIdAud addById(
- AccountGroup g, String subgroupUuid, int adder, Timestamp addedOn) {
- return new AccountGroupByIdAud(byId(g, subgroupUuid), new Account.Id(adder), addedOn);
- }
-
- private AccountGroupByIdAud addAndRemoveById(
- AccountGroup g,
- String subgroupUuid,
- int adder,
- Timestamp addedOn,
- int removedBy,
- Timestamp removedOn) {
- AccountGroupByIdAud a = addById(g, subgroupUuid, adder, addedOn);
- a.removed(new Account.Id(removedBy), removedOn);
- return a;
- }
-
- private AccountGroupById byId(AccountGroup g, String subgroupUuid) {
- return new AccountGroupById(
- new AccountGroupById.Key(g.getId(), new AccountGroup.UUID(subgroupUuid)));
- }
-
- private ImmutableList<CommitInfo> log(AccountGroup g) throws Exception {
- return GitTestUtil.log(repo, RefNames.refsGroups(g.getGroupUUID()));
- }
-
- private ImmutableList<CommitInfo> logGroupNames() throws Exception {
- return GitTestUtil.log(repo, REFS_GROUPNAMES);
- }
-
- private static GroupBundle.Builder builder() {
- return GroupBundle.builder().source(GroupBundle.Source.REVIEW_DB);
- }
-
- private static PersonIdent newPersonIdent() {
- return new PersonIdent(SERVER_NAME, SERVER_EMAIL, TimeUtil.nowTs(), TZ);
- }
-
- private static void assertServerCommit(CommitInfo commitInfo, String expectedMessage) {
- assertCommit(commitInfo, expectedMessage, SERVER_NAME, SERVER_EMAIL);
- }
-
- private static void assertCommit(
- CommitInfo commitInfo, String expectedMessage, String expectedName, String expectedEmail) {
- assertThat(commitInfo).message().isEqualTo(expectedMessage);
- assertThat(commitInfo).author().name().isEqualTo(expectedName);
- assertThat(commitInfo).author().email().isEqualTo(expectedEmail);
-
- // Committer should always be the server, regardless of author.
- assertThat(commitInfo).committer().name().isEqualTo(SERVER_NAME);
- assertThat(commitInfo).committer().email().isEqualTo(SERVER_EMAIL);
- assertThat(commitInfo).committer().date().isEqualTo(commitInfo.author.date);
- assertThat(commitInfo).committer().tz().isEqualTo(commitInfo.author.tz);
- }
-
- private static AuditLogFormatter getAuditLogFormatter() {
- return AuditLogFormatter.create(
- GroupRebuilderTest::getAccount, GroupRebuilderTest::getGroup, SERVER_ID);
- }
-
- private static Optional<Account> getAccount(Account.Id id) {
- Account account = new Account(id, TimeUtil.nowTs());
- account.setFullName("Account " + id);
- return Optional.of(account);
- }
-
- private static Optional<GroupDescription.Basic> getGroup(AccountGroup.UUID uuid) {
- GroupDescription.Basic group =
- new GroupDescription.Basic() {
- @Override
- public AccountGroup.UUID getGroupUUID() {
- return uuid;
- }
-
- @Override
- public String getName() {
- return "Group " + uuid;
- }
-
- @Nullable
- @Override
- public String getEmailAddress() {
- return null;
- }
-
- @Nullable
- @Override
- public String getUrl() {
- return null;
- }
- };
- return Optional.of(group);
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/HANATest.java b/javatests/com/google/gerrit/server/schema/HANATest.java
deleted file mode 100644
index ccf747f..0000000
--- a/javatests/com/google/gerrit/server/schema/HANATest.java
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright (C) 2016 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
-
-package com.google.gerrit.server.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.testing.GerritBaseTests;
-import org.eclipse.jgit.lib.Config;
-import org.junit.Before;
-import org.junit.Test;
-
-public class HANATest extends GerritBaseTests {
-
- private HANA hana;
- private Config config;
-
- @Before
- public void setup() {
- config = new Config();
- config.setString("database", null, "hostname", "my.host");
- hana = new HANA(config);
- }
-
- @Test
- public void getUrl() throws Exception {
- config.setString("database", null, "port", "4242");
- assertThat(hana.getUrl()).isEqualTo("jdbc:sap://my.host:4242");
- }
-
- @Test
- public void getIndexScript() throws Exception {
- assertThat(hana.getIndexScript()).isSameAs(ScriptRunner.NOOP);
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
index 9af7b1b..6018d85 100644
--- a/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaUpdaterTest.java
@@ -94,20 +94,25 @@
protected final NoteDbSchemaVersion.Arguments args;
private final List<String> messages;
- TestUpdate(Optional<Integer> initialVersion) throws Exception {
+ TestUpdate(Optional<Integer> initialVersion) {
cfg = new Config();
allProjectsName = new AllProjectsName("The-Projects");
allUsersName = new AllUsersName("The-Users");
repoManager = new InMemoryRepositoryManager();
- try (Repository repo = repoManager.createRepository(allProjectsName)) {
- if (initialVersion.isPresent()) {
- TestRepository<?> tr = new TestRepository<>(repo);
- tr.update(RefNames.REFS_VERSION, tr.blob(initialVersion.get().toString()));
- }
- }
- repoManager.createRepository(allUsersName).close();
- setUp();
+ SchemaCreator schemaCreator =
+ () -> {
+ try (Repository repo = repoManager.createRepository(allProjectsName)) {
+ if (initialVersion.isPresent()) {
+ TestRepository<?> tr = new TestRepository<>(repo);
+ tr.update(RefNames.REFS_VERSION, tr.blob(initialVersion.get().toString()));
+ }
+ } catch (Exception e) {
+ throw new OrmException(e);
+ }
+ repoManager.createRepository(allUsersName).close();
+ setUp();
+ };
args = new NoteDbSchemaVersion.Arguments(repoManager, allProjectsName);
NoteDbSchemaVersionManager versionManager =
@@ -117,8 +122,10 @@
updater =
new NoteDbSchemaUpdater(
cfg,
+ allProjectsName,
allUsersName,
repoManager,
+ schemaCreator,
notesMigration,
versionManager,
args,
@@ -133,7 +140,7 @@
cfg.setString("noteDb", "changes", "disableReviewDb", "true");
}
- protected void seedGroupSequenceRef() throws Exception {
+ protected void seedGroupSequenceRef() throws OrmException {
new RepoSequence(
repoManager,
GitReferenceUpdated.DISABLED,
@@ -144,7 +151,12 @@
.next();
}
- protected void setUp() throws Exception {}
+ /**
+ * Test-specific setup.
+ *
+ * @throws OrmException if an error occurs.
+ */
+ protected void setUp() throws OrmException {}
ImmutableList<String> update() throws Exception {
updater.update(
@@ -197,7 +209,7 @@
TestUpdate u =
new TestUpdate(Optional.empty()) {
@Override
- public void setUp() throws Exception {
+ public void setUp() throws OrmException {
setNotesMigrationConfig();
seedGroupSequenceRef();
}
@@ -217,7 +229,7 @@
TestUpdate u =
new TestUpdate(Optional.empty()) {
@Override
- public void setUp() throws Exception {
+ public void setUp() throws OrmException {
seedGroupSequenceRef();
}
};
@@ -236,7 +248,7 @@
TestUpdate u =
new TestUpdate(Optional.empty()) {
@Override
- public void setUp() throws Exception {
+ public void setUp() {
setNotesMigrationConfig();
}
};
diff --git a/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionsTest.java b/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionsTest.java
index 02388ba..042ac30 100644
--- a/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionsTest.java
+++ b/javatests/com/google/gerrit/server/schema/NoteDbSchemaVersionsTest.java
@@ -45,9 +45,7 @@
@Test
public void exceedsReviewDbVersion() {
- assertThat(NoteDbSchemaVersions.ALL.firstKey())
- // TODO(dborowitz): Replace with hard-coded max number once ReviewDb code is deleted.
- .isGreaterThan(ReviewDbSchemaVersion.guessVersion(ReviewDbSchemaVersion.C));
+ assertThat(NoteDbSchemaVersions.ALL.firstKey()).isGreaterThan(170);
}
@Test
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java b/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
deleted file mode 100644
index 55bd5f9..0000000
--- a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaUpdaterTest.java
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright (C) 2009 The Android Open Source Project
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package com.google.gerrit.server.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.extensions.config.FactoryModule;
-import com.google.gerrit.lifecycle.LifecycleManager;
-import com.google.gerrit.metrics.DisabledMetricMaker;
-import com.google.gerrit.metrics.MetricMaker;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.GerritPersonIdentProvider;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.config.AnonymousCowardName;
-import com.google.gerrit.server.config.AnonymousCowardNameProvider;
-import com.google.gerrit.server.config.GerritServerConfig;
-import com.google.gerrit.server.config.GerritServerId;
-import com.google.gerrit.server.config.GerritServerIdProvider;
-import com.google.gerrit.server.config.SitePaths;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.group.SystemGroupBackend;
-import com.google.gerrit.server.notedb.NotesMigration;
-import com.google.gerrit.testing.GerritBaseTests;
-import com.google.gerrit.testing.InMemoryDatabase;
-import com.google.gerrit.testing.InMemoryH2Type;
-import com.google.gerrit.testing.InMemoryRepositoryManager;
-import com.google.gerrit.testing.TestUpdateUI;
-import com.google.gwtorm.server.OrmException;
-import com.google.gwtorm.server.SchemaFactory;
-import com.google.inject.Guice;
-import com.google.inject.Key;
-import com.google.inject.ProvisionException;
-import com.google.inject.TypeLiteral;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.util.UUID;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Test;
-
-public class ReviewDbSchemaUpdaterTest extends GerritBaseTests {
- private LifecycleManager lifecycle;
- private InMemoryDatabase db;
-
- @Before
- public void setUp() throws Exception {
- lifecycle = new LifecycleManager();
- db = InMemoryDatabase.newDatabase(lifecycle);
- lifecycle.start();
- }
-
- @After
- public void tearDown() throws Exception {
- if (lifecycle != null) {
- lifecycle.stop();
- }
- InMemoryDatabase.drop(db);
- }
-
- @Test
- public void update() throws OrmException, FileNotFoundException, IOException {
- db.create();
-
- final Path site = Paths.get(UUID.randomUUID().toString());
- final SitePaths paths = new SitePaths(site);
- ReviewDbSchemaUpdater u =
- Guice.createInjector(
- new FactoryModule() {
- @Override
- protected void configure() {
- TypeLiteral<SchemaFactory<ReviewDb>> schemaFactory =
- new TypeLiteral<SchemaFactory<ReviewDb>>() {};
- bind(schemaFactory).to(NotesMigrationSchemaFactory.class);
- bind(Key.get(schemaFactory, ReviewDbFactory.class)).toInstance(db);
- bind(SitePaths.class).toInstance(paths);
-
- Config cfg = new Config();
- cfg.setString("user", null, "name", "Gerrit Code Review");
- cfg.setString("user", null, "email", "gerrit@localhost");
- cfg.setString(
- GerritServerIdProvider.SECTION,
- null,
- GerritServerIdProvider.KEY,
- "1234567");
- bind(Config.class) //
- .annotatedWith(GerritServerConfig.class) //
- .toInstance(cfg);
-
- bind(PersonIdent.class) //
- .annotatedWith(GerritPersonIdent.class) //
- .toProvider(GerritPersonIdentProvider.class);
-
- bind(String.class).annotatedWith(GerritServerId.class).toInstance("gerrit");
-
- bind(AllProjectsName.class).toInstance(new AllProjectsName("All-Projects"));
- bind(AllUsersName.class).toInstance(new AllUsersName("All-Users"));
-
- bind(GitRepositoryManager.class).toInstance(new InMemoryRepositoryManager());
-
- bind(String.class) //
- .annotatedWith(AnonymousCowardName.class) //
- .toProvider(AnonymousCowardNameProvider.class);
-
- bind(DataSourceType.class).to(InMemoryH2Type.class);
-
- bind(SystemGroupBackend.class);
- install(new NotesMigration.Module());
- bind(MetricMaker.class).to(DisabledMetricMaker.class);
- }
- })
- .getInstance(ReviewDbSchemaUpdater.class);
-
- for (ReviewDbSchemaVersion s = u.getLatestSchemaVersion();
- s.getVersionNbr() > 1;
- s = s.getPrior()) {
- try {
- assertThat(s.getPrior().getVersionNbr())
- .named(
- "schema %s has prior version %s. Not true that",
- s.getVersionNbr(), s.getPrior().getVersionNbr())
- .isEqualTo(s.getVersionNbr() - 1);
- } catch (ProvisionException e) {
- // Ignored
- // The oldest supported schema version doesn't have a prior schema
- // version.
- break;
- }
- }
-
- u.update(new TestUpdateUI());
-
- db.assertSchemaVersion();
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java b/javatests/com/google/gerrit/server/schema/SchemaCreatorImplTest.java
similarity index 76%
rename from javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
rename to javatests/com/google/gerrit/server/schema/SchemaCreatorImplTest.java
index fa0d8b3..ad2d184 100644
--- a/javatests/com/google/gerrit/server/schema/ReviewDbSchemaCreatorTest.java
+++ b/javatests/com/google/gerrit/server/schema/SchemaCreatorImplTest.java
@@ -28,27 +28,21 @@
import com.google.gerrit.testing.GerritBaseTests;
import com.google.gerrit.testing.InMemoryDatabase;
import com.google.gerrit.testing.InMemoryModule;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
-import java.io.File;
-import java.sql.ResultSet;
-import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.jgit.lib.Repository;
-import org.junit.After;
import org.junit.Before;
import org.junit.Test;
-public class ReviewDbSchemaCreatorTest extends GerritBaseTests {
+public class SchemaCreatorImplTest extends GerritBaseTests {
@Inject private AllProjectsName allProjects;
@Inject private GitRepositoryManager repoManager;
- @Inject private InMemoryDatabase db;
+ @Inject private InMemoryDatabase inMemoryDatabase;
@Inject private ProjectConfig.Factory projectConfigFactory;
@@ -57,35 +51,8 @@
new InMemoryModule().inject(this);
}
- @After
- public void tearDown() throws Exception {
- InMemoryDatabase.drop(db);
- }
-
- @Test
- public void getCauses_CreateSchema() throws OrmException, SQLException {
- // Initially the schema should be empty.
- String[] types = {"TABLE", "VIEW"};
- try (JdbcSchema d = (JdbcSchema) db.open();
- ResultSet rs = d.getConnection().getMetaData().getTables(null, null, null, types)) {
- assertThat(rs.next()).isFalse();
- }
-
- // Create the schema using the current schema version.
- //
- db.create();
- db.assertSchemaVersion();
-
- // By default sitePath is set to the current working directory.
- //
- File sitePath = new File(".").getAbsoluteFile();
- if (sitePath.getName().equals(".")) {
- sitePath = sitePath.getParentFile();
- }
- }
-
private LabelTypes getLabelTypes() throws Exception {
- db.create();
+ inMemoryDatabase.create();
ProjectConfig c = projectConfigFactory.create(allProjects);
try (Repository repo = repoManager.openRepository(allProjects)) {
c.load(repo);
diff --git a/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java b/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java
deleted file mode 100644
index 4d5db6d..0000000
--- a/javatests/com/google/gerrit/server/schema/Schema_150_to_151_Test.java
+++ /dev/null
@@ -1,253 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.TruthJUnit.assume;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.AccountGroup;
-import com.google.gerrit.reviewdb.client.AccountGroup.Id;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.reviewdb.server.ReviewDbWrapper;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.Sequences;
-import com.google.gerrit.server.account.GroupUUID;
-import com.google.gerrit.server.util.time.TimeUtil;
-import com.google.gerrit.testing.InMemoryTestEnvironment;
-import com.google.gerrit.testing.TestUpdateUI;
-import com.google.gwtorm.jdbc.JdbcSchema;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.sql.Connection;
-import java.sql.PreparedStatement;
-import java.sql.ResultSet;
-import java.sql.Statement;
-import java.sql.Timestamp;
-import java.time.Instant;
-import java.time.LocalDateTime;
-import java.time.Month;
-import java.time.ZoneOffset;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.junit.After;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class Schema_150_to_151_Test {
-
- @Rule public InMemoryTestEnvironment testEnv = new InMemoryTestEnvironment();
-
- @Inject private Schema_151 schema151;
- @Inject private ReviewDb db;
- @Inject private IdentifiedUser currentUser;
- @Inject private @GerritPersonIdent Provider<PersonIdent> serverIdent;
- @Inject private Sequences seq;
-
- private Connection connection;
- private PreparedStatement createdOnRetrieval;
- private PreparedStatement createdOnUpdate;
- private PreparedStatement auditEntryDeletion;
- private JdbcSchema jdbcSchema;
-
- @Before
- public void unwrapDb() {
- jdbcSchema = ReviewDbWrapper.unwrapJbdcSchema(db);
- }
-
- @Before
- public void setUp() throws Exception {
- assume().that(db instanceof JdbcSchema).isTrue();
-
- connection = ((JdbcSchema) db).getConnection();
-
- try (Statement stmt = connection.createStatement()) {
- stmt.execute(
- "CREATE TABLE account_groups ("
- + " group_uuid varchar(255) DEFAULT '' NOT NULL,"
- + " group_id INTEGER DEFAULT 0 NOT NULL,"
- + " name varchar(255) DEFAULT '' NOT NULL,"
- + " created_on TIMESTAMP,"
- + " description CLOB,"
- + " owner_group_uuid varchar(255) DEFAULT '' NOT NULL,"
- + " visible_to_all CHAR(1) DEFAULT 'N' NOT NULL"
- + ")");
-
- stmt.execute(
- "CREATE TABLE account_group_members ("
- + " group_id INTEGER DEFAULT 0 NOT NULL,"
- + " account_id INTEGER DEFAULT 0 NOT NULL"
- + ")");
-
- stmt.execute(
- "CREATE TABLE account_group_members_audit ("
- + " group_id INTEGER DEFAULT 0 NOT NULL,"
- + " account_id INTEGER DEFAULT 0 NOT NULL,"
- + " added_by INTEGER DEFAULT 0 NOT NULL,"
- + " added_on TIMESTAMP,"
- + " removed_by INTEGER,"
- + " removed_on TIMESTAMP"
- + ")");
- }
-
- createdOnRetrieval =
- connection.prepareStatement("SELECT created_on FROM account_groups WHERE group_id = ?");
- createdOnUpdate =
- connection.prepareStatement("UPDATE account_groups SET created_on = ? WHERE group_id = ?");
- auditEntryDeletion =
- connection.prepareStatement("DELETE FROM account_group_members_audit WHERE group_id = ?");
- }
-
- @After
- public void tearDown() throws Exception {
- if (auditEntryDeletion != null) {
- auditEntryDeletion.close();
- }
- if (createdOnUpdate != null) {
- createdOnUpdate.close();
- }
- if (createdOnRetrieval != null) {
- createdOnRetrieval.close();
- }
- if (connection != null) {
- connection.close();
- }
- }
-
- @Test
- public void createdOnIsPopulatedForGroupsCreatedAfterAudit() throws Exception {
- Timestamp testStartTime = TimeUtil.nowTs();
- AccountGroup.Id groupId = createGroupInReviewDb("Group for schema migration");
- setCreatedOnToVeryOldTimestamp(groupId);
-
- schema151.migrateData(db, new TestUpdateUI());
-
- Timestamp createdOn = getCreatedOn(groupId);
- assertThat(createdOn).isAtLeast(testStartTime);
- }
-
- @Test
- public void createdOnIsPopulatedForGroupsCreatedBeforeAudit() throws Exception {
- AccountGroup.Id groupId = createGroupInReviewDb("Ancient group for schema migration");
- setCreatedOnToVeryOldTimestamp(groupId);
- removeAuditEntriesFor(groupId);
-
- schema151.migrateData(db, new TestUpdateUI());
-
- Timestamp createdOn = getCreatedOn(groupId);
- assertThat(createdOn).isEqualTo(AccountGroup.auditCreationInstantTs());
- }
-
- private AccountGroup.Id createGroupInReviewDb(String name) throws Exception {
- AccountGroup group =
- new AccountGroup(
- new AccountGroup.NameKey(name),
- new AccountGroup.Id(seq.nextGroupId()),
- GroupUUID.make(name, serverIdent.get()),
- TimeUtil.nowTs());
- storeInReviewDb(group);
- addMembersInReviewDb(group.getId(), currentUser.getAccountId());
- return group.getId();
- }
-
- private Timestamp getCreatedOn(Id groupId) throws Exception {
- createdOnRetrieval.setInt(1, groupId.get());
- try (ResultSet results = createdOnRetrieval.executeQuery()) {
- if (results.first()) {
- return results.getTimestamp(1);
- }
- }
- return null;
- }
-
- private void setCreatedOnToVeryOldTimestamp(Id groupId) throws Exception {
- createdOnUpdate.setInt(1, groupId.get());
- Instant instant = LocalDateTime.of(1800, Month.JANUARY, 1, 0, 0).toInstant(ZoneOffset.UTC);
- createdOnUpdate.setTimestamp(1, Timestamp.from(instant));
- createdOnUpdate.setInt(2, groupId.get());
- createdOnUpdate.executeUpdate();
- }
-
- private void removeAuditEntriesFor(AccountGroup.Id groupId) throws Exception {
- auditEntryDeletion.setInt(1, groupId.get());
- auditEntryDeletion.executeUpdate();
- }
-
- private void storeInReviewDb(AccountGroup... groups) throws Exception {
- try (PreparedStatement stmt =
- jdbcSchema
- .getConnection()
- .prepareStatement(
- "INSERT INTO account_groups"
- + " (group_uuid,"
- + " group_id,"
- + " name,"
- + " description,"
- + " created_on,"
- + " owner_group_uuid,"
- + " visible_to_all) VALUES (?, ?, ?, ?, ?, ?, ?)")) {
- for (AccountGroup group : groups) {
- stmt.setString(1, group.getGroupUUID().get());
- stmt.setInt(2, group.getId().get());
- stmt.setString(3, group.getName());
- stmt.setString(4, group.getDescription());
- stmt.setTimestamp(5, group.getCreatedOn());
- stmt.setString(6, group.getOwnerGroupUUID().get());
- stmt.setString(7, group.isVisibleToAll() ? "Y" : "N");
- stmt.addBatch();
- }
- stmt.executeBatch();
- }
- }
-
- private void addMembersInReviewDb(AccountGroup.Id groupId, Account.Id... memberIds)
- throws Exception {
- try (PreparedStatement addMemberStmt =
- jdbcSchema
- .getConnection()
- .prepareStatement(
- "INSERT INTO account_group_members"
- + " (group_id,"
- + " account_id) VALUES ("
- + groupId.get()
- + ", ?)");
- PreparedStatement addMemberAuditStmt =
- jdbcSchema
- .getConnection()
- .prepareStatement(
- "INSERT INTO account_group_members_audit"
- + " (group_id,"
- + " account_id,"
- + " added_by,"
- + " added_on) VALUES ("
- + groupId.get()
- + ", ?, "
- + currentUser.getAccountId().get()
- + ", ?)")) {
- Timestamp addedOn = TimeUtil.nowTs();
- for (Account.Id memberId : memberIds) {
- addMemberStmt.setInt(1, memberId.get());
- addMemberStmt.addBatch();
-
- addMemberAuditStmt.setInt(1, memberId.get());
- addMemberAuditStmt.setTimestamp(2, addedOn);
- addMemberAuditStmt.addBatch();
- }
- addMemberStmt.executeBatch();
- addMemberAuditStmt.executeBatch();
- }
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/Schema_159_to_160_Test.java b/javatests/com/google/gerrit/server/schema/Schema_159_to_160_Test.java
deleted file mode 100644
index 0080f3f..0000000
--- a/javatests/com/google/gerrit/server/schema/Schema_159_to_160_Test.java
+++ /dev/null
@@ -1,223 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.base.MoreObjects.firstNonNull;
-import static com.google.common.collect.ImmutableMap.toImmutableMap;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth8.assertThat;
-import static com.google.gerrit.reviewdb.client.RefNames.REFS_USERS_DEFAULT;
-import static com.google.gerrit.server.git.UserConfigSections.KEY_URL;
-import static com.google.gerrit.server.git.UserConfigSections.MY;
-import static com.google.gerrit.server.schema.Schema_160.DEFAULT_DRAFT_ITEMS;
-import static com.google.gerrit.server.schema.VersionedAccountPreferences.PREFERENCES;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.extensions.client.GeneralPreferencesInfo;
-import com.google.gerrit.extensions.client.MenuItem;
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.IdentifiedUser;
-import com.google.gerrit.server.account.AccountCache;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.index.account.AccountIndexer;
-import com.google.gerrit.testing.InMemoryTestEnvironment;
-import com.google.gerrit.testing.TestUpdateUI;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-import java.util.List;
-import java.util.Optional;
-import java.util.function.Supplier;
-import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.BlobBasedConfig;
-import org.eclipse.jgit.lib.Config;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.Ref;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class Schema_159_to_160_Test {
- @Rule public InMemoryTestEnvironment testEnv = new InMemoryTestEnvironment();
-
- @Inject private AccountCache accountCache;
- @Inject private AccountIndexer accountIndexer;
- @Inject private AllUsersName allUsersName;
- @Inject private GerritApi gApi;
- @Inject private GitRepositoryManager repoManager;
- @Inject private Provider<IdentifiedUser> userProvider;
- @Inject private ReviewDb db;
- @Inject private Schema_160 schema160;
-
- private Account.Id accountId;
-
- @Before
- public void setUp() throws Exception {
- accountId = userProvider.get().getAccountId();
- }
-
- @Test
- public void skipUnmodified() throws Exception {
- ObjectId oldMetaId = metaRef(accountId);
- ImmutableSet<String> fromNoteDb = myMenusFromNoteDb(accountId);
- ImmutableSet<String> fromApi = myMenusFromApi(accountId);
- for (String item : DEFAULT_DRAFT_ITEMS) {
- assertThat(fromNoteDb).doesNotContain(item);
- assertThat(fromApi).doesNotContain(item);
- }
-
- schema160.migrateData(db, new TestUpdateUI());
-
- assertThat(metaRef(accountId)).isEqualTo(oldMetaId);
- }
-
- @Test
- public void deleteItems() throws Exception {
- ObjectId oldMetaId = metaRef(accountId);
- ImmutableSet<String> defaultNames = myMenusFromApi(accountId);
-
- GeneralPreferencesInfo prefs = gApi.accounts().id(accountId.get()).getPreferences();
- prefs.my.add(0, new MenuItem("Something else", DEFAULT_DRAFT_ITEMS.get(0) + "+is:mergeable"));
- for (int i = 0; i < DEFAULT_DRAFT_ITEMS.size(); i++) {
- prefs.my.add(new MenuItem("Draft entry " + i, DEFAULT_DRAFT_ITEMS.get(i)));
- }
- gApi.accounts().id(accountId.get()).setPreferences(prefs);
-
- List<String> oldNames =
- ImmutableList.<String>builder()
- .add("Something else")
- .addAll(defaultNames)
- .add("Draft entry 0")
- .add("Draft entry 1")
- .add("Draft entry 2")
- .add("Draft entry 3")
- .build();
- assertThat(myMenusFromApi(accountId)).containsExactlyElementsIn(oldNames).inOrder();
-
- schema160.migrateData(db, new TestUpdateUI());
- accountCache.evict(accountId);
- accountIndexer.index(accountId);
- testEnv.setApiUser(accountId);
-
- assertThat(metaRef(accountId)).isNotEqualTo(oldMetaId);
-
- List<String> newNames =
- ImmutableList.<String>builder().add("Something else").addAll(defaultNames).build();
- assertThat(myMenusFromNoteDb(accountId)).containsExactlyElementsIn(newNames).inOrder();
- assertThat(myMenusFromApi(accountId)).containsExactlyElementsIn(newNames).inOrder();
- }
-
- @Test
- public void skipNonExistentRefsUsersDefault() throws Exception {
- assertThat(readRef(REFS_USERS_DEFAULT)).isEmpty();
- schema160.migrateData(db, new TestUpdateUI());
- assertThat(readRef(REFS_USERS_DEFAULT)).isEmpty();
- }
-
- @Test
- public void deleteDefaultItem() throws Exception {
- assertThat(readRef(REFS_USERS_DEFAULT)).isEmpty();
- ImmutableSet<String> defaultNames = defaultMenusFromApi();
-
- // Setting *any* preference causes preferences.config to contain the full set of "my" sections.
- // This mimics real-world behavior prior to the 2.15 upgrade; see Issue 8439 for details.
- GeneralPreferencesInfo prefs = gApi.config().server().getDefaultPreferences();
- prefs.signedOffBy = !firstNonNull(prefs.signedOffBy, false);
- gApi.config().server().setDefaultPreferences(prefs);
-
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- Config cfg = new BlobBasedConfig(null, repo, readRef(REFS_USERS_DEFAULT).get(), PREFERENCES);
- assertThat(cfg.getSubsections("my")).containsExactlyElementsIn(defaultNames).inOrder();
-
- // Add more defaults directly in git, the SetPreferences endpoint doesn't respect the "my"
- // field in the input in 2.15 and earlier.
- cfg.setString("my", "Drafts", "url", "#/q/owner:self+is:draft");
- cfg.setString("my", "Something else", "url", "#/q/owner:self+is:draft+is:mergeable");
- cfg.setString("my", "Totally not drafts", "url", "#/q/owner:self+is:draft");
- new TestRepository<>(repo)
- .branch(REFS_USERS_DEFAULT)
- .commit()
- .add(PREFERENCES, cfg.toText())
- .create();
- }
-
- List<String> oldNames =
- ImmutableList.<String>builder()
- .addAll(defaultNames)
- .add("Drafts")
- .add("Something else")
- .add("Totally not drafts")
- .build();
- assertThat(defaultMenusFromApi()).containsExactlyElementsIn(oldNames).inOrder();
-
- schema160.migrateData(db, new TestUpdateUI());
-
- assertThat(readRef(REFS_USERS_DEFAULT)).isPresent();
-
- List<String> newNames =
- ImmutableList.<String>builder().addAll(defaultNames).add("Something else").build();
- assertThat(myMenusFromNoteDb(VersionedAccountPreferences::forDefault).keySet())
- .containsExactlyElementsIn(newNames)
- .inOrder();
- assertThat(defaultMenusFromApi()).containsExactlyElementsIn(newNames).inOrder();
- }
-
- private ImmutableSet<String> myMenusFromNoteDb(Account.Id id) throws Exception {
- return myMenusFromNoteDb(() -> VersionedAccountPreferences.forUser(id)).keySet();
- }
-
- // Raw config values, bypassing the defaults set by PreferencesConfig.
- private ImmutableMap<String, String> myMenusFromNoteDb(
- Supplier<VersionedAccountPreferences> prefsSupplier) throws Exception {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- VersionedAccountPreferences prefs = prefsSupplier.get();
- prefs.load(allUsersName, repo);
- Config cfg = prefs.getConfig();
- return cfg.getSubsections(MY)
- .stream()
- .collect(toImmutableMap(i -> i, i -> cfg.getString(MY, i, KEY_URL)));
- }
- }
-
- private ImmutableSet<String> myMenusFromApi(Account.Id id) throws Exception {
- return myMenus(gApi.accounts().id(id.get()).getPreferences()).keySet();
- }
-
- private ImmutableSet<String> defaultMenusFromApi() throws Exception {
- return myMenus(gApi.config().server().getDefaultPreferences()).keySet();
- }
-
- private static ImmutableMap<String, String> myMenus(GeneralPreferencesInfo prefs) {
-
- return prefs.my.stream().collect(toImmutableMap(i -> i.name, i -> i.url));
- }
-
- private ObjectId metaRef(Account.Id id) throws Exception {
- return readRef(RefNames.refsUsers(id))
- .orElseThrow(() -> new AssertionError("missing ref for account " + id));
- }
-
- private Optional<ObjectId> readRef(String ref) throws Exception {
- try (Repository repo = repoManager.openRepository(allUsersName)) {
- return Optional.ofNullable(repo.exactRef(ref)).map(Ref::getObjectId);
- }
- }
-}
diff --git a/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java b/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java
deleted file mode 100644
index 10aabe8..0000000
--- a/javatests/com/google/gerrit/server/schema/Schema_161_to_162_Test.java
+++ /dev/null
@@ -1,97 +0,0 @@
-// Copyright (C) 2017 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.schema;
-
-import static com.google.common.truth.Truth.assertThat;
-
-import com.google.gerrit.extensions.api.GerritApi;
-import com.google.gerrit.reviewdb.client.RefNames;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.GerritPersonIdent;
-import com.google.gerrit.server.config.AllProjectsName;
-import com.google.gerrit.server.config.AllUsersName;
-import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
-import com.google.gerrit.server.git.GitRepositoryManager;
-import com.google.gerrit.server.git.meta.MetaDataUpdate;
-import com.google.gerrit.server.project.ProjectConfig;
-import com.google.gerrit.testing.InMemoryTestEnvironment;
-import com.google.gerrit.testing.TestUpdateUI;
-import com.google.gwtorm.server.OrmException;
-import com.google.inject.Inject;
-import java.io.IOException;
-import org.eclipse.jgit.errors.ConfigInvalidException;
-import org.eclipse.jgit.lib.ObjectId;
-import org.eclipse.jgit.lib.PersonIdent;
-import org.eclipse.jgit.lib.Repository;
-import org.junit.Rule;
-import org.junit.Test;
-
-public class Schema_161_to_162_Test {
- @Rule public InMemoryTestEnvironment testEnv = new InMemoryTestEnvironment();
-
- @Inject private AllProjectsName allProjectsName;
- @Inject private AllUsersName allUsersName;
- @Inject private GerritApi gApi;
- @Inject private GitRepositoryManager repoManager;
- @Inject private Schema_162 schema162;
- @Inject private ReviewDb db;
- @Inject private ProjectConfig.Factory projectConfigFactory;
- @Inject @GerritPersonIdent private PersonIdent serverUser;
-
- @Test
- public void skipCorrectInheritance() throws Exception {
- assertThatAllUsersInheritsFrom(allProjectsName.get());
- ObjectId oldHead;
- try (Repository git = repoManager.openRepository(allUsersName)) {
- oldHead = git.findRef(RefNames.REFS_CONFIG).getObjectId();
- }
-
- schema162.migrateData(db, new TestUpdateUI());
-
- // Check that the parent remained unchanged and that no commit was made
- assertThatAllUsersInheritsFrom(allProjectsName.get());
- try (Repository git = repoManager.openRepository(allUsersName)) {
- assertThat(oldHead).isEqualTo(git.findRef(RefNames.REFS_CONFIG).getObjectId());
- }
- }
-
- @Test
- public void fixIncorrectInheritance() throws Exception {
- String testProject = gApi.projects().create("test").get().name;
- assertThatAllUsersInheritsFrom(allProjectsName.get());
-
- try (Repository git = repoManager.openRepository(allUsersName);
- MetaDataUpdate md = new MetaDataUpdate(GitReferenceUpdated.DISABLED, allUsersName, git)) {
- ProjectConfig cfg = projectConfigFactory.read(md);
- cfg.getProject().setParentName(testProject);
- md.getCommitBuilder().setCommitter(serverUser);
- md.getCommitBuilder().setAuthor(serverUser);
- md.setMessage("Test");
- cfg.commit(md);
- } catch (ConfigInvalidException | IOException ex) {
- throw new OrmException(ex);
- }
- assertThatAllUsersInheritsFrom(testProject);
-
- schema162.migrateData(db, new TestUpdateUI());
-
- assertThatAllUsersInheritsFrom(allProjectsName.get());
- }
-
- private void assertThatAllUsersInheritsFrom(String parent) throws Exception {
- assertThat(gApi.projects().name(allUsersName.get()).access().inheritsFrom.name)
- .isEqualTo(parent);
- }
-}
diff --git a/lib/BUILD b/lib/BUILD
index 80da4c0..e5e5765 100644
--- a/lib/BUILD
+++ b/lib/BUILD
@@ -505,10 +505,3 @@
visibility = ["//visibility:public"],
exports = ["@icu4j//jar"],
)
-
-java_library(
- name = "postgresql",
- data = ["//lib:LICENSE-postgresql"],
- visibility = ["//visibility:public"],
- exports = ["@postgresql//jar"],
-)
diff --git a/lib/LICENSE-postgresql b/lib/LICENSE-postgresql
deleted file mode 100644
index fd416d2..0000000
--- a/lib/LICENSE-postgresql
+++ /dev/null
@@ -1,26 +0,0 @@
-Copyright (c) 1997-2011, PostgreSQL Global Development Group
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without
-modification, are permitted provided that the following conditions are met:
-
-1. Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
-2. Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
-3. Neither the name of the PostgreSQL Global Development Group nor the names
- of its contributors may be used to endorse or promote products derived
- from this software without specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
-LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
-CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
-SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
-INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
-CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
-ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
-POSSIBILITY OF SUCH DAMAGE.
diff --git a/lib/commons/BUILD b/lib/commons/BUILD
index bb36389..93d3c2f 100644
--- a/lib/commons/BUILD
+++ b/lib/commons/BUILD
@@ -3,21 +3,18 @@
java_library(
name = "codec",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-codec//jar"],
)
java_library(
name = "compress",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-compress//jar"],
)
java_library(
name = "lang",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-lang//jar"],
)
@@ -30,14 +27,12 @@
java_library(
name = "net",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-net//jar"],
)
java_library(
name = "dbcp",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-dbcp//jar"],
runtime_deps = [":pool"],
)
@@ -45,20 +40,17 @@
java_library(
name = "pool",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-pool//jar"],
)
java_library(
name = "validator",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-validator//jar"],
)
java_library(
name = "io",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@commons-io//jar"],
)
diff --git a/lib/elasticsearch-rest-client/BUILD b/lib/elasticsearch-rest-client/BUILD
index c6357d0..8df3c70 100644
--- a/lib/elasticsearch-rest-client/BUILD
+++ b/lib/elasticsearch-rest-client/BUILD
@@ -3,6 +3,5 @@
java_library(
name = "elasticsearch-rest-client",
data = ["//lib:LICENSE-elasticsearch"],
- visibility = ["//visibility:public"],
exports = ["@elasticsearch-rest-client//jar"],
)
diff --git a/lib/greenmail/BUILD b/lib/greenmail/BUILD
index b09f27b..5d8e1d6 100644
--- a/lib/greenmail/BUILD
+++ b/lib/greenmail/BUILD
@@ -13,7 +13,6 @@
name = "greenmail",
testonly = 1,
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@greenmail//jar"],
runtime_deps = select({
"//:java9": POST_JDK8_DEPS,
diff --git a/lib/httpcomponents/BUILD b/lib/httpcomponents/BUILD
index 74cca14..03d9b68 100644
--- a/lib/httpcomponents/BUILD
+++ b/lib/httpcomponents/BUILD
@@ -3,7 +3,6 @@
java_library(
name = "fluent-hc",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@fluent-hc//jar"],
runtime_deps = [":httpclient"],
)
@@ -11,7 +10,6 @@
java_library(
name = "httpclient",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@httpclient//jar"],
runtime_deps = [
":httpcore",
@@ -23,7 +21,6 @@
java_library(
name = "httpcore",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@httpcore//jar"],
)
diff --git a/lib/jackson/BUILD b/lib/jackson/BUILD
index 3d751ab..0034748 100644
--- a/lib/jackson/BUILD
+++ b/lib/jackson/BUILD
@@ -1,5 +1,3 @@
-package(default_visibility = ["//visibility:public"])
-
java_library(
name = "jackson-core",
data = ["//lib:LICENSE-Apache2.0"],
diff --git a/lib/lucene/BUILD b/lib/lucene/BUILD
index 421caed..eab2ac8 100644
--- a/lib/lucene/BUILD
+++ b/lib/lucene/BUILD
@@ -11,13 +11,11 @@
"@lucene-core//jar",
],
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
)
java_library(
name = "lucene-analyzers-common",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@lucene-analyzers-common//jar"],
runtime_deps = [":lucene-core-and-backward-codecs"],
)
@@ -25,14 +23,12 @@
java_library(
name = "lucene-core",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@lucene-core//jar"],
)
java_library(
name = "lucene-misc",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@lucene-misc//jar"],
runtime_deps = [":lucene-core-and-backward-codecs"],
)
@@ -40,7 +36,6 @@
java_library(
name = "lucene-queryparser",
data = ["//lib:LICENSE-Apache2.0"],
- visibility = ["//visibility:public"],
exports = ["@lucene-queryparser//jar"],
runtime_deps = [":lucene-core-and-backward-codecs"],
)
diff --git a/lib/polymer_externs/BUILD b/lib/polymer_externs/BUILD
index 2f1bdbd..cd71d64 100644
--- a/lib/polymer_externs/BUILD
+++ b/lib/polymer_externs/BUILD
@@ -12,9 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-package(
- default_visibility = ["//visibility:public"],
-)
+package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_closure//closure:defs.bzl", "closure_js_library")
diff --git a/plugins/delete-project b/plugins/delete-project
index e0618f3..d8fdd55 160000
--- a/plugins/delete-project
+++ b/plugins/delete-project
@@ -1 +1 @@
-Subproject commit e0618f3dff8fcc1c36861a99b2162ac611e707c6
+Subproject commit d8fdd5596181cc06707665051f0e03a49e5c3a97
diff --git a/plugins/reviewnotes b/plugins/reviewnotes
index 863130d..fdbadf3 160000
--- a/plugins/reviewnotes
+++ b/plugins/reviewnotes
@@ -1 +1 @@
-Subproject commit 863130de158605c19809956864870ff05d86b494
+Subproject commit fdbadf312d829990d3a4be3491d13a79d6c0cf5b
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 384f835..5889ffd 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -1,6 +1,4 @@
-package(
- default_visibility = ["//visibility:public"],
-)
+package(default_visibility = ["//visibility:public"])
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
load("//tools/bzl:js.bzl", "bower_component_bundle")
@@ -51,7 +49,6 @@
"zip -qr $$ROOT/$@ fonts",
]),
output_to_bindir = 1,
- visibility = ["//visibility:public"],
)
go_binary(
diff --git a/polygerrit-ui/app/BUILD b/polygerrit-ui/app/BUILD
index c735746..0aa70b8 100644
--- a/polygerrit-ui/app/BUILD
+++ b/polygerrit-ui/app/BUILD
@@ -1,6 +1,4 @@
-package(
- default_visibility = ["//visibility:public"],
-)
+package(default_visibility = ["//visibility:public"])
load(":rules.bzl", "polygerrit_bundle")
load("//tools/bzl:genrule2.bzl", "genrule2")
diff --git a/resources/com/google/gerrit/reviewdb/BUILD b/resources/com/google/gerrit/reviewdb/BUILD
deleted file mode 100644
index 8a1b457..0000000
--- a/resources/com/google/gerrit/reviewdb/BUILD
+++ /dev/null
@@ -1,8 +0,0 @@
-filegroup(
- name = "reviewdb",
- srcs = glob(
- ["**/*"],
- exclude = ["BUILD"],
- ),
- visibility = ["//visibility:public"],
-)
diff --git a/resources/com/google/gerrit/reviewdb/server/index_generic.sql b/resources/com/google/gerrit/reviewdb/server/index_generic.sql
deleted file mode 100644
index c58edb7..0000000
--- a/resources/com/google/gerrit/reviewdb/server/index_generic.sql
+++ /dev/null
@@ -1,40 +0,0 @@
--- Gerrit 2 : Generic
---
-
--- Indexes to support @Query
---
-
--- *********************************************************************
--- ApprovalCategoryAccess
--- too small to bother indexing
-
-
--- *********************************************************************
--- ApprovalCategoryValueAccess
--- @PrimaryKey covers: byCategory
-
-
--- *********************************************************************
--- BranchAccess
--- @PrimaryKey covers: byProject
-
-
--- *********************************************************************
--- ChangeMessageAccess
--- @PrimaryKey covers: byChange
-
--- covers: byPatchSet
-CREATE INDEX change_messages_byPatchset
-ON change_messages (patchset_change_id, patchset_patch_set_id);
-
--- *********************************************************************
--- PatchLineCommentAccess
--- @PrimaryKey covers: published, draft
-CREATE INDEX patch_comment_drafts
-ON patch_comments (status, author_id);
-
-
--- *********************************************************************
--- PatchSetAccess
-CREATE INDEX patch_sets_byRevision
-ON patch_sets (revision);
diff --git a/resources/com/google/gerrit/reviewdb/server/index_maxdb.sql b/resources/com/google/gerrit/reviewdb/server/index_maxdb.sql
deleted file mode 100644
index 7f0f1bd..0000000
--- a/resources/com/google/gerrit/reviewdb/server/index_maxdb.sql
+++ /dev/null
@@ -1,43 +0,0 @@
-delimiter #
--- Gerrit 2 : MaxDB
---
-
--- Indexes to support @Query
---
-
--- *********************************************************************
--- ApprovalCategoryAccess
--- too small to bother indexing
-
-
--- *********************************************************************
--- ApprovalCategoryValueAccess
--- @PrimaryKey covers: byCategory
-
-
--- *********************************************************************
--- BranchAccess
--- @PrimaryKey covers: byProject
-
-
--- *********************************************************************
--- ChangeMessageAccess
--- @PrimaryKey covers: byChange
-
--- covers: byPatchSet
-CREATE INDEX change_messages_byPatchset
-ON change_messages (patchset_change_id, patchset_patch_set_id)
-#
-
--- *********************************************************************
--- PatchLineCommentAccess
--- @PrimaryKey covers: published, draft
-CREATE INDEX patch_comment_drafts
-ON patch_comments (status, author_id)
-#
-
--- *********************************************************************
--- PatchSetAccess
-CREATE INDEX patch_sets_byRevision
-ON patch_sets (revision)
-#
diff --git a/resources/com/google/gerrit/reviewdb/server/index_postgres.sql b/resources/com/google/gerrit/reviewdb/server/index_postgres.sql
deleted file mode 100644
index 439fed7..0000000
--- a/resources/com/google/gerrit/reviewdb/server/index_postgres.sql
+++ /dev/null
@@ -1,87 +0,0 @@
--- Gerrit 2 : PostgreSQL
---
-
--- Cluster hot tables by their primary method of access
---
-ALTER TABLE patch_sets CLUSTER ON patch_sets_pkey;
-ALTER TABLE change_messages CLUSTER ON change_messages_pkey;
-ALTER TABLE patch_comments CLUSTER ON patch_comments_pkey;
-ALTER TABLE patch_set_approvals CLUSTER ON patch_set_approvals_pkey;
-
-CLUSTER;
-
-
--- Define function for conditional installation of PL/pgSQL.
--- This is required, because starting with PostgreSQL 9.0, PL/pgSQL
--- language is installed by default and database returns error when
--- we try to install it again.
---
--- Source: http://wiki.postgresql.org/wiki/CREATE_OR_REPLACE_LANGUAGE
--- Author: David Fetter
---
-
-delimiter //
-
-CREATE OR REPLACE FUNCTION make_plpgsql()
-RETURNS VOID
-LANGUAGE SQL
-AS $$
-CREATE LANGUAGE plpgsql;
-$$;
-
-//
-
-delimiter ;
-
-SELECT
- CASE
- WHEN EXISTS(
- SELECT 1
- FROM pg_catalog.pg_language
- WHERE lanname='plpgsql'
- )
- THEN NULL
- ELSE make_plpgsql() END;
-
-DROP FUNCTION make_plpgsql();
-
-delimiter ;
-
--- Indexes to support @Query
---
-
--- *********************************************************************
--- ApprovalCategoryAccess
--- too small to bother indexing
-
-
--- *********************************************************************
--- ApprovalCategoryValueAccess
--- @PrimaryKey covers: byCategory
-
-
--- *********************************************************************
--- BranchAccess
--- @PrimaryKey covers: byProject
-
-
--- *********************************************************************
--- ChangeMessageAccess
--- @PrimaryKey covers: byChange
-
--- covers: byPatchSet
-CREATE INDEX change_messages_byPatchset
-ON change_messages (patchset_change_id, patchset_patch_set_id);
-
--- *********************************************************************
--- PatchLineCommentAccess
--- @PrimaryKey covers: published, draft
-CREATE INDEX patch_comment_drafts
-ON patch_comments (author_id)
-WHERE status = 'd';
-
-
--- *********************************************************************
--- PatchSetAccess
-CREATE INDEX patch_sets_byRevision
-ON patch_sets (revision);
diff --git a/tools/bzl/pkg_war.bzl b/tools/bzl/pkg_war.bzl
index 72de14b..1fd1c81 100644
--- a/tools/bzl/pkg_war.bzl
+++ b/tools/bzl/pkg_war.bzl
@@ -19,7 +19,6 @@
LIBS = [
"//java/com/google/gerrit/common:version",
"//java/com/google/gerrit/httpd/init",
- "//lib:postgresql",
"//lib/bouncycastle:bcpkix",
"//lib/bouncycastle:bcprov",
"//lib/bouncycastle:bcpg",
diff --git a/webapp/WEB-INF/extra/jetty7/gerrit.xml b/webapp/WEB-INF/extra/jetty7/gerrit.xml
index cb0a256..4102f56 100644
--- a/webapp/WEB-INF/extra/jetty7/gerrit.xml
+++ b/webapp/WEB-INF/extra/jetty7/gerrit.xml
@@ -6,11 +6,7 @@
so it answers to simple URLs like "/$changeid" and "/mine".
* Copy this file to $JETTY_HOME/contexts/gerrit.xml
- * Edit url, username, password as necessary below for database.
- * Copy commons-dbcp-*.jar to $JETTY_HOME/lib/ext/
- * Copy commons-pool-*.jar to $JETTY_HOME/lib/ext/
- * Copy JDBC driver to $JETTY_HOME/lib/ext/
* Copy www/gerrit-*.war to $JETTY_HOME/webapps/gerrit.war
* Make sure you remove $JETTY_HOME/context/test.xml
@@ -33,36 +29,4 @@
<Item>org.eclipse.jetty.webapp.JettyWebXmlConfiguration</Item>
</Array>
</Set>
-
- <New id="ReviewDb" class="org.eclipse.jetty.plus.jndi.Resource">
- <Arg></Arg>
- <Arg>jdbc/ReviewDb</Arg>
- <Arg>
- <New class="org.apache.commons.dbcp.BasicDataSource">
-<!-- PostgreSQL
- <Set name="driverClassName">org.postgresql.Driver</Set>
- <Set name="url">jdbc:postgresql:reviewdb</Set>
- <Set name="username">gerrit</Set>
- <Set name="password">secretkey</Set>
--->
-<!-- MySQL
- <Set name="driverClassName">com.mysql.jdbc.Driver</Set>
- <Set name="url">jdbc:mysql://localhost/reviewdb?user=gerrit&password=secretkey</Set>
--->
-<!-- MariaDB
- <Set name="driverClassName">org.mariadb.jdbc.Driver</Set>
- <Set name="url">jdbc:mariadb://localhost/reviewdb?user=gerrit&password=secretkey</Set>
--->
-<!-- H2
- <Set name="driverClassName">org.h2.Driver</Set>
- <Set name="url">jdbc:h2:file:ReviewDb</Set>
--->
- <Set name="initialSize">4</Set>
- <Set name="maxActive">8</Set>
- <Set name="minIdle">4</Set>
- <Set name="maxIdle">4</Set>
- <Set name="maxWait">30000</Set>
- </New>
- </Arg>
- </New>
</Configure>