Allow GitRepositoryManager methods to throw IOExceptions
RepositoryNotFoundException should really mean "this repository definitely doesn't exist", not "something went wrong when we tried to read this repo (maybe it doesn't exist?)". Since GitRepositoryManager could only throw RepositoryNotFoundExceptions, the easiest implementation was to wrap *all* exceptions in that class, i.e. to take the latter interpretation. We have some downstream caching code that treated RepositoryNotFoundExceptions as definite negatives, i.e. the former interpretation. This was causing poisoned caches on otherwise mostly harmless transient errors. Change GitRepositoryManager to distinguish between these two cases by using IOException for "something went wrong". This complicates the signature, but since RepositoryNotFound derives from IOException, many callers that just want to wrap-and-throw can still do so with minimal changes. Change-Id: Ib2aa2e2443cc3b530ae7fc50fe4eb20059bb16de
This commit is contained in:
committed by
gerrit code review
parent
e0d188ffd5
commit
7f4fbc8756
@@ -167,7 +167,12 @@ public class GitOverHttpServlet extends GitServlet {
|
||||
}
|
||||
req.setAttribute(ATT_CONTROL, pc);
|
||||
|
||||
try {
|
||||
return manager.openRepository(pc.getProject().getNameKey());
|
||||
} catch (IOException e) {
|
||||
throw new RepositoryNotFoundException(
|
||||
pc.getProject().getNameKey().get(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -141,6 +141,9 @@ class PatchScriptFactory extends Handler<PatchScript> {
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
log.error("Repository " + projectKey + " not found", e);
|
||||
throw new NoSuchChangeException(changeId, e);
|
||||
} catch (IOException e) {
|
||||
log.error("Cannot open repository " + projectKey, e);
|
||||
throw new NoSuchChangeException(changeId, e);
|
||||
}
|
||||
try {
|
||||
final PatchList list = listFor(keyFor(diffPrefs.getIgnoreWhitespace()));
|
||||
|
||||
@@ -65,7 +65,8 @@ class ChangeProjectSettings extends Handler<ProjectDetail> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectDetail call() throws NoSuchProjectException, OrmException {
|
||||
public ProjectDetail call() throws NoSuchProjectException, OrmException,
|
||||
IOException {
|
||||
final Project.NameKey projectName = update.getNameKey();
|
||||
projectControlFactory.ownerFor(projectName);
|
||||
|
||||
@@ -74,6 +75,8 @@ class ChangeProjectSettings extends Handler<ProjectDetail> {
|
||||
md = metaDataUpdateFactory.create(projectName);
|
||||
} catch (RepositoryNotFoundException notFound) {
|
||||
throw new NoSuchProjectException(projectName);
|
||||
} catch (IOException e) {
|
||||
throw new OrmException(e);
|
||||
}
|
||||
try {
|
||||
// TODO We really should take advantage of the Git commit DAG and
|
||||
|
||||
@@ -80,7 +80,7 @@ class DeleteBranches extends Handler<Set<Branch.NameKey>> {
|
||||
|
||||
@Override
|
||||
public Set<Branch.NameKey> call() throws NoSuchProjectException,
|
||||
RepositoryNotFoundException, OrmException {
|
||||
RepositoryNotFoundException, OrmException, IOException {
|
||||
final ProjectControl projectControl =
|
||||
projectControlFactory.controlFor(projectName);
|
||||
|
||||
|
||||
@@ -62,7 +62,7 @@ class ListBranches extends Handler<ListBranchesResult> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ListBranchesResult call() throws NoSuchProjectException {
|
||||
public ListBranchesResult call() throws NoSuchProjectException, IOException {
|
||||
final ProjectControl pctl = projectControlFactory.validateFor( //
|
||||
projectName, //
|
||||
ProjectControl.OWNER | ProjectControl.VISIBLE);
|
||||
|
||||
@@ -51,7 +51,7 @@ class ProjectDetailFactory extends Handler<ProjectDetail> {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProjectDetail call() throws NoSuchProjectException {
|
||||
public ProjectDetail call() throws NoSuchProjectException, IOException {
|
||||
final ProjectControl pc =
|
||||
projectControlFactory.validateFor(projectName, ProjectControl.OWNER
|
||||
| ProjectControl.VISIBLE);
|
||||
|
||||
@@ -14,7 +14,6 @@
|
||||
|
||||
package com.google.gerrit.httpd.rpc.project;
|
||||
|
||||
|
||||
import com.google.gerrit.common.data.ProjectDetail;
|
||||
import com.google.gerrit.httpd.rpc.Handler;
|
||||
import com.google.gerrit.reviewdb.client.Project;
|
||||
@@ -22,6 +21,7 @@ import com.google.gerrit.server.project.NoSuchProjectException;
|
||||
import com.google.gerrit.server.project.ProjectCache;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
@@ -50,6 +50,7 @@ class VisibleProjectDetails extends Handler<List<ProjectDetail>> {
|
||||
try {
|
||||
result.add(projectDetailFactory.create(projectName).call());
|
||||
} catch (NoSuchProjectException e) {
|
||||
} catch (IOException e) {
|
||||
}
|
||||
}
|
||||
Collections.sort(result, new Comparator<ProjectDetail>() {
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.google.inject.Injector;
|
||||
|
||||
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
import org.eclipse.jgit.lib.TextProgressMonitor;
|
||||
@@ -109,7 +108,7 @@ public class ScanTrackingIds extends SiteProgram {
|
||||
final Repository git;
|
||||
try {
|
||||
git = gitManager.openRepository(project);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -50,7 +50,6 @@ import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Config;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.RefUpdate;
|
||||
@@ -203,7 +202,7 @@ public class ChangeHookRunner implements ChangeHooks {
|
||||
private Repository openRepository(final Project.NameKey name) {
|
||||
try {
|
||||
return repoManager.openRepository(name);
|
||||
} catch (RepositoryNotFoundException err) {
|
||||
} catch (IOException err) {
|
||||
log.warn("Cannot open repository " + name.get(), err);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -189,6 +189,8 @@ public class RulesCache {
|
||||
git = gitMgr.openRepository(project);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
throw new CompileException("Cannot open repository " + project, e);
|
||||
} catch (IOException e) {
|
||||
throw new CompileException("Cannot open repository " + project, e);
|
||||
}
|
||||
try {
|
||||
ObjectLoader ldr = git.open(rulesId, Constants.OBJ_BLOB);
|
||||
|
||||
@@ -42,6 +42,7 @@ import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
public final class StoredValues {
|
||||
@@ -100,6 +101,8 @@ public final class StoredValues {
|
||||
repo = gitMgr.openRepository(projectKey);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
throw new SystemException(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
throw new SystemException(e.getMessage());
|
||||
}
|
||||
env.addToCleanup(new Runnable() {
|
||||
@Override
|
||||
|
||||
@@ -59,10 +59,11 @@ public interface GitRepositoryManager {
|
||||
* @return the cached Repository instance. Caller must call {@code close()}
|
||||
* when done to decrement the resource handle.
|
||||
* @throws RepositoryNotFoundException the name does not denote an existing
|
||||
* repository, or the name cannot be read as a repository.
|
||||
* repository.
|
||||
* @throws IOException the name cannot be read as a repository.
|
||||
*/
|
||||
public abstract Repository openRepository(Project.NameKey name)
|
||||
throws RepositoryNotFoundException;
|
||||
throws RepositoryNotFoundException, IOException;
|
||||
|
||||
/**
|
||||
* Create (and open) a repository by name.
|
||||
@@ -73,9 +74,11 @@ public interface GitRepositoryManager {
|
||||
* @throws RepositoryCaseMismatchException the name collides with an existing
|
||||
* repository name, but only in case of a character within the name.
|
||||
* @throws RepositoryNotFoundException the name is invalid.
|
||||
* @throws IOException the repository cannot be created.
|
||||
*/
|
||||
public abstract Repository createRepository(Project.NameKey name)
|
||||
throws RepositoryCaseMismatchException, RepositoryNotFoundException;
|
||||
throws RepositoryCaseMismatchException, RepositoryNotFoundException,
|
||||
IOException;
|
||||
|
||||
/** @return set of all known projects, sorted by natural NameKey order. */
|
||||
public abstract SortedSet<Project.NameKey> list();
|
||||
|
||||
@@ -319,6 +319,9 @@ public class MergeOp {
|
||||
} catch (RepositoryNotFoundException notGit) {
|
||||
final String m = "Repository \"" + name.get() + "\" unknown.";
|
||||
throw new MergeException(m, notGit);
|
||||
} catch (IOException err) {
|
||||
final String m = "Error opening repository \"" + name.get() + '"';
|
||||
throw new MergeException(m, err);
|
||||
}
|
||||
|
||||
rw = new RevWalk(repo) {
|
||||
|
||||
@@ -25,6 +25,8 @@ import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/** Helps with the updating of a {@link VersionedMetaData}. */
|
||||
public class MetaDataUpdate {
|
||||
public static class User {
|
||||
@@ -49,7 +51,7 @@ public class MetaDataUpdate {
|
||||
}
|
||||
|
||||
public MetaDataUpdate create(Project.NameKey name)
|
||||
throws RepositoryNotFoundException {
|
||||
throws RepositoryNotFoundException, IOException {
|
||||
MetaDataUpdate md = factory.create(name, mgr.openRepository(name));
|
||||
md.getCommitBuilder().setAuthor(userIdent);
|
||||
md.getCommitBuilder().setCommitter(serverIdent);
|
||||
@@ -71,7 +73,7 @@ public class MetaDataUpdate {
|
||||
}
|
||||
|
||||
public MetaDataUpdate create(Project.NameKey name)
|
||||
throws RepositoryNotFoundException {
|
||||
throws RepositoryNotFoundException, IOException {
|
||||
MetaDataUpdate md = factory.create(name, mgr.openRepository(name));
|
||||
md.getCommitBuilder().setAuthor(serverIdent);
|
||||
md.getCommitBuilder().setCommitter(serverIdent);
|
||||
|
||||
@@ -488,6 +488,10 @@ public class PushReplication implements ReplicationQueue {
|
||||
log.error("Internal error: project " + project
|
||||
+ " not found during replication", err);
|
||||
return;
|
||||
} catch (IOException err) {
|
||||
log.error("Internal error: unable to open project " + project
|
||||
+ " during replication", err);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Ref head = git.getRef(Constants.HEAD);
|
||||
|
||||
@@ -24,7 +24,6 @@ import com.google.gerrit.server.patch.PatchList;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
import java.io.IOException;
|
||||
@@ -140,7 +139,7 @@ public class CommentSender extends ReplyToChangeSender {
|
||||
private Repository getRepository() {
|
||||
try {
|
||||
return args.server.openRepository(projectState.getProject().getNameKey());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
|
||||
import org.eclipse.jgit.errors.MissingObjectException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.ObjectId;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -83,7 +82,7 @@ public class PatchSetInfoFactory {
|
||||
Repository repo;
|
||||
try {
|
||||
repo = repoManager.openRepository(change.getProject());
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
throw new PatchSetInfoNotAvailableException(e);
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -130,10 +130,10 @@ public class CreateProject {
|
||||
} finally {
|
||||
repo.close();
|
||||
}
|
||||
} catch (RepositoryNotFoundException doesNotExist) {
|
||||
} catch (IOException ioErr) {
|
||||
final String msg = "Cannot create " + nameKey;
|
||||
log.error(msg, err);
|
||||
throw new ProjectCreationFailedException(msg, err);
|
||||
throw new ProjectCreationFailedException(msg, ioErr);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
final String msg = "Cannot create " + nameKey;
|
||||
|
||||
@@ -158,9 +158,11 @@ class Schema_53 extends SchemaVersion {
|
||||
// inheritable permissions. For example 'All-Projects'.
|
||||
try {
|
||||
git = mgr.createRepository(nameKey);
|
||||
} catch (RepositoryNotFoundException err) {
|
||||
} catch (IOException err) {
|
||||
throw new OrmException("Cannot create repository " + name, err);
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new OrmException(e);
|
||||
}
|
||||
try {
|
||||
MetaDataUpdate md =
|
||||
|
||||
@@ -33,7 +33,6 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
|
||||
@@ -88,7 +87,7 @@ public class Schema_64 extends SchemaVersion {
|
||||
Repository git;
|
||||
try {
|
||||
git = mgr.openRepository(allProjects);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
throw new OrmException(e);
|
||||
}
|
||||
try {
|
||||
|
||||
@@ -43,8 +43,8 @@ import com.google.gwtorm.jdbc.JdbcSchema;
|
||||
import com.google.gwtorm.server.OrmException;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Provider;
|
||||
|
||||
import org.eclipse.jgit.errors.ConfigInvalidException;
|
||||
import org.eclipse.jgit.errors.RepositoryNotFoundException;
|
||||
import org.eclipse.jgit.lib.CommitBuilder;
|
||||
import org.eclipse.jgit.lib.PersonIdent;
|
||||
import org.eclipse.jgit.lib.Repository;
|
||||
@@ -87,7 +87,7 @@ public class Schema_65 extends SchemaVersion {
|
||||
Repository git;
|
||||
try {
|
||||
git = mgr.openRepository(allProjects);
|
||||
} catch (RepositoryNotFoundException e) {
|
||||
} catch (IOException e) {
|
||||
throw new OrmException(e);
|
||||
}
|
||||
try {
|
||||
|
||||
Reference in New Issue
Block a user