Merge "For the 'conflicts' operator return only changes that actually conflict"
This commit is contained in:
@@ -77,10 +77,9 @@ Change-Id that was scraped out of the commit message.
|
|||||||
[[conflicts]]
|
[[conflicts]]
|
||||||
conflicts:'ID'::
|
conflicts:'ID'::
|
||||||
+
|
+
|
||||||
Changes that potentially conflict with change 'ID' because they touch
|
Changes that conflict with change 'ID'. Change 'ID' can be specified
|
||||||
at least one file that was also touched by change 'ID'. Change 'ID' can
|
as a legacy numerical 'ID' such as 15183, or a newer style Change-Id
|
||||||
be specified as a legacy numerical 'ID' such as 15183, or a newer style
|
that was scraped out of the commit message.
|
||||||
Change-Id that was scraped out of the commit message.
|
|
||||||
|
|
||||||
[[owner]]
|
[[owner]]
|
||||||
owner:'USER'::
|
owner:'USER'::
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ import com.google.gerrit.server.project.ProjectNode;
|
|||||||
import com.google.gerrit.server.project.ProjectState;
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
import com.google.gerrit.server.project.SectionSortCache;
|
import com.google.gerrit.server.project.SectionSortCache;
|
||||||
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
import com.google.gerrit.server.query.change.ChangeQueryBuilder;
|
||||||
|
import com.google.gerrit.server.query.change.ConflictsCacheImpl;
|
||||||
import com.google.gerrit.server.ssh.SshAddressesModule;
|
import com.google.gerrit.server.ssh.SshAddressesModule;
|
||||||
import com.google.gerrit.server.tools.ToolsCatalog;
|
import com.google.gerrit.server.tools.ToolsCatalog;
|
||||||
import com.google.gerrit.server.util.IdGenerator;
|
import com.google.gerrit.server.util.IdGenerator;
|
||||||
@@ -143,13 +144,14 @@ public class GerritGlobalModule extends FactoryModule {
|
|||||||
install(authModule);
|
install(authModule);
|
||||||
install(AccountByEmailCacheImpl.module());
|
install(AccountByEmailCacheImpl.module());
|
||||||
install(AccountCacheImpl.module());
|
install(AccountCacheImpl.module());
|
||||||
|
install(ChangeCache.module());
|
||||||
|
install(ConflictsCacheImpl.module());
|
||||||
install(GroupCacheImpl.module());
|
install(GroupCacheImpl.module());
|
||||||
install(GroupIncludeCacheImpl.module());
|
install(GroupIncludeCacheImpl.module());
|
||||||
install(PatchListCacheImpl.module());
|
install(PatchListCacheImpl.module());
|
||||||
install(ProjectCacheImpl.module());
|
install(ProjectCacheImpl.module());
|
||||||
install(SectionSortCache.module());
|
install(SectionSortCache.module());
|
||||||
install(TagCache.module());
|
install(TagCache.module());
|
||||||
install(ChangeCache.module());
|
|
||||||
|
|
||||||
install(new AccessControlModule());
|
install(new AccessControlModule());
|
||||||
install(new CmdLineParserModule());
|
install(new CmdLineParserModule());
|
||||||
|
|||||||
@@ -33,8 +33,8 @@ public abstract class BasicChangeRewrites extends QueryRewriter<ChangeData> {
|
|||||||
new ChangeQueryBuilder.Arguments( //
|
new ChangeQueryBuilder.Arguments( //
|
||||||
new InvalidProvider<ReviewDb>(), //
|
new InvalidProvider<ReviewDb>(), //
|
||||||
new InvalidProvider<ChangeQueryRewriter>(), //
|
new InvalidProvider<ChangeQueryRewriter>(), //
|
||||||
null, null, null, null, null, null, //
|
null, null, null, null, null, null, null, //
|
||||||
null, null, null, null, null, null), null);
|
null, null, null, null, null, null, null), null);
|
||||||
|
|
||||||
static Schema<ChangeData> schema(@Nullable IndexCollection indexes) {
|
static Schema<ChangeData> schema(@Nullable IndexCollection indexes) {
|
||||||
ChangeIndex index = indexes != null ? indexes.getSearchIndex() : null;
|
ChangeIndex index = indexes != null ? indexes.getSearchIndex() : null;
|
||||||
|
|||||||
@@ -32,6 +32,7 @@ import com.google.gerrit.server.account.GroupBackend;
|
|||||||
import com.google.gerrit.server.account.GroupBackends;
|
import com.google.gerrit.server.account.GroupBackends;
|
||||||
import com.google.gerrit.server.config.AllProjectsName;
|
import com.google.gerrit.server.config.AllProjectsName;
|
||||||
import com.google.gerrit.server.git.GitRepositoryManager;
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.git.SubmitStrategyFactory;
|
||||||
import com.google.gerrit.server.index.ChangeIndex;
|
import com.google.gerrit.server.index.ChangeIndex;
|
||||||
import com.google.gerrit.server.index.IndexCollection;
|
import com.google.gerrit.server.index.IndexCollection;
|
||||||
import com.google.gerrit.server.index.Schema;
|
import com.google.gerrit.server.index.Schema;
|
||||||
@@ -153,6 +154,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
final ProjectCache projectCache;
|
final ProjectCache projectCache;
|
||||||
final Provider<ListChildProjects> listChildProjects;
|
final Provider<ListChildProjects> listChildProjects;
|
||||||
final IndexCollection indexes;
|
final IndexCollection indexes;
|
||||||
|
final SubmitStrategyFactory submitStrategyFactory;
|
||||||
|
final ConflictsCache conflictsCache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@@ -169,7 +172,9 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
GitRepositoryManager repoManager,
|
GitRepositoryManager repoManager,
|
||||||
ProjectCache projectCache,
|
ProjectCache projectCache,
|
||||||
Provider<ListChildProjects> listChildProjects,
|
Provider<ListChildProjects> listChildProjects,
|
||||||
IndexCollection indexes) {
|
IndexCollection indexes,
|
||||||
|
SubmitStrategyFactory submitStrategyFactory,
|
||||||
|
ConflictsCache conflictsCache) {
|
||||||
this.dbProvider = dbProvider;
|
this.dbProvider = dbProvider;
|
||||||
this.rewriter = rewriter;
|
this.rewriter = rewriter;
|
||||||
this.userFactory = userFactory;
|
this.userFactory = userFactory;
|
||||||
@@ -184,6 +189,8 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
this.projectCache = projectCache;
|
this.projectCache = projectCache;
|
||||||
this.listChildProjects = listChildProjects;
|
this.listChildProjects = listChildProjects;
|
||||||
this.indexes = indexes;
|
this.indexes = indexes;
|
||||||
|
this.submitStrategyFactory = submitStrategyFactory;
|
||||||
|
this.conflictsCache = conflictsCache;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -317,8 +324,10 @@ public class ChangeQueryBuilder extends QueryBuilder<ChangeData> {
|
|||||||
public Predicate<ChangeData> conflicts(String value) throws OrmException,
|
public Predicate<ChangeData> conflicts(String value) throws OrmException,
|
||||||
QueryParseException {
|
QueryParseException {
|
||||||
requireIndex(FIELD_CONFLICTS, value);
|
requireIndex(FIELD_CONFLICTS, value);
|
||||||
return new ConflictsPredicate(args.dbProvider, args.patchListCache, value,
|
return new ConflictsPredicate(args.dbProvider, args.patchListCache,
|
||||||
parseChange(value));
|
args.submitStrategyFactory, args.changeControlGenericFactory,
|
||||||
|
args.userFactory, args.repoManager, args.projectCache,
|
||||||
|
args.conflictsCache, value, parseChange(value));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Operator
|
@Operator
|
||||||
|
|||||||
@@ -0,0 +1,78 @@
|
|||||||
|
// Copyright (C) 2013 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.query.change;
|
||||||
|
|
||||||
|
import com.google.common.base.Objects;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
public class ConflictKey implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
private final ObjectId commit;
|
||||||
|
private final ObjectId otherCommit;
|
||||||
|
private final SubmitType submitType;
|
||||||
|
private final boolean contentMerge;
|
||||||
|
|
||||||
|
public ConflictKey(ObjectId commit, ObjectId otherCommit,
|
||||||
|
SubmitType submitType, boolean contentMerge) {
|
||||||
|
if (SubmitType.FAST_FORWARD_ONLY.equals(submitType)
|
||||||
|
|| commit.compareTo(otherCommit) < 0) {
|
||||||
|
this.commit = commit;
|
||||||
|
this.otherCommit = otherCommit;
|
||||||
|
} else {
|
||||||
|
this.commit = otherCommit;
|
||||||
|
this.otherCommit = commit;
|
||||||
|
}
|
||||||
|
this.submitType = submitType;
|
||||||
|
this.contentMerge = contentMerge;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId getCommit() {
|
||||||
|
return commit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ObjectId getOtherCommit() {
|
||||||
|
return otherCommit;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SubmitType getSubmitType() {
|
||||||
|
return submitType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isContentMerge() {
|
||||||
|
return contentMerge;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (!(o instanceof ConflictKey)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ConflictKey other = (ConflictKey)o;
|
||||||
|
return commit.equals(other.commit)
|
||||||
|
&& otherCommit.equals(other.otherCommit)
|
||||||
|
&& submitType.equals(other.submitType)
|
||||||
|
&& contentMerge == other.contentMerge;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
return Objects.hashCode(commit, otherCommit, submitType, contentMerge);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright (C) 2013 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.query.change;
|
||||||
|
|
||||||
|
import com.google.gerrit.common.Nullable;
|
||||||
|
|
||||||
|
public interface ConflictsCache {
|
||||||
|
|
||||||
|
public void put(ConflictKey key, Boolean value);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public Boolean getIfPresent(ConflictKey key);
|
||||||
|
}
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
// Copyright (C) 2013 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.query.change;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.gerrit.server.cache.CacheModule;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Singleton;
|
||||||
|
import com.google.inject.name.Named;
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
public class ConflictsCacheImpl implements ConflictsCache {
|
||||||
|
public final static String NAME = "conflicts";
|
||||||
|
|
||||||
|
public static Module module() {
|
||||||
|
return new CacheModule() {
|
||||||
|
@Override
|
||||||
|
protected void configure() {
|
||||||
|
persist(NAME, ConflictKey.class, Boolean.class)
|
||||||
|
.maximumWeight(37400);
|
||||||
|
bind(ConflictsCache.class).to(ConflictsCacheImpl.class);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Cache<ConflictKey, Boolean> conflictsCache;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public ConflictsCacheImpl(
|
||||||
|
@Named(NAME) Cache<ConflictKey, Boolean> conflictsCache) {
|
||||||
|
this.conflictsCache = conflictsCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void put(ConflictKey key, Boolean value) {
|
||||||
|
conflictsCache.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Boolean getIfPresent(ConflictKey key) {
|
||||||
|
return conflictsCache.getIfPresent(key);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,30 +15,71 @@
|
|||||||
package com.google.gerrit.server.query.change;
|
package com.google.gerrit.server.query.change;
|
||||||
|
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
import com.google.gerrit.common.data.SubmitTypeRecord;
|
||||||
import com.google.gerrit.reviewdb.client.Change;
|
import com.google.gerrit.reviewdb.client.Change;
|
||||||
|
import com.google.gerrit.reviewdb.client.Project.SubmitType;
|
||||||
import com.google.gerrit.reviewdb.server.ReviewDb;
|
import com.google.gerrit.reviewdb.server.ReviewDb;
|
||||||
|
import com.google.gerrit.server.IdentifiedUser;
|
||||||
|
import com.google.gerrit.server.git.CodeReviewCommit;
|
||||||
|
import com.google.gerrit.server.git.GitRepositoryManager;
|
||||||
|
import com.google.gerrit.server.git.MergeException;
|
||||||
|
import com.google.gerrit.server.git.SubmitStrategy;
|
||||||
|
import com.google.gerrit.server.git.SubmitStrategyFactory;
|
||||||
import com.google.gerrit.server.patch.PatchListCache;
|
import com.google.gerrit.server.patch.PatchListCache;
|
||||||
|
import com.google.gerrit.server.project.ChangeControl;
|
||||||
|
import com.google.gerrit.server.project.NoSuchChangeException;
|
||||||
|
import com.google.gerrit.server.project.NoSuchProjectException;
|
||||||
|
import com.google.gerrit.server.project.ProjectCache;
|
||||||
|
import com.google.gerrit.server.project.ProjectState;
|
||||||
|
import com.google.gerrit.server.query.OperatorPredicate;
|
||||||
import com.google.gerrit.server.query.OrPredicate;
|
import com.google.gerrit.server.query.OrPredicate;
|
||||||
import com.google.gerrit.server.query.Predicate;
|
import com.google.gerrit.server.query.Predicate;
|
||||||
import com.google.gwtorm.server.OrmException;
|
import com.google.gwtorm.server.OrmException;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
|
||||||
|
import org.eclipse.jgit.lib.AnyObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Constants;
|
||||||
|
import org.eclipse.jgit.lib.ObjectId;
|
||||||
|
import org.eclipse.jgit.lib.Ref;
|
||||||
|
import org.eclipse.jgit.lib.Repository;
|
||||||
|
import org.eclipse.jgit.revwalk.RevCommit;
|
||||||
|
import org.eclipse.jgit.revwalk.RevFlag;
|
||||||
|
import org.eclipse.jgit.revwalk.RevWalk;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
class ConflictsPredicate extends OrPredicate<ChangeData> {
|
class ConflictsPredicate extends OrPredicate<ChangeData> {
|
||||||
private final String value;
|
private final String value;
|
||||||
|
|
||||||
ConflictsPredicate(Provider<ReviewDb> db, PatchListCache plc, String value,
|
ConflictsPredicate(Provider<ReviewDb> db, PatchListCache plc,
|
||||||
List<Change> changes) throws OrmException {
|
SubmitStrategyFactory submitStrategyFactory,
|
||||||
super(predicates(db, plc, changes));
|
ChangeControl.GenericFactory changeControlFactory,
|
||||||
|
IdentifiedUser.GenericFactory identifiedUserFactory,
|
||||||
|
GitRepositoryManager repoManager, ProjectCache projectCache,
|
||||||
|
ConflictsCache conflictsCache, String value, List<Change> changes)
|
||||||
|
throws OrmException {
|
||||||
|
super(predicates(db, plc, submitStrategyFactory, changeControlFactory,
|
||||||
|
identifiedUserFactory, repoManager, projectCache, conflictsCache,
|
||||||
|
value, changes));
|
||||||
this.value = value;
|
this.value = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static List<Predicate<ChangeData>> predicates(Provider<ReviewDb> db,
|
private static List<Predicate<ChangeData>> predicates(
|
||||||
PatchListCache plc, List<Change> changes) throws OrmException {
|
final Provider<ReviewDb> db, final PatchListCache plc,
|
||||||
|
final SubmitStrategyFactory submitStrategyFactory,
|
||||||
|
final ChangeControl.GenericFactory changeControlFactory,
|
||||||
|
final IdentifiedUser.GenericFactory identifiedUserFactory,
|
||||||
|
final GitRepositoryManager repoManager, final ProjectCache projectCache,
|
||||||
|
final ConflictsCache conflictsCache, final String value,
|
||||||
|
List<Change> changes) throws OrmException {
|
||||||
List<Predicate<ChangeData>> changePredicates =
|
List<Predicate<ChangeData>> changePredicates =
|
||||||
Lists.newArrayListWithCapacity(changes.size());
|
Lists.newArrayListWithCapacity(changes.size());
|
||||||
for (Change c : changes) {
|
for (final Change c : changes) {
|
||||||
|
final ChangeDataCache changeDataCache = new ChangeDataCache(c, db, projectCache);
|
||||||
List<String> files = new ChangeData(c).currentFilePaths(db, plc);
|
List<String> files = new ChangeData(c).currentFilePaths(db, plc);
|
||||||
List<Predicate<ChangeData>> filePredicates =
|
List<Predicate<ChangeData>> filePredicates =
|
||||||
Lists.newArrayListWithCapacity(files.size());
|
Lists.newArrayListWithCapacity(files.size());
|
||||||
@@ -47,7 +88,7 @@ class ConflictsPredicate extends OrPredicate<ChangeData> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
List<Predicate<ChangeData>> predicatesForOneChange =
|
List<Predicate<ChangeData>> predicatesForOneChange =
|
||||||
Lists.newArrayListWithCapacity(4);
|
Lists.newArrayListWithCapacity(5);
|
||||||
predicatesForOneChange.add(
|
predicatesForOneChange.add(
|
||||||
not(new LegacyChangeIdPredicate(db, c.getId())));
|
not(new LegacyChangeIdPredicate(db, c.getId())));
|
||||||
predicatesForOneChange.add(
|
predicatesForOneChange.add(
|
||||||
@@ -55,7 +96,115 @@ class ConflictsPredicate extends OrPredicate<ChangeData> {
|
|||||||
predicatesForOneChange.add(
|
predicatesForOneChange.add(
|
||||||
new RefPredicate(db, c.getDest().get()));
|
new RefPredicate(db, c.getDest().get()));
|
||||||
predicatesForOneChange.add(or(filePredicates));
|
predicatesForOneChange.add(or(filePredicates));
|
||||||
|
predicatesForOneChange.add(new OperatorPredicate<ChangeData>(
|
||||||
|
ChangeQueryBuilder.FIELD_CONFLICTS, value) {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean match(ChangeData object) throws OrmException {
|
||||||
|
Change otherChange = object.change(db);
|
||||||
|
if (otherChange == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!otherChange.getDest().equals(c.getDest())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
SubmitType submitType = getSubmitType(otherChange, object);
|
||||||
|
if (submitType == null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
ObjectId other = ObjectId.fromString(
|
||||||
|
object.currentPatchSet(db).getRevision().get());
|
||||||
|
ConflictKey conflictsKey =
|
||||||
|
new ConflictKey(changeDataCache.getTestAgainst(), other, submitType,
|
||||||
|
changeDataCache.getProjectState().isUseContentMerge());
|
||||||
|
Boolean conflicts = conflictsCache.getIfPresent(conflictsKey);
|
||||||
|
if (conflicts != null) {
|
||||||
|
return conflicts;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
Repository repo =
|
||||||
|
repoManager.openRepository(otherChange.getProject());
|
||||||
|
try {
|
||||||
|
RevWalk rw = new RevWalk(repo) {
|
||||||
|
@Override
|
||||||
|
protected RevCommit createCommit(AnyObjectId id) {
|
||||||
|
return new CodeReviewCommit(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
try {
|
||||||
|
RevFlag canMergeFlag = rw.newFlag("CAN_MERGE");
|
||||||
|
CodeReviewCommit commit =
|
||||||
|
(CodeReviewCommit) rw.parseCommit(changeDataCache.getTestAgainst());
|
||||||
|
SubmitStrategy strategy =
|
||||||
|
submitStrategyFactory.create(submitType,
|
||||||
|
db.get(), repo, rw, null, canMergeFlag,
|
||||||
|
getAlreadyAccepted(repo, rw, commit),
|
||||||
|
otherChange.getDest());
|
||||||
|
CodeReviewCommit otherCommit =
|
||||||
|
(CodeReviewCommit) rw.parseCommit(other);
|
||||||
|
otherCommit.add(canMergeFlag);
|
||||||
|
conflicts = !strategy.dryRun(commit, otherCommit);
|
||||||
|
conflictsCache.put(conflictsKey, conflicts);
|
||||||
|
return conflicts;
|
||||||
|
} catch (MergeException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} catch (NoSuchProjectException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} finally {
|
||||||
|
rw.release();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
repo.close();
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCost() {
|
||||||
|
return 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
private SubmitType getSubmitType(Change change, ChangeData cd) throws OrmException {
|
||||||
|
try {
|
||||||
|
final SubmitTypeRecord r =
|
||||||
|
changeControlFactory.controlFor(change,
|
||||||
|
identifiedUserFactory.create(change.getOwner()))
|
||||||
|
.getSubmitTypeRecord(db.get(), cd.currentPatchSet(db), cd);
|
||||||
|
if (r.status != SubmitTypeRecord.Status.OK) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
return r.type;
|
||||||
|
} catch (NoSuchChangeException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<RevCommit> getAlreadyAccepted(Repository repo, RevWalk rw,
|
||||||
|
CodeReviewCommit tip) throws MergeException {
|
||||||
|
Set<RevCommit> alreadyAccepted = Sets.newHashSet();
|
||||||
|
|
||||||
|
if (tip != null) {
|
||||||
|
alreadyAccepted.add(tip);
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (ObjectId id : changeDataCache.getAlreadyAccepted(repo)) {
|
||||||
|
try {
|
||||||
|
alreadyAccepted.add(rw.parseCommit(id));
|
||||||
|
} catch (IncorrectObjectTypeException iote) {
|
||||||
|
// Not a commit? Skip over it.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new MergeException(
|
||||||
|
"Failed to determine already accepted commits.", e);
|
||||||
|
}
|
||||||
|
|
||||||
|
return alreadyAccepted;
|
||||||
|
}
|
||||||
|
});
|
||||||
changePredicates.add(and(predicatesForOneChange));
|
changePredicates.add(and(predicatesForOneChange));
|
||||||
}
|
}
|
||||||
return changePredicates;
|
return changePredicates;
|
||||||
@@ -65,4 +214,55 @@ class ConflictsPredicate extends OrPredicate<ChangeData> {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return ChangeQueryBuilder.FIELD_CONFLICTS + ":" + value;
|
return ChangeQueryBuilder.FIELD_CONFLICTS + ":" + value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static class ChangeDataCache {
|
||||||
|
private final Change change;
|
||||||
|
private final Provider<ReviewDb> db;
|
||||||
|
private final ProjectCache projectCache;
|
||||||
|
|
||||||
|
private ObjectId testAgainst;
|
||||||
|
private ProjectState projectState;
|
||||||
|
private Set<ObjectId> alreadyAccepted;
|
||||||
|
|
||||||
|
ChangeDataCache(Change change, Provider<ReviewDb> db, ProjectCache projectCache) {
|
||||||
|
this.change = change;
|
||||||
|
this.db = db;
|
||||||
|
this.projectCache = projectCache;
|
||||||
|
}
|
||||||
|
|
||||||
|
ObjectId getTestAgainst()
|
||||||
|
throws OrmException {
|
||||||
|
if (testAgainst == null) {
|
||||||
|
testAgainst = ObjectId.fromString(
|
||||||
|
new ChangeData(change).currentPatchSet(db).getRevision().get());
|
||||||
|
}
|
||||||
|
return testAgainst;
|
||||||
|
}
|
||||||
|
|
||||||
|
ProjectState getProjectState() {
|
||||||
|
if (projectState == null) {
|
||||||
|
projectState = projectCache.get(change.getProject());
|
||||||
|
if (projectState == null) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
new NoSuchProjectException(change.getProject()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return projectState;
|
||||||
|
}
|
||||||
|
|
||||||
|
Set<ObjectId> getAlreadyAccepted(Repository repo) {
|
||||||
|
if (alreadyAccepted == null) {
|
||||||
|
alreadyAccepted = Sets.newHashSet();
|
||||||
|
for (Ref r : repo.getAllRefs().values()) {
|
||||||
|
if (r.getName().startsWith(Constants.R_HEADS)
|
||||||
|
|| r.getName().startsWith(Constants.R_TAGS)) {
|
||||||
|
if (r.getObjectId() != null) {
|
||||||
|
alreadyAccepted.add(r.getObjectId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return alreadyAccepted;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ public class FakeQueryBuilder extends ChangeQueryBuilder {
|
|||||||
new FakeQueryBuilder.Definition<ChangeData, FakeQueryBuilder>(
|
new FakeQueryBuilder.Definition<ChangeData, FakeQueryBuilder>(
|
||||||
FakeQueryBuilder.class),
|
FakeQueryBuilder.class),
|
||||||
new ChangeQueryBuilder.Arguments(null, null, null, null, null, null,
|
new ChangeQueryBuilder.Arguments(null, null, null, null, null, null,
|
||||||
null, null, null, null, null, null, null, indexes),
|
null, null, null, null, null, null, null, indexes, null, null),
|
||||||
null);
|
null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user