Implement StalenessChecker for projects
This commit implements a staleness checker for projects in the same fashion that we have it for groups and accounts. It uses the newly added ref_state field. Change-Id: Icbcf0bd1c700df789ef26501e4218956d718ea4c
This commit is contained in:
		@@ -68,6 +68,8 @@ import com.google.gerrit.extensions.common.EditInfo;
 | 
				
			|||||||
import com.google.gerrit.extensions.restapi.BinaryResult;
 | 
					import com.google.gerrit.extensions.restapi.BinaryResult;
 | 
				
			||||||
import com.google.gerrit.extensions.restapi.IdString;
 | 
					import com.google.gerrit.extensions.restapi.IdString;
 | 
				
			||||||
import com.google.gerrit.extensions.restapi.RestApiException;
 | 
					import com.google.gerrit.extensions.restapi.RestApiException;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectIndex;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectIndexCollection;
 | 
				
			||||||
import com.google.gerrit.mail.Address;
 | 
					import com.google.gerrit.mail.Address;
 | 
				
			||||||
import com.google.gerrit.mail.EmailHeader;
 | 
					import com.google.gerrit.mail.EmailHeader;
 | 
				
			||||||
import com.google.gerrit.reviewdb.client.Account;
 | 
					import com.google.gerrit.reviewdb.client.Account;
 | 
				
			||||||
