Merge "Merge branch 'stable-2.15'"
This commit is contained in:
commit
228f2359f0
@ -90,6 +90,16 @@ reason:: Reason for abandoning the change.
|
||||
eventCreatedOn:: Time in seconds since the UNIX epoch when this event was
|
||||
created.
|
||||
|
||||
== Change Deleted
|
||||
|
||||
Sent when a change has been deleted.
|
||||
|
||||
type:: "change-deleted"
|
||||
|
||||
change:: link:json.html#change[change attribute]
|
||||
|
||||
deleter:: link:json.html#account[account attribute]
|
||||
|
||||
=== Change Merged
|
||||
|
||||
Sent when a change has been merged into the git repository.
|
||||
|
@ -186,9 +186,10 @@ the parent project.
|
||||
+
|
||||
Controls whether server-side signed push validation is required on the
|
||||
project. Only has an effect if signed push validation is enabled on the
|
||||
server, and link:#receive.enableSignedPush is set on the project. See
|
||||
the link:config-gerrit.html#receive.enableSignedPush[global
|
||||
configuration] for details.
|
||||
server, and link:#receive.enableSignedPush[`receive.enableSignedPush`] is
|
||||
set on the project. See the
|
||||
link:config-gerrit.html#receive.enableSignedPush[global configuration]
|
||||
for details.
|
||||
+
|
||||
Default is `INHERIT`, which means that this property is inherited from
|
||||
the parent project.
|
||||
|
@ -1098,10 +1098,7 @@ If the user has the global capability the string `ok` is returned.
|
||||
.Response
|
||||
----
|
||||
HTTP/1.1 200 OK
|
||||
Content-Disposition: attachment
|
||||
Content-Type: application/json; charset=UTF-8
|
||||
|
||||
)]}'
|
||||
ok
|
||||
----
|
||||
|
||||
|
@ -126,25 +126,7 @@ public class FormatUtil {
|
||||
if (size == 0) {
|
||||
return Resources.C.notAvailable();
|
||||
}
|
||||
int p = Math.abs(saturatedCast(delta * 100 / size));
|
||||
return p + "%";
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@code int} nearest in value to {@code value}.
|
||||
*
|
||||
* @param value any {@code long} value
|
||||
* @return the same value cast to {@code int} if it is in the range of the {@code int} type,
|
||||
* {@link Integer#MAX_VALUE} if it is too large, or {@link Integer#MIN_VALUE} if it is too
|
||||
* small
|
||||
*/
|
||||
private static int saturatedCast(long value) {
|
||||
if (value > Integer.MAX_VALUE) {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
if (value < Integer.MIN_VALUE) {
|
||||
return Integer.MIN_VALUE;
|
||||
}
|
||||
return (int) value;
|
||||
long percentage = Math.abs(Math.round(delta * 100.0 / size));
|
||||
return percentage + "%";
|
||||
}
|
||||
}
|
||||
|
@ -25,6 +25,7 @@ import com.google.gerrit.extensions.registration.RegistrationHandle;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.data.RefUpdateAttribute;
|
||||
import com.google.gerrit.server.events.ChangeDeletedEvent;
|
||||
import com.google.gerrit.server.events.ChangeMergedEvent;
|
||||
import com.google.gerrit.server.events.Event;
|
||||
import com.google.gerrit.server.events.RefEvent;
|
||||
@ -69,6 +70,8 @@ public class EventRecorder {
|
||||
public void onEvent(Event e) {
|
||||
if (e instanceof ReviewerDeletedEvent) {
|
||||
recordedEvents.put(ReviewerDeletedEvent.TYPE, (ReviewerDeletedEvent) e);
|
||||
} else if (e instanceof ChangeDeletedEvent) {
|
||||
recordedEvents.put(ChangeDeletedEvent.TYPE, (ChangeDeletedEvent) e);
|
||||
} else if (e instanceof RefEvent) {
|
||||
RefEvent event = (RefEvent) e;
|
||||
String key =
|
||||
@ -138,6 +141,21 @@ public class EventRecorder {
|
||||
return events;
|
||||
}
|
||||
|
||||
private ImmutableList<ChangeDeletedEvent> getChangeDeletedEvents(int expectedSize) {
|
||||
String key = ChangeDeletedEvent.TYPE;
|
||||
if (expectedSize == 0) {
|
||||
assertThat(recordedEvents).doesNotContainKey(key);
|
||||
return ImmutableList.of();
|
||||
}
|
||||
assertThat(recordedEvents).containsKey(key);
|
||||
ImmutableList<ChangeDeletedEvent> events =
|
||||
FluentIterable.from(recordedEvents.get(key))
|
||||
.transform(ChangeDeletedEvent.class::cast)
|
||||
.toList();
|
||||
assertThat(events).hasSize(expectedSize);
|
||||
return events;
|
||||
}
|
||||
|
||||
public void assertNoRefUpdatedEvents(String project, String branch) throws Exception {
|
||||
getRefUpdatedEvents(project, branch, 0);
|
||||
}
|
||||
@ -197,6 +215,18 @@ public class EventRecorder {
|
||||
}
|
||||
}
|
||||
|
||||
public void assertChangeDeletedEvents(String... expected) {
|
||||
ImmutableList<ChangeDeletedEvent> events = getChangeDeletedEvents(expected.length / 2);
|
||||
int i = 0;
|
||||
for (ChangeDeletedEvent event : events) {
|
||||
String id = event.change.get().id;
|
||||
assertThat(id).isEqualTo(expected[i]);
|
||||
String reviewer = event.deleter.get().email;
|
||||
assertThat(reviewer).isEqualTo(expected[i + 1]);
|
||||
i += 2;
|
||||
}
|
||||
}
|
||||
|
||||
public void close() {
|
||||
eventListenerRegistration.remove();
|
||||
}
|
||||
|
@ -0,0 +1,25 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
import com.google.gerrit.extensions.annotations.ExtensionPoint;
|
||||
|
||||
/** Notified whenever a Change is deleted. */
|
||||
@ExtensionPoint
|
||||
public interface ChangeDeletedListener {
|
||||
interface Event extends ChangeEvent {}
|
||||
|
||||
void onChangeDeleted(Event event);
|
||||
}
|
@ -33,6 +33,7 @@ import com.google.gerrit.extensions.events.AccountIndexedListener;
|
||||
import com.google.gerrit.extensions.events.AgreementSignupListener;
|
||||
import com.google.gerrit.extensions.events.AssigneeChangedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeAbandonedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeDeletedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeIndexedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeMergedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeRestoredListener;
|
||||
@ -311,6 +312,7 @@ public class GerritGlobalModule extends FactoryModule {
|
||||
DynamicSet.setOf(binder(), GitReferenceUpdatedListener.class);
|
||||
DynamicSet.setOf(binder(), AssigneeChangedListener.class);
|
||||
DynamicSet.setOf(binder(), ChangeAbandonedListener.class);
|
||||
DynamicSet.setOf(binder(), ChangeDeletedListener.class);
|
||||
DynamicSet.setOf(binder(), CommentAddedListener.class);
|
||||
DynamicSet.setOf(binder(), HashtagsEditedListener.class);
|
||||
DynamicSet.setOf(binder(), ChangeMergedListener.class);
|
||||
|
28
java/com/google/gerrit/server/events/ChangeDeletedEvent.java
Normal file
28
java/com/google/gerrit/server/events/ChangeDeletedEvent.java
Normal file
@ -0,0 +1,28 @@
|
||||
// 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.events;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.data.AccountAttribute;
|
||||
|
||||
public class ChangeDeletedEvent extends ChangeEvent {
|
||||
public static final String TYPE = "change-deleted";
|
||||
public Supplier<AccountAttribute> deleter;
|
||||
|
||||
public ChangeDeletedEvent(Change change) {
|
||||
super(TYPE, change);
|
||||
}
|
||||
}
|
@ -24,6 +24,7 @@ public class EventTypes {
|
||||
static {
|
||||
register(AssigneeChangedEvent.TYPE, AssigneeChangedEvent.class);
|
||||
register(ChangeAbandonedEvent.TYPE, ChangeAbandonedEvent.class);
|
||||
register(ChangeDeletedEvent.TYPE, ChangeDeletedEvent.class);
|
||||
register(ChangeMergedEvent.TYPE, ChangeMergedEvent.class);
|
||||
register(ChangeRestoredEvent.TYPE, ChangeRestoredEvent.class);
|
||||
register(CommentAddedEvent.TYPE, CommentAddedEvent.class);
|
||||
|
@ -26,6 +26,7 @@ import com.google.gerrit.extensions.common.ChangeInfo;
|
||||
import com.google.gerrit.extensions.common.RevisionInfo;
|
||||
import com.google.gerrit.extensions.events.AssigneeChangedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeAbandonedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeDeletedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeMergedListener;
|
||||
import com.google.gerrit.extensions.events.ChangeRestoredListener;
|
||||
import com.google.gerrit.extensions.events.CommentAddedListener;
|
||||
@ -75,6 +76,7 @@ import org.eclipse.jgit.revwalk.RevWalk;
|
||||
public class StreamEventsApiListener
|
||||
implements AssigneeChangedListener,
|
||||
ChangeAbandonedListener,
|
||||
ChangeDeletedListener,
|
||||
ChangeMergedListener,
|
||||
ChangeRestoredListener,
|
||||
WorkInProgressStateChangedListener,
|
||||
@ -95,6 +97,7 @@ public class StreamEventsApiListener
|
||||
protected void configure() {
|
||||
DynamicSet.bind(binder(), AssigneeChangedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeAbandonedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeDeletedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeMergedListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), ChangeRestoredListener.class).to(StreamEventsApiListener.class);
|
||||
DynamicSet.bind(binder(), CommentAddedListener.class).to(StreamEventsApiListener.class);
|
||||
@ -522,4 +525,20 @@ public class StreamEventsApiListener
|
||||
logger.atSevere().withCause(e).log("Failed to dispatch event");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChangeDeleted(ChangeDeletedListener.Event ev) {
|
||||
try {
|
||||
ChangeNotes notes = getNotes(ev.getChange());
|
||||
Change change = notes.getChange();
|
||||
ChangeDeletedEvent event = new ChangeDeletedEvent(change);
|
||||
|
||||
event.change = changeAttributeSupplier(change, notes);
|
||||
event.deleter = accountAttributeSupplier(ev.getWho());
|
||||
|
||||
dispatcher.get().postEvent(change, event);
|
||||
} catch (OrmException | PermissionBackendException e) {
|
||||
logger.atSevere().withCause(e).log("Failed to dispatch event");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,66 @@
|
||||
// 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.extensions.events;
|
||||
|
||||
import com.google.common.flogger.FluentLogger;
|
||||
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.ChangeDeletedListener;
|
||||
import com.google.gerrit.extensions.registration.DynamicSet;
|
||||
import com.google.gerrit.reviewdb.client.Change;
|
||||
import com.google.gerrit.server.account.AccountState;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import java.sql.Timestamp;
|
||||
|
||||
@Singleton
|
||||
public class ChangeDeleted {
|
||||
private static final FluentLogger logger = FluentLogger.forEnclosingClass();
|
||||
|
||||
private final DynamicSet<ChangeDeletedListener> listeners;
|
||||
private final EventUtil util;
|
||||
|
||||
@Inject
|
||||
ChangeDeleted(DynamicSet<ChangeDeletedListener> listeners, EventUtil util) {
|
||||
this.listeners = listeners;
|
||||
this.util = util;
|
||||
}
|
||||
|
||||
public void fire(Change change, AccountState deleter, Timestamp when) {
|
||||
if (!listeners.iterator().hasNext()) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Event event = new Event(util.changeInfo(change), util.accountInfo(deleter), when);
|
||||
for (ChangeDeletedListener l : listeners) {
|
||||
try {
|
||||
l.onChangeDeleted(event);
|
||||
} catch (Exception e) {
|
||||
util.logEventListenerError(this, l, e);
|
||||
}
|
||||
}
|
||||
} catch (OrmException e) {
|
||||
logger.atSevere().withCause(e).log("Couldn't fire event");
|
||||
}
|
||||
}
|
||||
|
||||
private static class Event extends AbstractChangeEvent implements ChangeDeletedListener.Event {
|
||||
Event(ChangeInfo change, AccountInfo deleter, Timestamp when) {
|
||||
super(change, deleter, when, NotifyHandling.ALL);
|
||||
}
|
||||
}
|
||||
}
|
@ -1089,14 +1089,15 @@ public class ChangeData {
|
||||
public boolean isReviewedBy(Account.Id accountId) throws OrmException {
|
||||
Collection<String> stars = stars(accountId);
|
||||
|
||||
if (stars.contains(
|
||||
StarredChangesUtil.REVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
|
||||
return true;
|
||||
}
|
||||
PatchSet ps = currentPatchSet();
|
||||
if (ps != null) {
|
||||
if (stars.contains(StarredChangesUtil.REVIEWED_LABEL + "/" + ps.getPatchSetId())) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (stars.contains(
|
||||
StarredChangesUtil.UNREVIEWED_LABEL + "/" + currentPatchSet().getPatchSetId())) {
|
||||
return false;
|
||||
if (stars.contains(StarredChangesUtil.UNREVIEWED_LABEL + "/" + ps.getPatchSetId())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return reviewedBy().contains(accountId);
|
||||
|
@ -26,8 +26,8 @@ import com.google.gerrit.extensions.api.access.GlobalOrPluginPermission;
|
||||
import com.google.gerrit.extensions.api.access.PluginPermission;
|
||||
import com.google.gerrit.extensions.config.CapabilityDefinition;
|
||||
import com.google.gerrit.extensions.registration.DynamicMap;
|
||||
import com.google.gerrit.extensions.restapi.BinaryResult;
|
||||
import com.google.gerrit.extensions.restapi.ResourceNotFoundException;
|
||||
import com.google.gerrit.extensions.restapi.Response;
|
||||
import com.google.gerrit.extensions.restapi.RestApiException;
|
||||
import com.google.gerrit.extensions.restapi.RestReadView;
|
||||
import com.google.gerrit.server.CurrentUser;
|
||||
@ -172,9 +172,9 @@ public class GetCapabilities implements RestReadView<AccountResource> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<String> apply(Capability resource) throws ResourceNotFoundException {
|
||||
public BinaryResult apply(Capability resource) throws ResourceNotFoundException {
|
||||
permissionBackend.checkUsesDefaultCapabilities();
|
||||
return Response.ok("ok");
|
||||
return BinaryResult.create("ok\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -26,6 +26,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||
import com.google.gerrit.server.PatchSetUtil;
|
||||
import com.google.gerrit.server.StarredChangesUtil;
|
||||
import com.google.gerrit.server.change.AccountPatchReviewStore;
|
||||
import com.google.gerrit.server.extensions.events.ChangeDeleted;
|
||||
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||
import com.google.gerrit.server.update.BatchUpdateOp;
|
||||
import com.google.gerrit.server.update.BatchUpdateReviewDb;
|
||||
@ -45,6 +46,7 @@ class DeleteChangeOp implements BatchUpdateOp {
|
||||
private final PatchSetUtil psUtil;
|
||||
private final StarredChangesUtil starredChangesUtil;
|
||||
private final DynamicItem<AccountPatchReviewStore> accountPatchReviewStore;
|
||||
private final ChangeDeleted changeDeleted;
|
||||
|
||||
private Change.Id id;
|
||||
|
||||
@ -52,10 +54,12 @@ class DeleteChangeOp implements BatchUpdateOp {
|
||||
DeleteChangeOp(
|
||||
PatchSetUtil psUtil,
|
||||
StarredChangesUtil starredChangesUtil,
|
||||
DynamicItem<AccountPatchReviewStore> accountPatchReviewStore) {
|
||||
DynamicItem<AccountPatchReviewStore> accountPatchReviewStore,
|
||||
ChangeDeleted changeDeleted) {
|
||||
this.psUtil = psUtil;
|
||||
this.starredChangesUtil = starredChangesUtil;
|
||||
this.accountPatchReviewStore = accountPatchReviewStore;
|
||||
this.changeDeleted = changeDeleted;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -75,6 +79,7 @@ class DeleteChangeOp implements BatchUpdateOp {
|
||||
deleteChangeElementsFromDb(ctx, id);
|
||||
|
||||
ctx.deleteChange();
|
||||
changeDeleted.fire(ctx.getChange(), ctx.getAccount(), ctx.getWhen());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -1089,6 +1089,7 @@ public class ChangeIT extends AbstractDaemonTest {
|
||||
|
||||
String ref = new Change.Id(id).toRefPrefix() + "1";
|
||||
eventRecorder.assertRefUpdatedEvents(projectName.get(), ref, null, commit, commit, null);
|
||||
eventRecorder.assertChangeDeletedEvents(changeId, deleteAs.email);
|
||||
} finally {
|
||||
removePermission(project, "refs/*", Permission.DELETE_OWN_CHANGES);
|
||||
removePermission(project, "refs/*", Permission.DELETE_CHANGES);
|
||||
|
@ -1 +1 @@
|
||||
Subproject commit cc74144db755a18c5a63764a336b93ab3d1be1fe
|
||||
Subproject commit 7185e5ce46646e952071befd9cf8f4267560b51d
|
Loading…
Reference in New Issue
Block a user