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.PeerDaemonUser;
|
||||||
import com.google.gerrit.server.account.CapabilityCollection;
|
import com.google.gerrit.server.account.CapabilityCollection;
|
||||||
import com.google.gerrit.server.cache.PerThreadCache;
|
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.ProjectCache;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -108,16 +106,15 @@ public class DefaultPermissionBackend extends PermissionBackend {
|
|||||||
public ForProject project(Project.NameKey project) {
|
public ForProject project(Project.NameKey project) {
|
||||||
try {
|
try {
|
||||||
ProjectState state = projectCache.checkedGet(project);
|
ProjectState state = projectCache.checkedGet(project);
|
||||||
if (state != null) {
|
ProjectControl control =
|
||||||
ProjectControl control =
|
PerThreadCache.getOrCompute(
|
||||||
PerThreadCache.getOrCompute(
|
PerThreadCache.Key.create(ProjectControl.class, project, user.getCacheKey()),
|
||||||
PerThreadCache.Key.create(ProjectControl.class, project, user.getCacheKey()),
|
() -> projectControlFactory.create(user, state));
|
||||||
() -> projectControlFactory.create(user, state));
|
return control.asForProject().database(db);
|
||||||
return control.asForProject().database(db);
|
} catch (Exception e) {
|
||||||
}
|
Throwable cause = e.getCause() != null ? e.getCause() : e;
|
||||||
return FailedPermissionBackend.project("not found", new NoSuchProjectException(project));
|
return FailedPermissionBackend.project(
|
||||||
} catch (IOException e) {
|
"project '" + project.get() + "' is unavailable", cause);
|
||||||
return FailedPermissionBackend.project("unavailable", e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ import java.util.EnumSet;
|
|||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
import org.eclipse.jgit.lib.Ref;
|
import org.eclipse.jgit.lib.Ref;
|
||||||
import org.eclipse.jgit.lib.Repository;
|
import org.eclipse.jgit.lib.Repository;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
@@ -280,6 +281,13 @@ public abstract class PermissionBackend {
|
|||||||
allowed.add(project);
|
allowed.add(project);
|
||||||
} catch (AuthException e) {
|
} catch (AuthException e) {
|
||||||
// Do not include this project in allowed.
|
// 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;
|
return allowed;
|
||||||
|
|||||||
@@ -48,6 +48,17 @@ public interface ProjectCache {
|
|||||||
*/
|
*/
|
||||||
ProjectState checkedGet(@Nullable Project.NameKey projectName) throws IOException;
|
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
|
* Invalidate the cached information about the given project, and triggers reindexing for it
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -142,13 +142,8 @@ public class ProjectCacheImpl implements ProjectCache {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
ProjectState state = byName.get(projectName.get());
|
return strictCheckedGet(projectName);
|
||||||
if (state != null && state.needsRefresh(clock.read())) {
|
} catch (Exception e) {
|
||||||
byName.invalidate(projectName.get());
|
|
||||||
state = byName.get(projectName.get());
|
|
||||||
}
|
|
||||||
return state;
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
if (!(e.getCause() instanceof RepositoryNotFoundException)) {
|
if (!(e.getCause() instanceof RepositoryNotFoundException)) {
|
||||||
log.warn(String.format("Cannot read project %s", projectName.get()), e);
|
log.warn(String.format("Cannot read project %s", projectName.get()), e);
|
||||||
Throwables.throwIfInstanceOf(e.getCause(), IOException.class);
|
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
|
@Override
|
||||||
public void evict(Project p) throws IOException {
|
public void evict(Project p) throws IOException {
|
||||||
evict(p.getNameKey());
|
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.ChangePermission;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackend;
|
import com.google.gerrit.server.permissions.PermissionBackend;
|
||||||
import com.google.gerrit.server.permissions.PermissionBackendException;
|
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.ProjectCache;
|
||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
@@ -89,8 +89,10 @@ public class ChangeIsVisibleToPredicate extends IsVisibleToPredicate<ChangeData>
|
|||||||
.database(db)
|
.database(db)
|
||||||
.test(ChangePermission.READ);
|
.test(ChangePermission.READ);
|
||||||
} catch (PermissionBackendException e) {
|
} catch (PermissionBackendException e) {
|
||||||
if (e.getCause() instanceof NoSuchProjectException) {
|
Throwable cause = e.getCause();
|
||||||
logger.info("No such project: {}", cd.project());
|
if (cause instanceof RepositoryNotFoundException) {
|
||||||
|
logger.warn(
|
||||||
|
"Skipping change {} because the corresponding repository was not found", cd.getId(), e);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
throw new OrmException("unable to check permissions on change " + cd.getId(), e);
|
throw new OrmException("unable to check permissions on change " + cd.getId(), e);
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ public class ForcePushIT extends AbstractDaemonTest {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void deleteAllowedWithDeletePermission() throws Exception {
|
public void deleteAllowedWithDeletePermission() throws Exception {
|
||||||
grant(project, "refs/*", Permission.PUSH, true);
|
grant(project, "refs/*", Permission.DELETE, true);
|
||||||
assertDeleteRef(OK);
|
assertDeleteRef(OK);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -259,6 +259,12 @@ public class RefControlTest {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void evict(Project.NameKey p) {}
|
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());
|
Injector injector = Guice.createInjector(new InMemoryModule());
|
||||||
|
|||||||
Reference in New Issue
Block a user