Merge branch 'stable-2.15'
* stable-2.15: ForcePushIT#deleteAllowedWithDeletePermission: Fix permission setting PermissionBackend#filter: Don't fail if project doesn't exist Reload actions when new change is loaded, not on new changeNum Fix lint errors Filter out changes for vanished projects Propagate cause of a project not found in cache Change-Id: I595235f32993802bfc1f27034734abdd4508ce91
This commit is contained in:
@@ -32,13 +32,11 @@ import com.google.gerrit.server.IdentifiedUser;
|
||||
import com.google.gerrit.server.PeerDaemonUser;
|
||||
import com.google.gerrit.server.account.CapabilityCollection;
|
||||
import com.google.gerrit.server.cache.PerThreadCache;
|
||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
import com.google.inject.Singleton;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
@@ -108,16 +106,15 @@ public class DefaultPermissionBackend extends PermissionBackend {
|
||||
public ForProject project(Project.NameKey project) {
|
||||
try {
|
||||
ProjectState state = projectCache.checkedGet(project);
|
||||
if (state != null) {
|
||||
ProjectControl control =
|
||||
PerThreadCache.getOrCompute(
|
||||
PerThreadCache.Key.create(ProjectControl.class, project, user.getCacheKey()),
|
||||
() -> projectControlFactory.create(user, state));
|
||||
return control.asForProject().database(db);
|
||||
}
|
||||
return FailedPermissionBackend.project("not found", new NoSuchProjectException(project));
|
||||
} catch (IOException e) {
|
||||
return FailedPermissionBackend.project("unavailable", e);
|
||||
} catch (Exception e) {
|
||||
Throwable cause = e.getCause() != null ? e.getCause() : e;
|
||||
return FailedPermissionBackend.project(
|
||||
"project '" + project.get() + "' is unavailable", cause);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -41,6 +41,7 @@ import java.util.EnumSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Ref;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.slf4j.Logger;
|
||||
@@ -280,6 +281,13 @@ public abstract class PermissionBackend {
|
||||
allowed.add(project);
|
||||
} catch (AuthException e) {
|
||||
// Do not include this project in allowed.
|
||||
} catch (PermissionBackendException e) {
|
||||
if (e.getCause() instanceof RepositoryNotFoundException) {
|
||||
logger.warn("Could not find repository of the project {} : ", project.get(), e);
|
||||
// Do not include this project because doesn't exist
|
||||
} else {
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
return allowed;
|
||||
|
||||
@@ -48,6 +48,17 @@ public interface ProjectCache {
|
||||
*/
|
||||
ProjectState checkedGet(@Nullable Project.NameKey projectName) throws IOException;
|
||||
|
||||
/**
|
||||
* Get the cached data for a project by its unique name.
|
||||
*
|
||||
* @param projectName name of the project.
|
||||
* @param strict true when any error generates an exception
|
||||
* @throws Exception in case of any error (strict = true) or only for I/O or other internal
|
||||
* errors.
|
||||
* @return the cached data or null when strict = false
|
||||
*/
|
||||
public ProjectState checkedGet(Project.NameKey projectName, boolean strict) throws Exception;
|
||||
|
||||
/**
|
||||
* Invalidate the cached information about the given project, and triggers reindexing for it
|
||||
*
|
||||
|
||||
@@ -142,13 +142,8 @@ public class ProjectCacheImpl implements ProjectCache {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
ProjectState state = byName.get(projectName.get());
|
||||
if (state != null && state.needsRefresh(clock.read())) {
|
||||
byName.invalidate(projectName.get());
|
||||
state = byName.get(projectName.get());
|
||||
}
|
||||
return state;
|
||||
} catch (ExecutionException e) {
|
||||
return strictCheckedGet(projectName);
|
||||
} catch (Exception e) {
|
||||
if (!(e.getCause() instanceof RepositoryNotFoundException)) {
|
||||
log.warn(String.format("Cannot read project %s", projectName.get()), e);
|
||||
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
|
||||
@@ -159,6 +154,20 @@ public class ProjectCacheImpl implements ProjectCache {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectState checkedGet(Project.NameKey projectName, boolean strict) throws Exception {
|
||||
return strict ? strictCheckedGet(projectName) : checkedGet(projectName);
|
||||
}
|
||||
|
||||
private ProjectState strictCheckedGet(Project.NameKey projectName) throws Exception {
|
||||
ProjectState state = byName.get(projectName.get());
|
||||
if (state != null && state.needsRefresh(clock.read())) {
|
||||
byName.invalidate(projectName.get());
|
||||
state = byName.get(projectName.get());
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void evict(Project p) throws IOException {
|
||||
evict(p.getNameKey());
|
||||
|
||||
@@ -23,12 +23,12 @@ import com.google.gerrit.server.notedb.ChangeNotes;
|
||||
import com.google.gerrit.server.permissions.ChangePermission;
|
||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
||||
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.gerrit.server.project.ProjectState;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Provider;
|
||||
import java.io.IOException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
@@ -89,8 +89,10 @@ public class ChangeIsVisibleToPredicate extends IsVisibleToPredicate<ChangeData>
|
||||
.database(db)
|
||||
.test(ChangePermission.READ);
|
||||
} catch (PermissionBackendException e) {
|
||||
if (e.getCause() instanceof NoSuchProjectException) {
|
||||
logger.info("No such project: {}", cd.project());
|
||||
Throwable cause = e.getCause();
|
||||
if (cause instanceof RepositoryNotFoundException) {
|
||||
logger.warn(
|
||||
"Skipping change {} because the corresponding repository was not found", cd.getId(), e);
|
||||
return false;
|
||||
}
|
||||
throw new OrmException("unable to check permissions on change " + cd.getId(), e);
|
||||
|
||||
@@ -94,7 +94,7 @@ public class ForcePushIT extends AbstractDaemonTest {
|
||||
|
||||
@Test
|
||||
public void deleteAllowedWithDeletePermission() throws Exception {
|
||||
grant(project, "refs/*", Permission.PUSH, true);
|
||||
grant(project, "refs/*", Permission.DELETE, true);
|
||||
assertDeleteRef(OK);
|
||||
}
|
||||
|
||||
|
||||
@@ -259,6 +259,12 @@ public class RefControlTest {
|
||||
|
||||
@Override
|
||||
public void evict(Project.NameKey p) {}
|
||||
|
||||
@Override
|
||||
public ProjectState checkedGet(Project.NameKey projectName, boolean strict)
|
||||
throws Exception {
|
||||
return all.get(projectName);
|
||||
}
|
||||
};
|
||||
|
||||
Injector injector = Guice.createInjector(new InMemoryModule());
|
||||
|
||||
Reference in New Issue
Block a user