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
This commit is contained in:
David Pursehouse
2017-10-06 19:59:44 +09:00
27 changed files with 694 additions and 101 deletions

View File

@@ -38,6 +38,7 @@ import static org.junit.Assert.fail;
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.ChangeInfo;
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.PublicKeyStore;
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.io.IOException;
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 @@ public class AccountIT extends AbstractDaemonTest {
@Inject private DynamicSet<AccountIndexedListener> accountIndexedListeners;
@Inject private DynamicSet<GitReferenceUpdatedListener> refUpdateListeners;
@Inject private Sequences seq;
@Inject private Provider<InternalAccountQuery> accountQueryProvider;
@@ -163,6 +170,8 @@ public class AccountIT extends AbstractDaemonTest {
private AccountIndexedCounter accountIndexedCounter;
private RegistrationHandle accountIndexEventCounterHandle;
private RefUpdateCounter refUpdateCounter;
private RegistrationHandle refUpdateCounterHandle;
private ExternalIdsUpdate externalIdsUpdate;
private List<ExternalId> savedExternalIds;
@@ -179,6 +188,19 @@ public class AccountIT extends AbstractDaemonTest {
}
}
@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 @@ public class AccountIT extends AbstractDaemonTest {
@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 @@ public class AccountIT extends AbstractDaemonTest {
assertThat(info.name).isEqualTo(name);
accountIndexedCounter.assertReindexOf(foo, expectedAccountReindexCalls);
assertUserBranch(foo.getId(), name, null);
return foo.getId();
}
@Test
@@ -378,15 +414,24 @@ public class AccountIT extends AbstractDaemonTest {
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 class AccountIT extends AbstractDaemonTest {
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 @@ public class AccountIT extends AbstractDaemonTest {
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 @@ public class AccountIT extends AbstractDaemonTest {
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 @@ public class AccountIT extends AbstractDaemonTest {
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();
}
}
}

View File

@@ -41,6 +41,7 @@ import static com.google.gerrit.extensions.client.ReviewerState.REMOVED;
import static com.google.gerrit.extensions.client.ReviewerState.REVIEWER;
import static com.google.gerrit.reviewdb.client.RefNames.changeMetaRef;
import static com.google.gerrit.reviewdb.server.ReviewDbUtil.unwrapDb;
import static com.google.gerrit.server.StarredChangesUtil.DEFAULT_LABEL;
import static com.google.gerrit.server.group.SystemGroupBackend.ANONYMOUS_USERS;
import static com.google.gerrit.server.group.SystemGroupBackend.CHANGE_OWNER;
import static com.google.gerrit.server.group.SystemGroupBackend.REGISTERED_USERS;
@@ -57,6 +58,7 @@ import com.google.common.collect.ImmutableMap;
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.MergePatchSetInput;
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 @@ public class ChangeIT extends AbstractDaemonTest {
@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 @@ public class ChangeIT extends AbstractDaemonTest {
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,
@@ -3298,6 +3319,25 @@ public class ChangeIT extends AbstractDaemonTest {
assertThat(trackingIds.iterator().next().id).isEqualTo("JRA001");
}
@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 @@ public class ChangeIT extends AbstractDaemonTest {
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();
}
}
}

View File

@@ -55,6 +55,7 @@ import com.google.gerrit.server.account.externalids.ExternalIds;
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
new DisabledExternalIdCache(),
serverIdent.get(),
serverIdent.get(),
null,
GitReferenceUpdated.DISABLED,
() -> {
if (!doneBgUpdate.getAndSet(true)) {
try {
@@ -726,6 +769,8 @@ public class ExternalIdIT extends AbstractDaemonTest {
new DisabledExternalIdCache(),
serverIdent.get(),
serverIdent.get(),
null,
GitReferenceUpdated.DISABLED,
() -> {
try {
extIdsUpdate
@@ -824,7 +869,17 @@ public class ExternalIdIT extends AbstractDaemonTest {
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 @@ public class ExternalIdIT extends AbstractDaemonTest {
}
ExternalIdsUpdate.commit(
allUsers,
testRepo.getRepository(),
testRepo.getRevWalk(),
ins,
@@ -846,7 +902,9 @@ public class ExternalIdIT extends AbstractDaemonTest {
noteMap,
"Add external ID",
admin.getIdent(),
admin.getIdent());
admin.getIdent(),
null,
GitReferenceUpdated.DISABLED);
}
}

View File

@@ -29,6 +29,7 @@ import com.google.gerrit.server.account.AccountResource;
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.PushCertificate;
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 class GpgApiAdapterImpl implements GpgApiAdapter {
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 @@ public class GpgApiAdapterImpl implements GpgApiAdapter {
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 class GpgApiAdapterImpl implements GpgApiAdapter {
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);
}

View File

@@ -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 @@ import java.util.Date;
* 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 @@ public class RelativeDateFormatter {
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 @@ public class RelativeDateFormatter {
// 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) {

View File

@@ -22,11 +22,23 @@ import static com.google.gerrit.client.RelativeDateFormatter.YEAR_IN_MILLIS;
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 @@ public class RelativeDateFormatterTest {
@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 @@ public class RelativeDateFormatterTest {
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 @@ public class RelativeDateFormatterTest {
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";
}
}
}

View File

@@ -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",

View File

@@ -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);
}
}

View File

@@ -32,6 +32,7 @@ import com.google.gerrit.pgm.util.SiteProgram;
import com.google.gerrit.pgm.util.ThreadLimiter;
import com.google.gerrit.server.change.ChangeResource;
import com.google.gerrit.server.config.GerritServerConfig;
import com.google.gerrit.server.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 @@ public class Reindex extends SiteProgram {
@Override
protected void configure() {
factory(ChangeResource.Factory.class);
bind(GitReferenceUpdated.class).toInstance(GitReferenceUpdated.DISABLED);
}
});

View File

@@ -16,11 +16,13 @@ package com.google.gerrit.pgm.init;
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 @@ public class ExternalIdsOnInit {
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);
}
}
}

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.pgm.init.api;
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 @@ public class SequencesOnInit {
RepoSequence accountSeq =
new RepoSequence(
repoManager,
GitReferenceUpdated.DISABLED,
new Project.NameKey(allUsersName.get()),
Sequences.NAME_ACCOUNTS,
accountSeed,

View File

@@ -289,7 +289,11 @@ fi
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`

View File

@@ -27,6 +27,7 @@ import com.google.gerrit.reviewdb.server.ReviewDb;
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 @@ public class Sequences {
Provider<ReviewDb> db,
NotesMigration migration,
GitRepositoryManager repoManager,
GitReferenceUpdated gitRefUpdated,
AllProjectsName allProjects,
AllUsersName allUsers,
MetricMaker metrics) {
@@ -74,6 +76,7 @@ public class Sequences {
accountSeq =
new RepoSequence(
repoManager,
gitRefUpdated,
allUsers,
NAME_ACCOUNTS,
() -> ReviewDb.FIRST_ACCOUNT_ID,
@@ -84,7 +87,8 @@ public class Sequences {
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(

View File

@@ -37,6 +37,7 @@ import com.google.gerrit.reviewdb.client.RefNames;
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 @@ public class StarredChangesUtil {
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 @@ public class StarredChangesUtil {
@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 @@ public class StarredChangesUtil {
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 class StarredChangesUtil {
}
}
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 @@ public class StarredChangesUtil {
case FORCED:
case NO_CHANGE:
case FAST_FORWARD:
gitRefUpdated.fire(allUsers, u, null);
return;
case IO_FAILURE:
case LOCK_FAILURE:
@@ -481,6 +485,7 @@ public class StarredChangesUtil {
RefUpdate.Result result = u.delete();
switch (result) {
case FORCED:
gitRefUpdated.fire(allUsers, u, null);
return;
case NEW:
case NO_CHANGE:

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.account.externalids;
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 @@ import org.eclipse.jgit.revwalk.RevWalk;
*/
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 @@ public class ExternalIdsBatchUpdate {
@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 @@ public class ExternalIdsBatchUpdate {
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);
}

View File

@@ -41,11 +41,13 @@ import com.google.gerrit.metrics.Counter0;
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 @@ public class ExternalIdsUpdate {
private final ExternalIds externalIds;
private final ExternalIdCache externalIdCache;
private final Provider<PersonIdent> serverIdent;
private final GitReferenceUpdated gitRefUpdated;
@Inject
public Server(
@@ -120,7 +123,8 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
private final ExternalIds externalIds;
private final ExternalIdCache externalIdCache;
private final Provider<PersonIdent> serverIdent;
private final GitReferenceUpdated gitRefUpdated;
@Inject
public ServerNoReindex(
@@ -162,19 +177,30 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
ExternalIds externalIds,
ExternalIdCache externalIdCache,
PersonIdent committerIdent,
PersonIdent authorIdent) {
PersonIdent authorIdent,
@Nullable IdentifiedUser currentUser,
GitReferenceUpdated gitRefUpdated) {
this(
repoManager,
accountCache,
@@ -275,6 +311,8 @@ public class ExternalIdsUpdate {
externalIdCache,
committerIdent,
authorIdent,
currentUser,
gitRefUpdated,
Runnables.doNothing(),
RETRYER);
}
@@ -289,6 +327,8 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
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 @@ public class ExternalIdsUpdate {
default:
throw new IOException("Updating external IDs failed with " + res);
}
gitRefUpdated.fire(project, u, user != null ? user.getAccount() : null);
return rw.parseCommit(commitId);
}

View File

@@ -88,7 +88,7 @@ public class ReindexAfterRefUpdate implements GitReferenceUpdatedListener {
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) {

View File

@@ -36,6 +36,7 @@ import com.google.common.util.concurrent.Runnables;
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 @@ public class RepoSequence {
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 class RepoSequence {
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 @@ public class RepoSequence {
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 @@ public class RepoSequence {
}
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 @@ public class RepoSequence {
}
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)

View File

@@ -51,6 +51,7 @@ import com.google.gerrit.server.Sequences;
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 @@ public class NoteDbMigrator implements AutoCloseable {
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

View File

@@ -36,6 +36,7 @@ import com.google.gerrit.index.query.LimitPredicate;
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 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
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);
}
}

View File

@@ -24,6 +24,7 @@ import com.google.gerrit.extensions.restapi.BadRequestException;
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.ArrayList;
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 @@ public class QueryChanges implements RestReadView<TopLevelResource> {
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);
}

View File

@@ -21,6 +21,7 @@ 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.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 @@ public class Schema_144 extends SchemaVersion {
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);

View File

@@ -23,6 +23,7 @@ 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.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 @@ public class Schema_148 extends SchemaVersion {
}
}
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);

View File

@@ -17,6 +17,7 @@ package com.google.gerrit.server.schema;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.notedb.RepoSequence;
import com.google.gwtorm.server.OrmException;
@@ -42,7 +43,13 @@ public class Schema_155 extends SchemaVersion {
@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();

View File

@@ -16,6 +16,7 @@ package com.google.gerrit.server.schema;
import static java.util.stream.Collectors.toList;
import com.google.common.primitives.Ints;
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.server.ReviewDb;
import com.google.gerrit.server.StarredChangesUtil;
@@ -27,6 +28,9 @@ import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
import java.io.IOException;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import org.eclipse.jgit.lib.BatchRefUpdate;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
@@ -54,19 +58,53 @@ public class Schema_161 extends SchemaVersion {
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) {

View File

@@ -25,6 +25,7 @@ import com.github.rholder.retry.StopStrategies;
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 @@ public class RepoSequenceTest {
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) {

View File

@@ -51,6 +51,7 @@
'is:open',
'is:owner',
'is:pending',
'is:private',
'is:reviewed',
'is:reviewer',
'is:starred',