Merge branch 'stable-2.15' * stable-2.15: StarredChangesUtil: Handle unexpected format of reviewed/unreviewed labels Fix migration of mute stars Test that change is reindexed when change is starred/unstarred Suggest "is:private" in autocompete Trigger GitRefUpdatedEvent when star labels are updated Trigger GitReferenceUpdated event when account or change sequence is updated Fix bad rounding of relative dates like '1 year, 12 months ago' Fix test of RelativeDateFormatter Trigger GitReferenceUpdated event when external IDs are updated Increase the value of GERRIT_FDS parameter Add rel="external" to link to CLA Fix invalid operator invalidating web session Address test flakiness in gr-project-detail-list Update patchset selector styles Change-Id: I4ec66d2d53c9fbe98878fa02585724db2eda216a
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java index 84f3533..22d27ac 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/accounts/AccountIT.java
@@ -38,6 +38,7 @@ import com.google.common.collect.FluentIterable; import com.google.common.collect.ImmutableList; +import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSetMultimap; import com.google.common.collect.Iterables; @@ -67,6 +68,7 @@ import com.google.gerrit.extensions.common.GpgKeyInfo; import com.google.gerrit.extensions.common.SshKeyInfo; import com.google.gerrit.extensions.events.AccountIndexedListener; +import com.google.gerrit.extensions.events.GitReferenceUpdatedListener; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.registration.RegistrationHandle; import com.google.gerrit.extensions.restapi.AuthException; @@ -79,6 +81,8 @@ import com.google.gerrit.gpg.testutil.TestKey; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountGroup; +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.server.Sequences; import com.google.gerrit.server.account.AccountConfig; @@ -106,6 +110,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.EnumSet; +import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; @@ -155,6 +160,8 @@ @Inject private DynamicSet<AccountIndexedListener> accountIndexedListeners; + @Inject private DynamicSet<GitReferenceUpdatedListener> refUpdateListeners; + @Inject private Sequences seq; @Inject private Provider<InternalAccountQuery> accountQueryProvider; @@ -163,6 +170,8 @@ private AccountIndexedCounter accountIndexedCounter; private RegistrationHandle accountIndexEventCounterHandle; + private RefUpdateCounter refUpdateCounter; + private RegistrationHandle refUpdateCounterHandle; private ExternalIdsUpdate externalIdsUpdate; private List<ExternalId> savedExternalIds; @@ -180,6 +189,19 @@ } @Before + public void addRefUpdateCounter() { + refUpdateCounter = new RefUpdateCounter(); + refUpdateCounterHandle = refUpdateListeners.add(refUpdateCounter); + } + + @After + public void removeRefUpdateCounter() { + if (refUpdateCounterHandle != null) { + refUpdateCounterHandle.remove(); + } + } + + @Before public void saveExternalIds() throws Exception { externalIdsUpdate = externalIdsUpdateFactory.create(); @@ -228,16 +250,29 @@ @Test public void create() throws Exception { - create(2); // account creation + external ID creation + Account.Id accountId = create(2); // account creation + external ID creation + refUpdateCounter.assertRefUpdateFor( + RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)), + RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS), + RefUpdateCounter.projectRef(allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS)); } @Test @UseSsh public void createWithSshKeys() throws Exception { - create(3); // account creation + external ID creation + adding SSH keys + Account.Id accountId = create(3); // account creation + external ID creation + adding SSH keys + refUpdateCounter.assertRefUpdateFor( + ImmutableMap.of( + RefUpdateCounter.projectRef(allUsers, RefNames.refsUsers(accountId)), + 2, + RefUpdateCounter.projectRef(allUsers, RefNames.REFS_EXTERNAL_IDS), + 1, + RefUpdateCounter.projectRef( + allUsers, RefNames.REFS_SEQUENCES + Sequences.NAME_ACCOUNTS), + 1)); } - private void create(int expectedAccountReindexCalls) throws Exception { + private Account.Id create(int expectedAccountReindexCalls) throws Exception { String name = "foo"; TestAccount foo = accountCreator.create(name); AccountInfo info = gApi.accounts().id(foo.id.get()).get(); @@ -245,6 +280,7 @@ assertThat(info.name).isEqualTo(name); accountIndexedCounter.assertReindexOf(foo, expectedAccountReindexCalls); assertUserBranch(foo.getId(), name, null); + return foo.getId(); } @Test @@ -378,15 +414,24 @@ public void starUnstarChange() throws Exception { PushOneCommit.Result r = createChange(); String triplet = project.get() + "~master~" + r.getChangeId(); + refUpdateCounter.clear(); + gApi.accounts().self().starChange(triplet); ChangeInfo change = info(triplet); assertThat(change.starred).isTrue(); assertThat(change.stars).contains(DEFAULT_LABEL); + refUpdateCounter.assertRefUpdateFor( + RefUpdateCounter.projectRef( + allUsers, RefNames.refsStarredChanges(new Change.Id(change._number), admin.id))); gApi.accounts().self().unstarChange(triplet); change = info(triplet); assertThat(change.starred).isNull(); assertThat(change.stars).isNull(); + refUpdateCounter.assertRefUpdateFor( + RefUpdateCounter.projectRef( + allUsers, RefNames.refsStarredChanges(new Change.Id(change._number), admin.id))); + accountIndexedCounter.assertNoReindex(); } @@ -394,6 +439,8 @@ public void starUnstarChangeWithLabels() throws Exception { PushOneCommit.Result r = createChange(); String triplet = project.get() + "~master~" + r.getChangeId(); + refUpdateCounter.clear(); + assertThat(gApi.accounts().self().getStars(triplet)).isEmpty(); assertThat(gApi.accounts().self().getStarredChanges()).isEmpty(); @@ -412,6 +459,9 @@ assertThat(starredChange._number).isEqualTo(r.getChange().getId().get()); assertThat(starredChange.starred).isTrue(); assertThat(starredChange.stars).containsExactly("blue", "red", DEFAULT_LABEL).inOrder(); + refUpdateCounter.assertRefUpdateFor( + RefUpdateCounter.projectRef( + allUsers, RefNames.refsStarredChanges(new Change.Id(change._number), admin.id))); gApi.accounts() .self() @@ -428,6 +478,10 @@ assertThat(starredChange._number).isEqualTo(r.getChange().getId().get()); assertThat(starredChange.starred).isNull(); assertThat(starredChange.stars).containsExactly("red", "yellow").inOrder(); + refUpdateCounter.assertRefUpdateFor( + RefUpdateCounter.projectRef( + allUsers, RefNames.refsStarredChanges(new Change.Id(change._number), admin.id))); + accountIndexedCounter.assertNoReindex(); setApiUser(user); @@ -1899,4 +1953,45 @@ assertThat(countsByAccount).isEmpty(); } } + + private static class RefUpdateCounter implements GitReferenceUpdatedListener { + private final AtomicLongMap<String> countsByProjectRefs = AtomicLongMap.create(); + + static String projectRef(Project.NameKey project, String ref) { + return projectRef(project.get(), ref); + } + + static String projectRef(String project, String ref) { + return project + ":" + ref; + } + + @Override + public void onGitReferenceUpdated(Event event) { + countsByProjectRefs.incrementAndGet(projectRef(event.getProjectName(), event.getRefName())); + } + + void clear() { + countsByProjectRefs.clear(); + } + + long getCount(String projectRef) { + return countsByProjectRefs.get(projectRef); + } + + void assertRefUpdateFor(String... projectRefs) { + Map<String, Integer> expectedRefUpdateCounts = new HashMap<>(); + for (String projectRef : projectRefs) { + expectedRefUpdateCounts.put(projectRef, 1); + } + assertRefUpdateFor(expectedRefUpdateCounts); + } + + void assertRefUpdateFor(Map<String, Integer> expectedProjectRefUpdateCounts) { + for (Map.Entry<String, Integer> e : expectedProjectRefUpdateCounts.entrySet()) { + assertThat(getCount(e.getKey())).isEqualTo(e.getValue()); + } + assertThat(countsByProjectRefs).hasSize(expectedProjectRefUpdateCounts.size()); + clear(); + } + } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java index c2d3184..baa0a68 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -41,6 +41,7 @@ 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; import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS; @@ -57,6 +58,7 @@ import com.google.common.collect.ImmutableSet; import com.google.common.collect.Iterables; import com.google.common.collect.Lists; +import com.google.common.util.concurrent.AtomicLongMap; import com.google.gerrit.acceptance.AbstractDaemonTest; import com.google.gerrit.acceptance.AcceptanceTestRequestScope; import com.google.gerrit.acceptance.GerritConfig; @@ -105,6 +107,7 @@ import com.google.gerrit.extensions.common.PureRevertInfo; import com.google.gerrit.extensions.common.RevisionInfo; import com.google.gerrit.extensions.common.TrackingIdInfo; +import com.google.gerrit.extensions.events.ChangeIndexedListener; import com.google.gerrit.extensions.registration.DynamicSet; import com.google.gerrit.extensions.registration.RegistrationHandle; import com.google.gerrit.extensions.restapi.AuthException; @@ -170,6 +173,11 @@ @Inject private DynamicSet<ChangeMessageModifier> changeMessageModifiers; + @Inject private DynamicSet<ChangeIndexedListener> changeIndexedListeners; + + private ChangeIndexedCounter changeIndexedCounter; + private RegistrationHandle changeIndexedCounterHandle; + @Before public void setTimeForTesting() { systemTimeZone = System.setProperty("user.timezone", "US/Eastern"); @@ -181,6 +189,19 @@ System.setProperty("user.timezone", systemTimeZone); } + @Before + public void addChangeIndexedCounter() { + changeIndexedCounter = new ChangeIndexedCounter(); + changeIndexedCounterHandle = changeIndexedListeners.add(changeIndexedCounter); + } + + @After + public void removeChangeIndexedCounter() { + if (changeIndexedCounterHandle != null) { + changeIndexedCounterHandle.remove(); + } + } + @Test public void reflog() throws Exception { // Tests are using DfsRepository which does not implement getReflogReader, @@ -3299,6 +3320,25 @@ } @Test + public void starUnstar() throws Exception { + PushOneCommit.Result r = createChange(); + String triplet = project.get() + "~master~" + r.getChangeId(); + changeIndexedCounter.clear(); + + gApi.accounts().self().starChange(triplet); + ChangeInfo change = info(triplet); + assertThat(change.starred).isTrue(); + assertThat(change.stars).contains(DEFAULT_LABEL); + changeIndexedCounter.assertReindexOf(change); + + gApi.accounts().self().unstarChange(triplet); + change = info(triplet); + assertThat(change.starred).isNull(); + assertThat(change.stars).isNull(); + changeIndexedCounter.assertReindexOf(change); + } + + @Test public void ignore() throws Exception { TestAccount user2 = accountCreator.user2(); @@ -3480,4 +3520,36 @@ exception.expectMessage("invalid labels: " + invalidLabel); gApi.accounts().self().setStars(changeId, new StarsInput(ImmutableSet.of(invalidLabel))); } + + private static class ChangeIndexedCounter implements ChangeIndexedListener { + private final AtomicLongMap<Integer> countsByChange = AtomicLongMap.create(); + + @Override + public void onChangeIndexed(int id) { + countsByChange.incrementAndGet(id); + } + + @Override + public void onChangeDeleted(int id) { + countsByChange.incrementAndGet(id); + } + + void clear() { + countsByChange.clear(); + } + + long getCount(ChangeInfo info) { + return countsByChange.get(info._number); + } + + void assertReindexOf(ChangeInfo info) { + assertReindexOf(info, 1); + } + + void assertReindexOf(ChangeInfo info, int expectedCount) { + assertThat(getCount(info)).isEqualTo(expectedCount); + assertThat(countsByChange).hasSize(1); + clear(); + } + } }
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java index 2fe9dcd..4c4bc94 100644 --- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java +++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/account/ExternalIdIT.java
@@ -55,6 +55,7 @@ import com.google.gerrit.server.account.externalids.ExternalIdsUpdate; import com.google.gerrit.server.account.externalids.ExternalIdsUpdate.RefsMetaExternalIdsUpdate; import com.google.gerrit.server.config.AllUsersName; +import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.git.LockFailureException; import com.google.gson.reflect.TypeToken; import com.google.gwtorm.server.OrmDuplicateKeyException; @@ -579,7 +580,17 @@ noteMap.set(noteId, dataBlob); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, "Add external ID", admin.getIdent(), admin.getIdent()); + allUsers, + repo, + rw, + ins, + rev, + noteMap, + "Add external ID", + admin.getIdent(), + admin.getIdent(), + null, + GitReferenceUpdated.DISABLED); return noteId.getName(); } } @@ -600,7 +611,17 @@ noteMap.set(noteId, dataBlob); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, "Add external ID", admin.getIdent(), admin.getIdent()); + allUsers, + repo, + rw, + ins, + rev, + noteMap, + "Add external ID", + admin.getIdent(), + admin.getIdent(), + null, + GitReferenceUpdated.DISABLED); return noteId.getName(); } } @@ -617,7 +638,17 @@ noteMap.set(noteId, dataBlob); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, "Add external ID", admin.getIdent(), admin.getIdent()); + allUsers, + repo, + rw, + ins, + rev, + noteMap, + "Add external ID", + admin.getIdent(), + admin.getIdent(), + null, + GitReferenceUpdated.DISABLED); return noteId.getName(); } } @@ -634,7 +665,17 @@ noteMap.set(noteId, dataBlob); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, "Add external ID", admin.getIdent(), admin.getIdent()); + allUsers, + repo, + rw, + ins, + rev, + noteMap, + "Add external ID", + admin.getIdent(), + admin.getIdent(), + null, + GitReferenceUpdated.DISABLED); return noteId.getName(); } } @@ -690,6 +731,8 @@ new DisabledExternalIdCache(), serverIdent.get(), serverIdent.get(), + null, + GitReferenceUpdated.DISABLED, () -> { if (!doneBgUpdate.getAndSet(true)) { try { @@ -726,6 +769,8 @@ new DisabledExternalIdCache(), serverIdent.get(), serverIdent.get(), + null, + GitReferenceUpdated.DISABLED, () -> { try { extIdsUpdate @@ -824,7 +869,17 @@ NoteMap noteMap = ExternalIdReader.readNoteMap(rw, rev); ExternalIdsUpdate.insert(rw, ins, noteMap, extId); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, "insert new ID", serverIdent.get(), serverIdent.get()); + allUsers, + repo, + rw, + ins, + rev, + noteMap, + "insert new ID", + serverIdent.get(), + serverIdent.get(), + null, + GitReferenceUpdated.DISABLED); } } @@ -839,6 +894,7 @@ } ExternalIdsUpdate.commit( + allUsers, testRepo.getRepository(), testRepo.getRevWalk(), ins, @@ -846,7 +902,9 @@ noteMap, "Add external ID", admin.getIdent(), - admin.getIdent()); + admin.getIdent(), + null, + GitReferenceUpdated.DISABLED); } }
diff --git a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/api/GpgApiAdapterImpl.java b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/api/GpgApiAdapterImpl.java index ba79a6f..49c7f67 100644 --- a/gerrit-gpg/src/main/java/com/google/gerrit/gpg/api/GpgApiAdapterImpl.java +++ b/gerrit-gpg/src/main/java/com/google/gerrit/gpg/api/GpgApiAdapterImpl.java
@@ -29,6 +29,7 @@ import com.google.gerrit.server.api.accounts.GpgApiAdapter; 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.Map; @@ -38,15 +39,15 @@ import org.eclipse.jgit.transport.PushCertificateParser; public class GpgApiAdapterImpl implements GpgApiAdapter { - private final PostGpgKeys postGpgKeys; - private final GpgKeys gpgKeys; + private final Provider<PostGpgKeys> postGpgKeys; + private final Provider<GpgKeys> gpgKeys; private final GpgKeyApiImpl.Factory gpgKeyApiFactory; private final GerritPushCertificateChecker.Factory pushCertCheckerFactory; @Inject GpgApiAdapterImpl( - PostGpgKeys postGpgKeys, - GpgKeys gpgKeys, + Provider<PostGpgKeys> postGpgKeys, + Provider<GpgKeys> gpgKeys, GpgKeyApiImpl.Factory gpgKeyApiFactory, GerritPushCertificateChecker.Factory pushCertCheckerFactory) { this.postGpgKeys = postGpgKeys; @@ -64,7 +65,7 @@ public Map<String, GpgKeyInfo> listGpgKeys(AccountResource account) throws RestApiException, GpgException { try { - return gpgKeys.list().apply(account); + return gpgKeys.get().list().apply(account); } catch (OrmException | PGPException | IOException e) { throw new GpgException(e); } @@ -78,7 +79,7 @@ in.add = add; in.delete = delete; try { - return postGpgKeys.apply(account, in); + return postGpgKeys.get().apply(account, in); } catch (PGPException | OrmException | IOException | ConfigInvalidException e) { throw new GpgException(e); } @@ -88,7 +89,7 @@ public GpgKeyApi gpgKey(AccountResource account, IdString idStr) throws RestApiException, GpgException { try { - return gpgKeyApiFactory.create(gpgKeys.parse(account, idStr)); + return gpgKeyApiFactory.create(gpgKeys.get().parse(account, idStr)); } catch (PGPException | OrmException | IOException e) { throw new GpgException(e); }
diff --git a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java index 7c62ed7..a0c4aa6 100644 --- a/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java +++ b/gerrit-gwtui-common/src/main/java/com/google/gerrit/client/RelativeDateFormatter.java
@@ -14,9 +14,6 @@ package com.google.gerrit.client; -import static com.google.gerrit.client.CommonConstants.C; -import static com.google.gerrit.client.CommonMessages.M; - import java.util.Date; /** @@ -24,6 +21,9 @@ * defined by {@code git log --relative-date}. */ public class RelativeDateFormatter { + private static CommonConstants constants; + private static CommonMessages messages; + static final long SECOND_IN_MILLIS = 1000; static final long MINUTE_IN_MILLIS = 60 * SECOND_IN_MILLIS; static final long HOUR_IN_MILLIS = 60 * MINUTE_IN_MILLIS; @@ -32,6 +32,19 @@ static final long MONTH_IN_MILLIS = 30 * DAY_IN_MILLIS; static final long YEAR_IN_MILLIS = 365 * DAY_IN_MILLIS; + static void setConstants(CommonConstants c, CommonMessages m) { + constants = c; + messages = m; + } + + private static CommonConstants c() { + return constants != null ? constants : CommonConstants.C; + } + + private static CommonMessages m() { + return messages != null ? messages : CommonMessages.M; + } + /** * @param when {@link Date} to format * @return age of given {@link Date} compared to now formatted in the same relative format as @@ -42,81 +55,85 @@ // shouldn't happen in a perfect world if (ageMillis < 0) { - return C.inTheFuture(); + return c().inTheFuture(); } // seconds if (ageMillis < upperLimit(MINUTE_IN_MILLIS)) { long seconds = round(ageMillis, SECOND_IN_MILLIS); if (seconds == 1) { - return C.oneSecondAgo(); + return c().oneSecondAgo(); } - return M.secondsAgo(seconds); + return m().secondsAgo(seconds); } // minutes if (ageMillis < upperLimit(HOUR_IN_MILLIS)) { long minutes = round(ageMillis, MINUTE_IN_MILLIS); if (minutes == 1) { - return C.oneMinuteAgo(); + return c().oneMinuteAgo(); } - return M.minutesAgo(minutes); + return m().minutesAgo(minutes); } // hours if (ageMillis < upperLimit(DAY_IN_MILLIS)) { long hours = round(ageMillis, HOUR_IN_MILLIS); if (hours == 1) { - return C.oneHourAgo(); + return c().oneHourAgo(); } - return M.hoursAgo(hours); + return m().hoursAgo(hours); } // up to 14 days use days if (ageMillis < 14 * DAY_IN_MILLIS) { long days = round(ageMillis, DAY_IN_MILLIS); if (days == 1) { - return C.oneDayAgo(); + return c().oneDayAgo(); } - return M.daysAgo(days); + return m().daysAgo(days); } // up to 10 weeks use weeks if (ageMillis < 10 * WEEK_IN_MILLIS) { long weeks = round(ageMillis, WEEK_IN_MILLIS); if (weeks == 1) { - return C.oneWeekAgo(); + return c().oneWeekAgo(); } - return M.weeksAgo(weeks); + return m().weeksAgo(weeks); } // months if (ageMillis < YEAR_IN_MILLIS) { long months = round(ageMillis, MONTH_IN_MILLIS); if (months == 1) { - return C.oneMonthAgo(); + return c().oneMonthAgo(); } - return M.monthsAgo(months); + return m().monthsAgo(months); } // up to 5 years use "year, months" rounded to months if (ageMillis < 5 * YEAR_IN_MILLIS) { long years = ageMillis / YEAR_IN_MILLIS; - String yearLabel = (years > 1) ? C.years() : C.year(); + String yearLabel = (years > 1) ? c().years() : c().year(); long months = round(ageMillis % YEAR_IN_MILLIS, MONTH_IN_MILLIS); - String monthLabel = (months > 1) ? C.months() : (months == 1 ? C.month() : ""); + String monthLabel = (months > 1) ? c().months() : (months == 1 ? c().month() : ""); if (months == 0) { - return M.years0MonthsAgo(years, yearLabel); + return m().years0MonthsAgo(years, yearLabel); } - return M.yearsMonthsAgo(years, yearLabel, months, monthLabel); + if (months == 12) { + years++; + return m().years0MonthsAgo(years, yearLabel); + } + return m().yearsMonthsAgo(years, yearLabel, months, monthLabel); } // years long years = round(ageMillis, YEAR_IN_MILLIS); if (years == 1) { - return C.oneYearAgo(); + return c().oneYearAgo(); } - return M.yearsAgo(years); + return m().yearsAgo(years); } private static long upperLimit(long unit) {
diff --git a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java b/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java index 937fc96..5180410 100644 --- a/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java +++ b/gerrit-gwtui-common/src/test/java/com/google/gerrit/client/RelativeDateFormatterTest.java
@@ -22,11 +22,23 @@ import static org.junit.Assert.assertEquals; import java.util.Date; -import org.eclipse.jgit.util.RelativeDateFormatter; +import org.junit.AfterClass; +import org.junit.BeforeClass; import org.junit.Test; public class RelativeDateFormatterTest { + @BeforeClass + public static void setConstants() { + Constants c = new Constants(); + RelativeDateFormatter.setConstants(c, c); + } + + @AfterClass + public static void unsetConstants() { + RelativeDateFormatter.setConstants(null, null); + } + private static void assertFormat(long ageFromNow, long timeUnit, String expectedFormat) { Date d = new Date(System.currentTimeMillis() - ageFromNow * timeUnit); String s = RelativeDateFormatter.format(d); @@ -41,7 +53,7 @@ @Test public void formatSeconds() { - assertFormat(1, SECOND_IN_MILLIS, "1 seconds ago"); + assertFormat(1, SECOND_IN_MILLIS, "1 second ago"); assertFormat(89, SECOND_IN_MILLIS, "89 seconds ago"); } @@ -85,7 +97,7 @@ assertFormat(380, DAY_IN_MILLIS, "1 year, 1 month ago"); assertFormat(410, DAY_IN_MILLIS, "1 year, 2 months ago"); assertFormat(2, YEAR_IN_MILLIS, "2 years ago"); - assertFormat(1824, DAY_IN_MILLIS, "4 years, 12 months ago"); + assertFormat(1824, DAY_IN_MILLIS, "5 years ago"); } @Test @@ -93,4 +105,111 @@ assertFormat(5, YEAR_IN_MILLIS, "5 years ago"); assertFormat(60, YEAR_IN_MILLIS, "60 years ago"); } + + private static class Constants implements CommonConstants, CommonMessages { + @Override + public String inTheFuture() { + return "in the future"; + } + + @Override + public String month() { + return "month"; + } + + @Override + public String months() { + return "months"; + } + + @Override + public String year() { + return "year"; + } + + @Override + public String years() { + return "years"; + } + + @Override + public String oneSecondAgo() { + return "1 second ago"; + } + + @Override + public String oneMinuteAgo() { + return "1 minute ago"; + } + + @Override + public String oneHourAgo() { + return "1 hour ago"; + } + + @Override + public String oneDayAgo() { + return "1 day ago"; + } + + @Override + public String oneWeekAgo() { + return "1 week ago"; + } + + @Override + public String oneMonthAgo() { + return "1 month ago"; + } + + @Override + public String oneYearAgo() { + return "1 year ago"; + } + + @Override + public String secondsAgo(long seconds) { + return seconds + " seconds ago"; + } + + @Override + public String minutesAgo(long minutes) { + return minutes + " minutes ago"; + } + + @Override + public String hoursAgo(long hours) { + return hours + " hours ago"; + } + + @Override + public String daysAgo(long days) { + return days + " days ago"; + } + + @Override + public String weeksAgo(long weeks) { + return weeks + " weeks ago"; + } + + @Override + public String monthsAgo(long months) { + return months + " months ago"; + } + + @Override + public String yearsAgo(long years) { + return years + " years ago"; + } + + @Override + public String years0MonthsAgo(long years, String yearLabel) { + return years + " " + yearLabel + " ago"; + } + + @Override + public String yearsMonthsAgo(long years, String yearLabel, long months, String monthLabel) { + return years + " " + yearLabel + ", " + months + " " + monthLabel + " ago"; + } + } }
diff --git a/gerrit-index/BUILD b/gerrit-index/BUILD index 41eed60b..11c4f08 100644 --- a/gerrit-index/BUILD +++ b/gerrit-index/BUILD
@@ -1,7 +1,10 @@ load("//tools/bzl:genrule2.bzl", "genrule2") load("//tools/bzl:junit.bzl", "junit_tests") -QUERY_PARSE_EXCEPTION_SRCS = ["src/main/java/com/google/gerrit/index/query/QueryParseException.java"] +QUERY_PARSE_EXCEPTION_SRCS = [ + "src/main/java/com/google/gerrit/index/query/QueryParseException.java", + "src/main/java/com/google/gerrit/index/query/QueryRequiresAuthException.java", +] java_library( name = "query_exception",
diff --git a/gerrit-index/src/main/java/com/google/gerrit/index/query/QueryRequiresAuthException.java b/gerrit-index/src/main/java/com/google/gerrit/index/query/QueryRequiresAuthException.java new file mode 100644 index 0000000..67c159e --- /dev/null +++ b/gerrit-index/src/main/java/com/google/gerrit/index/query/QueryRequiresAuthException.java
@@ -0,0 +1,32 @@ +// 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.index.query; + +/** + * Exception thrown when a search query is invalid. + * + * <p><b>NOTE:</b> the message is visible to end users. + */ +public class QueryRequiresAuthException extends QueryParseException { + private static final long serialVersionUID = 1L; + + public QueryRequiresAuthException(String message) { + super(message); + } + + public QueryRequiresAuthException(String msg, Throwable why) { + super(msg, why); + } +}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java index bee9928..d8451d5 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Reindex.java
@@ -32,6 +32,7 @@ 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.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.index.IndexModule; import com.google.gerrit.server.index.IndexModule.IndexType; import com.google.gerrit.server.index.change.ChangeSchemaDefinitions; @@ -170,6 +171,7 @@ @Override protected void configure() { factory(ChangeResource.Factory.class); + bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED); } });
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/ExternalIdsOnInit.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/ExternalIdsOnInit.java index feb91e7..ab491f7c 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/ExternalIdsOnInit.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/ExternalIdsOnInit.java
@@ -16,11 +16,13 @@ import com.google.gerrit.pgm.init.api.AllUsersNameOnInitProvider; import com.google.gerrit.pgm.init.api.InitFlags; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.server.GerritPersonIdentProvider; import com.google.gerrit.server.account.externalids.ExternalId; import com.google.gerrit.server.account.externalids.ExternalIdReader; import com.google.gerrit.server.account.externalids.ExternalIdsUpdate; import com.google.gerrit.server.config.SitePaths; +import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gwtorm.server.OrmException; import com.google.inject.Inject; import java.io.File; @@ -67,7 +69,17 @@ PersonIdent serverIdent = new GerritPersonIdentProvider(flags.cfg).get(); ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, commitMessage, serverIdent, serverIdent); + new Project.NameKey(allUsers), + repo, + rw, + ins, + rev, + noteMap, + commitMessage, + serverIdent, + serverIdent, + null, + GitReferenceUpdated.DISABLED); } } }
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/SequencesOnInit.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/SequencesOnInit.java index bfad889..e1cef62 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/SequencesOnInit.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/init/api/SequencesOnInit.java
@@ -17,6 +17,7 @@ import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.Sequences; +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; @@ -40,6 +41,7 @@ RepoSequence accountSeq = new RepoSequence( repoManager, + GitReferenceUpdated.DISABLED, new Project.NameKey(allUsersName.get()), Sequences.NAME_ACCOUNTS, accountSeed,
diff --git a/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/gerrit.sh b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/gerrit.sh index d331347..20edbd3 100755 --- a/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/gerrit.sh +++ b/gerrit-pgm/src/main/resources/com/google/gerrit/pgm/init/gerrit.sh
@@ -289,7 +289,11 @@ GERRIT_FDS=`get_config --int core.packedGitOpenFiles` test -z "$GERRIT_FDS" && GERRIT_FDS=128 -GERRIT_FDS=`expr $GERRIT_FDS + $GERRIT_FDS` +FDS_MULTIPLIER=2 +USE_LFS=`get_config --get lfs.plugin` +test -n "$USE_LFS" && FDS_MULTIPLIER=3 + +GERRIT_FDS=`expr $FDS_MULTIPLIER \* $GERRIT_FDS` test $GERRIT_FDS -lt 1024 && GERRIT_FDS=1024 GERRIT_STARTUP_TIMEOUT=`get_config --get container.startupTimeout`
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java b/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java index 28fde9e..930f3f3 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/Sequences.java
@@ -27,6 +27,7 @@ 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.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.notedb.NotesMigration; import com.google.gerrit.server.notedb.RepoSequence; @@ -64,6 +65,7 @@ Provider<ReviewDb> db, NotesMigration migration, GitRepositoryManager repoManager, + GitReferenceUpdated gitRefUpdated, AllProjectsName allProjects, AllUsersName allUsers, MetricMaker metrics) { @@ -74,6 +76,7 @@ accountSeq = new RepoSequence( repoManager, + gitRefUpdated, allUsers, NAME_ACCOUNTS, () -> ReviewDb.FIRST_ACCOUNT_ID, @@ -84,7 +87,8 @@ RepoSequence.Seed changeSeed = () -> db.get().nextChangeId() + gap; int changeBatchSize = cfg.getInt("noteDb", "changes", "sequenceBatchSize", 20); changeSeq = - new RepoSequence(repoManager, allProjects, NAME_CHANGES, changeSeed, changeBatchSize); + new RepoSequence( + repoManager, gitRefUpdated, allProjects, NAME_CHANGES, changeSeed, changeBatchSize); nextIdLatency = metrics.newTimer(
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java index a8cc0f4..12bd8ff 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/StarredChangesUtil.java
@@ -37,6 +37,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb; import com.google.gerrit.server.change.ChangeResource; 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.index.change.ChangeField; import com.google.gerrit.server.index.change.ChangeIndexer; @@ -163,6 +164,7 @@ ImmutableSortedSet.of(DEFAULT_LABEL); private final GitRepositoryManager repoManager; + private final GitReferenceUpdated gitRefUpdated; private final AllUsersName allUsers; private final Provider<ReviewDb> dbProvider; private final PersonIdent serverIdent; @@ -172,12 +174,14 @@ @Inject StarredChangesUtil( GitRepositoryManager repoManager, + GitReferenceUpdated gitRefUpdated, AllUsersName allUsers, Provider<ReviewDb> dbProvider, @GerritPersonIdent PersonIdent serverIdent, ChangeIndexer indexer, Provider<InternalChangeQuery> queryProvider) { this.repoManager = repoManager; + this.gitRefUpdated = gitRefUpdated; this.allUsers = allUsers; this.dbProvider = dbProvider; this.serverIdent = serverIdent; @@ -403,18 +407,8 @@ throw new MutuallyExclusiveLabelsException(DEFAULT_LABEL, IGNORE_LABEL); } - Set<Integer> reviewedPatchSets = - labels - .stream() - .filter(l -> l.startsWith(REVIEWED_LABEL)) - .map(l -> Integer.valueOf(l.substring(REVIEWED_LABEL.length() + 1))) - .collect(toSet()); - Set<Integer> unreviewedPatchSets = - labels - .stream() - .filter(l -> l.startsWith(UNREVIEWED_LABEL)) - .map(l -> Integer.valueOf(l.substring(UNREVIEWED_LABEL.length() + 1))) - .collect(toSet()); + Set<Integer> reviewedPatchSets = getStarredPatchSets(labels, REVIEWED_LABEL); + Set<Integer> unreviewedPatchSets = getStarredPatchSets(labels, UNREVIEWED_LABEL); Optional<Integer> ps = Sets.intersection(reviewedPatchSets, unreviewedPatchSets).stream().findFirst(); if (ps.isPresent()) { @@ -423,6 +417,15 @@ } } + public static Set<Integer> getStarredPatchSets(Set<String> labels, String label) { + return labels + .stream() + .filter(l -> l.startsWith(label)) + .filter(l -> Ints.tryParse(l.substring(label.length() + 1)) != null) + .map(l -> Integer.valueOf(l.substring(label.length() + 1))) + .collect(toSet()); + } + private static void validateLabels(Collection<String> labels) throws InvalidLabelsException { if (labels == null) { return; @@ -455,6 +458,7 @@ case FORCED: case NO_CHANGE: case FAST_FORWARD: + gitRefUpdated.fire(allUsers, u, null); return; case IO_FAILURE: case LOCK_FAILURE: @@ -481,6 +485,7 @@ RefUpdate.Result result = u.delete(); switch (result) { case FORCED: + gitRefUpdated.fire(allUsers, u, null); return; case NEW: case NO_CHANGE:
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsBatchUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsBatchUpdate.java index e35b0c3..8e5582c 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsBatchUpdate.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsBatchUpdate.java
@@ -17,6 +17,7 @@ import com.google.common.collect.ImmutableSet; 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.gwtorm.server.OrmException; import com.google.inject.Inject; @@ -41,6 +42,7 @@ */ public class ExternalIdsBatchUpdate { private final GitRepositoryManager repoManager; + private final GitReferenceUpdated gitRefUpdated; private final AllUsersName allUsersName; private final PersonIdent serverIdent; private final ExternalIdCache externalIdCache; @@ -50,10 +52,12 @@ @Inject public ExternalIdsBatchUpdate( GitRepositoryManager repoManager, + GitReferenceUpdated gitRefUpdated, AllUsersName allUsersName, @GerritPersonIdent PersonIdent serverIdent, ExternalIdCache externalIdCache) { this.repoManager = repoManager; + this.gitRefUpdated = gitRefUpdated; this.allUsersName = allUsersName; this.serverIdent = serverIdent; this.externalIdCache = externalIdCache; @@ -105,7 +109,17 @@ ObjectId newRev = ExternalIdsUpdate.commit( - repo, rw, ins, rev, noteMap, commitMessage, serverIdent, serverIdent); + allUsersName, + repo, + rw, + ins, + rev, + noteMap, + commitMessage, + serverIdent, + serverIdent, + null, + gitRefUpdated); externalIdCache.onReplace(rev, newRev, toDelete, toAdd); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java index e4434fb..00dc05a5 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/externalids/ExternalIdsUpdate.java
@@ -41,11 +41,13 @@ import com.google.gerrit.metrics.Description; import com.google.gerrit.metrics.MetricMaker; import com.google.gerrit.reviewdb.client.Account; +import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RefNames; import com.google.gerrit.server.GerritPersonIdent; 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.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gerrit.server.git.LockFailureException; import com.google.gwtorm.server.OrmDuplicateKeyException; @@ -111,6 +113,7 @@ private final ExternalIds externalIds; private final ExternalIdCache externalIdCache; private final Provider<PersonIdent> serverIdent; + private final GitReferenceUpdated gitRefUpdated; @Inject public Server( @@ -120,7 +123,8 @@ MetricMaker metricMaker, ExternalIds externalIds, ExternalIdCache externalIdCache, - @GerritPersonIdent Provider<PersonIdent> serverIdent) { + @GerritPersonIdent Provider<PersonIdent> serverIdent, + GitReferenceUpdated gitRefUpdated) { this.repoManager = repoManager; this.accountCache = accountCache; this.allUsersName = allUsersName; @@ -128,12 +132,22 @@ this.externalIds = externalIds; this.externalIdCache = externalIdCache; this.serverIdent = serverIdent; + this.gitRefUpdated = gitRefUpdated; } public ExternalIdsUpdate create() { PersonIdent i = serverIdent.get(); return new ExternalIdsUpdate( - repoManager, accountCache, allUsersName, metricMaker, externalIds, externalIdCache, i, i); + repoManager, + accountCache, + allUsersName, + metricMaker, + externalIds, + externalIdCache, + i, + i, + null, + gitRefUpdated); } } @@ -154,6 +168,7 @@ private final ExternalIds externalIds; private final ExternalIdCache externalIdCache; private final Provider<PersonIdent> serverIdent; + private final GitReferenceUpdated gitRefUpdated; @Inject public ServerNoReindex( @@ -162,19 +177,30 @@ MetricMaker metricMaker, ExternalIds externalIds, ExternalIdCache externalIdCache, - @GerritPersonIdent Provider<PersonIdent> serverIdent) { + @GerritPersonIdent Provider<PersonIdent> serverIdent, + GitReferenceUpdated gitRefUpdated) { this.repoManager = repoManager; this.allUsersName = allUsersName; this.metricMaker = metricMaker; this.externalIds = externalIds; this.externalIdCache = externalIdCache; this.serverIdent = serverIdent; + this.gitRefUpdated = gitRefUpdated; } public ExternalIdsUpdate create() { PersonIdent i = serverIdent.get(); return new ExternalIdsUpdate( - repoManager, null, allUsersName, metricMaker, externalIds, externalIdCache, i, i); + repoManager, + null, + allUsersName, + metricMaker, + externalIds, + externalIdCache, + i, + i, + null, + gitRefUpdated); } } @@ -194,6 +220,7 @@ private final ExternalIdCache externalIdCache; private final Provider<PersonIdent> serverIdent; private final Provider<IdentifiedUser> identifiedUser; + private final GitReferenceUpdated gitRefUpdated; @Inject public User( @@ -204,7 +231,8 @@ ExternalIds externalIds, ExternalIdCache externalIdCache, @GerritPersonIdent Provider<PersonIdent> serverIdent, - Provider<IdentifiedUser> identifiedUser) { + Provider<IdentifiedUser> identifiedUser, + GitReferenceUpdated gitRefUpdated) { this.repoManager = repoManager; this.accountCache = accountCache; this.allUsersName = allUsersName; @@ -213,9 +241,11 @@ this.externalIdCache = externalIdCache; this.serverIdent = serverIdent; this.identifiedUser = identifiedUser; + this.gitRefUpdated = gitRefUpdated; } public ExternalIdsUpdate create() { + IdentifiedUser user = identifiedUser.get(); PersonIdent i = serverIdent.get(); return new ExternalIdsUpdate( repoManager, @@ -224,8 +254,10 @@ metricMaker, externalIds, externalIdCache, - createPersonIdent(i, identifiedUser.get()), - i); + createPersonIdent(i, user), + i, + user, + gitRefUpdated); } private PersonIdent createPersonIdent(PersonIdent ident, IdentifiedUser user) { @@ -253,6 +285,8 @@ private final ExternalIdCache externalIdCache; private final PersonIdent committerIdent; private final PersonIdent authorIdent; + @Nullable private final IdentifiedUser currentUser; + private final GitReferenceUpdated gitRefUpdated; private final Runnable afterReadRevision; private final Retryer<RefsMetaExternalIdsUpdate> retryer; private final Counter0 updateCount; @@ -265,7 +299,9 @@ ExternalIds externalIds, ExternalIdCache externalIdCache, PersonIdent committerIdent, - PersonIdent authorIdent) { + PersonIdent authorIdent, + @Nullable IdentifiedUser currentUser, + GitReferenceUpdated gitRefUpdated) { this( repoManager, accountCache, @@ -275,6 +311,8 @@ externalIdCache, committerIdent, authorIdent, + currentUser, + gitRefUpdated, Runnables.doNothing(), RETRYER); } @@ -289,6 +327,8 @@ ExternalIdCache externalIdCache, PersonIdent committerIdent, PersonIdent authorIdent, + @Nullable IdentifiedUser currentUser, + GitReferenceUpdated gitRefUpdated, Runnable afterReadRevision, Retryer<RefsMetaExternalIdsUpdate> retryer) { this.repoManager = checkNotNull(repoManager, "repoManager"); @@ -298,6 +338,8 @@ this.externalIds = checkNotNull(externalIds, "externalIds"); this.externalIdCache = checkNotNull(externalIdCache, "externalIdCache"); this.authorIdent = checkNotNull(authorIdent, "authorIdent"); + this.currentUser = currentUser; + this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated"); this.afterReadRevision = checkNotNull(afterReadRevision, "afterReadRevision"); this.retryer = checkNotNull(retryer, "retryer"); this.updateCount = @@ -732,13 +774,26 @@ NoteMap noteMap, UpdatedExternalIds updatedExtIds) throws IOException { - ObjectId newRev = commit(repo, rw, ins, rev, noteMap, COMMIT_MSG, committerIdent, authorIdent); + ObjectId newRev = + commit( + allUsersName, + repo, + rw, + ins, + rev, + noteMap, + COMMIT_MSG, + committerIdent, + authorIdent, + currentUser, + gitRefUpdated); updateCount.increment(); return RefsMetaExternalIdsUpdate.create(rev, newRev, updatedExtIds); } /** Commits updates to the external IDs. */ public static ObjectId commit( + Project.NameKey project, Repository repo, RevWalk rw, ObjectInserter ins, @@ -746,7 +801,9 @@ NoteMap noteMap, String commitMessage, PersonIdent committerIdent, - PersonIdent authorIdent) + PersonIdent authorIdent, + @Nullable IdentifiedUser user, + GitReferenceUpdated gitRefUpdated) throws IOException { CommitBuilder cb = new CommitBuilder(); cb.setMessage(commitMessage); @@ -793,6 +850,7 @@ default: throw new IOException("Updating external IDs failed with " + res); } + gitRefUpdated.fire(project, u, user != null ? user.getAccount() : null); return rw.parseCommit(commitId); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java index 2ab5c55..2e1da65 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/index/change/ReindexAfterRefUpdate.java
@@ -88,7 +88,7 @@ public void onGitReferenceUpdated(Event event) { if (allUsersName.get().equals(event.getProjectName())) { Account.Id accountId = Account.Id.fromRef(event.getRefName()); - if (accountId != null) { + if (accountId != null && !event.getRefName().startsWith(RefNames.REFS_STARRED_CHANGES)) { try { accountCache.evict(accountId); } catch (IOException e) {
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java index 43813f8..777624a 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/RepoSequence.java
@@ -36,6 +36,7 @@ import com.google.gerrit.common.Nullable; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RefNames; +import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.server.git.GitRepositoryManager; import com.google.gwtorm.server.OrmException; import java.io.IOException; @@ -86,6 +87,7 @@ private static final Retryer<RefUpdate.Result> RETRYER = retryerBuilder().build(); private final GitRepositoryManager repoManager; + private final GitReferenceUpdated gitRefUpdated; private final Project.NameKey projectName; private final String refName; private final Seed seed; @@ -103,16 +105,26 @@ public RepoSequence( GitRepositoryManager repoManager, + GitReferenceUpdated gitRefUpdated, Project.NameKey projectName, String name, Seed seed, int batchSize) { - this(repoManager, projectName, name, seed, batchSize, Runnables.doNothing(), RETRYER); + this( + repoManager, + gitRefUpdated, + projectName, + name, + seed, + batchSize, + Runnables.doNothing(), + RETRYER); } @VisibleForTesting RepoSequence( GitRepositoryManager repoManager, + GitReferenceUpdated gitRefUpdated, Project.NameKey projectName, String name, Seed seed, @@ -120,6 +132,7 @@ Runnable afterReadRef, Retryer<RefUpdate.Result> retryer) { this.repoManager = checkNotNull(repoManager, "repoManager"); + this.gitRefUpdated = checkNotNull(gitRefUpdated, "gitRefUpdated"); this.projectName = checkNotNull(projectName, "projectName"); checkArgument( @@ -213,11 +226,15 @@ } private void checkResult(RefUpdate.Result result) throws OrmException { - if (result != RefUpdate.Result.NEW && result != RefUpdate.Result.FORCED) { + if (!refUpdated(result)) { throw new OrmException("failed to update " + refName + ": " + result); } } + private boolean refUpdated(RefUpdate.Result result) { + return result == RefUpdate.Result.NEW || result == RefUpdate.Result.FORCED; + } + private class TryAcquire implements Callable<RefUpdate.Result> { private final Repository repo; private final RevWalk rw; @@ -275,7 +292,11 @@ } ru.setNewObjectId(newId); ru.setForceUpdate(true); // Required for non-commitish updates. - return ru.update(rw); + RefUpdate.Result result = ru.update(rw); + if (refUpdated(result)) { + gitRefUpdated.fire(projectName, ru, null); + } + return result; } public static ReceiveCommand storeNew(ObjectInserter ins, String name, int val)
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java index 7913e82..f302177 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/rebuild/NoteDbMigrator.java
@@ -51,6 +51,7 @@ import com.google.gerrit.server.config.AllProjectsName; 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.LockFailureException; import com.google.gerrit.server.git.WorkQueue; @@ -505,6 +506,7 @@ 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
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java index 1ae579e..1f28dbd 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/ChangeQueryBuilder.java
@@ -36,6 +36,7 @@ import com.google.gerrit.index.query.Predicate; import com.google.gerrit.index.query.QueryBuilder; import com.google.gerrit.index.query.QueryParseException; +import com.google.gerrit.index.query.QueryRequiresAuthException; import com.google.gerrit.reviewdb.client.Account; import com.google.gerrit.reviewdb.client.AccountGroup; import com.google.gerrit.reviewdb.client.Branch; @@ -391,23 +392,23 @@ return asUser(userFactory.create(otherId)); } - IdentifiedUser getIdentifiedUser() throws QueryParseException { + IdentifiedUser getIdentifiedUser() throws QueryRequiresAuthException { try { CurrentUser u = getUser(); if (u.isIdentifiedUser()) { return u.asIdentifiedUser(); } - throw new QueryParseException(NotSignedInException.MESSAGE); + throw new QueryRequiresAuthException(NotSignedInException.MESSAGE); } catch (ProvisionException e) { - throw new QueryParseException(NotSignedInException.MESSAGE, e); + throw new QueryRequiresAuthException(NotSignedInException.MESSAGE, e); } } - CurrentUser getUser() throws QueryParseException { + CurrentUser getUser() throws QueryRequiresAuthException { try { return self.get(); } catch (ProvisionException e) { - throw new QueryParseException(NotSignedInException.MESSAGE, e); + throw new QueryRequiresAuthException(NotSignedInException.MESSAGE, e); } }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java index c7a525a..fadc853 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/query/change/QueryChanges.java
@@ -24,6 +24,7 @@ import com.google.gerrit.extensions.restapi.RestReadView; import com.google.gerrit.extensions.restapi.TopLevelResource; import com.google.gerrit.index.query.QueryParseException; +import com.google.gerrit.index.query.QueryRequiresAuthException; import com.google.gerrit.index.query.QueryResult; import com.google.gerrit.server.change.ChangeJson; import com.google.gwtorm.server.OrmException; @@ -32,8 +33,6 @@ import java.util.Collections; import java.util.EnumSet; import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; import org.kohsuke.args4j.Option; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -110,15 +109,9 @@ List<List<ChangeInfo>> out; try { out = query(); + } catch (QueryRequiresAuthException e) { + throw new AuthException("Must be signed-in to use this operator"); } catch (QueryParseException e) { - // This is a hack to detect an operator that requires authentication. - Pattern p = - Pattern.compile("^Error in operator (.*:self|is:watched|is:owner|is:reviewer|has:.*)$"); - Matcher m = p.matcher(e.getMessage()); - if (m.matches()) { - String op = m.group(1); - throw new AuthException("Must be signed-in to use " + op); - } log.debug("Reject change query with 400 Bad Request: " + queries, e); throw new BadRequestException(e.getMessage(), e); }
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_144.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_144.java index eaa97e4d5..d43b887 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_144.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_144.java
@@ -21,6 +21,7 @@ import com.google.gerrit.server.account.externalids.ExternalIdReader; import com.google.gerrit.server.account.externalids.ExternalIdsUpdate; 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.gwtorm.jdbc.JdbcSchema; import com.google.gwtorm.server.OrmException; @@ -93,7 +94,18 @@ ExternalIdsUpdate.upsert(rw, ins, noteMap, extId); } - ExternalIdsUpdate.commit(repo, rw, ins, rev, noteMap, COMMIT_MSG, serverIdent, serverIdent); + ExternalIdsUpdate.commit( + allUsersName, + repo, + rw, + ins, + rev, + noteMap, + COMMIT_MSG, + serverIdent, + serverIdent, + null, + GitReferenceUpdated.DISABLED); } } catch (IOException | ConfigInvalidException e) { throw new OrmException("Failed to migrate external IDs to NoteDb", e);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_148.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_148.java index 421e28d..47751cd 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_148.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_148.java
@@ -23,6 +23,7 @@ import com.google.gerrit.server.account.externalids.ExternalIdReader; import com.google.gerrit.server.account.externalids.ExternalIdsUpdate; 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.gwtorm.server.OrmException; import com.google.inject.Inject; @@ -84,7 +85,18 @@ } } if (dirty) { - ExternalIdsUpdate.commit(repo, rw, ins, rev, noteMap, COMMIT_MSG, serverUser, serverUser); + ExternalIdsUpdate.commit( + allUsersName, + repo, + rw, + ins, + rev, + noteMap, + COMMIT_MSG, + serverUser, + serverUser, + null, + GitReferenceUpdated.DISABLED); } } catch (IOException e) { throw new OrmException("Failed to update external IDs", e);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_155.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_155.java index 64f60e3..2bb2a33 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_155.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_155.java
@@ -17,6 +17,7 @@ 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; @@ -42,7 +43,13 @@ @SuppressWarnings("deprecation") RepoSequence.Seed accountSeed = () -> db.nextAccountId(); RepoSequence accountSeq = - new RepoSequence(repoManager, allUsersName, Sequences.NAME_ACCOUNTS, accountSeed, 1); + new RepoSequence( + repoManager, + GitReferenceUpdated.DISABLED, + allUsersName, + Sequences.NAME_ACCOUNTS, + accountSeed, + 1); // consume one account ID to ensure that the account sequence is initialized in NoteDb accountSeq.next();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_161.java b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_161.java index 407492d..febe80e 100644 --- a/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_161.java +++ b/gerrit-server/src/main/java/com/google/gerrit/server/schema/Schema_161.java
@@ -16,6 +16,7 @@ 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; @@ -27,6 +28,9 @@ 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; @@ -54,19 +58,53 @@ try (Repository git = repoManager.openRepository(allUsersName); RevWalk rw = new RevWalk(git)) { BatchRefUpdate bru = git.getRefDatabase().newBatchUpdate(); + bru.setAllowNonFastForwards(true); + for (Ref ref : git.getRefDatabase().getRefs(RefNames.REFS_STARRED_CHANGES).values()) { StarRef starRef = StarredChangesUtil.readLabels(git, ref.getName()); - if (starRef.labels().contains(MUTE_LABEL)) { - ObjectId id = - StarredChangesUtil.writeLabels( - git, - starRef - .labels() - .stream() - .map(l -> l.equals(MUTE_LABEL) ? StarredChangesUtil.REVIEWED_LABEL : l) - .collect(toList())); - bru.addCommand(new ReceiveCommand(ObjectId.zeroId(), id, 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) {
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/RepoSequenceTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/RepoSequenceTest.java index 66ccdad..76be4569 100644 --- a/gerrit-server/src/test/java/com/google/gerrit/server/notedb/RepoSequenceTest.java +++ b/gerrit-server/src/test/java/com/google/gerrit/server/notedb/RepoSequenceTest.java
@@ -25,6 +25,7 @@ import com.google.common.util.concurrent.Runnables; import com.google.gerrit.reviewdb.client.Project; import com.google.gerrit.reviewdb.client.RefNames; +import com.google.gerrit.server.extensions.events.GitReferenceUpdated; import com.google.gerrit.testutil.InMemoryRepositoryManager; import com.google.gwtorm.server.OrmException; import java.io.IOException; @@ -264,7 +265,14 @@ Runnable afterReadRef, Retryer<RefUpdate.Result> retryer) { return new RepoSequence( - repoManager, project, name, () -> start, batchSize, afterReadRef, retryer); + repoManager, + GitReferenceUpdated.DISABLED, + project, + name, + () -> start, + batchSize, + afterReadRef, + retryer); } private ObjectId writeBlob(String sequenceName, String value) {
diff --git a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js index 3605e1d..f811e9e 100644 --- a/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js +++ b/polygerrit-ui/app/elements/core/gr-search-bar/gr-search-bar.js
@@ -51,6 +51,7 @@ 'is:open', 'is:owner', 'is:pending', + 'is:private', 'is:reviewed', 'is:reviewer', 'is:starred',