Optimize check visibility for a commit

First if there is any visible changes associate with the commit.
Second fallback to the ProjectControl.canReadCommitFromVisibleRef
which check if the commit is reachable in one of the visible ref.

Change-Id: Ia64bdf5868e8deb109b1b949c1b1d3c868f1e66c
This commit is contained in:
Zhen Chen
2016-11-17 17:26:54 -08:00
parent 6426c22404
commit 50c8b63f67
3 changed files with 33 additions and 1 deletions

View File

@@ -42,6 +42,8 @@ import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.VisibleRefFilter;
import com.google.gerrit.server.group.SystemGroupBackend;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -153,6 +155,7 @@ public class ProjectControl {
private final Collection<ContributorAgreement> contributorAgreements;
private final TagCache tagCache;
@Nullable private final SearchingChangeCacheImpl changeCache;
private final Provider<InternalChangeQuery> queryProvider;
private List<SectionMatcher> allSections;
private List<SectionMatcher> localSections;
@@ -168,6 +171,7 @@ public class ProjectControl {
ChangeNotes.Factory changeNotesFactory,
ChangeControl.Factory changeControlFactory,
TagCache tagCache,
Provider<InternalChangeQuery> queryProvider,
@Nullable SearchingChangeCacheImpl changeCache,
@CanonicalWebUrl @Nullable String canonicalWebUrl,
@Assisted CurrentUser who,
@@ -181,6 +185,7 @@ public class ProjectControl {
this.permissionFilter = permissionFilter;
this.contributorAgreements = pc.getAllProjects().getConfig().getContributorAgreements();
this.canonicalWebUrl = canonicalWebUrl;
this.queryProvider = queryProvider;
user = who;
state = ps;
}
@@ -513,7 +518,27 @@ public class ProjectControl {
return false;
}
/** @return whether a commit is visible to user. */
public boolean canReadCommit(ReviewDb db, Repository repo, RevCommit commit) {
// Look for changes associated with the commit.
try {
List<ChangeData> changes = queryProvider.get()
.byProjectCommit(getProject().getNameKey(), commit);
for (ChangeData change : changes) {
if (controlFor(db, change.change()).isVisible(db)) {
return true;
}
}
} catch (OrmException e) {
log.error("Cannot look up change for commit " + commit.name() + " in "
+ getProject().getName(), e);
}
// Scan all visible refs.
return canReadCommitFromVisibleRef(db, repo, commit);
}
private boolean canReadCommitFromVisibleRef(ReviewDb db, Repository repo,
RevCommit commit) {
try (RevWalk rw = new RevWalk(repo)) {
return isMergedIntoVisibleRef(repo, db, rw, commit,
repo.getAllRefs().values());

View File

@@ -241,6 +241,11 @@ public class InternalChangeQuery extends InternalQuery<ChangeData> {
return query(commit(hash));
}
public List<ChangeData> byProjectCommit(Project.NameKey project,
ObjectId id) throws OrmException {
return byProjectCommit(project, id.name());
}
public List<ChangeData> byProjectCommit(Project.NameKey project,
String hash) throws OrmException {
return query(and(project(project), commit(hash)));

View File

@@ -57,6 +57,7 @@ import com.google.gerrit.server.config.AllUsersName;
import com.google.gerrit.server.config.AllUsersNameProvider;
import com.google.gerrit.server.config.SitePaths;
import com.google.gerrit.server.git.ProjectConfig;
import com.google.gerrit.server.query.change.InternalChangeQuery;
import com.google.gerrit.server.schema.SchemaCreator;
import com.google.gerrit.server.util.RequestContext;
import com.google.gerrit.server.util.ThreadLocalRequestContext;
@@ -241,6 +242,7 @@ public class RefControlTest {
@Inject private SchemaCreator schemaCreator;
@Inject private InMemoryDatabase schemaFactory;
@Inject private ThreadLocalRequestContext requestContext;
@Inject private Provider<InternalChangeQuery> queryProvider;
@Before
public void setUp() throws Exception {
@@ -927,7 +929,7 @@ public class RefControlTest {
return new ProjectControl(Collections.<AccountGroup.UUID> emptySet(),
Collections.<AccountGroup.UUID> emptySet(), projectCache,
sectionSorter, null, changeControlFactory, null, null,
sectionSorter, null, changeControlFactory, null, queryProvider, null,
canonicalWebUrl, new MockUser(name, memberOf), newProjectState(local));
}