Merge branch 'stable-2.13'

* stable-2.13:
  WatchConfig: Add synchronization to prevent concurrent read/write
  VersionedAuthorizedKeys: Synchronize read/write of the git repository
  Add release notes for Gerrit 2.13.2
  Update git submodules
  ProjectAccessHandler: Check for CLA before creating changes
  Read project watches from ReviewDb
  Fix server error when navigating up to change while working

Change-Id: If2495aea9fb278b729e8d13a506a7e9bf8de9fed
This commit is contained in:
David Pursehouse 2016-09-28 17:49:10 +09:00
commit f1197a214d
8 changed files with 55 additions and 9 deletions

View File

@ -0,0 +1,34 @@
= Release notes for Gerrit 2.13.2
Gerrit 2.13.2 is now available:
link:https://gerrit-releases.storage.googleapis.com/gerrit-2.13.2.war[
https://gerrit-releases.storage.googleapis.com/gerrit-2.13.2.war]
== Schema Upgrade
There are no schema changes from link:ReleaseNotes-2.13.1.html[2.13.1].
== Bug Fixes
* link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4630[Issue 4630]:
Fix server error when navigating up to change while 'Working' is displayed.
* link:https://bugs.chromium.org/p/gerrit/issues/detail?id=4631[Issue 4631]:
Read project watches from database.
+
Project watches were being read from the git backend by default, but the
migration to git is not yet completed.
* Hooks plugin: Fix incorrect value passed to `--change-url` parameter.
+
The URL was being generated using the change's Change-Id rather than the
change number.
* Check for CLA when creating project config changes from the web UI.
+
If contributor agreements were enabled and required for a project, and
the user had not signed a CLA, it was still possible to upload changes
for review on `refs/meta/config` by making changes in the project access
editor and pressing 'Save for Review'.

View File

@ -2,6 +2,7 @@
[[s2_13]]
== Version 2.13.x
* link:ReleaseNotes-2.13.2.html[2.13.2]
* link:ReleaseNotes-2.13.1.html[2.13.1]
* link:ReleaseNotes-2.13.html[2.13]

View File

@ -18,11 +18,13 @@ import static com.google.gerrit.common.ProjectAccessUtil.mergeSections;
import com.google.common.base.MoreObjects;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.Capable;
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.common.errors.InvalidNameException;
import com.google.gerrit.common.errors.NoSuchGroupException;
import com.google.gerrit.common.errors.PermissionDeniedException;
import com.google.gerrit.common.errors.UpdateParentFailedException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.ResourceConflictException;
@ -89,10 +91,15 @@ public abstract class ProjectAccessHandler<T> extends Handler<T> {
@Override
public final T call() throws NoSuchProjectException, IOException,
ConfigInvalidException, InvalidNameException, NoSuchGroupException,
OrmException, UpdateParentFailedException {
OrmException, UpdateParentFailedException, PermissionDeniedException {
final ProjectControl projectControl =
projectControlFactory.controlFor(projectName);
Capable r = projectControl.canPushToAtLeastOneRef();
if (r != Capable.OK) {
throw new PermissionDeniedException(r.getMessage());
}
try (MetaDataUpdate md = metaDataUpdateFactory.create(projectName)) {
ProjectConfig config = ProjectConfig.read(md, base);
Set<String> toDelete = scanSectionNames(config);

View File

@ -174,7 +174,7 @@ public class AccountCacheImpl implements AccountCache {
this.loader = loader;
this.byName = byUsername;
this.readFromGit =
cfg.getBoolean("user", null, "readProjectWatchesFromGit", true);
cfg.getBoolean("user", null, "readProjectWatchesFromGit", false);
this.watchConfig = watchConfig;
}

View File

@ -60,7 +60,7 @@ public class GetWatchedProjects implements RestReadView<AccountResource> {
this.dbProvider = dbProvider;
this.self = self;
this.readFromGit =
cfg.getBoolean("user", null, "readProjectWatchesFromGit", true);
cfg.getBoolean("user", null, "readProjectWatchesFromGit", false);
this.watchConfig = watchConfig;
}

View File

@ -101,7 +101,7 @@ public class VersionedAuthorizedKeys extends VersionedMetaData {
return read(accountId).getKey(seq);
}
public AccountSshKey addKey(Account.Id accountId, String pub)
public synchronized AccountSshKey addKey(Account.Id accountId, String pub)
throws IOException, ConfigInvalidException, InvalidSshKeyException {
VersionedAuthorizedKeys authorizedKeys = read(accountId);
AccountSshKey key = authorizedKeys.addKey(pub);
@ -109,7 +109,7 @@ public class VersionedAuthorizedKeys extends VersionedMetaData {
return key;
}
public void deleteKey(Account.Id accountId, int seq)
public synchronized void deleteKey(Account.Id accountId, int seq)
throws IOException, ConfigInvalidException {
VersionedAuthorizedKeys authorizedKeys = read(accountId);
if (authorizedKeys.deleteKey(seq)) {
@ -117,7 +117,7 @@ public class VersionedAuthorizedKeys extends VersionedMetaData {
}
}
public void markKeyInvalid(Account.Id accountId, int seq)
public synchronized void markKeyInvalid(Account.Id accountId, int seq)
throws IOException, ConfigInvalidException {
VersionedAuthorizedKeys authorizedKeys = read(accountId);
if (authorizedKeys.markKeyInvalid(seq)) {

View File

@ -121,7 +121,7 @@ public class WatchConfig extends VersionedMetaData
}
}
public void upsertProjectWatches(Account.Id accountId,
public synchronized void upsertProjectWatches(Account.Id accountId,
Map<ProjectWatchKey, Set<NotifyType>> newProjectWatches)
throws IOException, ConfigInvalidException {
WatchConfig watchConfig = read(accountId);
@ -131,7 +131,7 @@ public class WatchConfig extends VersionedMetaData
commit(watchConfig);
}
public void deleteProjectWatches(Account.Id accountId,
public synchronized void deleteProjectWatches(Account.Id accountId,
Collection<ProjectWatchKey> projectWatchKeys)
throws IOException, ConfigInvalidException {
WatchConfig watchConfig = read(accountId);

View File

@ -176,7 +176,11 @@ public class H2AccountPatchReviewStore
}
stmt.executeBatch();
} catch (SQLException e) {
throw convertError("insert", e);
OrmException ormException = convertError("insert", e);
if (ormException instanceof OrmDuplicateKeyException) {
return;
}
throw ormException;
}
}