@@ -274,6 +276,7 @@ public abstract class AbstractDaemonTest {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
  @Inject private ChangeIndexCollection changeIndexes;
 | 
					  @Inject private ChangeIndexCollection changeIndexes;
 | 
				
			||||||
  @Inject private AccountIndexCollection accountIndexes;
 | 
					  @Inject private AccountIndexCollection accountIndexes;
 | 
				
			||||||
 | 
					  @Inject private ProjectIndexCollection projectIndexes;
 | 
				
			||||||
  @Inject private EventRecorder.Factory eventRecorderFactory;
 | 
					  @Inject private EventRecorder.Factory eventRecorderFactory;
 | 
				
			||||||
  @Inject private InProcessProtocol inProcessProtocol;
 | 
					  @Inject private InProcessProtocol inProcessProtocol;
 | 
				
			||||||
  @Inject private Provider<AnonymousUser> anonymousUser;
 | 
					  @Inject private Provider<AnonymousUser> anonymousUser;
 | 
				
			||||||
@@ -900,6 +903,41 @@ public abstract class AbstractDaemonTest {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected AutoCloseable disableProjectIndex() {
 | 
				
			||||||
 | 
					    disableProjectIndexWrites();
 | 
				
			||||||
 | 
					    ProjectIndex searchIndex = projectIndexes.getSearchIndex();
 | 
				
			||||||
 | 
					    if (!(searchIndex instanceof DisabledProjectIndex)) {
 | 
				
			||||||
 | 
					      projectIndexes.setSearchIndex(new DisabledProjectIndex(searchIndex), false);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return new AutoCloseable() {
 | 
				
			||||||
 | 
					      @Override
 | 
				
			||||||
 | 
					      public void close() {
 | 
				
			||||||
 | 
					        enableProjectIndexWrites();
 | 
				
			||||||
 | 
					        ProjectIndex searchIndex = projectIndexes.getSearchIndex();
 | 
				
			||||||
 | 
					        if (searchIndex instanceof DisabledProjectIndex) {
 | 
				
			||||||
 | 
					          projectIndexes.setSearchIndex(((DisabledProjectIndex) searchIndex).unwrap(), false);
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected void disableProjectIndexWrites() {
 | 
				
			||||||
 | 
					    for (ProjectIndex i : projectIndexes.getWriteIndexes()) {
 | 
				
			||||||
 | 
					      if (!(i instanceof DisabledProjectIndex)) {
 | 
				
			||||||
 | 
					        projectIndexes.addWriteIndex(new DisabledProjectIndex(i));
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  protected void enableProjectIndexWrites() {
 | 
				
			||||||
 | 
					    for (ProjectIndex i : projectIndexes.getWriteIndexes()) {
 | 
				
			||||||
 | 
					      if (i instanceof DisabledProjectIndex) {
 | 
				
			||||||
 | 
					        projectIndexes.addWriteIndex(((DisabledProjectIndex) i).unwrap());
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  protected static Gson newGson() {
 | 
					  protected static Gson newGson() {
 | 
				
			||||||
    return OutputFormat.JSON_COMPACT.newGson();
 | 
					    return OutputFormat.JSON_COMPACT.newGson();
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -99,6 +99,7 @@ java_library2(
 | 
				
			|||||||
        "//java/com/google/gerrit/extensions:api",
 | 
					        "//java/com/google/gerrit/extensions:api",
 | 
				
			||||||
        "//java/com/google/gerrit/httpd",
 | 
					        "//java/com/google/gerrit/httpd",
 | 
				
			||||||
        "//java/com/google/gerrit/index",
 | 
					        "//java/com/google/gerrit/index",
 | 
				
			||||||
 | 
					        "//java/com/google/gerrit/index/project",
 | 
				
			||||||
        "//java/com/google/gerrit/lucene",
 | 
					        "//java/com/google/gerrit/lucene",
 | 
				
			||||||
        "//java/com/google/gerrit/mail",
 | 
					        "//java/com/google/gerrit/mail",
 | 
				
			||||||
        "//java/com/google/gerrit/metrics",
 | 
					        "//java/com/google/gerrit/metrics",
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										76
									
								
								java/com/google/gerrit/acceptance/DisabledProjectIndex.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								java/com/google/gerrit/acceptance/DisabledProjectIndex.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2018 The Android Open Source Project
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.google.gerrit.acceptance;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.gerrit.index.QueryOptions;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.Schema;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectData;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectIndex;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.query.DataSource;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.query.Predicate;
 | 
				
			||||||
 | 
					import com.google.gerrit.reviewdb.client.Project;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * This class wraps an index and assumes the search index can't handle any queries. However, it does
 | 
				
			||||||
 | 
					 * return the current schema as the assumption is that we need a search index for starting Gerrit in
 | 
				
			||||||
 | 
					 * the first place and only later lose the index connection (making it so that we can't send
 | 
				
			||||||
 | 
					 * requests there anymore).
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					public class DisabledProjectIndex implements ProjectIndex {
 | 
				
			||||||
 | 
					  private final ProjectIndex index;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public DisabledProjectIndex(ProjectIndex index) {
 | 
				
			||||||
 | 
					    this.index = index;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public ProjectIndex unwrap() {
 | 
				
			||||||
 | 
					    return index;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public Schema<ProjectData> getSchema() {
 | 
				
			||||||
 | 
					    return index.getSchema();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public void close() {
 | 
				
			||||||
 | 
					    index.close();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public void replace(ProjectData obj) {
 | 
				
			||||||
 | 
					    throw new UnsupportedOperationException("ProjectIndex is disabled");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public void delete(Project.NameKey key) {
 | 
				
			||||||
 | 
					    throw new UnsupportedOperationException("ProjectIndex is disabled");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public void deleteAll() {
 | 
				
			||||||
 | 
					    throw new UnsupportedOperationException("ProjectIndex is disabled");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public DataSource<ProjectData> getSource(Predicate<ProjectData> p, QueryOptions opts) {
 | 
				
			||||||
 | 
					    throw new UnsupportedOperationException("ProjectIndex is disabled");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Override
 | 
				
			||||||
 | 
					  public void markReady(boolean ready) {
 | 
				
			||||||
 | 
					    throw new UnsupportedOperationException("ProjectIndex is disabled");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -0,0 +1,81 @@
 | 
				
			|||||||
 | 
					// Copyright (C) 2018 The Android Open Source Project
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Licensed under the Apache License, Version 2.0 (the "License");
 | 
				
			||||||
 | 
					// you may not use this file except in compliance with the License.
 | 
				
			||||||
 | 
					// You may obtain a copy of the License at
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// http://www.apache.org/licenses/LICENSE-2.0
 | 
				
			||||||
 | 
					//
 | 
				
			||||||
 | 
					// Unless required by applicable law or agreed to in writing, software
 | 
				
			||||||
 | 
					// distributed under the License is distributed on an "AS IS" BASIS,
 | 
				
			||||||
 | 
					// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
				
			||||||
 | 
					// See the License for the specific language governing permissions and
 | 
				
			||||||
 | 
					// limitations under the License.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					package com.google.gerrit.server.index.project;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import com.google.common.collect.ImmutableSet;
 | 
				
			||||||
 | 
					import com.google.common.collect.MultimapBuilder;
 | 
				
			||||||
 | 
					import com.google.common.collect.SetMultimap;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.IndexConfig;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.QueryOptions;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.RefState;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectData;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectField;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectIndex;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.project.ProjectIndexCollection;
 | 
				
			||||||
 | 
					import com.google.gerrit.index.query.FieldBundle;
 | 
				
			||||||
 | 
					import com.google.gerrit.reviewdb.client.Project;
 | 
				
			||||||
 | 
					import com.google.gerrit.reviewdb.client.RefNames;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.project.ProjectCache;
 | 
				
			||||||
 | 
					import java.io.IOException;
 | 
				
			||||||
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import javax.inject.Inject;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					public class StalenessChecker {
 | 
				
			||||||
 | 
					  private static final ImmutableSet<String> FIELDS =
 | 
				
			||||||
 | 
					      ImmutableSet.of(ProjectField.NAME.getName(), ProjectField.REF_STATE.getName());
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private final ProjectCache projectCache;
 | 
				
			||||||
 | 
					  private final ProjectIndexCollection indexes;
 | 
				
			||||||
 | 
					  private final IndexConfig indexConfig;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Inject
 | 
				
			||||||
 | 
					  StalenessChecker(
 | 
				
			||||||
 | 
					      ProjectCache projectCache, ProjectIndexCollection indexes, IndexConfig indexConfig) {
 | 
				
			||||||
 | 
					    this.projectCache = projectCache;
 | 
				
			||||||
 | 
					    this.indexes = indexes;
 | 
				
			||||||
 | 
					    this.indexConfig = indexConfig;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  public boolean isStale(Project.NameKey project) throws IOException {
 | 
				
			||||||
 | 
					    ProjectData projectData = projectCache.get(project).toProjectData();
 | 
				
			||||||
 | 
					    ProjectIndex i = indexes.getSearchIndex();
 | 
				
			||||||
 | 
					    if (i == null) {
 | 
				
			||||||
 | 
					      return false; // No index; caller couldn't do anything if it is stale.
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Optional<FieldBundle> result =
 | 
				
			||||||
 | 
					        i.getRaw(project, QueryOptions.create(indexConfig, 0, 1, FIELDS));
 | 
				
			||||||
 | 
					    if (!result.isPresent()) {
 | 
				
			||||||
 | 
					      return true;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SetMultimap<Project.NameKey, RefState> indexedRefStates =
 | 
				
			||||||
 | 
					        RefState.parseStates(result.get().getValue(ProjectField.REF_STATE));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    SetMultimap<Project.NameKey, RefState> currentRefStates =
 | 
				
			||||||
 | 
					        MultimapBuilder.hashKeys().hashSetValues().build();
 | 
				
			||||||
 | 
					    projectData
 | 
				
			||||||
 | 
					        .tree()
 | 
				
			||||||
 | 
					        .stream()
 | 
				
			||||||
 | 
					        .filter(p -> p.getProject().getConfigRefState() != null)
 | 
				
			||||||
 | 
					        .forEach(
 | 
				
			||||||
 | 
					            p ->
 | 
				
			||||||
 | 
					                currentRefStates.put(
 | 
				
			||||||
 | 
					                    p.getProject().getNameKey(),
 | 
				
			||||||
 | 
					                    RefState.create(RefNames.REFS_CONFIG, p.getProject().getConfigRefState())));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return !currentRefStates.equals(indexedRefStates);
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -28,10 +28,13 @@ import com.google.gerrit.index.project.ProjectIndexCollection;
 | 
				
			|||||||
import com.google.gerrit.index.project.ProjectIndexer;
 | 
					import com.google.gerrit.index.project.ProjectIndexer;
 | 
				
			||||||
import com.google.gerrit.index.query.FieldBundle;
 | 
					import com.google.gerrit.index.query.FieldBundle;
 | 
				
			||||||
import com.google.gerrit.reviewdb.client.Project;
 | 
					import com.google.gerrit.reviewdb.client.Project;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.index.project.StalenessChecker;
 | 
				
			||||||
 | 
					import com.google.gerrit.server.project.ProjectConfig;
 | 
				
			||||||
import com.google.inject.Inject;
 | 
					import com.google.inject.Inject;
 | 
				
			||||||
import java.util.Collection;
 | 
					import java.util.Collection;
 | 
				
			||||||
import java.util.Map;
 | 
					import java.util.Map;
 | 
				
			||||||
import java.util.Optional;
 | 
					import java.util.Optional;
 | 
				
			||||||
 | 
					import java.util.function.Consumer;
 | 
				
			||||||
import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 | 
					import org.eclipse.jgit.internal.storage.dfs.InMemoryRepository;
 | 
				
			||||||
import org.eclipse.jgit.junit.TestRepository;
 | 
					import org.eclipse.jgit.junit.TestRepository;
 | 
				
			||||||
import org.eclipse.jgit.lib.Ref;
 | 
					import org.eclipse.jgit.lib.Ref;
 | 
				
			||||||
@@ -41,6 +44,7 @@ public class ProjectIndexerIT extends AbstractDaemonTest {
 | 
				
			|||||||
  @Inject private ProjectIndexer projectIndexer;
 | 
					  @Inject private ProjectIndexer projectIndexer;
 | 
				
			||||||
  @Inject private ProjectIndexCollection indexes;
 | 
					  @Inject private ProjectIndexCollection indexes;
 | 
				
			||||||
  @Inject private IndexConfig indexConfig;
 | 
					  @Inject private IndexConfig indexConfig;
 | 
				
			||||||
 | 
					  @Inject private StalenessChecker stalenessChecker;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  private static final ImmutableSet<String> FIELDS =
 | 
					  private static final ImmutableSet<String> FIELDS =
 | 
				
			||||||
      ImmutableSet.of(ProjectField.NAME.getName(), ProjectField.REF_STATE.getName());
 | 
					      ImmutableSet.of(ProjectField.NAME.getName(), ProjectField.REF_STATE.getName());
 | 
				
			||||||
@@ -72,4 +76,54 @@ public class ProjectIndexerIT extends AbstractDaemonTest {
 | 
				
			|||||||
            allProjects,
 | 
					            allProjects,
 | 
				
			||||||
            ImmutableSet.of(RefState.of(allProjectConfigRef)));
 | 
					            ImmutableSet.of(RefState.of(allProjectConfigRef)));
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void stalenessChecker_currentProject_notStale() throws Exception {
 | 
				
			||||||
 | 
					    assertThat(stalenessChecker.isStale(project)).isFalse();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void stalenessChecker_currentProjectUpdates_isStale() throws Exception {
 | 
				
			||||||
 | 
					    updateProjectConfigWithoutIndexUpdate(project);
 | 
				
			||||||
 | 
					    assertThat(stalenessChecker.isStale(project)).isTrue();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void stalenessChecker_parentProjectUpdates_isStale() throws Exception {
 | 
				
			||||||
 | 
					    updateProjectConfigWithoutIndexUpdate(allProjects);
 | 
				
			||||||
 | 
					    assertThat(stalenessChecker.isStale(project)).isTrue();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  @Test
 | 
				
			||||||
 | 
					  public void stalenessChecker_hierarchyChange_isStale() throws Exception {
 | 
				
			||||||
 | 
					    Project.NameKey p1 = createProject("p1", allProjects);
 | 
				
			||||||
 | 
					    Project.NameKey p2 = createProject("p2", allProjects);
 | 
				
			||||||
 | 
					    try (ProjectConfigUpdate u = updateProject(project)) {
 | 
				
			||||||
 | 
					      u.getConfig().getProject().setParentName(p1);
 | 
				
			||||||
 | 
					      u.save();
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    assertThat(stalenessChecker.isStale(project)).isFalse();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    updateProjectConfigWithoutIndexUpdate(p1, c -> c.getProject().setParentName(p2));
 | 
				
			||||||
 | 
					    assertThat(stalenessChecker.isStale(project)).isTrue();
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private void updateProjectConfigWithoutIndexUpdate(Project.NameKey project) throws Exception {
 | 
				
			||||||
 | 
					    updateProjectConfigWithoutIndexUpdate(
 | 
				
			||||||
 | 
					        project, c -> c.getProject().setDescription("making it stale"));
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  private void updateProjectConfigWithoutIndexUpdate(
 | 
				
			||||||
 | 
					      Project.NameKey project, Consumer<ProjectConfig> update) throws Exception {
 | 
				
			||||||
 | 
					    try (AutoCloseable ignored = disableProjectIndex()) {
 | 
				
			||||||
 | 
					      try (ProjectConfigUpdate u = updateProject(project)) {
 | 
				
			||||||
 | 
					        update.accept(u.getConfig());
 | 
				
			||||||
 | 
					        u.save();
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (UnsupportedOperationException e) {
 | 
				
			||||||
 | 
					      // Drop, as we just wanted to drop the index update
 | 
				
			||||||
 | 
					      return;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    fail("should have a UnsupportedOperationException");
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user