Merge branch 'stable-2.15'
* stable-2.15: NoteDbMigrator: Set checkExisting(false) on PackInserter ChangeRebuilderImpl: Fail when new NoteDb state is null PrimaryStorageMigrator: Log individual migrations at debug Document the deprecation of old change IDs Update JGit to get PackInserter fix AbstractChangeNotes: Never open repo when NoteDb is off MigrateToNoteDb: Only reindex change index PolyGerrit: Add background-repeat to gr-main-header Revert "Add privateByDefault config to /config/server/info" Private state changed event WIP state changed event Populate ChangeAttribute with WIP and private status. Fix invalid json example in POST access endpoint Add default values in create project dialog and group config Update JGit to 4.9.2.201712150930-r gerrit_plugin: Don't add Implementation-Vendor manifest entry Fix schema_154 migration from version 2.13 and older Default to writing comments in JSON format Change-Id: Iee55a0f00ce2430cd400c64491acde3651a0390d
This commit is contained in:
commit
3619a8ffb9
@ -261,6 +261,33 @@ oldTopic:: Topic name before it was changed.
|
||||
eventCreatedOn:: Time in seconds since the UNIX epoch when this event was
|
||||
created.
|
||||
|
||||
=== Work In Progress State Changed
|
||||
|
||||
Sent when the the link:intro-user.html#wip[WIP] state of the change has changed.
|
||||
|
||||
type:: wip-state-changed
|
||||
|
||||
change:: link:json.html#change[change attribute]
|
||||
|
||||
changer:: link:json.html#account[account attribute]
|
||||
|
||||
eventCreatedOn:: Time in seconds since the UNIX epoch when this event was
|
||||
created.
|
||||
|
||||
=== Private State Changed
|
||||
|
||||
Sent when the the link:intro-user.html#private-changes[private] state of the
|
||||
change has changed.
|
||||
|
||||
type:: private-state-changed
|
||||
|
||||
change:: link:json.html#change[change attribute]
|
||||
|
||||
changer:: link:json.html#account[account attribute]
|
||||
|
||||
eventCreatedOn:: Time in seconds since the UNIX epoch when this event was
|
||||
created.
|
||||
|
||||
=== Vote Deleted
|
||||
|
||||
Sent when a vote was removed from a change.
|
||||
|
@ -45,6 +45,12 @@ status:: Current state of this change.
|
||||
|
||||
ABANDONED;; Change was abandoned by its owner or administrator.
|
||||
|
||||
private:: Boolean indicating if the change is
|
||||
link:intro-user.html#private-changes[private].
|
||||
|
||||
wip:: Boolean indicating if the change is
|
||||
link:intro-user.html#wip[work in progress].
|
||||
|
||||
comments:: All inline/file comments for this change in <<message,message attributes>>.
|
||||
|
||||
trackingIds:: Issue tracking system links in
|
||||
|
@ -1386,9 +1386,6 @@ allowed].
|
||||
|`large_change` ||
|
||||
link:config-gerrit.html#change.largeChange[Number of changed lines from
|
||||
which on a change is considered as a large change].
|
||||
|`private_by_default` |not set if `false`|
|
||||
Returns true if changes are by default created as private.
|
||||
See link:config-gerrit.html#change.privateByDefault[privateByDefault]
|
||||
|`reply_label` ||
|
||||
link:config-gerrit.html#change.replyTooltip[Label name for the reply
|
||||
button].
|
||||
|
@ -1165,12 +1165,14 @@ As result a link:#project-access-info[ProjectAccessInfo] entity is returned.
|
||||
|
||||
{
|
||||
"remove": [
|
||||
"refs/*": {
|
||||
"permissions": {
|
||||
"read": {
|
||||
"rules": {
|
||||
"c2ce4749a32ceb82cd6adcce65b8216e12afb41c": {
|
||||
"action": "ALLOW"
|
||||
{
|
||||
"refs/*": {
|
||||
"permissions": {
|
||||
"read": {
|
||||
"rules": {
|
||||
"c2ce4749a32ceb82cd6adcce65b8216e12afb41c": {
|
||||
"action": "ALLOW"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ public class ChangeConfigInfo {
|
||||
public Boolean showAssigneeInChangesTable;
|
||||
public Boolean allowDrafts;
|
||||
public int largeChange;
|
||||
public Boolean privateByDefault;
|
||||
public String replyLabel;
|
||||
public String replyTooltip;
|
||||
public int updateDelay;
|
||||
|
@ -0,0 +1,21 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
public interface PrivateStateChangedListener {
|
||||
interface Event extends ChangeEvent {}
|
||||
|
||||
void onPrivateStateChanged(Event event);
|
||||
}
|
@ -0,0 +1,21 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
public interface WorkInProgressStateChangedListener {
|
||||
interface Event extends ChangeEvent {}
|
||||
|
||||
void onWorkInProgressStateChanged(Event event);
|
||||
}
|
@ -31,6 +31,7 @@ import com.google.gerrit.reviewdb.client.Project;
|
||||
import com.google.gerrit.server.change.ChangeResource;
|
||||
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
|
||||
import com.google.gerrit.server.index.DummyIndexModule;
|
||||
import com.google.gerrit.server.index.change.ChangeSchemaDefinitions;
|
||||
import com.google.gerrit.server.notedb.rebuild.NoteDbMigrator;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
@ -145,7 +146,12 @@ public class MigrateToNoteDb extends SiteProgram {
|
||||
// their server is offline.
|
||||
List<String> reindexArgs =
|
||||
ImmutableList.of(
|
||||
"--site-path", getSitePath().toString(), "--threads", Integer.toString(threads));
|
||||
"--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();
|
||||
|
@ -40,17 +40,20 @@ public class DeletePrivate
|
||||
private final ChangeMessagesUtil cmUtil;
|
||||
private final Provider<ReviewDb> dbProvider;
|
||||
private final PermissionBackend permissionBackend;
|
||||
private final SetPrivateOp.Factory setPrivateOpFactory;
|
||||
|
||||
@Inject
|
||||
DeletePrivate(
|
||||
Provider<ReviewDb> dbProvider,
|
||||
RetryHelper retryHelper,
|
||||
ChangeMessagesUtil cmUtil,
|
||||
PermissionBackend permissionBackend) {
|
||||
PermissionBackend permissionBackend,
|
||||
SetPrivateOp.Factory setPrivateOpFactory) {
|
||||
super(retryHelper);
|
||||
this.dbProvider = dbProvider;
|
||||
this.cmUtil = cmUtil;
|
||||
this.permissionBackend = permissionBackend;
|
||||
this.setPrivateOpFactory = setPrivateOpFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -65,7 +68,7 @@ public class DeletePrivate
|
||||
throw new ResourceConflictException("change is not private");
|
||||
}
|
||||
|
||||
SetPrivateOp op = new SetPrivateOp(cmUtil, false, input);
|
||||
SetPrivateOp op = setPrivateOpFactory.create(cmUtil, false, input);
|
||||
try (BatchUpdate u =
|
||||
updateFactory.create(
|
||||
dbProvider.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
|
||||
|
@ -32,8 +32,9 @@ public class DeletePrivateByPost extends DeletePrivate implements UiAction<Chang
|
||||
Provider<ReviewDb> dbProvider,
|
||||
RetryHelper retryHelper,
|
||||
ChangeMessagesUtil cmUtil,
|
||||
PermissionBackend permissionBackend) {
|
||||
super(dbProvider, retryHelper, cmUtil, permissionBackend);
|
||||
PermissionBackend permissionBackend,
|
||||
SetPrivateOp.Factory setPrivateOpFactory) {
|
||||
super(dbProvider, retryHelper, cmUtil, permissionBackend, setPrivateOpFactory);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -177,6 +177,7 @@ public class Module extends RestApiModule {
|
||||
factory(ReviewerResource.Factory.class);
|
||||
factory(SetAssigneeOp.Factory.class);
|
||||
factory(SetHashtagsOp.Factory.class);
|
||||
factory(SetPrivateOp.Factory.class);
|
||||
factory(WorkInProgressOp.Factory.class);
|
||||
}
|
||||
}
|
||||
|
@ -43,17 +43,20 @@ public class PostPrivate
|
||||
private final ChangeMessagesUtil cmUtil;
|
||||
private final Provider<ReviewDb> dbProvider;
|
||||
private final PermissionBackend permissionBackend;
|
||||
private final SetPrivateOp.Factory setPrivateOpFactory;
|
||||
|
||||
@Inject
|
||||
PostPrivate(
|
||||
Provider<ReviewDb> dbProvider,
|
||||
RetryHelper retryHelper,
|
||||
ChangeMessagesUtil cmUtil,
|
||||
PermissionBackend permissionBackend) {
|
||||
PermissionBackend permissionBackend,
|
||||
SetPrivateOp.Factory setPrivateOpFactory) {
|
||||
super(retryHelper);
|
||||
this.dbProvider = dbProvider;
|
||||
this.cmUtil = cmUtil;
|
||||
this.permissionBackend = permissionBackend;
|
||||
this.setPrivateOpFactory = setPrivateOpFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -68,7 +71,7 @@ public class PostPrivate
|
||||
return Response.ok("");
|
||||
}
|
||||
|
||||
SetPrivateOp op = new SetPrivateOp(cmUtil, true, input);
|
||||
SetPrivateOp op = setPrivateOpFactory.create(cmUtil, true, input);
|
||||
try (BatchUpdate u =
|
||||
updateFactory.create(
|
||||
dbProvider.get(), rsrc.getProject(), rsrc.getUser(), TimeUtil.nowTs())) {
|
||||
|
@ -19,10 +19,14 @@ import com.google.gerrit.extensions.restapi.ResourceConflictException;
|
||||
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.extensions.events.PrivateStateChanged;
|
||||
import com.google.gerrit.server.notedb.ChangeUpdate;
|
||||
import com.google.gerrit.server.update.BatchUpdateOp;
|
||||
import com.google.gerrit.server.update.ChangeContext;
|
||||
import com.google.gerrit.server.update.Context;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
public class SetPrivateOp implements BatchUpdateOp {
|
||||
public static class Input {
|
||||
@ -35,19 +39,32 @@ public class SetPrivateOp implements BatchUpdateOp {
|
||||
}
|
||||
}
|
||||
|
||||
public interface Factory {
|
||||
SetPrivateOp create(ChangeMessagesUtil cmUtil, boolean isPrivate, Input input);
|
||||
}
|
||||
|
||||
private final ChangeMessagesUtil cmUtil;
|
||||
private final boolean isPrivate;
|
||||
private final Input input;
|
||||
private final PrivateStateChanged privateStateChanged;
|
||||
|
||||
SetPrivateOp(ChangeMessagesUtil cmUtil, boolean isPrivate, Input input) {
|
||||
private Change change;
|
||||
|
||||
@Inject
|
||||
SetPrivateOp(
|
||||
PrivateStateChanged privateStateChanged,
|
||||
@Assisted ChangeMessagesUtil cmUtil,
|
||||
@Assisted boolean isPrivate,
|
||||
@Assisted Input input) {
|
||||
this.cmUtil = cmUtil;
|
||||
this.isPrivate = isPrivate;
|
||||
this.input = input;
|
||||
this.privateStateChanged = privateStateChanged;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean updateChange(ChangeContext ctx) throws ResourceConflictException, OrmException {
|
||||
Change change = ctx.getChange();
|
||||
change = ctx.getChange();
|
||||
ChangeUpdate update = ctx.getUpdate(change.currentPatchSetId());
|
||||
change.setPrivate(isPrivate);
|
||||
change.setLastUpdatedOn(ctx.getWhen());
|
||||
@ -56,6 +73,11 @@ public class SetPrivateOp implements BatchUpdateOp {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postUpdate(Context ctx) {
|
||||
privateStateChanged.fire(change, ctx.getAccount(), ctx.getWhen());
|
||||
}
|
||||
|
||||
private void addMessage(ChangeContext ctx, ChangeUpdate update) throws OrmException {
|
||||
Change c = ctx.getChange();
|
||||
StringBuilder buf = new StringBuilder(c.isPrivate() ? "Set private" : "Unset private");
|
||||
|
@ -25,6 +25,7 @@ import com.google.gerrit.reviewdb.client.ChangeMessage;
|
||||
import com.google.gerrit.reviewdb.client.PatchSet;
|
||||
import com.google.gerrit.server.ChangeMessagesUtil;
|
||||
import com.google.gerrit.server.PatchSetUtil;
|
||||
import com.google.gerrit.server.extensions.events.WorkInProgressStateChanged;
|
||||
import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.notedb.ChangeUpdate;
|
||||
import com.google.gerrit.server.update.BatchUpdateOp;
|
||||
@ -58,6 +59,7 @@ public class WorkInProgressOp implements BatchUpdateOp {
|
||||
private final boolean workInProgress;
|
||||
private final Input in;
|
||||
private final NotifyHandling notify;
|
||||
private final WorkInProgressStateChanged stateChanged;
|
||||
|
||||
private Change change;
|
||||
private ChangeNotes notes;
|
||||
@ -69,11 +71,13 @@ public class WorkInProgressOp implements BatchUpdateOp {
|
||||
ChangeMessagesUtil cmUtil,
|
||||
EmailReviewComments.Factory email,
|
||||
PatchSetUtil psUtil,
|
||||
WorkInProgressStateChanged stateChanged,
|
||||
@Assisted boolean workInProgress,
|
||||
@Assisted Input in) {
|
||||
this.cmUtil = cmUtil;
|
||||
this.email = email;
|
||||
this.psUtil = psUtil;
|
||||
this.stateChanged = stateChanged;
|
||||
this.workInProgress = workInProgress;
|
||||
this.in = in;
|
||||
notify =
|
||||
@ -121,6 +125,7 @@ public class WorkInProgressOp implements BatchUpdateOp {
|
||||
|
||||
@Override
|
||||
public void postUpdate(Context ctx) {
|
||||
stateChanged.fire(change, ctx.getAccount(), ctx.getWhen());
|
||||
if (workInProgress || notify.ordinal() < NotifyHandling.OWNER_REVIEWERS.ordinal()) {
|
||||
return;
|
||||
}
|
||||
|
@ -46,6 +46,7 @@ import com.google.gerrit.extensions.events.HeadUpdatedListener;
|
||||
import com.google.gerrit.extensions.events.LifecycleListener;
|
||||
import com.google.gerrit.extensions.events.NewProjectCreatedListener;
|
||||
import com.google.gerrit.extensions.events.PluginEventListener;
|
||||
import com.google.gerrit.extensions.events.PrivateStateChangedListener;
|
||||
import com.google.gerrit.extensions.events.ProjectDeletedListener;
|
||||
import com.google.gerrit.extensions.events.ProjectIndexedListener;
|
||||
import com.google.gerrit.extensions.events.ReviewerAddedListener;
|
||||
@ -54,6 +55,7 @@ import com.google.gerrit.extensions.events.RevisionCreatedListener;
|
||||
import com.google.gerrit.extensions.events.TopicEditedListener;
|
||||
import com.google.gerrit.extensions.events.UsageDataPublishedListener;
|
||||
import com.google.gerrit.extensions.events.VoteDeletedListener;
|
||||
import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicItem;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
@ -326,9 +328,11 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
|
||||
DynamicSet.setOf(binder(), ChangeRestoredListener.class);
|
||||
DynamicSet.setOf(binder(), ChangeRevertedListener.class);
|
||||
DynamicSet.setOf(binder(), PrivateStateChangedListener.class);
|
||||
DynamicSet.setOf(binder(), ReviewerAddedListener.class);
|
||||
DynamicSet.setOf(binder(), ReviewerDeletedListener.class);
|
||||
DynamicSet.setOf(binder(), VoteDeletedListener.class);
|
||||
DynamicSet.setOf(binder(), WorkInProgressStateChangedListener.class);
|
||||
DynamicSet.setOf(binder(), RevisionCreatedListener.class);
|
||||
DynamicSet.setOf(binder(), TopicEditedListener.class);
|
||||
DynamicSet.setOf(binder(), AgreementSignupListener.class);
|
||||
|
@ -16,6 +16,7 @@ package com.google.gerrit.server.data;
|
||||
|
||||
import com.google.gerrit.extensions.common.PluginDefinedInfo;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
import java.util.List;
|
||||
|
||||
public class ChangeAttribute {
|
||||
@ -35,6 +36,10 @@ public class ChangeAttribute {
|
||||
public Boolean open;
|
||||
public Change.Status status;
|
||||
public List<MessageAttribute> comments;
|
||||
public Boolean wip;
|
||||
|
||||
@SerializedName("private")
|
||||
public Boolean isPrivate;
|
||||
|
||||
public List<TrackingIdAttribute> trackingIds;
|
||||
public PatchSetAttribute currentPatchSet;
|
||||
|
@ -158,6 +158,8 @@ public class EventFactory {
|
||||
a.assignee = asAccountAttribute(change.getAssignee());
|
||||
a.status = change.getStatus();
|
||||
a.createdOn = change.getCreatedOn().getTime() / 1000L;
|
||||
a.wip = change.isWorkInProgress() ? true : null;
|
||||
a.isPrivate = change.isPrivate() ? true : null;
|
||||
return a;
|
||||
}
|
||||
|
||||
|
@ -30,6 +30,7 @@ public class EventTypes {
|
||||
register(CommitReceivedEvent.TYPE, CommitReceivedEvent.class);
|
||||
register(HashtagsChangedEvent.TYPE, HashtagsChangedEvent.class);
|
||||
register(PatchSetCreatedEvent.TYPE, PatchSetCreatedEvent.class);
|
||||
register(PrivateStateChangedEvent.TYPE, PrivateStateChangedEvent.class);
|
||||
register(ProjectCreatedEvent.TYPE, ProjectCreatedEvent.class);
|
||||
register(RefReceivedEvent.TYPE, RefReceivedEvent.class);
|
||||
register(RefUpdatedEvent.TYPE, RefUpdatedEvent.class);
|
||||
@ -37,6 +38,7 @@ public class EventTypes {
|
||||
register(ReviewerDeletedEvent.TYPE, ReviewerDeletedEvent.class);
|
||||
register(TopicChangedEvent.TYPE, TopicChangedEvent.class);
|
||||
register(VoteDeletedEvent.TYPE, VoteDeletedEvent.class);
|
||||
register(WorkInProgressStateChangedEvent.TYPE, WorkInProgressStateChangedEvent.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -0,0 +1,28 @@
|
||||
// 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.events;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.data.AccountAttribute;
|
||||
|
||||
public class PrivateStateChangedEvent extends ChangeEvent {
|
||||
static final String TYPE = "private-state-changed";
|
||||
public Supplier<AccountAttribute> changer;
|
||||
|
||||
protected PrivateStateChangedEvent(Change change) {
|
||||
super(TYPE, change);
|
||||
}
|
||||
}
|
@ -31,11 +31,13 @@ import com.google.gerrit.extensions.events.CommentAddedListener;
|
||||
import com.google.gerrit.extensions.events.GitReferenceUpdatedListener;
|
||||
import com.google.gerrit.extensions.events.HashtagsEditedListener;
|
||||
import com.google.gerrit.extensions.events.NewProjectCreatedListener;
|
||||
import com.google.gerrit.extensions.events.PrivateStateChangedListener;
|
||||
import com.google.gerrit.extensions.events.ReviewerAddedListener;
|
||||
import com.google.gerrit.extensions.events.ReviewerDeletedListener;
|
||||
import com.google.gerrit.extensions.events.RevisionCreatedListener;
|
||||
import com.google.gerrit.extensions.events.TopicEditedListener;
|
||||
import com.google.gerrit.extensions.events.VoteDeletedListener;
|
||||
import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicItem;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
@ -76,6 +78,8 @@ public class StreamEventsApiListener
|
||||
ChangeAbandonedListener,
|
||||
ChangeMergedListener,
|
||||
ChangeRestoredListener,
|
||||
WorkInProgressStateChangedListener,
|
||||
PrivateStateChangedListener,
|
||||
CommentAddedListener,
|
||||
GitReferenceUpdatedListener,
|
||||
HashtagsEditedListener,
|
||||
@ -99,11 +103,15 @@ public class StreamEventsApiListener
|
||||
.to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), HashtagsEditedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), NewProjectCreatedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), PrivateStateChangedListener.class)
|
||||
.to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ReviewerAddedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ReviewerDeletedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), RevisionCreatedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), TopicEditedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), VoteDeletedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), WorkInProgressStateChangedListener.class)
|
||||
.to(StreamEventsApiListener.class);
|
||||
}
|
||||
}
|
||||
|
||||
@ -461,6 +469,36 @@ public class StreamEventsApiListener
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorkInProgressStateChanged(WorkInProgressStateChangedListener.Event ev) {
|
||||
try {
|
||||
Change change = getChange(ev.getChange());
|
||||
WorkInProgressStateChangedEvent event = new WorkInProgressStateChangedEvent(change);
|
||||
|
||||
event.change = changeAttributeSupplier(change);
|
||||
event.changer = accountAttributeSupplier(ev.getWho());
|
||||
|
||||
dispatcher.get().postEvent(change, event);
|
||||
} catch (OrmException | PermissionBackendException e) {
|
||||
log.error("Failed to dispatch event", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrivateStateChanged(PrivateStateChangedListener.Event ev) {
|
||||
try {
|
||||
Change change = getChange(ev.getChange());
|
||||
PrivateStateChangedEvent event = new PrivateStateChangedEvent(change);
|
||||
|
||||
event.change = changeAttributeSupplier(change);
|
||||
event.changer = accountAttributeSupplier(ev.getWho());
|
||||
|
||||
dispatcher.get().postEvent(change, event);
|
||||
} catch (OrmException | PermissionBackendException e) {
|
||||
log.error("Failed to dispatch event", e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onVoteDeleted(VoteDeletedListener.Event ev) {
|
||||
try {
|
||||
|
@ -0,0 +1,28 @@
|
||||
// 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.events;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.data.AccountAttribute;
|
||||
|
||||
public class WorkInProgressStateChangedEvent extends ChangeEvent {
|
||||
static final String TYPE = "wip-state-changed";
|
||||
public Supplier<AccountAttribute> changer;
|
||||
|
||||
protected WorkInProgressStateChangedEvent(Change change) {
|
||||
super(TYPE, change);
|
||||
}
|
||||
}
|
@ -0,0 +1,68 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.events.PrivateStateChangedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import java.sql.Timestamp;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class PrivateStateChanged {
|
||||
private static final Logger log = LoggerFactory.getLogger(PrivateStateChanged.class);
|
||||
|
||||
private final DynamicSet<PrivateStateChangedListener> listeners;
|
||||
private final EventUtil util;
|
||||
|
||||
@Inject
|
||||
PrivateStateChanged(DynamicSet<PrivateStateChangedListener> listeners, EventUtil util) {
|
||||
this.listeners = listeners;
|
||||
this.util = util;
|
||||
}
|
||||
|
||||
public void fire(Change change, Account account, Timestamp when) {
|
||||
|
||||
if (!listeners.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Event event = new Event(util.changeInfo(change), util.accountInfo(account), when);
|
||||
for (PrivateStateChangedListener l : listeners) {
|
||||
try {
|
||||
l.onPrivateStateChanged(event);
|
||||
} catch (Exception e) {
|
||||
util.logEventListenerError(event, l, e);
|
||||
}
|
||||
}
|
||||
} catch (OrmException e) {
|
||||
log.error("Couldn't fire event", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Event extends AbstractChangeEvent
|
||||
implements PrivateStateChangedListener.Event {
|
||||
|
||||
protected Event(ChangeInfo change, AccountInfo who, Timestamp when) {
|
||||
super(change, who, when, NotifyHandling.ALL);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,69 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
import com.google.gerrit.extensions.api.changes.NotifyHandling;
|
||||
import com.google.gerrit.extensions.common.AccountInfo;
|
||||
import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.events.WorkInProgressStateChangedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import java.sql.Timestamp;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
public class WorkInProgressStateChanged {
|
||||
private static final Logger log = LoggerFactory.getLogger(WorkInProgressStateChanged.class);
|
||||
|
||||
private final DynamicSet<WorkInProgressStateChangedListener> listeners;
|
||||
private final EventUtil util;
|
||||
|
||||
@Inject
|
||||
WorkInProgressStateChanged(
|
||||
DynamicSet<WorkInProgressStateChangedListener> listeners, EventUtil util) {
|
||||
this.listeners = listeners;
|
||||
this.util = util;
|
||||
}
|
||||
|
||||
public void fire(Change change, Account account, Timestamp when) {
|
||||
|
||||
if (!listeners.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Event event = new Event(util.changeInfo(change), util.accountInfo(account), when);
|
||||
for (WorkInProgressStateChangedListener l : listeners) {
|
||||
try {
|
||||
l.onWorkInProgressStateChanged(event);
|
||||
} catch (Exception e) {
|
||||
util.logEventListenerError(event, l, e);
|
||||
}
|
||||
}
|
||||
} catch (OrmException e) {
|
||||
log.error("Couldn't fire event", e);
|
||||
}
|
||||
}
|
||||
|
||||
private static class Event extends AbstractChangeEvent
|
||||
implements WorkInProgressStateChangedListener.Event {
|
||||
|
||||
protected Event(ChangeInfo change, AccountInfo who, Timestamp when) {
|
||||
super(change, who, when, NotifyHandling.ALL);
|
||||
}
|
||||
}
|
||||
}
|
@ -147,7 +147,10 @@ public abstract class AbstractChangeNotes<T> {
|
||||
throw new OrmException("NoteDb is required to read change " + changeId);
|
||||
}
|
||||
boolean readOrWrite = read || args.migration.rawWriteChangesSetting();
|
||||
if (!readOrWrite && !autoRebuild) {
|
||||
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();
|
||||
}
|
||||
|
@ -737,6 +737,9 @@ public class ChangeNotes extends AbstractChangeNotes<ChangeNotes> {
|
||||
if (state == null) {
|
||||
return super.openHandle(repo, id);
|
||||
} else if (shouldExist) {
|
||||
// TODO(dborowitz): This means we have a state recorded in noteDbState but the ref doesn't
|
||||
// exist for whatever reason. Doesn't this mean we should trigger an auto-rebuild, rather
|
||||
// than throwing?
|
||||
throw new NoSuchChangeException(getChangeId());
|
||||
}
|
||||
}
|
||||
|
@ -265,7 +265,7 @@ public class PrimaryStorageMigrator {
|
||||
// the primary storage to NoteDb.
|
||||
|
||||
setPrimaryStorageNoteDb(id, rebuiltState);
|
||||
log.info("Migrated change {} to NoteDb primary in {}ms", id, sw.elapsed(MILLISECONDS));
|
||||
log.debug("Migrated change {} to NoteDb primary in {}ms", id, sw.elapsed(MILLISECONDS));
|
||||
}
|
||||
|
||||
private Change setReadOnlyInReviewDb(Change.Id id) throws OrmException {
|
||||
@ -399,7 +399,7 @@ public class PrimaryStorageMigrator {
|
||||
rebuilder.rebuildReviewDb(db(), project, id);
|
||||
setPrimaryStorageReviewDb(id, newMetaId);
|
||||
releaseReadOnlyLeaseInNoteDb(project, id);
|
||||
log.info("Migrated change {} to ReviewDb primary in {}ms", id, sw.elapsed(MILLISECONDS));
|
||||
log.debug("Migrated change {} to ReviewDb primary in {}ms", id, sw.elapsed(MILLISECONDS));
|
||||
}
|
||||
|
||||
private ObjectId setReadOnlyInNoteDb(Project.NameKey project, Change.Id id)
|
||||
|
@ -15,6 +15,7 @@
|
||||
package com.google.gerrit.server.notedb.rebuild;
|
||||
|
||||
import static com.google.common.base.MoreObjects.firstNonNull;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
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;
|
||||
@ -228,9 +229,16 @@ public class ChangeRebuilderImpl extends ChangeRebuilder {
|
||||
throw new NoSuchChangeException(changeId);
|
||||
}
|
||||
|
||||
final String oldNoteDbState = change.getNoteDbState();
|
||||
String oldNoteDbStateStr = change.getNoteDbState();
|
||||
Result r = manager.stageAndApplyDelta(change);
|
||||
final String newNoteDbState = change.getNoteDbState();
|
||||
String newNoteDbStateStr = change.getNoteDbState();
|
||||
if (newNoteDbStateStr == null) {
|
||||
throw new OrmException(
|
||||
"Rebuilding change %s produced no writes to NoteDb: "
|
||||
+ bundleReader.fromReviewDb(db, changeId));
|
||||
}
|
||||
NoteDbChangeState newNoteDbState =
|
||||
checkNotNull(NoteDbChangeState.parse(changeId, newNoteDbStateStr));
|
||||
try {
|
||||
db.changes()
|
||||
.atomicUpdate(
|
||||
@ -241,15 +249,15 @@ public class ChangeRebuilderImpl extends ChangeRebuilder {
|
||||
if (checkReadOnly) {
|
||||
NoteDbChangeState.checkNotReadOnly(change, skewMs);
|
||||
}
|
||||
String currNoteDbState = change.getNoteDbState();
|
||||
if (Objects.equals(currNoteDbState, newNoteDbState)) {
|
||||
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(oldNoteDbState, currNoteDbState)) {
|
||||
} else if (!Objects.equals(oldNoteDbStateStr, currNoteDbStateStr)) {
|
||||
// Another thread updated the state to something else.
|
||||
throw new ConflictingUpdateRuntimeException(change, oldNoteDbState);
|
||||
throw new ConflictingUpdateRuntimeException(change, oldNoteDbStateStr);
|
||||
}
|
||||
change.setNoteDbState(newNoteDbState);
|
||||
change.setNoteDbState(newNoteDbStateStr);
|
||||
return change;
|
||||
}
|
||||
});
|
||||
@ -259,10 +267,9 @@ public class ChangeRebuilderImpl extends ChangeRebuilder {
|
||||
// rebuild had executed before the other thread.
|
||||
throw new ConflictingUpdateException(e);
|
||||
} catch (AbortUpdateException e) {
|
||||
if (NoteDbChangeState.parse(changeId, newNoteDbState)
|
||||
.isUpToDate(
|
||||
manager.getChangeRepo().cmds.getRepoRefCache(),
|
||||
manager.getAllUsersRepo().cmds.getRepoRefCache())) {
|
||||
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
|
||||
|
@ -91,6 +91,7 @@ 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.Config;
|
||||
import org.eclipse.jgit.lib.ObjectInserter;
|
||||
import org.eclipse.jgit.lib.ObjectReader;
|
||||
@ -748,9 +749,12 @@ public class NoteDbMigrator implements AutoCloseable {
|
||||
}
|
||||
|
||||
private static ObjectInserter newPackInserter(Repository repo) {
|
||||
return repo instanceof FileRepository
|
||||
? ((FileRepository) repo).getObjectDatabase().newPackInserter()
|
||||
: repo.newObjectInserter();
|
||||
if (!(repo instanceof FileRepository)) {
|
||||
return repo.newObjectInserter();
|
||||
}
|
||||
PackInserter ins = ((FileRepository) repo).getObjectDatabase().newPackInserter();
|
||||
ins.checkExisting(false);
|
||||
return ins;
|
||||
}
|
||||
|
||||
private boolean rebuildProject(
|
||||
|
@ -239,7 +239,6 @@ public class GetServerInfo implements RestReadView<ConfigResource> {
|
||||
toBoolean(
|
||||
cfg.getBoolean("change", "showAssigneeInChangesTable", false) && hasAssigneeInIndex);
|
||||
info.largeChange = cfg.getInt("change", "largeChange", 500);
|
||||
info.privateByDefault = toBoolean(cfg.getBoolean("change", "privateByDefault", false));
|
||||
info.replyTooltip =
|
||||
Optional.ofNullable(cfg.getString("change", null, "replyTooltip")).orElse("Reply and score")
|
||||
+ " (Shortcut: a)";
|
||||
|
@ -14,6 +14,9 @@
|
||||
|
||||
package com.google.gerrit.server.schema;
|
||||
|
||||
import static java.util.stream.Collectors.toMap;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.gerrit.reviewdb.client.Account;
|
||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.GerritPersonIdent;
|
||||
@ -22,23 +25,40 @@ 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.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;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/** Migrate accounts to NoteDb. */
|
||||
public class Schema_154 extends SchemaVersion {
|
||||
private static final Logger log = LoggerFactory.getLogger(Schema_154.class);
|
||||
private static final String TABLE = "accounts";
|
||||
private static final Map<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;
|
||||
@ -76,23 +96,24 @@ public class Schema_154 extends SchemaVersion {
|
||||
}
|
||||
|
||||
private Set<Account> scanAccounts(ReviewDb db, ProgressMonitor pm) throws SQLException {
|
||||
Map<String, AccountSetter> fields = getFields(db);
|
||||
if (fields.isEmpty()) {
|
||||
log.warn("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(
|
||||
"SELECT account_id,"
|
||||
+ " registered_on,"
|
||||
+ " full_name, "
|
||||
+ " preferred_email,"
|
||||
+ " status,"
|
||||
+ " inactive"
|
||||
+ " FROM accounts")) {
|
||||
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));
|
||||
a.setFullName(rs.getString(3));
|
||||
a.setPreferredEmail(rs.getString(4));
|
||||
a.setStatus(rs.getString(5));
|
||||
a.setActive(rs.getString(6).equals("N"));
|
||||
for (Map.Entry<String, AccountSetter> field : fields.entrySet()) {
|
||||
field.getValue().set(a, rs, field.getKey());
|
||||
}
|
||||
s.add(a);
|
||||
pm.update(1);
|
||||
}
|
||||
@ -100,6 +121,17 @@ public class Schema_154 extends SchemaVersion {
|
||||
}
|
||||
}
|
||||
|
||||
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 =
|
||||
@ -112,4 +144,9 @@ public class Schema_154 extends SchemaVersion {
|
||||
accountConfig.setAccount(account);
|
||||
accountConfig.commit(md);
|
||||
}
|
||||
|
||||
@FunctionalInterface
|
||||
private interface AccountSetter {
|
||||
void set(Account a, ResultSet rs, String field) throws SQLException;
|
||||
}
|
||||
}
|
||||
|
@ -56,7 +56,6 @@ public class ServerInfoIT extends AbstractDaemonTest {
|
||||
// change
|
||||
@GerritConfig(name = "change.allowDrafts", value = "false")
|
||||
@GerritConfig(name = "change.largeChange", value = "300")
|
||||
@GerritConfig(name = "change.privateByDefault", value = "true")
|
||||
@GerritConfig(name = "change.replyTooltip", value = "Publish votes and draft comments")
|
||||
@GerritConfig(name = "change.replyLabel", value = "Vote")
|
||||
@GerritConfig(name = "change.updateDelay", value = "50s")
|
||||
@ -101,7 +100,6 @@ public class ServerInfoIT extends AbstractDaemonTest {
|
||||
// change
|
||||
assertThat(i.change.allowDrafts).isNull();
|
||||
assertThat(i.change.largeChange).isEqualTo(300);
|
||||
assertThat(i.change.privateByDefault).isTrue();
|
||||
assertThat(i.change.replyTooltip).startsWith("Publish votes and draft comments");
|
||||
assertThat(i.change.replyLabel).isEqualTo("Vote\u2026");
|
||||
assertThat(i.change.updateDelay).isEqualTo(50);
|
||||
|
@ -1287,6 +1287,28 @@ public class ChangeRebuilderIT extends AbstractDaemonTest {
|
||||
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();
|
||||
}
|
||||
|
||||
private void assertChangesReadOnly(RestApiException e) throws Exception {
|
||||
Throwable cause = e.getCause();
|
||||
assertThat(cause).isInstanceOf(UpdateException.class);
|
||||
|
@ -45,10 +45,7 @@ def gerrit_plugin(
|
||||
|
||||
native.java_binary(
|
||||
name = '%s__non_stamped' % name,
|
||||
deploy_manifest_lines = manifest_entries + [
|
||||
"Gerrit-ApiType: plugin",
|
||||
"Implementation-Vendor: Gerrit Code Review",
|
||||
],
|
||||
deploy_manifest_lines = manifest_entries + ["Gerrit-ApiType: plugin"],
|
||||
main_class = 'Dummy',
|
||||
runtime_deps = [
|
||||
':%s__plugin' % name,
|
||||
|
Loading…
Reference in New Issue
Block a user