Merge "Leave comments for deleted @Column fields"
diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs
index 3cc353b..b0cf0cb 100644
--- a/.settings/org.eclipse.jdt.core.prefs
+++ b/.settings/org.eclipse.jdt.core.prefs
@@ -33,7 +33,7 @@
org.eclipse.jdt.core.compiler.problem.missingDefaultCase=ignore
org.eclipse.jdt.core.compiler.problem.missingDeprecatedAnnotation=ignore
org.eclipse.jdt.core.compiler.problem.missingEnumCaseDespiteDefault=disabled
-org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=ignore
+org.eclipse.jdt.core.compiler.problem.missingHashCodeMethod=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotation=warning
org.eclipse.jdt.core.compiler.problem.missingOverrideAnnotationForInterfaceMethodImplementation=enabled
org.eclipse.jdt.core.compiler.problem.missingSerialVersion=warning
@@ -48,12 +48,12 @@
org.eclipse.jdt.core.compiler.problem.nullUncheckedConversion=warning
org.eclipse.jdt.core.compiler.problem.overridingPackageDefaultMethod=warning
org.eclipse.jdt.core.compiler.problem.parameterAssignment=ignore
-org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=ignore
+org.eclipse.jdt.core.compiler.problem.possibleAccidentalBooleanAssignment=warning
org.eclipse.jdt.core.compiler.problem.potentialNullReference=ignore
org.eclipse.jdt.core.compiler.problem.potentiallyUnclosedCloseable=ignore
org.eclipse.jdt.core.compiler.problem.rawTypeReference=warning
org.eclipse.jdt.core.compiler.problem.redundantNullAnnotation=warning
-org.eclipse.jdt.core.compiler.problem.redundantNullCheck=ignore
+org.eclipse.jdt.core.compiler.problem.redundantNullCheck=warning
org.eclipse.jdt.core.compiler.problem.redundantSpecificationOfTypeArguments=warning
org.eclipse.jdt.core.compiler.problem.redundantSuperinterface=ignore
org.eclipse.jdt.core.compiler.problem.reportMethodCanBePotentiallyStatic=ignore
diff --git a/Documentation/rest-api-changes.txt b/Documentation/rest-api-changes.txt
index d86e3bd..19ad9f6 100644
--- a/Documentation/rest-api-changes.txt
+++ b/Documentation/rest-api-changes.txt
@@ -2154,9 +2154,6 @@
If the `other-branches` parameter is specified, the mergeability will also be
checked for all other branches.
-If the `force` parameter is specified, the mergeability against the destination
-will be rechecked, in case of prior transient failures or bugs.
-
.Request
----
GET /changes/myProject~master~I8473b95934b5732ac55d26311a706c9c2bde9940/revisions/current/mergeable?other-branches HTTP/1.0
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
index 1d904bd..b6f52f4 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/revision/RevisionIT.java
@@ -121,7 +121,7 @@
@Test
public void cherryPick() throws Exception {
- PushOneCommit.Result r = createChange();
+ PushOneCommit.Result r = pushTo("refs/for/master%topic=someTopic");
CherryPickInput in = new CherryPickInput();
in.destination = "foo";
in.message = "it goes to stable branch";
@@ -138,6 +138,7 @@
assertEquals(2, orig.get().messages.size());
assertTrue(cherry.get().subject.contains(in.message));
+ assertEquals("someTopic", cherry.get().topic);
cherry.current().review(ReviewInput.approve());
cherry.current().submit();
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java
index 6c7423c..3afa208 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/diff/LineMapper.java
@@ -17,6 +17,7 @@
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Objects;
/** Helper class to handle calculations involving line gaps. */
class LineMapper {
@@ -193,6 +194,11 @@
}
@Override
+ public int hashCode() {
+ return Objects.hash(this);
+ }
+
+ @Override
public String toString() {
return line + " " + aligned;
}
diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/BatchProgramModule.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/BatchProgramModule.java
index 91ffa91..2ee2450 100644
--- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/BatchProgramModule.java
+++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/util/BatchProgramModule.java
@@ -30,7 +30,7 @@
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.cache.h2.DefaultCacheFactory;
import com.google.gerrit.server.change.ChangeKindCacheImpl;
-import com.google.gerrit.server.change.MergeabilityCache;
+import com.google.gerrit.server.change.MergeabilityCacheImpl;
import com.google.gerrit.server.change.PatchSetInserter;
import com.google.gerrit.server.config.CanonicalWebUrl;
import com.google.gerrit.server.config.CanonicalWebUrlProvider;
@@ -111,7 +111,7 @@
install(SectionSortCache.module());
install(ChangeKindCacheImpl.module());
install(ChangeCache.module());
- install(MergeabilityCache.module());
+ install(MergeabilityCacheImpl.module());
install(TagCache.module());
factory(CapabilityControl.Factory.class);
factory(ChangeData.Factory.class);
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml b/gerrit-plugin-gwt-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
index b443c4d..575f4ac 100644
--- a/gerrit-plugin-gwt-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/META-INF/maven/archetype-metadata.xml
@@ -51,6 +51,18 @@
</includes>
</fileSet>
+ <fileSet filtered="true">
+ <directory></directory>
+ <include>.buckconfig</include>
+ <include>BUCK</include>
+ <include>VERSION</include>
+ <include>lib/gerrit/BUCK</include>
+ <include>lib/gwt/BUCK</include>
+ <excludes>
+ <exclude>**/*.java</exclude>
+ </excludes>
+ </fileSet>
+
<fileSet>
<directory></directory>
<includes>
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.buckconfig b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.buckconfig
new file mode 100644
index 0000000..1044c12
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.buckconfig
@@ -0,0 +1,14 @@
+[alias]
+ ${pluginName} = //:${pluginName}
+ plugin = //:${pluginName}
+
+[java]
+ src_roots = java, resources
+
+[project]
+ ignore = .git
+
+[cache]
+ mode = dir
+ dir = buck-out/cache
+
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.gitignore b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.gitignore
index 80d6257..43838b0 100644
--- a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.gitignore
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/.gitignore
@@ -1,3 +1,7 @@
+/.buckversion
+/.buckd
+/buck-out
+/bucklets
/target
/.classpath
/.project
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/BUCK b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/BUCK
new file mode 100644
index 0000000..b19312c
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/BUCK
@@ -0,0 +1,23 @@
+include_defs('//bucklets/gerrit_plugin.bucklet')
+
+gerrit_plugin(
+ name = '${pluginName}',
+ srcs = glob(['src/main/java/**/*.java']),
+ resources = glob(['src/main/**/*']),
+ gwt_module = '${package}.HelloPlugin',
+ manifest_entries = [
+ 'Gerrit-PluginName: ${pluginName}',
+ 'Gerrit-ApiType: plugin',
+ 'Gerrit-ApiVersion: ${gerritApiVersion}',
+ 'Gerrit-Module: ${package}.Module',
+ 'Gerrit-SshModule: ${package}.SshModule',
+ 'Gerrit-HttpModule: ${package}.HttpModule',
+ ],
+)
+
+# this is required for bucklets/tools/eclipse/project.py to work
+java_library(
+ name = 'classpath',
+ deps = [':${pluginName}__plugin'],
+)
+
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/VERSION b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/VERSION
new file mode 100644
index 0000000..8bbb460
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/VERSION
@@ -0,0 +1,5 @@
+# Used by BUCK to include "Implementation-Version" in plugin Manifest.
+# If this file doesn't exist the output of 'git describe' is used
+# instead.
+PLUGIN_VERSION = '${version}'
+
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gerrit/BUCK b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gerrit/BUCK
new file mode 100644
index 0000000..0a0d8b9
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gerrit/BUCK
@@ -0,0 +1,20 @@
+include_defs('//bucklets/maven_jar.bucklet')
+
+VER = '${gerritApiVersion}'
+REPO = MAVEN_LOCAL
+
+maven_jar(
+ name = 'plugin-api',
+ id = 'com.google.gerrit:gerrit-plugin-api:' + VER,
+ attach_source = False,
+ repository = REPO,
+ license = 'Apache2.0',
+)
+
+maven_jar(
+ name = 'gwtui-api',
+ id = 'com.google.gerrit:gerrit-plugin-gwtui:' + VER,
+ attach_source = False,
+ repository = REPO,
+ license = 'Apache2.0',
+)
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gwt/BUCK b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gwt/BUCK
new file mode 100644
index 0000000..511a8ec
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/lib/gwt/BUCK
@@ -0,0 +1,32 @@
+include_defs('//bucklets/maven_jar.bucklet')
+
+VERSION = '${Gwt-Version}'
+
+maven_jar(
+ name = 'user',
+ id = 'com.google.gwt:gwt-user:' + VERSION,
+ license = 'Apache2.0',
+ attach_source = False,
+)
+
+maven_jar(
+ name = 'dev',
+ id = 'com.google.gwt:gwt-dev:' + VERSION,
+ license = 'Apache2.0',
+ deps = [
+ ':javax-validation',
+ ':javax-validation_src',
+ ],
+ attach_source = False,
+ exclude = ['org/eclipse/jetty/*'],
+)
+
+maven_jar(
+ name = 'javax-validation',
+ id = 'javax.validation:validation-api:1.0.0.GA',
+ bin_sha1 = 'b6bd7f9d78f6fdaa3c37dae18a4bd298915f328e',
+ src_sha1 = '7a561191db2203550fbfa40d534d4997624cd369',
+ license = 'Apache2.0',
+ visibility = [],
+)
+
diff --git a/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/resources/Documentation/build.md b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/resources/Documentation/build.md
new file mode 100644
index 0000000..4c56ed6
--- /dev/null
+++ b/gerrit-plugin-gwt-archetype/src/main/resources/archetype-resources/src/main/resources/Documentation/build.md
@@ -0,0 +1,77 @@
+Build
+=====
+
+This plugin can be built with Buck or Maven.
+
+Buck
+----
+
+Two build modes are supported: Standalone and in Gerrit tree.
+The standalone build mode is recommended, as this mode doesn't require
+the Gerrit tree to exist locally.
+
+
+
+Clone bucklets library:
+
+```
+ git clone https://gerrit.googlesource.com/bucklets
+
+```
+and link it to @PLUGIN@ plugin directory:
+
+```
+ cd @PLUGIN@ && ln -s ../bucklets .
+```
+
+Add link to the .buckversion file:
+
+```
+ cd @PLUGIN@ && ln -s bucklets/buckversion .buckversion
+```
+
+To build the plugin, issue the following command:
+
+
+```
+ buck build plugin
+```
+
+The output is created in
+
+```
+ buck-out/gen/@PLUGIN@.jar
+```
+
+
+Clone or link this plugin to the plugins directory of Gerrit's source
+tree, and issue the command:
+
+```
+ buck build plugins/@PLUGIN@
+```
+
+The output is created in
+
+```
+ buck-out/gen/plugins/@PLUGIN@/@PLUGIN@.jar
+```
+
+This project can be imported into the Eclipse IDE:
+
+```
+ ./tools/eclipse/project.py
+```
+
+Maven
+-----
+
+Note that the Maven build is provided for compatibility reasons, but
+it is considered to be deprecated and will be removed in a future
+version of this plugin.
+
+To build with Maven, run
+
+```
+mvn clean package
+```
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
index 3d52845..b97cf05 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/CherryPickChange.java
@@ -113,7 +113,8 @@
"Cherry Pick: Destination branch cannot be null or empty");
}
- Project.NameKey project = db.get().changes().get(changeId).getProject();
+ Change change = db.get().changes().get(changeId);
+ Project.NameKey project = change.getProject();
IdentifiedUser identifiedUser = (IdentifiedUser) currentUser.get();
final Repository git;
try {
@@ -188,7 +189,7 @@
// Change key not found on destination branch. We can create a new
// change.
return createNewChange(git, revWalk, changeKey, project, patchSetId, destRef,
- cherryPickCommit, refControl, identifiedUser);
+ cherryPickCommit, refControl, identifiedUser, change.getTopic());
}
} finally {
revWalk.release();
@@ -221,12 +222,13 @@
private Change.Id createNewChange(Repository git, RevWalk revWalk,
Change.Key changeKey, Project.NameKey project, PatchSet.Id patchSetId,
Ref destRef, RevCommit cherryPickCommit, RefControl refControl,
- IdentifiedUser identifiedUser)
+ IdentifiedUser identifiedUser, String topic)
throws OrmException, InvalidChangeOperationException, IOException {
Change change =
new Change(changeKey, new Change.Id(db.get().nextChangeId()),
identifiedUser.getAccountId(), new Branch.NameKey(project,
destRef.getName()), TimeUtil.nowTs());
+ change.setTopic(topic);
ChangeInserter ins =
changeInserterFactory.create(refControl, change, cherryPickCommit);
PatchSet newPatchSet = ins.getPatchSet();
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCache.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCache.java
index 7589ea5..584a81b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCache.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCache.java
@@ -14,309 +14,34 @@
package com.google.gerrit.server.change;
-import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.base.Preconditions.checkState;
-import static com.google.gerrit.server.ioutil.BasicSerialization.readString;
-import static com.google.gerrit.server.ioutil.BasicSerialization.writeString;
-import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
-import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
-
-import com.google.common.base.MoreObjects;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.cache.Weigher;
-import com.google.common.collect.BiMap;
-import com.google.common.collect.ImmutableBiMap;
-import com.google.common.collect.Sets;
import com.google.gerrit.extensions.common.SubmitType;
import com.google.gerrit.reviewdb.client.Branch;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.cache.CacheModule;
-import com.google.gerrit.server.git.CodeReviewCommit;
-import com.google.gerrit.server.git.MergeException;
-import com.google.gerrit.server.git.strategy.SubmitStrategyFactory;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.inject.Inject;
-import com.google.inject.Key;
-import com.google.inject.Module;
-import com.google.inject.Singleton;
-import com.google.inject.TypeLiteral;
-import com.google.inject.name.Named;
-import com.google.inject.name.Names;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
-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 org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import java.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.Arrays;
-import java.util.Collection;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.concurrent.ExecutionException;
-
-@Singleton
-public class MergeabilityCache {
- private static final Logger log =
- LoggerFactory.getLogger(MergeabilityCache.class);
-
- private static final String CACHE_NAME = "mergeability";
-
- public static final BiMap<SubmitType, Character> SUBMIT_TYPES = ImmutableBiMap.of(
- SubmitType.FAST_FORWARD_ONLY, 'F',
- SubmitType.MERGE_IF_NECESSARY, 'M',
- SubmitType.REBASE_IF_NECESSARY, 'R',
- SubmitType.MERGE_ALWAYS, 'A',
- SubmitType.CHERRY_PICK, 'C');
-
- static {
- checkState(SUBMIT_TYPES.size() == SubmitType.values().length,
- "SubmitType <-> char BiMap needs updating");
- }
-
- @SuppressWarnings("rawtypes")
- public static Key bindingKey() {
- return Key.get(new TypeLiteral<LoadingCache<EntryKey, Boolean>>() {},
- Names.named(CACHE_NAME));
- }
-
- public static Module module() {
- return new CacheModule() {
- @Override
- protected void configure() {
- persist(CACHE_NAME, EntryKey.class, Boolean.class)
- .maximumWeight(1 << 20)
- .weigher(MergeabilityWeigher.class)
- .loader(Loader.class);
- bind(MergeabilityCache.class);
- }
- };
- }
-
- public static ObjectId toId(Ref ref) {
- return ref != null && ref.getObjectId() != null
- ? ref.getObjectId()
- : ObjectId.zeroId();
- }
-
- public static class EntryKey implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private ObjectId commit;
- private ObjectId into;
- private SubmitType submitType;
- private String mergeStrategy;
-
- // Only used for loading, not stored.
- private transient LoadHelper load;
-
- public EntryKey(ObjectId commit, ObjectId into, SubmitType submitType,
- String mergeStrategy) {
- this.commit = checkNotNull(commit, "commit");
- this.into = checkNotNull(into, "into");
- this.submitType = checkNotNull(submitType, "submitType");
- this.mergeStrategy = checkNotNull(mergeStrategy, "mergeStrategy");
- }
-
- private EntryKey(ObjectId commit, ObjectId into, SubmitType submitType,
+/** Cache for mergeability of commits into destination branches. */
+public interface MergeabilityCache {
+ public static class NotImplemented implements MergeabilityCache {
+ @Override
+ public boolean get(ObjectId commit, Ref intoRef, SubmitType submitType,
String mergeStrategy, Branch.NameKey dest, Repository repo,
ReviewDb db) {
- this(commit, into, submitType, mergeStrategy);
- load = new LoadHelper(dest, repo, db);
- }
-
- public ObjectId getCommit() {
- return commit;
- }
-
- public ObjectId getInto() {
- return into;
- }
-
- public SubmitType getSubmitType() {
- return submitType;
- }
-
- public String getMergeStrategy() {
- return mergeStrategy;
+ throw new UnsupportedOperationException("Mergeability checking disabled");
}
@Override
- public boolean equals(Object o) {
- if (o instanceof EntryKey) {
- EntryKey k = (EntryKey) o;
- return commit.equals(k.commit)
- && into.equals(k.into)
- && submitType == k.submitType
- && mergeStrategy.equals(k.mergeStrategy);
- }
- return false;
+ public boolean getIfPresent(ObjectId commit, Ref intoRef,
+ SubmitType submitType, String mergeStrategy) {
+ throw new UnsupportedOperationException("Mergeability checking disabled");
}
-
- @Override
- public int hashCode() {
- return Objects.hash(commit, into, submitType, mergeStrategy);
- }
-
- @Override
- public String toString() {
- return MoreObjects.toStringHelper(this)
- .add("commit", commit.name())
- .add("into", into.name())
- .addValue(submitType)
- .addValue(mergeStrategy)
- .toString();
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
- writeNotNull(out, commit);
- writeNotNull(out, into);
- Character c = SUBMIT_TYPES.get(submitType);
- if (c == null) {
- throw new IOException("Invalid submit type: " + submitType);
- }
- out.writeChar(c);
- writeString(out, mergeStrategy);
- }
-
- private void readObject(ObjectInputStream in) throws IOException {
- commit = readNotNull(in);
- into = readNotNull(in);
- char t = in.readChar();
- submitType = SUBMIT_TYPES.inverse().get(t);
- if (submitType == null) {
- throw new IOException("Invalid submit type code: " + t);
- }
- mergeStrategy = readString(in);
- }
- }
-
- private static class LoadHelper {
- private final Branch.NameKey dest;
- private final Repository repo;
- private final ReviewDb db;
-
- private LoadHelper(Branch.NameKey dest, Repository repo, ReviewDb db) {
- this.dest = checkNotNull(dest, "dest");
- this.repo = checkNotNull(repo, "repo");
- this.db = checkNotNull(db, "db");
- }
- }
-
- @Singleton
- public static class Loader extends CacheLoader<EntryKey, Boolean> {
- private final SubmitStrategyFactory submitStrategyFactory;
-
- @Inject
- Loader(SubmitStrategyFactory submitStrategyFactory) {
- this.submitStrategyFactory = submitStrategyFactory;
- }
-
- @Override
- public Boolean load(EntryKey key)
- throws NoSuchProjectException, MergeException, IOException {
- checkArgument(key.load != null, "Key cannot be loaded: %s", key);
- if (key.into.equals(ObjectId.zeroId())) {
- return true; // Assume yes on new branch.
- }
- try {
- Map<String, Ref> refs = key.load.repo.getAllRefs();
- RevWalk rw = CodeReviewCommit.newRevWalk(key.load.repo);
- try {
- RevFlag canMerge = rw.newFlag("CAN_MERGE");
- CodeReviewCommit rev = parse(rw, key.commit);
- rev.add(canMerge);
- CodeReviewCommit tip = parse(rw, key.into);
- Set<RevCommit> accepted = alreadyAccepted(rw, refs.values());
- accepted.add(tip);
- accepted.addAll(Arrays.asList(rev.getParents()));
- return submitStrategyFactory.create(
- key.submitType,
- key.load.db,
- key.load.repo,
- rw,
- null /*inserter*/,
- canMerge,
- accepted,
- key.load.dest).dryRun(tip, rev);
- } finally {
- rw.release();
- }
- } finally {
- key.load = null;
- }
- }
-
- private static Set<RevCommit> alreadyAccepted(RevWalk rw,
- Collection<Ref> refs) throws MissingObjectException, IOException {
- Set<RevCommit> accepted = Sets.newHashSet();
- for (Ref r : refs) {
- if (r.getName().startsWith(Constants.R_HEADS)
- || r.getName().startsWith(Constants.R_TAGS)) {
- try {
- accepted.add(rw.parseCommit(r.getObjectId()));
- } catch (IncorrectObjectTypeException nonCommit) {
- // Not a commit? Skip over it.
- }
- }
- }
- return accepted;
- }
-
- private static CodeReviewCommit parse(RevWalk rw, ObjectId id)
- throws MissingObjectException, IncorrectObjectTypeException,
- IOException {
- return (CodeReviewCommit) rw.parseCommit(id);
- }
- }
-
- public static class MergeabilityWeigher
- implements Weigher<EntryKey, Boolean> {
- @Override
- public int weigh(EntryKey k, Boolean v) {
- return 16 + 2 * (16 + 20) + 3 * 8 // Size of EntryKey, 64-bit JVM.
- + 8; // Size of Boolean.
- }
- }
-
- private final LoadingCache<EntryKey, Boolean> cache;
-
- @Inject
- MergeabilityCache(@Named(CACHE_NAME) LoadingCache<EntryKey, Boolean> cache) {
- this.cache = cache;
}
public boolean get(ObjectId commit, Ref intoRef, SubmitType submitType,
- String mergeStrategy, Branch.NameKey dest, Repository repo, ReviewDb db) {
- ObjectId into = intoRef != null ? intoRef.getObjectId() : ObjectId.zeroId();
- EntryKey key =
- new EntryKey(commit, into, submitType, mergeStrategy, dest, repo, db);
- try {
- return cache.get(key);
- } catch (ExecutionException e) {
- log.error(String.format("Error checking mergeability of %s into %s (%s)",
- key.commit.name(), key.into.name(), key.submitType.name()),
- e.getCause());
- return false;
- }
- }
+ String mergeStrategy, Branch.NameKey dest, Repository repo, ReviewDb db);
public boolean getIfPresent(ObjectId commit, Ref intoRef,
- SubmitType submitType, String mergeStrategy) {
- return cache.getIfPresent(new EntryKey(
- commit, toId(intoRef), submitType, mergeStrategy, null, null, null));
- }
+ SubmitType submitType, String mergeStrategy);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
new file mode 100644
index 0000000..31b2aa0
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/MergeabilityCacheImpl.java
@@ -0,0 +1,315 @@
+// Copyright (C) 2014 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.change;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Preconditions.checkState;
+import static com.google.gerrit.server.ioutil.BasicSerialization.readString;
+import static com.google.gerrit.server.ioutil.BasicSerialization.writeString;
+import static org.eclipse.jgit.lib.ObjectIdSerialization.readNotNull;
+import static org.eclipse.jgit.lib.ObjectIdSerialization.writeNotNull;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.cache.Weigher;
+import com.google.common.collect.BiMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.Sets;
+import com.google.gerrit.extensions.common.SubmitType;
+import com.google.gerrit.reviewdb.client.Branch;
+import com.google.gerrit.reviewdb.server.ReviewDb;
+import com.google.gerrit.server.cache.CacheModule;
+import com.google.gerrit.server.git.CodeReviewCommit;
+import com.google.gerrit.server.git.MergeException;
+import com.google.gerrit.server.git.strategy.SubmitStrategyFactory;
+import com.google.gerrit.server.project.NoSuchProjectException;
+import com.google.inject.Inject;
+import com.google.inject.Module;
+import com.google.inject.Singleton;
+import com.google.inject.name.Named;
+
+import org.eclipse.jgit.errors.IncorrectObjectTypeException;
+import org.eclipse.jgit.errors.MissingObjectException;
+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 org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+
+@Singleton
+public class MergeabilityCacheImpl implements MergeabilityCache {
+ private static final Logger log =
+ LoggerFactory.getLogger(MergeabilityCacheImpl.class);
+
+ private static final String CACHE_NAME = "mergeability";
+
+ public static final BiMap<SubmitType, Character> SUBMIT_TYPES = ImmutableBiMap.of(
+ SubmitType.FAST_FORWARD_ONLY, 'F',
+ SubmitType.MERGE_IF_NECESSARY, 'M',
+ SubmitType.REBASE_IF_NECESSARY, 'R',
+ SubmitType.MERGE_ALWAYS, 'A',
+ SubmitType.CHERRY_PICK, 'C');
+
+ static {
+ checkState(SUBMIT_TYPES.size() == SubmitType.values().length,
+ "SubmitType <-> char BiMap needs updating");
+ }
+
+ public static Module module() {
+ return new CacheModule() {
+ @Override
+ protected void configure() {
+ persist(CACHE_NAME, EntryKey.class, Boolean.class)
+ .maximumWeight(1 << 20)
+ .weigher(MergeabilityWeigher.class)
+ .loader(Loader.class);
+ bind(MergeabilityCache.class).to(MergeabilityCacheImpl.class);
+ }
+ };
+ }
+
+ public static ObjectId toId(Ref ref) {
+ return ref != null && ref.getObjectId() != null
+ ? ref.getObjectId()
+ : ObjectId.zeroId();
+ }
+
+ public static class EntryKey implements Serializable {
+ private static final long serialVersionUID = 1L;
+
+ private ObjectId commit;
+ private ObjectId into;
+ private SubmitType submitType;
+ private String mergeStrategy;
+
+ // Only used for loading, not stored.
+ private transient LoadHelper load;
+
+ public EntryKey(ObjectId commit, ObjectId into, SubmitType submitType,
+ String mergeStrategy) {
+ this.commit = checkNotNull(commit, "commit");
+ this.into = checkNotNull(into, "into");
+ this.submitType = checkNotNull(submitType, "submitType");
+ this.mergeStrategy = checkNotNull(mergeStrategy, "mergeStrategy");
+ }
+
+ private EntryKey(ObjectId commit, ObjectId into, SubmitType submitType,
+ String mergeStrategy, Branch.NameKey dest, Repository repo,
+ ReviewDb db) {
+ this(commit, into, submitType, mergeStrategy);
+ load = new LoadHelper(dest, repo, db);
+ }
+
+ public ObjectId getCommit() {
+ return commit;
+ }
+
+ public ObjectId getInto() {
+ return into;
+ }
+
+ public SubmitType getSubmitType() {
+ return submitType;
+ }
+
+ public String getMergeStrategy() {
+ return mergeStrategy;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (o instanceof EntryKey) {
+ EntryKey k = (EntryKey) o;
+ return commit.equals(k.commit)
+ && into.equals(k.into)
+ && submitType == k.submitType
+ && mergeStrategy.equals(k.mergeStrategy);
+ }
+ return false;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(commit, into, submitType, mergeStrategy);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this)
+ .add("commit", commit.name())
+ .add("into", into.name())
+ .addValue(submitType)
+ .addValue(mergeStrategy)
+ .toString();
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+ writeNotNull(out, commit);
+ writeNotNull(out, into);
+ Character c = SUBMIT_TYPES.get(submitType);
+ if (c == null) {
+ throw new IOException("Invalid submit type: " + submitType);
+ }
+ out.writeChar(c);
+ writeString(out, mergeStrategy);
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException {
+ commit = readNotNull(in);
+ into = readNotNull(in);
+ char t = in.readChar();
+ submitType = SUBMIT_TYPES.inverse().get(t);
+ if (submitType == null) {
+ throw new IOException("Invalid submit type code: " + t);
+ }
+ mergeStrategy = readString(in);
+ }
+ }
+
+ private static class LoadHelper {
+ private final Branch.NameKey dest;
+ private final Repository repo;
+ private final ReviewDb db;
+
+ private LoadHelper(Branch.NameKey dest, Repository repo, ReviewDb db) {
+ this.dest = checkNotNull(dest, "dest");
+ this.repo = checkNotNull(repo, "repo");
+ this.db = checkNotNull(db, "db");
+ }
+ }
+
+ @Singleton
+ public static class Loader extends CacheLoader<EntryKey, Boolean> {
+ private final SubmitStrategyFactory submitStrategyFactory;
+
+ @Inject
+ Loader(SubmitStrategyFactory submitStrategyFactory) {
+ this.submitStrategyFactory = submitStrategyFactory;
+ }
+
+ @Override
+ public Boolean load(EntryKey key)
+ throws NoSuchProjectException, MergeException, IOException {
+ checkArgument(key.load != null, "Key cannot be loaded: %s", key);
+ if (key.into.equals(ObjectId.zeroId())) {
+ return true; // Assume yes on new branch.
+ }
+ try {
+ Map<String, Ref> refs = key.load.repo.getAllRefs();
+ RevWalk rw = CodeReviewCommit.newRevWalk(key.load.repo);
+ try {
+ RevFlag canMerge = rw.newFlag("CAN_MERGE");
+ CodeReviewCommit rev = parse(rw, key.commit);
+ rev.add(canMerge);
+ CodeReviewCommit tip = parse(rw, key.into);
+ Set<RevCommit> accepted = alreadyAccepted(rw, refs.values());
+ accepted.add(tip);
+ accepted.addAll(Arrays.asList(rev.getParents()));
+ return submitStrategyFactory.create(
+ key.submitType,
+ key.load.db,
+ key.load.repo,
+ rw,
+ null /*inserter*/,
+ canMerge,
+ accepted,
+ key.load.dest).dryRun(tip, rev);
+ } finally {
+ rw.release();
+ }
+ } finally {
+ key.load = null;
+ }
+ }
+
+ private static Set<RevCommit> alreadyAccepted(RevWalk rw,
+ Collection<Ref> refs) throws MissingObjectException, IOException {
+ Set<RevCommit> accepted = Sets.newHashSet();
+ for (Ref r : refs) {
+ if (r.getName().startsWith(Constants.R_HEADS)
+ || r.getName().startsWith(Constants.R_TAGS)) {
+ try {
+ accepted.add(rw.parseCommit(r.getObjectId()));
+ } catch (IncorrectObjectTypeException nonCommit) {
+ // Not a commit? Skip over it.
+ }
+ }
+ }
+ return accepted;
+ }
+
+ private static CodeReviewCommit parse(RevWalk rw, ObjectId id)
+ throws MissingObjectException, IncorrectObjectTypeException,
+ IOException {
+ return (CodeReviewCommit) rw.parseCommit(id);
+ }
+ }
+
+ public static class MergeabilityWeigher
+ implements Weigher<EntryKey, Boolean> {
+ @Override
+ public int weigh(EntryKey k, Boolean v) {
+ return 16 + 2 * (16 + 20) + 3 * 8 // Size of EntryKey, 64-bit JVM.
+ + 8; // Size of Boolean.
+ }
+ }
+
+ private final LoadingCache<EntryKey, Boolean> cache;
+
+ @Inject
+ MergeabilityCacheImpl(@Named(CACHE_NAME) LoadingCache<EntryKey, Boolean> cache) {
+ this.cache = cache;
+ }
+
+ @Override
+ public boolean get(ObjectId commit, Ref intoRef, SubmitType submitType,
+ String mergeStrategy, Branch.NameKey dest, Repository repo, ReviewDb db) {
+ ObjectId into = intoRef != null ? intoRef.getObjectId() : ObjectId.zeroId();
+ EntryKey key =
+ new EntryKey(commit, into, submitType, mergeStrategy, dest, repo, db);
+ try {
+ return cache.get(key);
+ } catch (ExecutionException e) {
+ log.error(String.format("Error checking mergeability of %s into %s (%s)",
+ key.commit.name(), key.into.name(), key.submitType.name()),
+ e.getCause());
+ return false;
+ }
+ }
+
+ @Override
+ public boolean getIfPresent(ObjectId commit, Ref intoRef,
+ SubmitType submitType, String mergeStrategy) {
+ return cache.getIfPresent(new EntryKey(
+ commit, toId(intoRef), submitType, mergeStrategy, null, null, null));
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
index ca83a20..0f20e27 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Mergeable.java
@@ -62,12 +62,6 @@
usage = "test mergeability for other branches too")
private boolean otherBranches;
- @Option(name = "--force", aliases = {"-f"},
- usage = "force recheck of mergeable field")
- public void setForce(boolean force) {
- this.force = force;
- }
-
private final GitRepositoryManager gitManager;
private final ProjectCache projectCache;
private final MergeUtil.Factory mergeUtilFactory;
@@ -76,8 +70,6 @@
private final ChangeIndexer indexer;
private final MergeabilityCache cache;
- private boolean force;
-
@Inject
Mergeable(GitRepositoryManager gitManager,
ProjectCache projectCache,
@@ -133,7 +125,7 @@
Boolean old =
cache.getIfPresent(commit, ref, result.submitType, strategy);
- if (force || old == null) {
+ if (old == null) {
result.mergeable = refresh(change, commit, ref, result.submitType,
strategy, git, old);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
index 8d6cef2..02ade49 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/config/GerritGlobalModule.java
@@ -71,7 +71,7 @@
import com.google.gerrit.server.avatar.AvatarProvider;
import com.google.gerrit.server.cache.CacheRemovalListener;
import com.google.gerrit.server.change.ChangeKindCacheImpl;
-import com.google.gerrit.server.change.MergeabilityCache;
+import com.google.gerrit.server.change.MergeabilityCacheImpl;
import com.google.gerrit.server.events.EventFactory;
import com.google.gerrit.server.extensions.events.GitReferenceUpdated;
import com.google.gerrit.server.git.ChangeCache;
@@ -167,7 +167,7 @@
install(ConflictsCacheImpl.module());
install(GroupCacheImpl.module());
install(GroupIncludeCacheImpl.module());
- install(MergeabilityCache.module());
+ install(MergeabilityCacheImpl.module());
install(PatchListCacheImpl.module());
install(ProjectCacheImpl.module());
install(SectionSortCache.module());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
index fb2e6f7..b7c7679 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReceiveCommits.java
@@ -2385,6 +2385,9 @@
closeChange(cmd, PatchSet.Id.fromRef(ref.getName()), c);
closeProgress.update(1);
if (closedChange != null) {
+ if (byKey == null) {
+ byKey = openChangesByKey(branch);
+ }
byKey.remove(closedChange);
}
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
index 5f2ffcb..b587791 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/mail/CommentSender.java
@@ -121,7 +121,7 @@
try {
patchList = getPatchList();
} catch (PatchListNotAvailableException e) {
- patchList = null;
+ log.error("Failed to get patch list", e);
}
}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java b/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
index 9e58bea..2f48c02 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/project/Util.java
@@ -280,7 +280,8 @@
bind(String.class).annotatedWith(AnonymousCowardName.class)
.toProvider(AnonymousCowardNameProvider.class);
bind(ChangeKindCache.class).to(ChangeKindCacheImpl.NoCache.class);
- bind(MergeabilityCache.bindingKey()).toProvider(nullProvider);
+ bind(MergeabilityCache.class)
+ .to(MergeabilityCache.NotImplemented.class);
}
});