Merge "Additional AccountExternalId when creating account"
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 6019150..01dfcc2 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -1200,20 +1200,16 @@
[...]
// update change
ReviewDb db = dbProvider.get();
- db.changes().beginTransaction(change.getId());
- try {
- change = db.changes().atomicUpdate(
- change.getId(),
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- ChangeUtil.updated(change);
- return change;
- }
- });
- db.commit();
- } finally {
- db.rollback();
+ try (BatchUpdate bu = batchUpdateFactory.create(
+ db, project.getNameKey(), user, TimeUtil.nowTs())) {
+ bu.addOp(change.getId(), new BatchUpdate.Op() {
+ @Override
+ public boolean updateChange(BatchUpdate.ChangeContext ctx) {
+ ctx.saveChange();
+ return true;
+ }
+ });
+ bu.execute();
}
[...]
}
diff --git a/Documentation/index.txt b/Documentation/index.txt
index 50770a9..3114814 100644
--- a/Documentation/index.txt
+++ b/Documentation/index.txt
@@ -25,9 +25,9 @@
== Project Management
. link:project-configuration.html[Project Configuration]
-. link:access-control.html[Access Controls]
.. link:config-labels.html[Review Labels]
-.. link:config-project-config.html[Access Controls Configuration Format]
+.. link:config-project-config.html[Project Configuration File Format]
+. link:access-control.html[Access Controls]
. Multi-project management
.. link:user-submodules.html[Submodules]
.. link:https://source.android.com/source/using-repo.html[Repo] (external)
diff --git a/Documentation/rest-api-groups.txt b/Documentation/rest-api-groups.txt
index e0df4ca..336c7ca 100644
--- a/Documentation/rest-api-groups.txt
+++ b/Documentation/rest-api-groups.txt
@@ -174,13 +174,12 @@
[[suggest-group]]
==== Suggest Group
-The `suggest` option indicates a user-entered string that
+The `suggest` or `s` option indicates a user-entered string that
should be auto-completed to group names.
If this option is set and `n` is not set, then `n` defaults to 10.
-When using this option,
-the `project` or `p` option can be used to name the current project,
-to allow context-dependent suggestions.
+When using this option, the `project` or `p` option can be used to
+name the current project, to allow context-dependent suggestions.
Not compatible with `visible-to-all`, `owned`, `user`, `match`, `q`,
or `S`.
diff --git a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
index 5788ec9..35e86c5 100644
--- a/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
+++ b/gerrit-acceptance-framework/src/test/java/com/google/gerrit/acceptance/PushOneCommit.java
@@ -37,7 +37,6 @@
import org.eclipse.jgit.api.TagCommand;
import org.eclipse.jgit.junit.TestRepository;
-import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.PersonIdent;
import org.eclipse.jgit.revwalk.RevCommit;
import org.eclipse.jgit.transport.PushResult;
@@ -254,10 +253,6 @@
return changeId;
}
- public ObjectId getCommitId() {
- return commit;
- }
-
public RevCommit getCommit() {
return commit;
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 0baf527..0bd1df1 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -238,7 +238,8 @@
.rebase();
// Second change should have 2 patch sets
- assertThat(r2.getPatchSetId().get()).isEqualTo(2);
+ ChangeInfo c2 = gApi.changes().id(r2.getChangeId()).get();
+ assertThat(c2.revisions.get(c2.currentRevision)._number).isEqualTo(2);
// ...and the committer should be correct
ChangeInfo info = gApi.changes()
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 ebca92b..46e8959 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
@@ -634,7 +634,7 @@
Locale.US);
String date = df.format(rev.commit.author.date);
assertThat(res).isEqualTo(
- String.format(PATCH, r.getCommitId().name(), date, r.getChangeId()));
+ String.format(PATCH, r.getCommit().name(), date, r.getChangeId()));
}
@Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
index 4dbd6ad..b7dd532 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/git/SubmitOnPushIT.java
@@ -190,7 +190,7 @@
r.assertOkStatus();
git().push()
- .setRefSpecs(new RefSpec(r.getCommitId().name() + ":refs/heads/master"))
+ .setRefSpecs(new RefSpec(r.getCommit().name() + ":refs/heads/master"))
.call();
assertCommit(project, "refs/heads/master");
assertThat(getSubmitter(r.getPatchSetId())).isNull();
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
index 1d99bfd..85495ed 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmit.java
@@ -138,7 +138,7 @@
public void submitToEmptyRepo() throws Exception {
PushOneCommit.Result change = createChange();
submit(change.getChangeId());
- assertThat(getRemoteHead().getId()).isEqualTo(change.getCommitId());
+ assertThat(getRemoteHead().getId()).isEqualTo(change.getCommit());
}
@Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
index dc1c8a8..12afff2 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/AbstractSubmitByMerge.java
@@ -52,7 +52,7 @@
RevCommit head = getRemoteHead();
assertThat(head.getParentCount()).isEqualTo(2);
assertThat(head.getParent(0)).isEqualTo(oldHead);
- assertThat(head.getParent(1)).isEqualTo(change2.getCommitId());
+ assertThat(head.getParent(1)).isEqualTo(change2.getCommit());
}
@Test
@@ -66,14 +66,14 @@
submit(change2.getChangeId());
RevCommit oldHead = getRemoteHead();
- testRepo.reset(change.getCommitId());
+ testRepo.reset(change.getCommit());
PushOneCommit.Result change3 =
createChange("Change 3", "a.txt", "bbb\nccc\n");
submit(change3.getChangeId());
RevCommit head = getRemoteHead();
assertThat(head.getParentCount()).isEqualTo(2);
assertThat(head.getParent(0)).isEqualTo(oldHead);
- assertThat(head.getParent(1)).isEqualTo(change3.getCommitId());
+ assertThat(head.getParent(1)).isEqualTo(change3.getCommit());
}
@Test
@@ -104,7 +104,7 @@
PushOneCommit.Result change2 = createChange();
approve(change1.getChangeId());
submit(change2.getChangeId());
- assertThat(getRemoteHead().getId()).isEqualTo(change2.getCommitId());
+ assertThat(getRemoteHead().getId()).isEqualTo(change2.getCommit());
}
@Test
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ListChangesOptionsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ListChangesOptionsIT.java
index 3728a51..54eca70 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ListChangesOptionsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/ListChangesOptionsIT.java
@@ -95,6 +95,6 @@
}
private String commitId(int i) {
- return results.get(i).getCommitId().name();
+ return results.get(i).getCommit().name();
}
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
index f285070..04f926e 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByCherryPickIT.java
@@ -89,7 +89,7 @@
submit(change2.getChangeId());
RevCommit oldHead = getRemoteHead();
- testRepo.reset(change.getCommitId());
+ testRepo.reset(change.getCommit());
PushOneCommit.Result change3 =
createChange("Change 3", "a.txt", "bbb\nccc\n");
submit(change3.getChangeId());
@@ -121,7 +121,7 @@
"upload the rebased commit for review.");
assertThat(getRemoteHead()).isEqualTo(oldHead);
- assertCurrentRevision(change2.getChangeId(), 1, change2.getCommitId());
+ assertCurrentRevision(change2.getChangeId(), 1, change2.getCommit());
assertNoSubmitter(change2.getChangeId(), 1);
}
@@ -166,7 +166,7 @@
"upload the rebased commit for review.");
assertThat(getRemoteHead()).isEqualTo(oldHead);
- assertCurrentRevision(change3.getChangeId(), 1, change3.getCommitId());
+ assertCurrentRevision(change3.getChangeId(), 1, change3.getCommit());
assertNoSubmitter(change3.getChangeId(), 1);
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
index 1380214..2ca006d 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByFastForwardIT.java
@@ -49,7 +49,7 @@
PushOneCommit.Result change = createChange();
submit(change.getChangeId());
RevCommit head = getRemoteHead();
- assertThat(head.getId()).isEqualTo(change.getCommitId());
+ assertThat(head.getId()).isEqualTo(change.getCommit());
assertThat(head.getParent(0)).isEqualTo(oldHead);
assertSubmitter(change.getChangeId(), 1);
}
@@ -65,8 +65,8 @@
submit(id2);
RevCommit head = getRemoteHead();
- assertThat(head.getId()).isEqualTo(change2.getCommitId());
- assertThat(head.getParent(0).getId()).isEqualTo(change.getCommitId());
+ assertThat(head.getId()).isEqualTo(change2.getCommit());
+ assertThat(head.getParent(0).getId()).isEqualTo(change.getCommit());
assertSubmitter(change.getChangeId(), 1);
assertSubmitter(change2.getChangeId(), 1);
assertPersonEquals(admin.getIdent(), head.getAuthorIdent());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java
index eb1d16b..ae47f261 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeAlwaysIT.java
@@ -39,7 +39,7 @@
RevCommit head = getRemoteHead();
assertThat(head.getParentCount()).isEqualTo(2);
assertThat(head.getParent(0)).isEqualTo(oldHead);
- assertThat(head.getParent(1)).isEqualTo(change.getCommitId());
+ assertThat(head.getParent(1)).isEqualTo(change.getCommit());
assertSubmitter(change.getChangeId(), 1);
assertPersonEquals(admin.getIdent(), head.getAuthorIdent());
assertPersonEquals(serverIdent.get(), head.getCommitterIdent());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
index 7fcf46f..7e772ea 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByMergeIfNecessaryIT.java
@@ -26,7 +26,7 @@
PushOneCommit.Result change = createChange();
submit(change.getChangeId());
RevCommit head = getRemoteHead();
- assertThat(head.getId()).isEqualTo(change.getCommitId());
+ assertThat(head.getId()).isEqualTo(change.getCommit());
assertThat(head.getParent(0)).isEqualTo(oldHead);
assertSubmitter(change.getChangeId(), 1);
assertPersonEquals(admin.getIdent(), head.getAuthorIdent());
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java
index 636399f..f67fec0 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/change/SubmitByRebaseIfNecessaryIT.java
@@ -49,7 +49,7 @@
PushOneCommit.Result change = createChange();
submit(change.getChangeId());
RevCommit head = getRemoteHead();
- assertThat(head.getId()).isEqualTo(change.getCommitId());
+ assertThat(head.getId()).isEqualTo(change.getCommit());
assertThat(head.getParent(0)).isEqualTo(oldHead);
assertApproved(change.getChangeId());
assertCurrentRevision(change.getChangeId(), 1, head);
@@ -130,7 +130,7 @@
submit(change2.getChangeId());
RevCommit oldHead = getRemoteHead();
- testRepo.reset(change.getCommitId());
+ testRepo.reset(change.getCommit());
PushOneCommit.Result change3 =
createChange("Change 3", "a.txt", "bbb\nccc\n");
submit(change3.getChangeId());
@@ -158,7 +158,7 @@
submitWithConflict(change2.getChangeId(), "Merge Conflict");
RevCommit head = getRemoteHead();
assertThat(head).isEqualTo(oldHead);
- assertCurrentRevision(change2.getChangeId(), 1, change2.getCommitId());
+ assertCurrentRevision(change2.getChangeId(), 1, change2.getCommit());
assertNoSubmitter(change2.getChangeId(), 1);
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GetCommitIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GetCommitIT.java
index d32be8b..54371f2 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GetCommitIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/GetCommitIT.java
@@ -96,8 +96,8 @@
.to("refs/for/master");
r.assertOkStatus();
- CommitInfo info = getCommit(r.getCommitId());
- assertThat(info.commit).isEqualTo(r.getCommitId().name());
+ CommitInfo info = getCommit(r.getCommit());
+ assertThat(info.commit).isEqualTo(r.getCommit().name());
assertThat(info.subject).isEqualTo("test commit");
assertThat(info.message).isEqualTo(
"test commit\n\nChange-Id: " + r.getChangeId() + "\n");
@@ -119,7 +119,7 @@
PushOneCommit.Result r = pushFactory.create(db, admin.getIdent(), testRepo)
.to("refs/for/master");
r.assertOkStatus();
- assertNotFound(r.getCommitId());
+ assertNotFound(r.getCommit());
}
private void unblockRead() throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
index 33cfe99..ed67d66 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/rest/project/TagsIT.java
@@ -112,18 +112,18 @@
TagInfo t = result.get(0);
assertThat(t.ref).isEqualTo(Constants.R_TAGS + tag1.name);
- assertThat(t.revision).isEqualTo(r1.getCommitId().getName());
+ assertThat(t.revision).isEqualTo(r1.getCommit().getName());
t = result.get(1);
assertThat(t.ref).isEqualTo(Constants.R_TAGS + tag2.name);
- assertThat(t.object).isEqualTo(r2.getCommitId().getName());
+ assertThat(t.object).isEqualTo(r2.getCommit().getName());
assertThat(t.message).isEqualTo(tag2.message);
assertThat(t.tagger.name).isEqualTo(tag2.tagger.getName());
assertThat(t.tagger.email).isEqualTo(tag2.tagger.getEmailAddress());
t = result.get(2);
assertThat(t.ref).isEqualTo(tag3Ref);
- assertThat(t.object).isEqualTo(r2.getCommitId().getName());
+ assertThat(t.object).isEqualTo(r2.getCommit().getName());
assertThat(t.message).isEqualTo(tag2.message);
assertThat(t.tagger.name).isEqualTo(tag2.tagger.getName());
assertThat(t.tagger.email).isEqualTo(tag2.tagger.getEmailAddress());
@@ -207,15 +207,15 @@
List<TagInfo> result = getTags().get();
assertThat(result).hasSize(2);
assertThat(result.get(0).ref).isEqualTo("refs/tags/" + tag1.name);
- assertThat(result.get(0).revision).isEqualTo(r1.getCommitId().getName());
+ assertThat(result.get(0).revision).isEqualTo(r1.getCommit().getName());
assertThat(result.get(1).ref).isEqualTo("refs/tags/" + tag2.name);
- assertThat(result.get(1).revision).isEqualTo(r2.getCommitId().getName());
+ assertThat(result.get(1).revision).isEqualTo(r2.getCommit().getName());
blockRead("refs/heads/hidden");
result = getTags().get();
assertThat(result).hasSize(1);
assertThat(result.get(0).ref).isEqualTo("refs/tags/" + tag1.name);
- assertThat(result.get(0).revision).isEqualTo(r1.getCommitId().getName());
+ assertThat(result.get(0).revision).isEqualTo(r1.getCommit().getName());
}
@Test
@@ -232,7 +232,7 @@
TagInfo tagInfo = getTag(tag1.name);
assertThat(tagInfo.ref).isEqualTo("refs/tags/" + tag1.name);
- assertThat(tagInfo.revision).isEqualTo(r1.getCommitId().getName());
+ assertThat(tagInfo.revision).isEqualTo(r1.getCommit().getName());
}
private void createTags() throws Exception {
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
index c16b60e..1a3b644 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/server/project/LabelTypeIT.java
@@ -365,7 +365,7 @@
revision(r).submit();
try (Repository repo = repoManager.openRepository(project)) {
assertThat(repo.exactRef("refs/heads/master").getObjectId()).isEqualTo(
- r.getCommitId());
+ r.getCommit());
}
}
diff --git a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
index 88821ce..a087b22 100644
--- a/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
+++ b/gerrit-acceptance-tests/src/test/java/com/google/gerrit/acceptance/ssh/UploadArchiveIT.java
@@ -55,7 +55,7 @@
@Test
public void zipFormat() throws Exception {
PushOneCommit.Result r = createChange();
- String abbreviated = r.getCommitId().abbreviate(8).name();
+ String abbreviated = r.getCommit().abbreviate(8).name();
String c = command(r, abbreviated);
InputStream out =
@@ -98,7 +98,7 @@
private void archiveNotPermitted() throws Exception {
PushOneCommit.Result r = createChange();
- String abbreviated = r.getCommitId().abbreviate(8).name();
+ String abbreviated = r.getCommit().abbreviate(8).name();
String c = command(r, abbreviated);
InputStream out =
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
index ad09027..2fce1cd 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/PageLinks.java
@@ -14,7 +14,6 @@
package com.google.gerrit.common;
-import com.google.gerrit.common.data.ChangeInfo;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.Change.Status;
@@ -51,10 +50,6 @@
public static final String MY_GROUPS = "/groups/self";
public static final String DOCUMENTATION = "/Documentation/";
- public static String toChange(final ChangeInfo c) {
- return toChange(c.getId());
- }
-
public static String toChangeInEditMode(Change.Id c) {
return "/c/" + c + ",edit/";
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
index 8614be5..e8f9fd5 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
+++ b/gerrit-common/src/main/java/com/google/gerrit/common/data/AccountInfo.java
@@ -76,51 +76,4 @@
public String getUsername() {
return username;
}
-
- /**
- * Formats an account name.
- * <p>
- * If the account has a full name, it returns only the full name. Otherwise it
- * returns a longer form that includes the email address.
- */
- public String getName(String anonymousCowardName) {
- if (getFullName() != null) {
- return getFullName();
- }
- if (getPreferredEmail() != null) {
- return getPreferredEmail();
- }
- return getNameEmail(anonymousCowardName);
- }
-
- /**
- * Formats an account as a name and an email address.
- * <p>
- * Example output:
- * <ul>
- * <li>{@code A U. Thor <author@example.com>}: full populated</li>
- * <li>{@code A U. Thor (12)}: missing email address</li>
- * <li>{@code Anonymous Coward <author@example.com>}: missing name</li>
- * <li>{@code Anonymous Coward (12)}: missing name and email address</li>
- * </ul>
- */
- public String getNameEmail(String anonymousCowardName) {
- String name = getFullName();
- if (name == null) {
- name = anonymousCowardName;
- }
-
- final StringBuilder b = new StringBuilder();
- b.append(name);
- if (getPreferredEmail() != null) {
- b.append(" <");
- b.append(getPreferredEmail());
- b.append(">");
- } else if (getId() != null) {
- b.append(" (");
- b.append(getId().get());
- b.append(")");
- }
- return b.toString();
- }
}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java
deleted file mode 100644
index d0f8cd3..0000000
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ChangeInfo.java
+++ /dev/null
@@ -1,113 +0,0 @@
-// Copyright (C) 2008 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.common.data;
-
-import com.google.gerrit.reviewdb.client.Account;
-import com.google.gerrit.reviewdb.client.Change;
-import com.google.gerrit.reviewdb.client.PatchSet;
-
-import java.sql.Timestamp;
-
-public class ChangeInfo {
- protected Change.Id id;
- protected Change.Key key;
- protected Account.Id owner;
- protected String subject;
- protected Change.Status status;
- protected ProjectInfo project;
- protected String branch;
- protected String topic;
- protected boolean starred;
- protected Timestamp lastUpdatedOn;
- protected PatchSet.Id patchSetId;
- protected boolean latest;
-
- public ChangeInfo() {
- }
-
- public ChangeInfo(final Change c, final PatchSet.Id patchId) {
- set(c, patchId);
- }
-
- public void set(final Change c, final PatchSet.Id patchId) {
- id = c.getId();
- key = c.getKey();
- owner = c.getOwner();
- subject = c.getSubject();
- status = c.getStatus();
- project = new ProjectInfo(c.getProject());
- branch = c.getDest().getShortName();
- topic = c.getTopic();
- lastUpdatedOn = c.getLastUpdatedOn();
- patchSetId = patchId;
- latest = patchSetId == null || patchSetId.equals(c.currentPatchSetId());
- }
-
- public ChangeInfo(final Change c) {
- this(c, null);
- }
-
- public Change.Id getId() {
- return id;
- }
-
- public Change.Key getKey() {
- return key;
- }
-
- public Account.Id getOwner() {
- return owner;
- }
-
- public String getSubject() {
- return subject;
- }
-
- public Change.Status getStatus() {
- return status;
- }
-
- public ProjectInfo getProject() {
- return project;
- }
-
- public String getBranch() {
- return branch;
- }
-
- public String getTopic() {
- return topic;
- }
-
- public boolean isStarred() {
- return starred;
- }
-
- public void setStarred(final boolean s) {
- starred = s;
- }
-
- public PatchSet.Id getPatchSetId() {
- return patchSetId;
- }
-
- public boolean isLatest() {
- return latest;
- }
-
- public Timestamp getLastUpdatedOn() {
- return lastUpdatedOn;
- }
-}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java
deleted file mode 100644
index 9365db8..0000000
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/IncludedInDetail.java
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright (C) 2010 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.common.data;
-
-import java.util.Collections;
-import java.util.List;
-
-public class IncludedInDetail {
- private List<String> branches;
- private List<String> tags;
-
- public IncludedInDetail() {
- }
-
- public void setBranches(final List<String> b) {
- Collections.sort(b);
- branches = b;
- }
-
- public List<String> getBranches() {
- return branches;
- }
-
- public void setTags(final List<String> t) {
- Collections.sort(t);
- tags = t;
- }
-
- public List<String> getTags() {
- return tags;
- }
-}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java
deleted file mode 100644
index dfef806..0000000
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ProjectInfo.java
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (C) 2008 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.common.data;
-
-import com.google.gerrit.reviewdb.client.Project;
-
-public class ProjectInfo {
- protected Project.NameKey key;
-
- protected ProjectInfo() {
- }
-
- public ProjectInfo(final Project.NameKey key) {
- this.key = key;
- }
-
- public Project.NameKey getKey() {
- return key;
- }
-
- public String getName() {
- return key.get();
- }
-}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java
deleted file mode 100644
index 76785d8..0000000
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/ReviewResult.java
+++ /dev/null
@@ -1,134 +0,0 @@
-// Copyright (C) 2011 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.common.data;
-
-import com.google.gerrit.reviewdb.client.Change;
-
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Result from performing a review (comment, abandon, etc.)
- */
-public class ReviewResult {
- protected List<Error> errors;
- protected Change.Id changeId;
-
- public ReviewResult() {
- errors = new ArrayList<>();
- }
-
- public void addError(final Error e) {
- errors.add(e);
- }
-
- public List<Error> getErrors() {
- return errors;
- }
-
- public Change.Id getChangeId() {
- return changeId;
- }
-
- public void setChangeId(Change.Id changeId) {
- this.changeId = changeId;
- }
-
- public static class Error {
- public static enum Type {
- /** Not permitted to abandon this change. */
- ABANDON_NOT_PERMITTED,
-
- /** Not permitted to restore this change. */
- RESTORE_NOT_PERMITTED,
-
- /** Not permitted to submit this change. */
- SUBMIT_NOT_PERMITTED,
-
- /** Approvals or dependencies are lacking for submission. */
- SUBMIT_NOT_READY,
-
- /** Review operation invalid because change is closed. */
- CHANGE_IS_CLOSED,
-
- /** Review operation invalid because change is not abandoned. */
- CHANGE_NOT_ABANDONED,
-
- /** Not permitted to publish this draft patch set */
- PUBLISH_NOT_PERMITTED,
-
- /** Not permitted to delete this draft patch set */
- DELETE_NOT_PERMITTED,
-
- /** Review operation not permitted by rule. */
- RULE_ERROR,
-
- /** Review operation invalid because patch set is not a draft. */
- NOT_A_DRAFT,
-
- /** Error writing change to git repository */
- GIT_ERROR,
-
- /** The destination branch does not exist */
- DEST_BRANCH_NOT_FOUND,
-
- /** Not permitted to edit the topic name */
- EDIT_TOPIC_NAME_NOT_PERMITTED,
-
- /** Not permitted to edit the hashtags */
- EDIT_HASHTAGS_NOT_PERMITTED
- }
-
- protected Type type;
- protected String message;
-
- protected Error() {
- }
-
- public Error(final Type type) {
- this.type = type;
- this.message = null;
- }
-
- public Error(final Type type, final String message) {
- this.type = type;
- this.message = message;
- }
-
- public Type getType() {
- return type;
- }
-
- public String getMessage() {
- return message;
- }
-
- public String getMessageOrType() {
- if (message != null) {
- return message;
- }
- return "" + type;
- }
-
- @Override
- public String toString() {
- String ret = type + "";
- if (message != null) {
- ret += " " + message;
- }
- return ret;
- }
- }
-}
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java b/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java
deleted file mode 100644
index 7b25a23..0000000
--- a/gerrit-common/src/main/java/com/google/gerrit/common/data/SuggestService.java
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright (C) 2008 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.common.data;
-
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.gwtjsonrpc.common.RemoteJsonService;
-import com.google.gwtjsonrpc.common.RpcImpl;
-import com.google.gwtjsonrpc.common.RpcImpl.Version;
-
-import java.util.List;
-
-@RpcImpl(version = Version.V2_0)
-public interface SuggestService extends RemoteJsonService {
- void suggestAccountGroupForProject(Project.NameKey project, String query,
- int limit, AsyncCallback<List<GroupReference>> callback);
-}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
index b9baccc..91107d3 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/admin/PermissionEditor.java
@@ -14,8 +14,8 @@
package com.google.gerrit.client.admin;
+import com.google.gerrit.client.groups.GroupMap;
import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.client.ui.SuggestUtil;
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.GroupInfo;
@@ -241,14 +241,16 @@
// If the oracle didn't get to complete a UUID, resolve it now.
//
addRule.setEnabled(false);
- SuggestUtil.SVC.suggestAccountGroupForProject(
- projectName, ref.getName(), 1,
- new GerritCallback<List<GroupReference>>() {
+ GroupMap.suggestAccountGroupForProject(
+ projectName.get(), ref.getName(), 1,
+ new GerritCallback<GroupMap>() {
@Override
- public void onSuccess(List<GroupReference> result) {
+ public void onSuccess(GroupMap result) {
addRule.setEnabled(true);
- if (result.size() == 1) {
- addGroup(result.get(0));
+ if (result.values().length() == 1) {
+ addGroup(new GroupReference(
+ result.values().get(0).getGroupUUID(),
+ result.values().get(0).name()));
} else {
groupToAdd.setFocus(true);
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java
index f28fb86..5532285 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/groups/GroupMap.java
@@ -38,6 +38,21 @@
call.get(NativeMap.copyKeysIntoChildren(cb));
}
+ public static void suggestAccountGroupForProject(String project, String query,
+ int limit, AsyncCallback<GroupMap> cb) {
+ RestApi call = groups();
+ if (project != null) {
+ call.addParameter("p", project);
+ }
+ if (query != null) {
+ call.addParameter("s", query);
+ }
+ if (limit > 0) {
+ call.addParameter("n", limit);
+ }
+ call.get(NativeMap.copyKeysIntoChildren(cb));
+ }
+
public static void myOwned(AsyncCallback<GroupMap> cb) {
myOwnedGroups().get(NativeMap.copyKeysIntoChildren(cb));
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
index 5f4081b..aa76128 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountGroupSuggestOracle.java
@@ -14,16 +14,16 @@
package com.google.gerrit.client.ui;
-import com.google.gerrit.client.RpcStatus;
+import com.google.gerrit.client.groups.GroupInfo;
+import com.google.gerrit.client.groups.GroupMap;
import com.google.gerrit.client.rpc.GerritCallback;
-import com.google.gerrit.common.data.GroupReference;
+import com.google.gerrit.client.rpc.Natives;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.reviewdb.client.Project;
import com.google.gwt.user.client.ui.SuggestOracle;
import java.util.ArrayList;
import java.util.HashMap;
-import java.util.List;
import java.util.Map;
/** Suggestion Oracle for AccountGroup entities. */
@@ -34,26 +34,20 @@
@Override
public void _onRequestSuggestions(final Request req, final Callback callback) {
- RpcStatus.hide(new Runnable() {
- @Override
- public void run() {
- SuggestUtil.SVC.suggestAccountGroupForProject(
- projectName, req.getQuery(), req.getLimit(),
- new GerritCallback<List<GroupReference>>() {
- @Override
- public void onSuccess(final List<GroupReference> result) {
- priorResults.clear();
- final ArrayList<AccountGroupSuggestion> r =
- new ArrayList<>(result.size());
- for (final GroupReference p : result) {
- r.add(new AccountGroupSuggestion(p));
- priorResults.put(p.getName(), p.getUUID());
- }
- callback.onSuggestionsReady(req, new Response(r));
- }
- });
- }
- });
+ GroupMap.suggestAccountGroupForProject(
+ projectName.get(), req.getQuery(), req.getLimit(),
+ new GerritCallback<GroupMap>() {
+ @Override
+ public void onSuccess(GroupMap result) {
+ priorResults.clear();
+ ArrayList<AccountGroupSuggestion> r = new ArrayList<>(result.size());
+ for (GroupInfo group : Natives.asList(result.values())) {
+ r.add(new AccountGroupSuggestion(group));
+ priorResults.put(group.name(), group.getGroupUUID());
+ }
+ callback.onSuggestionsReady(req, new Response(r));
+ }
+ });
}
public void setProject(Project.NameKey projectName) {
@@ -62,20 +56,20 @@
private static class AccountGroupSuggestion implements
SuggestOracle.Suggestion {
- private final GroupReference info;
+ private final GroupInfo info;
- AccountGroupSuggestion(final GroupReference k) {
+ AccountGroupSuggestion(final GroupInfo k) {
info = k;
}
@Override
public String getDisplayString() {
- return info.getName();
+ return info.name();
}
@Override
public String getReplacementString() {
- return info.getName();
+ return info.name();
}
}
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
index 288549f..8c80e55 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/AccountLinkPanel.java
@@ -19,24 +19,12 @@
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.client.info.AccountInfo;
import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.AccountInfoCache;
-import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.UserIdentity;
import com.google.gwt.user.client.ui.FlowPanel;
/** Link to any user's account dashboard. */
public class AccountLinkPanel extends FlowPanel {
- /** Create a link after locating account details from an active cache. */
- public static AccountLinkPanel link(AccountInfoCache cache, Account.Id id) {
- com.google.gerrit.common.data.AccountInfo ai = cache.get(id);
- return ai != null ? new AccountLinkPanel(ai) : null;
- }
-
- public AccountLinkPanel(com.google.gerrit.common.data.AccountInfo ai) {
- this(FormatUtil.asInfo(ai));
- }
-
public AccountLinkPanel(UserIdentity ident) {
this(AccountInfo.create(
ident.getAccount().get(),
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
index 72c80ac..241b354 100644
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
+++ b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/ChangeLink.java
@@ -16,7 +16,6 @@
import com.google.gerrit.client.Gerrit;
import com.google.gerrit.common.PageLinks;
-import com.google.gerrit.common.data.ChangeInfo;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gwt.core.client.GWT;
@@ -42,17 +41,6 @@
psid = ps;
}
- public ChangeLink(final String text, final ChangeInfo info) {
- super(text, getTarget(info));
- cid = info.getId();
- psid = info.getPatchSetId();
- }
-
- public static String getTarget(final ChangeInfo info) {
- PatchSet.Id ps = info.getPatchSetId();
- return (ps == null) ? PageLinks.toChange(info) : PageLinks.toChange(ps);
- }
-
@Override
public void go() {
Gerrit.display(getTargetHistoryToken());
diff --git a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestUtil.java b/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestUtil.java
deleted file mode 100644
index 6e81b71..0000000
--- a/gerrit-gwtui/src/main/java/com/google/gerrit/client/ui/SuggestUtil.java
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (C) 2008 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.client.ui;
-
-import com.google.gerrit.common.data.SuggestService;
-import com.google.gwt.core.client.GWT;
-import com.google.gwtjsonrpc.client.JsonUtil;
-
-public class SuggestUtil {
- public static final SuggestService SVC;
-
- static {
- SVC = GWT.create(SuggestService.class);
- JsonUtil.bind(SVC, "rpc/SuggestService");
- }
-
- private SuggestUtil() {
- }
-}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
deleted file mode 100644
index 69db233..0000000
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/SuggestServiceImpl.java
+++ /dev/null
@@ -1,76 +0,0 @@
-// Copyright (C) 2008 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.httpd.rpc;
-
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Lists;
-import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.GroupReference;
-import com.google.gerrit.common.data.SuggestService;
-import com.google.gerrit.reviewdb.client.Project;
-import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.CurrentUser;
-import com.google.gerrit.server.account.GroupBackend;
-import com.google.gerrit.server.project.NoSuchProjectException;
-import com.google.gerrit.server.project.ProjectControl;
-import com.google.gwtjsonrpc.common.AsyncCallback;
-import com.google.inject.Inject;
-import com.google.inject.Provider;
-
-import java.util.Collections;
-import java.util.List;
-
-class SuggestServiceImpl extends BaseServiceImplementation implements
- SuggestService {
- private final ProjectControl.Factory projectControlFactory;
- private final GroupBackend groupBackend;
-
- @Inject
- SuggestServiceImpl(final Provider<ReviewDb> schema,
- final Provider<CurrentUser> currentUser,
- final ProjectControl.Factory projectControlFactory,
- final GroupBackend groupBackend) {
- super(schema, currentUser);
- this.projectControlFactory = projectControlFactory;
- this.groupBackend = groupBackend;
- }
-
- @Override
- public void suggestAccountGroupForProject(final Project.NameKey project,
- final String query, final int limit,
- final AsyncCallback<List<GroupReference>> callback) {
- run(callback, new Action<List<GroupReference>>() {
- @Override
- public List<GroupReference> run(final ReviewDb db) {
- ProjectControl projectControl = null;
- if (project != null) {
- try {
- projectControl = projectControlFactory.controlFor(project);
- } catch (NoSuchProjectException e) {
- return Collections.emptyList();
- }
- }
- return suggestAccountGroup(projectControl, query, limit);
- }
- });
- }
-
- private List<GroupReference> suggestAccountGroup(
- @Nullable final ProjectControl projectControl, final String query, final int limit) {
- return Lists.newArrayList(Iterables.limit(
- groupBackend.suggest(query, projectControl),
- limit <= 0 ? 10 : Math.min(limit, 10)));
- }
-}
diff --git a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/UiRpcModule.java b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/UiRpcModule.java
index 08e1582..f3577b9 100644
--- a/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/UiRpcModule.java
+++ b/gerrit-httpd/src/main/java/com/google/gerrit/httpd/rpc/UiRpcModule.java
@@ -27,7 +27,6 @@
@Override
protected void configureServlets() {
- rpc(SuggestServiceImpl.class);
rpc(SystemInfoServiceImpl.class);
install(new AccountModule());
diff --git a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
index 295239f..2bb6702 100644
--- a/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
+++ b/gerrit-reviewdb/src/main/java/com/google/gerrit/reviewdb/client/Account.java
@@ -243,6 +243,49 @@
preferredEmail = addr;
}
+ /**
+ * Formats an account name.
+ * <p>
+ * If the account has a full name, it returns only the full name. Otherwise it
+ * returns a longer form that includes the email address.
+ */
+ public String getName(String anonymousCowardName) {
+ if (fullName != null) {
+ return fullName;
+ }
+ if (preferredEmail != null) {
+ return preferredEmail;
+ }
+ return getNameEmail(anonymousCowardName);
+ }
+
+ /**
+ * Get the name and email address.
+ * <p>
+ * Example output:
+ * <ul>
+ * <li>{@code A U. Thor <author@example.com>}: full populated</li>
+ * <li>{@code A U. Thor (12)}: missing email address</li>
+ * <li>{@code Anonymous Coward <author@example.com>}: missing name</li>
+ * <li>{@code Anonymous Coward (12)}: missing name and email address</li>
+ * </ul>
+ */
+ public String getNameEmail(String anonymousCowardName) {
+ String name = fullName != null ? fullName : anonymousCowardName;
+ StringBuilder b = new StringBuilder();
+ b.append(name);
+ if (preferredEmail != null) {
+ b.append(" <");
+ b.append(preferredEmail);
+ b.append(">");
+ } else if (accountId != null) {
+ b.append(" (");
+ b.append(accountId.get());
+ b.append(")");
+ }
+ return b.toString();
+ }
+
/** Get the date and time the user first registered. */
public Timestamp getRegisteredOn() {
return registeredOn;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
index bf93329..b694cd8 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/ChangeUtil.java
@@ -16,7 +16,6 @@
import com.google.common.base.Function;
import com.google.common.collect.Ordering;
-import com.google.gerrit.common.TimeUtil;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.PatchSet;
import com.google.gerrit.reviewdb.server.ReviewDb;
@@ -87,10 +86,6 @@
}
}
- public static void updated(Change c) {
- c.setLastUpdatedOn(TimeUtil.nowTs());
- }
-
public static PatchSet.Id nextPatchSetId(Map<String, Ref> allRefs,
PatchSet.Id id) {
PatchSet.Id next = nextPatchSetId(id);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
index 8d31c11..2e93ce7 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/IdentifiedUser.java
@@ -18,7 +18,6 @@
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountProjectWatch;
import com.google.gerrit.reviewdb.client.Change;
@@ -308,12 +307,8 @@
return validEmails;
}
- public String getName() {
- return new AccountInfo(getAccount()).getName(anonymousCowardName);
- }
-
public String getNameEmail() {
- return new AccountInfo(getAccount()).getNameEmail(anonymousCowardName);
+ return getAccount().getNameEmail(anonymousCowardName);
}
@Override
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
index 4a9d263..9ac20f6 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/AccountManager.java
@@ -20,7 +20,6 @@
import com.google.gerrit.common.data.AccessSection;
import com.google.gerrit.common.data.GlobalCapability;
import com.google.gerrit.common.data.Permission;
-import com.google.gerrit.common.errors.InvalidUserNameException;
import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountExternalId;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
index b413e81..f466fa3 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/ChangeUserName.java
@@ -17,7 +17,6 @@
import static com.google.gerrit.reviewdb.client.AccountExternalId.SCHEME_USERNAME;
import com.google.gerrit.common.Nullable;
-import com.google.gerrit.common.errors.InvalidUserNameException;
import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.AccountExternalId;
diff --git a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/InvalidUserNameException.java
similarity index 95%
rename from gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java
rename to gerrit-server/src/main/java/com/google/gerrit/server/account/InvalidUserNameException.java
index f1c35a8..d60b7af 100644
--- a/gerrit-common/src/main/java/com/google/gerrit/common/errors/InvalidUserNameException.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/InvalidUserNameException.java
@@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.
-package com.google.gerrit.common.errors;
+package com.google.gerrit.server.account;
import com.google.gerrit.reviewdb.client.Account;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutUsername.java b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutUsername.java
index 9506b01..6f20e9a 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/account/PutUsername.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/account/PutUsername.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.account;
-import com.google.gerrit.common.errors.InvalidUserNameException;
import com.google.gerrit.common.errors.NameAlreadyUsedException;
import com.google.gerrit.extensions.restapi.AuthException;
import com.google.gerrit.extensions.restapi.DefaultInput;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
index ac842e5..37d400c 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedIn.java
@@ -14,7 +14,6 @@
package com.google.gerrit.server.change;
-import com.google.gerrit.common.data.IncludedInDetail;
import com.google.gerrit.extensions.config.ExternalIncludedIn;
import com.google.gerrit.extensions.registration.DynamicMap;
import com.google.gerrit.extensions.restapi.BadRequestException;
@@ -80,7 +79,7 @@
throw new ResourceConflictException(err.getMessage());
}
- IncludedInDetail d = IncludedInResolver.resolve(r, rw, rev);
+ IncludedInResolver.Result d = IncludedInResolver.resolve(r, rw, rev);
Map<String, Collection<String>> external = new HashMap<>();
for (DynamicMap.Entry<ExternalIncludedIn> i : includedIn) {
external.put(i.getExportName(),
@@ -96,7 +95,7 @@
Collection<String> tags;
Map<String, Collection<String>> external;
- IncludedInInfo(IncludedInDetail in, Map<String, Collection<String>> e) {
+ IncludedInInfo(IncludedInResolver.Result in, Map<String, Collection<String>> e) {
branches = in.getBranches();
tags = in.getTags();
external = e;
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedInResolver.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedInResolver.java
index fcac76d..2c5eda4 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedInResolver.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/IncludedInResolver.java
@@ -18,7 +18,6 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
-import com.google.gerrit.common.data.IncludedInDetail;
import org.eclipse.jgit.errors.IncorrectObjectTypeException;
import org.eclipse.jgit.errors.MissingObjectException;
@@ -47,7 +46,7 @@
private static final Logger log = LoggerFactory
.getLogger(IncludedInResolver.class);
- public static IncludedInDetail resolve(final Repository repo,
+ public static Result resolve(final Repository repo,
final RevWalk rw, final RevCommit commit) throws IOException {
RevFlag flag = newFlag(rw);
try {
@@ -87,7 +86,7 @@
this.containsTarget = containsTarget;
}
- private IncludedInDetail resolve() throws IOException {
+ private Result resolve() throws IOException {
RefDatabase refDb = repo.getRefDatabase();
Collection<Ref> tags = refDb.getRefs(Constants.R_TAGS).values();
Collection<Ref> branches = refDb.getRefs(Constants.R_HEADS).values();
@@ -98,7 +97,7 @@
parseCommits(allTagsAndBranches);
Set<String> allMatchingTagsAndBranches = includedIn(tipsByCommitTime, 0);
- IncludedInDetail detail = new IncludedInDetail();
+ Result detail = new Result();
detail
.setBranches(getMatchingRefNames(allMatchingTagsAndBranches, branches));
detail.setTags(getMatchingRefNames(allMatchingTagsAndBranches, tags));
@@ -228,4 +227,30 @@
}
});
}
+
+ public static class Result {
+ private List<String> branches;
+ private List<String> tags;
+
+ public Result() {
+ }
+
+ public void setBranches(final List<String> b) {
+ Collections.sort(b);
+ branches = b;
+ }
+
+ public List<String> getBranches() {
+ return branches;
+ }
+
+ public void setTags(final List<String> t) {
+ Collections.sort(t);
+ tags = t;
+ }
+
+ public List<String> getTags() {
+ return tags;
+ }
+ }
}
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 4baaa63..34bc00a 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
@@ -101,34 +101,16 @@
}
ChangeData cd = changeDataFactory.create(db.get(), resource.getControl());
- SubmitTypeRecord rec = new SubmitRuleEvaluator(cd)
- .setPatchSet(ps)
- .getSubmitType();
- if (rec.status != SubmitTypeRecord.Status.OK) {
- throw new OrmException("Submit type rule failed: " + rec);
- }
- result.submitType = rec.type;
+ result.submitType = getSubmitType(cd, ps);
try (Repository git = gitManager.openRepository(change.getProject())) {
ObjectId commit = toId(ps);
- if (commit == null) {
- result.mergeable = false;
- return result;
- }
-
Ref ref = git.getRefDatabase().exactRef(change.getDest().get());
ProjectState projectState = projectCache.get(change.getProject());
String strategy = mergeUtilFactory.create(projectState)
.mergeStrategyName();
- Boolean old =
- cache.getIfPresent(commit, ref, result.submitType, strategy);
-
- if (old == null) {
- result.mergeable = refresh(change, commit, ref, result.submitType,
- strategy, git, old);
- } else {
- result.mergeable = old;
- }
+ result.mergeable =
+ isMergable(git, change, commit, ref, result.submitType, strategy);
if (otherBranches) {
result.mergeableInto = new ArrayList<>();
@@ -153,6 +135,31 @@
return result;
}
+ private SubmitType getSubmitType(ChangeData cd, PatchSet patchSet)
+ throws OrmException {
+ SubmitTypeRecord rec =
+ new SubmitRuleEvaluator(cd).setPatchSet(patchSet).getSubmitType();
+ if (rec.status != SubmitTypeRecord.Status.OK) {
+ throw new OrmException("Submit type rule failed: " + rec);
+ }
+ return rec.type;
+ }
+
+ private boolean isMergable(Repository git, Change change, ObjectId commit,
+ Ref ref, SubmitType submitType, String strategy)
+ throws IOException, OrmException {
+ if (commit == null) {
+ return false;
+ }
+
+ Boolean old = cache.getIfPresent(commit, ref, submitType, strategy);
+ if (old != null) {
+ return old;
+ }
+ return refresh(change, commit, ref, submitType,
+ strategy, git, old);
+ }
+
private static ObjectId toId(PatchSet ps) {
try {
return ObjectId.fromString(ps.getRevision().get());
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
index 16d80a5..a12bd39 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/change/Revert.java
@@ -37,11 +37,12 @@
import com.google.gerrit.server.PatchSetUtil;
import com.google.gerrit.server.Sequences;
import com.google.gerrit.server.git.BatchUpdate;
+import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
+import com.google.gerrit.server.git.BatchUpdate.Context;
import com.google.gerrit.server.git.GitRepositoryManager;
import com.google.gerrit.server.git.UpdateException;
import com.google.gerrit.server.git.validators.CommitValidators;
import com.google.gerrit.server.mail.RevertedSender;
-import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.project.ChangeControl;
import com.google.gerrit.server.project.NoSuchChangeException;
import com.google.gerrit.server.project.RefControl;
@@ -50,8 +51,6 @@
import com.google.inject.Provider;
import com.google.inject.Singleton;
-import org.eclipse.jgit.errors.IncorrectObjectTypeException;
-import org.eclipse.jgit.errors.MissingObjectException;
import org.eclipse.jgit.errors.RepositoryNotFoundException;
import org.eclipse.jgit.lib.CommitBuilder;
import org.eclipse.jgit.lib.ObjectId;
@@ -77,7 +76,6 @@
private final GitRepositoryManager repoManager;
private final ChangeInserter.Factory changeInserterFactory;
private final ChangeMessagesUtil cmUtil;
- private final ChangeUpdate.Factory changeUpdateFactory;
private final BatchUpdate.Factory updateFactory;
private final Sequences seq;
private final PatchSetUtil psUtil;
@@ -90,7 +88,6 @@
GitRepositoryManager repoManager,
ChangeInserter.Factory changeInserterFactory,
ChangeMessagesUtil cmUtil,
- ChangeUpdate.Factory changeUpdateFactory,
BatchUpdate.Factory updateFactory,
Sequences seq,
PatchSetUtil psUtil,
@@ -101,7 +98,6 @@
this.repoManager = repoManager;
this.changeInserterFactory = changeInserterFactory;
this.cmUtil = cmUtil;
- this.changeUpdateFactory = changeUpdateFactory;
this.updateFactory = updateFactory;
this.seq = seq;
this.psUtil = psUtil;
@@ -122,28 +118,20 @@
throw new ResourceConflictException("change is " + status(change));
}
- Change.Id revertedChangeId;
- try {
- revertedChangeId = revert(req.getControl(),
- change.currentPatchSetId(),
- Strings.emptyToNull(input.message));
- } catch (NoSuchChangeException e) {
- throw new ResourceNotFoundException(e.getMessage());
- }
+ Change.Id revertedChangeId =
+ revert(req.getControl(), Strings.emptyToNull(input.message));
return json.create(ChangeJson.NO_OPTIONS).format(req.getProject(),
revertedChangeId);
}
- private Change.Id revert(ChangeControl ctl, PatchSet.Id patchSetId,
- String message) throws NoSuchChangeException, OrmException,
- MissingObjectException, IncorrectObjectTypeException, IOException,
- RestApiException, UpdateException {
- Change.Id changeIdToRevert = patchSetId.getParentKey();
+ private Change.Id revert(ChangeControl ctl, String message)
+ throws OrmException, IOException, RestApiException, UpdateException {
+ Change.Id changeIdToRevert = ctl.getChange().getId();
+ PatchSet.Id patchSetId = ctl.getChange().currentPatchSetId();
PatchSet patch = psUtil.get(db.get(), ctl.getNotes(), patchSetId);
if (patch == null) {
- throw new NoSuchChangeException(changeIdToRevert);
+ throw new ResourceNotFoundException(changeIdToRevert.toString());
}
- Change changeToRevert = db.get().changes().get(changeIdToRevert);
Project.NameKey project = ctl.getProject().getNameKey();
CurrentUser user = ctl.getUser();
@@ -169,6 +157,7 @@
revertCommitBuilder.setAuthor(authorIdent);
revertCommitBuilder.setCommitter(authorIdent);
+ Change changeToRevert = ctl.getChange();
if (message == null) {
message = MessageFormat.format(
ChangeMessages.get().revertChangeDefaultMessage,
@@ -181,54 +170,31 @@
revertCommitBuilder.setMessage(
ChangeIdUtil.insertId(message, computedChangeId, true));
- RevCommit revertCommit;
- ChangeInserter ins;
Change.Id changeId = new Change.Id(seq.nextChangeId());
try (ObjectInserter oi = git.newObjectInserter()) {
ObjectId id = oi.insert(revertCommitBuilder);
oi.flush();
- revertCommit = revWalk.parseCommit(id);
+ RevCommit revertCommit = revWalk.parseCommit(id);
- ins = changeInserterFactory.create(
+ ChangeInserter ins = changeInserterFactory.create(
changeId, revertCommit, ctl.getChange().getDest().get())
.setValidatePolicy(CommitValidators.Policy.GERRIT)
.setTopic(changeToRevert.getTopic());
-
- ChangeMessage changeMessage = new ChangeMessage(
- new ChangeMessage.Key(
- patchSetId.getParentKey(), ChangeUtil.messageUUID(db.get())),
- user.getAccountId(), now, patchSetId);
- StringBuilder msgBuf = new StringBuilder();
- msgBuf.append("Patch Set ").append(patchSetId.get()).append(": Reverted");
- msgBuf.append("\n\n");
- msgBuf.append("This patchset was reverted in change: ")
- .append("I").append(computedChangeId.name());
- changeMessage.setMessage(msgBuf.toString());
- ChangeUpdate update = changeUpdateFactory.create(ctl, now);
- cmUtil.addChangeMessage(db.get(), update, changeMessage);
- update.commit();
-
ins.setMessage("Uploaded patch set 1.");
+
try (BatchUpdate bu = updateFactory.create(
db.get(), project, user, now)) {
bu.setRepository(git, revWalk, oi);
bu.insertChange(ins);
+ bu.addOp(changeId, new SendEmailOp(ins));
+ bu.addOp(changeToRevert.getId(),
+ new PostRevertedMessageOp(computedChangeId));
bu.execute();
}
}
-
- try {
- RevertedSender cm = revertedSenderFactory.create(project, changeId);
- cm.setFrom(user.getAccountId());
- cm.setChangeMessage(ins.getChangeMessage());
- cm.send();
- } catch (Exception err) {
- log.error("Cannot send email for revert change " + changeId, err);
- }
-
return changeId;
} catch (RepositoryNotFoundException e) {
- throw new NoSuchChangeException(changeIdToRevert, e);
+ throw new ResourceNotFoundException(changeIdToRevert.toString(), e);
}
}
@@ -243,5 +209,55 @@
private static String status(Change change) {
return change != null ? change.getStatus().name().toLowerCase() : "deleted";
- }
- }
+ }
+
+ private class SendEmailOp extends BatchUpdate.Op {
+ private final ChangeInserter ins;
+
+ public SendEmailOp(ChangeInserter ins) {
+ this.ins = ins;
+ }
+
+ @Override
+ public void postUpdate(Context ctx) throws Exception {
+ Change.Id changeId = ins.getChange().getId();
+ try {
+ RevertedSender cm =
+ revertedSenderFactory.create(ctx.getProject(), changeId);
+ cm.setFrom(ctx.getUser().getAccountId());
+ cm.setChangeMessage(ins.getChangeMessage());
+ cm.send();
+ } catch (Exception err) {
+ log.error("Cannot send email for revert change " + changeId, err);
+ }
+ }
+ }
+
+ private class PostRevertedMessageOp extends BatchUpdate.Op {
+ private final ObjectId computedChangeId;
+
+ public PostRevertedMessageOp(ObjectId computedChangeId) {
+ this.computedChangeId = computedChangeId;
+ }
+
+ @Override
+ public boolean updateChange(ChangeContext ctx) throws Exception {
+ Change change = ctx.getChange();
+ PatchSet.Id patchSetId = change.currentPatchSetId();
+ ChangeMessage changeMessage = new ChangeMessage(
+ new ChangeMessage.Key(change.getId(),
+ ChangeUtil.messageUUID(db.get())),
+ ctx.getUser().getAccountId(), ctx.getWhen(), patchSetId);
+ StringBuilder msgBuf = new StringBuilder();
+ msgBuf.append("Patch Set ").append(patchSetId.get())
+ .append(": Reverted");
+ msgBuf.append("\n\n");
+ msgBuf.append("This patchset was reverted in change: ")
+ .append("I").append(computedChangeId.name());
+ changeMessage.setMessage(msgBuf.toString());
+ cmUtil.addChangeMessage(ctx.getDb(), ctx.getUpdate(patchSetId),
+ changeMessage);
+ return true;
+ }
+ }
+}
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 9936330..ed462ad 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
@@ -86,6 +86,7 @@
import com.google.gerrit.server.git.MergeUtil;
import com.google.gerrit.server.git.NotesBranchUtil;
import com.google.gerrit.server.git.ReceivePackInitializer;
+import com.google.gerrit.server.git.ReplaceOp;
import com.google.gerrit.server.git.TagCache;
import com.google.gerrit.server.git.TransferConfig;
import com.google.gerrit.server.git.strategy.SubmitStrategy;
@@ -318,6 +319,7 @@
factory(ProjectConfigValidator.Factory.class);
factory(NotesBranchUtil.Factory.class);
factory(SubmoduleSectionParser.Factory.class);
+ factory(ReplaceOp.Factory.class);
bind(AccountManager.class);
factory(ChangeUserName.Factory.class);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
index eefba9d..d7b407b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/MergeOp.java
@@ -51,23 +51,20 @@
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
import com.google.gerrit.server.IdentifiedUser;
+import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
import com.google.gerrit.server.git.CodeReviewCommit.CodeReviewRevWalk;
import com.google.gerrit.server.git.strategy.SubmitStrategy;
import com.google.gerrit.server.git.strategy.SubmitStrategyFactory;
import com.google.gerrit.server.git.strategy.SubmitStrategyListener;
import com.google.gerrit.server.git.validators.MergeValidationException;
import com.google.gerrit.server.git.validators.MergeValidators;
-import com.google.gerrit.server.index.ChangeIndexer;
-import com.google.gerrit.server.notedb.ChangeUpdate;
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.project.SubmitRuleEvaluator;
import com.google.gerrit.server.query.change.ChangeData;
import com.google.gerrit.server.query.change.InternalChangeQuery;
-import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.OrmException;
import com.google.inject.Inject;
import com.google.inject.Provider;
@@ -308,10 +305,7 @@
}
}
- private final ChangeControl.GenericFactory changeControlFactory;
- private final ChangeIndexer indexer;
private final ChangeMessagesUtil cmUtil;
- private final ChangeUpdate.Factory changeUpdateFactory;
private final BatchUpdate.Factory batchUpdateFactory;
private final GitRepositoryManager repoManager;
private final IdentifiedUser.GenericFactory identifiedUserFactory;
@@ -343,10 +337,7 @@
private SubmitInput submitInput;
@Inject
- MergeOp(ChangeControl.GenericFactory changeControlFactory,
- ChangeIndexer indexer,
- ChangeMessagesUtil cmUtil,
- ChangeUpdate.Factory changeUpdateFactory,
+ MergeOp(ChangeMessagesUtil cmUtil,
BatchUpdate.Factory batchUpdateFactory,
GitRepositoryManager repoManager,
IdentifiedUser.GenericFactory identifiedUserFactory,
@@ -356,10 +347,7 @@
InternalChangeQuery internalChangeQuery,
SubmitStrategyFactory submitStrategyFactory,
Provider<SubmoduleOp> subOpProvider) {
- this.changeControlFactory = changeControlFactory;
- this.indexer = indexer;
this.cmUtil = cmUtil;
- this.changeUpdateFactory = changeUpdateFactory;
this.batchUpdateFactory = batchUpdateFactory;
this.repoManager = repoManager;
this.identifiedUserFactory = identifiedUserFactory;
@@ -874,67 +862,56 @@
} catch (NoSuchProjectException noProject) {
logWarn("Project " + noProject.project() + " no longer exists, "
+ "abandoning open changes");
- abandonAllOpenChanges(noProject.project());
+ abandonAllOpenChangeForDeletedProject(noProject.project());
} catch (IOException e) {
throw new IntegrationException("Error opening project " + project, e);
}
}
}
- private void abandonAllOpenChanges(Project.NameKey destProject) {
+ private void abandonAllOpenChangeForDeletedProject(
+ Project.NameKey destProject) {
try {
for (ChangeData cd : internalChangeQuery.byProjectOpen(destProject)) {
- abandonOneChange(cd.change());
+ //TODO: Use InternalUser instead of change owner
+ try (BatchUpdate bu = batchUpdateFactory.create(db, destProject,
+ identifiedUserFactory.create(cd.change().getOwner()),
+ TimeUtil.nowTs())) {
+ bu.addOp(cd.getId(), new BatchUpdate.Op() {
+ @Override
+ public boolean updateChange(ChangeContext ctx) throws OrmException {
+ Change change = ctx.getChange();
+ if (!change.getStatus().isOpen()) {
+ return false;
+ }
+
+ change.setStatus(Change.Status.ABANDONED);
+
+ ChangeMessage msg = new ChangeMessage(
+ new ChangeMessage.Key(change.getId(),
+ ChangeUtil.messageUUID(ctx.getDb())),
+ null, change.getLastUpdatedOn(), change.currentPatchSetId());
+ msg.setMessage("Project was deleted.");
+ cmUtil.addChangeMessage(ctx.getDb(),
+ ctx.getUpdate(change.currentPatchSetId()), msg);
+
+ ctx.saveChange();
+ return true;
+ }
+ });
+ try {
+ bu.execute();
+ } catch (UpdateException | RestApiException e) {
+ logWarn("Cannot abandon changes for deleted project " + destProject,
+ e);
+ }
+ }
}
- } catch (NoSuchChangeException | IOException | OrmException e) {
+ } catch (OrmException e) {
logWarn("Cannot abandon changes for deleted project " + destProject, e);
}
}
- private void abandonOneChange(Change change) throws OrmException,
- NoSuchChangeException, IOException {
- db.changes().beginTransaction(change.getId());
-
- //TODO(dborowitz): support InternalUser in ChangeUpdate
- ChangeControl control = changeControlFactory.controlFor(db, change,
- identifiedUserFactory.create(change.getOwner()));
- // TODO(dborowitz): Convert to BatchUpdate.
- ChangeUpdate update = changeUpdateFactory.create(control);
- try {
- change = db.changes().atomicUpdate(
- change.getId(),
- new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- if (change.getStatus().isOpen()) {
- change.setStatus(Change.Status.ABANDONED);
- return change;
- }
- return null;
- }
- });
-
- if (change != null) {
- ChangeMessage msg = new ChangeMessage(
- new ChangeMessage.Key(
- change.getId(),
- ChangeUtil.messageUUID(db)),
- null,
- change.getLastUpdatedOn(),
- change.currentPatchSetId());
- msg.setMessage("Project was deleted.");
-
- //TODO(yyonas): atomic change is not propagated.
- cmUtil.addChangeMessage(db, update, msg);
- db.commit();
- indexer.index(db, change);
- }
- } finally {
- db.rollback();
- }
- update.commit();
- }
-
private void logDebug(String msg, Object... args) {
if (log.isDebugEnabled()) {
log.debug("[" + submissionId + "]" + msg, args);
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReadOnlyRepository.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReadOnlyRepository.java
index d6bda29..32faeac 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReadOnlyRepository.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReadOnlyRepository.java
@@ -39,11 +39,15 @@
private static BaseRepositoryBuilder<?, ?> builder(Repository r) {
checkNotNull(r);
- return new BaseRepositoryBuilder<>()
+ BaseRepositoryBuilder<?, ?> builder = new BaseRepositoryBuilder<>()
.setFS(r.getFS())
- .setGitDir(r.getDirectory())
- .setWorkTree(r.getWorkTree())
- .setIndexFile(r.getIndexFile());
+ .setGitDir(r.getDirectory());
+
+ if (!r.isBare()) {
+ builder.setWorkTree(r.getWorkTree())
+ .setIndexFile(r.getIndexFile());
+ }
+ return builder;
}
private final Repository delegate;
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 d9932b7..bb1940e 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
@@ -20,7 +20,6 @@
import static com.google.gerrit.server.change.HashtagsUtil.cleanupHashtag;
import static com.google.gerrit.server.git.MultiProgressMonitor.UNKNOWN;
import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
-import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromReviewers;
import static org.eclipse.jgit.lib.Constants.R_HEADS;
import static org.eclipse.jgit.lib.RefDatabase.ALL;
import static org.eclipse.jgit.transport.ReceiveCommand.Result.NOT_ATTEMPTED;
@@ -81,7 +80,6 @@
import com.google.gerrit.reviewdb.client.RefNames;
import com.google.gerrit.reviewdb.client.SubmoduleSubscription;
import com.google.gerrit.reviewdb.server.ReviewDb;
-import com.google.gerrit.server.ApprovalCopier;
import com.google.gerrit.server.ApprovalsUtil;
import com.google.gerrit.server.ChangeMessagesUtil;
import com.google.gerrit.server.ChangeUtil;
@@ -91,8 +89,6 @@
import com.google.gerrit.server.account.AccountCache;
import com.google.gerrit.server.account.AccountResolver;
import com.google.gerrit.server.change.ChangeInserter;
-import com.google.gerrit.server.change.ChangeKind;
-import com.google.gerrit.server.change.ChangeKindCache;
import com.google.gerrit.server.change.ChangesCollection;
import com.google.gerrit.server.change.RevisionResource;
import com.google.gerrit.server.change.SetHashtagsOp;
@@ -110,10 +106,8 @@
import com.google.gerrit.server.git.validators.CommitValidationException;
import com.google.gerrit.server.git.validators.CommitValidationMessage;
import com.google.gerrit.server.git.validators.CommitValidators;
-import com.google.gerrit.server.index.ChangeIndexer;
import com.google.gerrit.server.mail.MailUtil.MailRecipients;
import com.google.gerrit.server.mail.MergedSender;
-import com.google.gerrit.server.mail.ReplacePatchSetSender;
import com.google.gerrit.server.notedb.ChangeNotes;
import com.google.gerrit.server.notedb.ChangeUpdate;
import com.google.gerrit.server.notedb.NotesMigration;
@@ -130,7 +124,6 @@
import com.google.gerrit.server.util.MagicBranch;
import com.google.gerrit.server.util.RequestScopePropagator;
import com.google.gerrit.util.cli.CmdLineParser;
-import com.google.gwtorm.server.AtomicUpdate;
import com.google.gwtorm.server.OrmException;
import com.google.gwtorm.server.ResultSet;
import com.google.gwtorm.server.SchemaFactory;
@@ -172,7 +165,6 @@
import java.io.IOException;
import java.io.StringWriter;
-import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -292,19 +284,14 @@
private final ReviewDb db;
private final Sequences seq;
private final Provider<InternalChangeQuery> queryProvider;
- private final ChangeData.Factory changeDataFactory;
private final ChangeNotes.Factory notesFactory;
- private final ChangeUpdate.Factory updateFactory;
private final SchemaFactory<ReviewDb> schemaFactory;
private final AccountResolver accountResolver;
private final CmdLineParser.Factory optionParserFactory;
private final MergedSender.Factory mergedSenderFactory;
- private final ReplacePatchSetSender.Factory replacePatchSetFactory;
private final GitReferenceUpdated gitRefUpdated;
private final PatchSetInfoFactory patchSetInfoFactory;
private final ChangeHooks hooks;
- private final ApprovalsUtil approvalsUtil;
- private final ApprovalCopier approvalCopier;
private final ChangeMessagesUtil cmUtil;
private final PatchSetUtil psUtil;
private final GitRepositoryManager repoManager;
@@ -318,14 +305,13 @@
private final ExecutorService sendEmailExecutor;
private final ListeningExecutorService changeUpdateExector;
private final RequestScopePropagator requestScopePropagator;
- private final ChangeIndexer indexer;
private final SshInfo sshInfo;
private final AllProjectsName allProjectsName;
private final ReceiveConfig receiveConfig;
private final DynamicSet<ReceivePackInitializer> initializers;
- private final ChangeKindCache changeKindCache;
private final BatchUpdate.Factory batchUpdateFactory;
private final SetHashtagsOp.Factory hashtagsFactory;
+ private final ReplaceOp.Factory replaceOpFactory;
private final ProjectControl projectControl;
private final Project project;
@@ -367,18 +353,13 @@
final Sequences seq,
final Provider<InternalChangeQuery> queryProvider,
final SchemaFactory<ReviewDb> schemaFactory,
- final ChangeData.Factory changeDataFactory,
final ChangeNotes.Factory notesFactory,
- final ChangeUpdate.Factory updateFactory,
final AccountResolver accountResolver,
final CmdLineParser.Factory optionParserFactory,
final MergedSender.Factory mergedSenderFactory,
- final ReplacePatchSetSender.Factory replacePatchSetFactory,
final GitReferenceUpdated gitRefUpdated,
final PatchSetInfoFactory patchSetInfoFactory,
final ChangeHooks hooks,
- final ApprovalsUtil approvalsUtil,
- final ApprovalCopier approvalCopier,
final ChangeMessagesUtil cmUtil,
final PatchSetUtil psUtil,
final ProjectCache projectCache,
@@ -393,7 +374,6 @@
@SendEmailExecutor final ExecutorService sendEmailExecutor,
@ChangeUpdateExecutor ListeningExecutorService changeUpdateExector,
final RequestScopePropagator requestScopePropagator,
- final ChangeIndexer indexer,
final SshInfo sshInfo,
final AllProjectsName allProjectsName,
ReceiveConfig receiveConfig,
@@ -405,29 +385,24 @@
final Provider<SubmoduleOp> subOpProvider,
final Provider<Submit> submitProvider,
final Provider<MergeOp> mergeOpProvider,
- final ChangeKindCache changeKindCache,
final DynamicMap<ProjectConfigEntry> pluginConfigEntries,
final NotesMigration notesMigration,
final ChangeEditUtil editUtil,
final BatchUpdate.Factory batchUpdateFactory,
- final SetHashtagsOp.Factory hashtagsFactory) throws IOException {
+ final SetHashtagsOp.Factory hashtagsFactory,
+ final ReplaceOp.Factory replaceOpFactory) throws IOException {
this.user = projectControl.getUser().asIdentifiedUser();
this.db = db;
this.seq = seq;
this.queryProvider = queryProvider;
- this.changeDataFactory = changeDataFactory;
this.notesFactory = notesFactory;
- this.updateFactory = updateFactory;
this.schemaFactory = schemaFactory;
this.accountResolver = accountResolver;
this.optionParserFactory = optionParserFactory;
this.mergedSenderFactory = mergedSenderFactory;
- this.replacePatchSetFactory = replacePatchSetFactory;
this.gitRefUpdated = gitRefUpdated;
this.patchSetInfoFactory = patchSetInfoFactory;
this.hooks = hooks;
- this.approvalsUtil = approvalsUtil;
- this.approvalCopier = approvalCopier;
this.cmUtil = cmUtil;
this.psUtil = psUtil;
this.projectCache = projectCache;
@@ -441,14 +416,13 @@
this.sendEmailExecutor = sendEmailExecutor;
this.changeUpdateExector = changeUpdateExector;
this.requestScopePropagator = requestScopePropagator;
- this.indexer = indexer;
this.sshInfo = sshInfo;
this.allProjectsName = allProjectsName;
this.receiveConfig = receiveConfig;
this.initializers = initializers;
- this.changeKindCache = changeKindCache;
this.batchUpdateFactory = batchUpdateFactory;
this.hashtagsFactory = hashtagsFactory;
+ this.replaceOpFactory = replaceOpFactory;
this.projectControl = projectControl;
this.labelTypes = projectControl.getLabelTypes();
@@ -1157,7 +1131,7 @@
}
}
- private static class MagicBranchInput {
+ static class MagicBranchInput {
private static final Splitter COMMAS = Splitter.on(',').omitEmptyStrings();
final ReceiveCommand cmd;
@@ -1956,7 +1930,6 @@
final ObjectId newCommitId;
final ReceiveCommand inputCommand;
final boolean checkMergedInto;
- final Timestamp createdOn;
Change change;
ChangeControl changeCtl;
BiMap<RevCommit, PatchSet.Id> revisions;
@@ -1964,8 +1937,6 @@
ReceiveCommand prev;
ReceiveCommand cmd;
PatchSetInfo info;
- ChangeMessage msg;
- String mergedIntoRef;
boolean skip;
private PatchSet.Id priorPatchSet;
List<String> groups = ImmutableList.of();
@@ -1976,7 +1947,6 @@
this.newCommitId = newCommit.copy();
this.inputCommand = cmd;
this.checkMergedInto = checkMergedInto;
- createdOn = TimeUtil.nowTs();
revisions = HashBiMap.create();
for (Ref ref : refs(toChange)) {
@@ -2177,54 +2147,6 @@
return Futures.makeChecked(future, INSERT_EXCEPTION);
}
- private ChangeMessage newChangeMessage(ReviewDb db, ChangeKind changeKind,
- Map<String, Short> approvals)
- throws OrmException {
- msg =
- new ChangeMessage(new ChangeMessage.Key(change.getId(), ChangeUtil
- .messageUUID(db)), user.getAccountId(), createdOn, psId);
-
- msg.setMessage(renderMessageWithApprovals(psId.get(),
- changeKindMessage(changeKind), approvals, scanLabels(db, approvals)));
-
- return msg;
- }
-
- private String changeKindMessage(ChangeKind changeKind) {
- switch (changeKind) {
- case MERGE_FIRST_PARENT_UPDATE:
- case TRIVIAL_REBASE:
- case NO_CHANGE:
- return ": Patch Set " + priorPatchSet.get() + " was rebased";
- case NO_CODE_CHANGE:
- return ": Commit message was updated";
- case REWORK:
- default:
- return null;
- }
- }
-
- private Map<String, PatchSetApproval> scanLabels(ReviewDb db,
- Map<String, Short> approvals)
- throws OrmException {
- Map<String, PatchSetApproval> current = new HashMap<>();
- // We optimize here and only retrieve current when approvals provided
- if (!approvals.isEmpty()) {
- for (PatchSetApproval a : approvalsUtil.byPatchSetUser(
- db, changeCtl, priorPatchSet, user.getAccountId())) {
- if (a.isSubmit()) {
- continue;
- }
-
- LabelType lt = labelTypes.byLabel(a.getLabelId());
- if (lt != null) {
- current.put(lt.getName(), a);
- }
- }
- }
- return current;
- }
-
PatchSet.Id upsertEdit() {
if (cmd.getResult() == NOT_ATTEMPTED) {
cmd.execute(rp);
@@ -2234,187 +2156,41 @@
PatchSet.Id insertPatchSet(RequestState state)
throws OrmException, IOException, RestApiException, UpdateException {
- ReviewDb db = state.db;
- Repository repo = state.repo;
- final RevCommit newCommit = state.rw.parseCommit(newCommitId);
+ RevCommit newCommit = state.rw.parseCommit(newCommitId);
state.rw.parseBody(newCommit);
- final Account.Id me = user.getAccountId();
- final List<FooterLine> footerLines = newCommit.getFooterLines();
- final MailRecipients recipients = new MailRecipients();
- final PatchSet newPatchSet;
- Map<String, Short> approvals = new HashMap<>();
- ChangeUpdate update = updateFactory.create(changeCtl, createdOn);
- update.setSubjectForCommit("Create patch set " + psId.get());
- update.setPatchSetId(psId);
+ RevCommit priorCommit = revisions.inverse().get(priorPatchSet);
- if (magicBranch != null) {
- recipients.add(magicBranch.getMailRecipients());
- approvals = magicBranch.labels;
- Set<String> hashtags = magicBranch.hashtags;
- ChangeNotes notes = changeCtl.getNotes().load();
- if (!hashtags.isEmpty()) {
- hashtags.addAll(notes.getHashtags());
- update.setHashtags(hashtags);
- }
- if (magicBranch.topic != null
- && !magicBranch.topic.equals(notes.getChange().getTopic())) {
- update.setTopic(magicBranch.topic);
- }
+ ReplaceOp replaceOp = replaceOpFactory.create(requestScopePropagator,
+ projectControl, checkMergedInto, priorPatchSet, priorCommit, psId,
+ newCommit, info, groups, magicBranch, rp.getPushCertificate());
+ try (BatchUpdate bu = batchUpdateFactory.create(state.db, project.getNameKey(),
+ user, TimeUtil.nowTs())) {
+ bu.setRepository(state.repo, state.rw, state.ins);
+ bu.addOp(change.getId(), replaceOp);
+ bu.execute();
}
- db.changes().beginTransaction(change.getId());
- ChangeKind changeKind = ChangeKind.REWORK;
- try {
- change = db.changes().get(change.getId());
- if (change == null || change.getStatus().isClosed()) {
- reject(inputCommand, "change is closed");
- return null;
- }
-
- List<String> newGroups = groups;
- if (newGroups.isEmpty()) {
- PatchSet prevPs = psUtil.current(db, update.getChangeNotes());
- newGroups = prevPs != null
- ? prevPs.getGroups()
- : ImmutableList.<String> of();
- }
-
- boolean draft = magicBranch != null && magicBranch.draft;
- newPatchSet = psUtil.insert(
- db, state.rw, update, psId, newCommit, draft, newGroups,
- rp.getPushCertificate() != null
- ? rp.getPushCertificate().toTextWithSignature()
- : null);
-
- if (checkMergedInto) {
- final Ref mergedInto = findMergedInto(change.getDest().get(), newCommit);
- mergedIntoRef = mergedInto != null ? mergedInto.getName() : null;
- }
-
- recipients.add(getRecipientsFromFooters(
- accountResolver, draft, footerLines));
- recipients.remove(me);
- ChangeData cd = changeDataFactory.create(db, changeCtl);
- MailRecipients oldRecipients =
- getRecipientsFromReviewers(cd.reviewers());
- approvalCopier.copy(db, changeCtl, newPatchSet);
- approvalsUtil.addReviewers(db, update, labelTypes, change, newPatchSet,
- info, recipients.getReviewers(), oldRecipients.getAll());
- approvalsUtil.addApprovals(db, update, labelTypes, newPatchSet,
- changeCtl, approvals);
- recipients.add(oldRecipients);
-
- RevCommit priorCommit = revisions.inverse().get(priorPatchSet);
- changeKind = changeKindCache.getChangeKind(
- projectControl.getProjectState(), repo, priorCommit, newCommit);
-
- cmUtil.addChangeMessage(db, update, newChangeMessage(db, changeKind,
- approvals));
-
- if (mergedIntoRef == null) {
- // Change should be new, so it can go through review again.
- //
- change =
- db.changes().atomicUpdate(change.getId(), new AtomicUpdate<Change>() {
- @Override
- public Change update(Change change) {
- if (change.getStatus().isClosed()) {
- return null;
- }
-
- if (!change.currentPatchSetId().equals(priorPatchSet)) {
- return change;
- }
-
- if (magicBranch != null && magicBranch.topic != null) {
- change.setTopic(magicBranch.topic);
- }
- if (change.getStatus() == Change.Status.DRAFT && newPatchSet.isDraft()) {
- // Leave in draft status.
- } else {
- change.setStatus(Change.Status.NEW);
- }
- change.setCurrentPatchSet(info);
-
- final List<String> idList = newCommit.getFooterLines(CHANGE_ID);
- if (idList.isEmpty()) {
- change.setKey(new Change.Key("I" + newCommit.name()));
- } else {
- change.setKey(new Change.Key(idList.get(idList.size() - 1).trim()));
- }
-
- ChangeUtil.updated(change);
- return change;
- }
- });
- if (change == null) {
- db.patchSets().delete(Collections.singleton(newPatchSet));
- db.changeMessages().delete(Collections.singleton(msg));
- reject(inputCommand, "change is closed");
- return null;
- }
- }
-
- db.commit();
- } finally {
- db.rollback();
+ if (replaceOp.getRejectMessage() != null) {
+ reject(inputCommand, replaceOp.getRejectMessage());
+ return null;
}
- update.commit();
+ groups = replaceOp.getGroups();
- if (mergedIntoRef != null) {
+ //TODO(ekempin): mark changes as merged inside of ReplaceOp
+ if (replaceOp.getMergedIntoRef() != null) {
// Change was already submitted to a branch, close it.
//
- markChangeMergedByPush(db, info, mergedIntoRef);
+ markChangeMergedByPush(db, info, replaceOp.getMergedIntoRef());
}
if (cmd.getResult() == NOT_ATTEMPTED) {
cmd.execute(rp);
}
- indexer.index(db, change);
- if (changeKind != ChangeKind.TRIVIAL_REBASE) {
- sendEmailExecutor.submit(requestScopePropagator.wrap(new Runnable() {
- @Override
- public void run() {
- try {
- ReplacePatchSetSender cm = replacePatchSetFactory
- .create(project.getNameKey(), change.getId());
- cm.setFrom(me);
- cm.setPatchSet(newPatchSet, info);
- cm.setChangeMessage(msg);
- if (magicBranch != null) {
- cm.setNotify(magicBranch.notify);
- }
- cm.addReviewers(recipients.getReviewers());
- cm.addExtraCC(recipients.getCcOnly());
- cm.send();
- } catch (Exception e) {
- log.error("Cannot send email for new patch set " + newPatchSet.getId(), e);
- }
- if (mergedIntoRef != null) {
- sendMergedEmail(newPatchSet, info);
- }
- }
- @Override
- public String toString() {
- return "send-email newpatchset";
- }
- }));
- }
-
+ PatchSet newPatchSet = replaceOp.getPatchSet();
gitRefUpdated.fire(project.getNameKey(), newPatchSet.getRefName(),
ObjectId.zeroId(), newCommit);
- hooks.doPatchsetCreatedHook(change, newPatchSet, db);
- if (mergedIntoRef != null) {
- hooks.doChangeMergedHook(
- change, user.getAccount(), newPatchSet, db, newCommit.getName());
- }
-
- if (!approvals.isEmpty()) {
- hooks.doCommentAddedHook(change, user.getAccount(), newPatchSet,
- null, approvals, db);
- }
if (magicBranch != null && magicBranch.submit) {
submit(changeCtl, newPatchSet);
@@ -2549,33 +2325,6 @@
}
}
- private Ref findMergedInto(final String first, final RevCommit commit) {
- try {
- final Map<String, Ref> all = repo.getRefDatabase().getRefs(ALL);
- Ref firstRef = all.get(first);
- if (firstRef != null && isMergedInto(commit, firstRef)) {
- return firstRef;
- }
- for (Ref ref : all.values()) {
- if (isHead(ref)) {
- if (isMergedInto(commit, ref)) {
- return ref;
- }
- }
- }
- return null;
- } catch (IOException e) {
- log.warn("Can't check for already submitted change", e);
- return null;
- }
- }
-
- private boolean isMergedInto(final RevCommit commit, final Ref ref)
- throws IOException {
- final RevWalk rw = rp.getRevWalk();
- return rw.isMergedInto(commit, rw.parseCommit(ref.getObjectId()));
- }
-
private void validateNewCommits(RefControl ctl, ReceiveCommand cmd) {
if (ctl.canForgeAuthor()
&& ctl.canForgeCommitter()
@@ -2845,10 +2594,6 @@
commandProgress.update(1);
}
- private static boolean isHead(final Ref ref) {
- return ref.getName().startsWith(Constants.R_HEADS);
- }
-
private static boolean isHead(final ReceiveCommand cmd) {
return cmd.getRefName().startsWith(Constants.R_HEADS);
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java
new file mode 100644
index 0000000..b38bd97
--- /dev/null
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/git/ReplaceOp.java
@@ -0,0 +1,465 @@
+// Copyright (C) 2016 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.git;
+
+import static com.google.gerrit.common.FooterConstants.CHANGE_ID;
+import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromFooters;
+import static com.google.gerrit.server.mail.MailUtil.getRecipientsFromReviewers;
+
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+import com.google.gerrit.common.ChangeHooks;
+import com.google.gerrit.common.Nullable;
+import com.google.gerrit.common.data.LabelType;
+import com.google.gerrit.reviewdb.client.Account;
+import com.google.gerrit.reviewdb.client.Change;
+import com.google.gerrit.reviewdb.client.ChangeMessage;
+import com.google.gerrit.reviewdb.client.PatchSet;
+import com.google.gerrit.reviewdb.client.PatchSetApproval;
+import com.google.gerrit.reviewdb.client.PatchSetInfo;
+import com.google.gerrit.server.ApprovalCopier;
+import com.google.gerrit.server.ApprovalsUtil;
+import com.google.gerrit.server.ChangeMessagesUtil;
+import com.google.gerrit.server.ChangeUtil;
+import com.google.gerrit.server.PatchSetUtil;
+import com.google.gerrit.server.account.AccountResolver;
+import com.google.gerrit.server.change.ChangeKind;
+import com.google.gerrit.server.change.ChangeKindCache;
+import com.google.gerrit.server.git.BatchUpdate.ChangeContext;
+import com.google.gerrit.server.git.BatchUpdate.Context;
+import com.google.gerrit.server.git.BatchUpdate.RepoContext;
+import com.google.gerrit.server.git.ReceiveCommits.MagicBranchInput;
+import com.google.gerrit.server.mail.MailUtil.MailRecipients;
+import com.google.gerrit.server.mail.MergedSender;
+import com.google.gerrit.server.mail.ReplacePatchSetSender;
+import com.google.gerrit.server.notedb.ChangeUpdate;
+import com.google.gerrit.server.project.ProjectControl;
+import com.google.gerrit.server.query.change.ChangeData;
+import com.google.gerrit.server.util.LabelVote;
+import com.google.gerrit.server.util.RequestScopePropagator;
+import com.google.gwtorm.server.OrmException;
+import com.google.inject.assistedinject.Assisted;
+import com.google.inject.assistedinject.AssistedInject;
+
+import org.eclipse.jgit.lib.Constants;
+import org.eclipse.jgit.lib.Ref;
+import org.eclipse.jgit.lib.RefDatabase;
+import org.eclipse.jgit.revwalk.RevCommit;
+import org.eclipse.jgit.revwalk.RevWalk;
+import org.eclipse.jgit.transport.PushCertificate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+
+public class ReplaceOp extends BatchUpdate.Op {
+ public interface Factory {
+ ReplaceOp create(
+ RequestScopePropagator requestScopePropagator,
+ ProjectControl projectControl,
+ boolean checkMergedInto,
+ @Assisted("priorPatchSetId") PatchSet.Id priorPatchSetId,
+ @Assisted("priorCommit") RevCommit priorCommit,
+ @Assisted("patchSetId") PatchSet.Id patchSetId,
+ @Assisted("commit") RevCommit commit,
+ PatchSetInfo info,
+ List<String> groups,
+ @Nullable MagicBranchInput magicBranch,
+ @Nullable PushCertificate pushCertificate);
+ }
+
+ private static final Logger log =
+ LoggerFactory.getLogger(ReplaceOp.class);
+
+ private static final String CHANGE_IS_CLOSED = "change is closed";
+
+ private final PatchSetUtil psUtil;
+ private final ChangeData.Factory changeDataFactory;
+ private final ChangeKindCache changeKindCache;
+ private final ChangeMessagesUtil cmUtil;
+ private final ChangeHooks hooks;
+ private final ApprovalsUtil approvalsUtil;
+ private final ApprovalCopier approvalCopier;
+ private final AccountResolver accountResolver;
+ private final ExecutorService sendEmailExecutor;
+ private final ReplacePatchSetSender.Factory replacePatchSetFactory;
+ private final MergedSender.Factory mergedSenderFactory;
+
+ private final RequestScopePropagator requestScopePropagator;
+ private final ProjectControl projectControl;
+ private final boolean checkMergedInto;
+ private final PatchSet.Id priorPatchSetId;
+ private final RevCommit priorCommit;
+ private final PatchSet.Id patchSetId;
+ private final RevCommit commit;
+ private final PatchSetInfo info;
+ private final MagicBranchInput magicBranch;
+ private final PushCertificate pushCertificate;
+ private List<String> groups = ImmutableList.of();
+
+ private final Map<String, Short> approvals = new HashMap<>();
+ private final MailRecipients recipients = new MailRecipients();
+ private Change change;
+ private PatchSet newPatchSet;
+ private ChangeKind changeKind;
+ private ChangeMessage msg;
+ private String rejectMessage;
+ private String mergedIntoRef;
+
+ @AssistedInject
+ ReplaceOp(PatchSetUtil psUtil,
+ ChangeData.Factory changeDataFactory,
+ ChangeKindCache changeKindCache,
+ ChangeMessagesUtil cmUtil,
+ ChangeHooks hooks,
+ ApprovalsUtil approvalsUtil,
+ ApprovalCopier approvalCopier,
+ AccountResolver accountResolver,
+ @SendEmailExecutor ExecutorService sendEmailExecutor,
+ ReplacePatchSetSender.Factory replacePatchSetFactory,
+ MergedSender.Factory mergedSenderFactory,
+ @Assisted RequestScopePropagator requestScopePropagator,
+ @Assisted ProjectControl projectControl,
+ @Assisted boolean checkMergedInto,
+ @Assisted("priorPatchSetId") PatchSet.Id priorPatchSetId,
+ @Assisted("priorCommit") RevCommit priorCommit,
+ @Assisted("patchSetId") PatchSet.Id patchSetId,
+ @Assisted("commit") RevCommit commit,
+ @Assisted PatchSetInfo info,
+ @Assisted List<String> groups,
+ @Assisted @Nullable MagicBranchInput magicBranch,
+ @Assisted @Nullable PushCertificate pushCertificate) {
+ this.psUtil = psUtil;
+ this.changeDataFactory = changeDataFactory;
+ this.changeKindCache = changeKindCache;
+ this.cmUtil = cmUtil;
+ this.hooks = hooks;
+ this.approvalsUtil = approvalsUtil;
+ this.approvalCopier = approvalCopier;
+ this.accountResolver = accountResolver;
+ this.sendEmailExecutor = sendEmailExecutor;
+ this.replacePatchSetFactory = replacePatchSetFactory;
+ this.mergedSenderFactory = mergedSenderFactory;
+
+ this.requestScopePropagator = requestScopePropagator;
+ this.projectControl = projectControl;
+ this.checkMergedInto = checkMergedInto;
+ this.priorPatchSetId = priorPatchSetId;
+ this.priorCommit = priorCommit;
+ this.patchSetId = patchSetId;
+ this.commit = commit;
+ this.info = info;
+ this.groups = groups;
+ this.magicBranch = magicBranch;
+ this.pushCertificate = pushCertificate;
+ }
+
+ @Override
+ public void updateRepo(RepoContext ctx) throws Exception {
+ changeKind = changeKindCache.getChangeKind(projectControl.getProjectState(),
+ ctx.getRepository(), priorCommit, commit);
+ }
+
+ @Override
+ public boolean updateChange(BatchUpdate.ChangeContext ctx)
+ throws OrmException, IOException {
+ change = ctx.getChange();
+ if (change == null || change.getStatus().isClosed()) {
+ rejectMessage = CHANGE_IS_CLOSED;
+ return false;
+ }
+ if (groups.isEmpty()) {
+ PatchSet prevPs = psUtil.current(ctx.getDb(), ctx.getNotes());
+ groups = prevPs != null
+ ? prevPs.getGroups()
+ : ImmutableList.<String> of();
+ }
+
+ ChangeUpdate update = ctx.getUpdate(patchSetId);
+ update.setSubjectForCommit("Create patch set " + patchSetId.get());
+
+ if (magicBranch != null) {
+ recipients.add(magicBranch.getMailRecipients());
+ approvals.putAll(magicBranch.labels);
+ Set<String> hashtags = magicBranch.hashtags;
+ if (hashtags != null && !hashtags.isEmpty()) {
+ hashtags.addAll(ctx.getNotes().getHashtags());
+ update.setHashtags(hashtags);
+ }
+ if (magicBranch.topic != null
+ && !magicBranch.topic.equals(ctx.getChange().getTopic())) {
+ update.setTopic(magicBranch.topic);
+ }
+ }
+
+ boolean draft = magicBranch != null && magicBranch.draft;
+ newPatchSet = psUtil.insert(
+ ctx.getDb(), ctx.getRevWalk(), update, patchSetId, commit, draft, groups,
+ pushCertificate != null
+ ? pushCertificate.toTextWithSignature()
+ : null);
+
+ if (checkMergedInto) {
+ Ref mergedInto = findMergedInto(ctx, change.getDest().get(), commit);
+ mergedIntoRef = mergedInto != null ? mergedInto.getName() : null;
+ }
+
+ recipients.add(getRecipientsFromFooters(
+ accountResolver, draft, commit.getFooterLines()));
+ recipients.remove(ctx.getUser().getAccountId());
+ ChangeData cd = changeDataFactory.create(ctx.getDb(), ctx.getControl());
+ MailRecipients oldRecipients =
+ getRecipientsFromReviewers(cd.reviewers());
+ approvalCopier.copy(ctx.getDb(), ctx.getControl(), newPatchSet);
+ approvalsUtil.addReviewers(ctx.getDb(), update,
+ projectControl.getLabelTypes(), change, newPatchSet, info,
+ recipients.getReviewers(), oldRecipients.getAll());
+ approvalsUtil.addApprovals(ctx.getDb(), update,
+ projectControl.getLabelTypes(), newPatchSet, ctx.getControl(),
+ approvals);
+ recipients.add(oldRecipients);
+
+ msg = new ChangeMessage(
+ new ChangeMessage.Key(change.getId(),
+ ChangeUtil.messageUUID(ctx.getDb())),
+ ctx.getUser().getAccountId(), ctx.getWhen(), patchSetId);
+ msg.setMessage(renderMessageWithApprovals(patchSetId.get(),
+ changeKindMessage(changeKind), approvals, scanLabels(ctx, approvals)));
+ cmUtil.addChangeMessage(ctx.getDb(), update, msg);
+
+ if (mergedIntoRef == null) {
+ resetChange(ctx, msg);
+ }
+ ctx.saveChange();
+
+ return true;
+ }
+
+ private String changeKindMessage(ChangeKind changeKind) {
+ switch (changeKind) {
+ case MERGE_FIRST_PARENT_UPDATE:
+ case TRIVIAL_REBASE:
+ case NO_CHANGE:
+ return ": Patch Set " + priorPatchSetId.get() + " was rebased";
+ case NO_CODE_CHANGE:
+ return ": Commit message was updated";
+ case REWORK:
+ default:
+ return null;
+ }
+ }
+
+ private static String renderMessageWithApprovals(int patchSetId,
+ String suffix, Map<String, Short> n, Map<String, PatchSetApproval> c) {
+ StringBuilder msgs = new StringBuilder("Uploaded patch set " + patchSetId);
+ if (!n.isEmpty()) {
+ boolean first = true;
+ for (Map.Entry<String, Short> e : n.entrySet()) {
+ if (c.containsKey(e.getKey())
+ && c.get(e.getKey()).getValue() == e.getValue()) {
+ continue;
+ }
+ if (first) {
+ msgs.append(":");
+ first = false;
+ }
+ msgs.append(" ")
+ .append(LabelVote.create(e.getKey(), e.getValue()).format());
+ }
+ }
+
+ if (!Strings.isNullOrEmpty(suffix)) {
+ msgs.append(suffix);
+ }
+
+ return msgs.append('.').toString();
+ }
+
+ private Map<String, PatchSetApproval> scanLabels(ChangeContext ctx,
+ Map<String, Short> approvals) throws OrmException {
+ Map<String, PatchSetApproval> current = new HashMap<>();
+ // We optimize here and only retrieve current when approvals provided
+ if (!approvals.isEmpty()) {
+ for (PatchSetApproval a : approvalsUtil.byPatchSetUser(ctx.getDb(),
+ ctx.getControl(), priorPatchSetId,
+ ctx.getUser().getAccountId())) {
+ if (a.isSubmit()) {
+ continue;
+ }
+
+ LabelType lt = projectControl.getLabelTypes().byLabel(a.getLabelId());
+ if (lt != null) {
+ current.put(lt.getName(), a);
+ }
+ }
+ }
+ return current;
+ }
+
+ private void resetChange(ChangeContext ctx, ChangeMessage msg)
+ throws OrmException {
+ Change change = ctx.getChange();
+ if (change.getStatus().isClosed()) {
+ ctx.getDb().patchSets().delete(Collections.singleton(newPatchSet));
+ ctx.getDb().changeMessages().delete(Collections.singleton(msg));
+ rejectMessage = CHANGE_IS_CLOSED;
+ return;
+ }
+
+ if (!change.currentPatchSetId().equals(priorPatchSetId)) {
+ return;
+ }
+
+ if (magicBranch != null && magicBranch.topic != null) {
+ change.setTopic(magicBranch.topic);
+ }
+ if (change.getStatus() == Change.Status.DRAFT && newPatchSet.isDraft()) {
+ // Leave in draft status.
+ } else {
+ change.setStatus(Change.Status.NEW);
+ }
+ change.setCurrentPatchSet(info);
+
+ List<String> idList = commit.getFooterLines(CHANGE_ID);
+ if (idList.isEmpty()) {
+ change.setKey(new Change.Key("I" + commit.name()));
+ } else {
+ change.setKey(new Change.Key(idList.get(idList.size() - 1).trim()));
+ }
+ }
+
+ @Override
+ public void postUpdate(final Context ctx) throws Exception {
+ if (changeKind != ChangeKind.TRIVIAL_REBASE) {
+ Runnable sender = new Runnable() {
+ @Override
+ public void run() {
+ try {
+ ReplacePatchSetSender cm = replacePatchSetFactory.create(
+ projectControl.getProject().getNameKey(), change.getId());
+ cm.setFrom(ctx.getUser().getAccountId());
+ cm.setPatchSet(newPatchSet, info);
+ cm.setChangeMessage(msg);
+ if (magicBranch != null && magicBranch.notify != null) {
+ cm.setNotify(magicBranch.notify);
+ }
+ cm.addReviewers(recipients.getReviewers());
+ cm.addExtraCC(recipients.getCcOnly());
+ cm.send();
+ } catch (Exception e) {
+ log.error("Cannot send email for new patch set " + newPatchSet.getId(), e);
+ }
+ if (mergedIntoRef != null) {
+ sendMergedEmail(ctx);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "send-email newpatchset";
+ }
+ };
+
+ if (requestScopePropagator != null) {
+ sendEmailExecutor.submit(requestScopePropagator.wrap(sender));
+ } else {
+ sender.run();
+ }
+ }
+
+ Account account = ctx.getUser().asIdentifiedUser().getAccount();
+ hooks.doPatchsetCreatedHook(change, newPatchSet, ctx.getDb());
+ if (mergedIntoRef != null) {
+ hooks.doChangeMergedHook(change, account, newPatchSet, ctx.getDb(),
+ commit.getName());
+ }
+ if (!approvals.isEmpty()) {
+ hooks.doCommentAddedHook(change, account, newPatchSet, null, approvals,
+ ctx.getDb());
+ }
+ }
+
+ private void sendMergedEmail(final Context ctx) {
+ sendEmailExecutor.submit(requestScopePropagator.wrap(new Runnable() {
+ @Override
+ public void run() {
+ try {
+ MergedSender cm = mergedSenderFactory
+ .create(projectControl.getProject().getNameKey(), change.getId());
+ cm.setFrom(ctx.getUser().getAccountId());
+ cm.setPatchSet(newPatchSet, info);
+ cm.send();
+ } catch (Exception e) {
+ log.error("Cannot send email for submitted patch set "
+ + patchSetId, e);
+ }
+ }
+
+ @Override
+ public String toString() {
+ return "send-email merged";
+ }
+ }));
+ }
+
+ public PatchSet getPatchSet() {
+ return newPatchSet;
+ }
+
+ public List<String> getGroups() {
+ return groups;
+ }
+
+ public String getMergedIntoRef() {
+ return mergedIntoRef;
+ }
+
+ public String getRejectMessage() {
+ return rejectMessage;
+ }
+
+ private Ref findMergedInto(ChangeContext ctx, String first, RevCommit commit) {
+ try {
+ RefDatabase refDatabase = ctx.getRepository().getRefDatabase();
+
+ Ref firstRef = refDatabase.exactRef(first);
+ if (firstRef != null
+ && isMergedInto(ctx.getRevWalk(), commit, firstRef)) {
+ return firstRef;
+ }
+
+ for (Ref ref : refDatabase.getRefs(Constants.R_HEADS).values()) {
+ if (isMergedInto(ctx.getRevWalk(), commit, ref)) {
+ return ref;
+ }
+ }
+ return null;
+ } catch (IOException e) {
+ log.warn("Can't check for already submitted change", e);
+ return null;
+ }
+ }
+
+ private static boolean isMergedInto(RevWalk rw, RevCommit commit, Ref ref)
+ throws IOException {
+ return rw.isMergedInto(commit, rw.parseCommit(ref.getObjectId()));
+ }
+}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java b/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
index f3a2ea2..1b1ddbf 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/group/ListGroups.java
@@ -127,7 +127,8 @@
this.matchSubstring = matchSubstring;
}
- @Option(name = "--suggest", usage = "to get a suggestion of groups")
+ @Option(name = "--suggest", aliases = {"-s"},
+ usage = "to get a suggestion of groups")
public void setSuggest(String suggest) {
this.suggest = suggest;
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
index 3199a47..f6f7dd5 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/ChangeNoteUtil.java
@@ -16,7 +16,6 @@
import com.google.common.annotations.VisibleForTesting;
import com.google.common.primitives.Ints;
-import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.RefNames;
@@ -62,7 +61,7 @@
public static PersonIdent newIdent(Account author, Date when,
PersonIdent serverIdent, String anonymousCowardName) {
return new PersonIdent(
- new AccountInfo(author).getName(anonymousCowardName),
+ author.getName(anonymousCowardName),
author.getId().get() + "@" + GERRIT_PLACEHOLDER_HOST,
when, serverIdent.getTimeZone());
}
diff --git a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
index a35e7b9..b59386b 100644
--- a/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
+++ b/gerrit-server/src/main/java/com/google/gerrit/server/notedb/CommentsInNotesUtil.java
@@ -26,7 +26,6 @@
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.primitives.Ints;
-import com.google.gerrit.common.data.AccountInfo;
import com.google.gerrit.reviewdb.client.Account;
import com.google.gerrit.reviewdb.client.Change;
import com.google.gerrit.reviewdb.client.CommentRange;
@@ -364,7 +363,7 @@
private PersonIdent newIdent(Account author, Date when) {
return new PersonIdent(
- new AccountInfo(author).getName(anonymousCowardName),
+ author.getName(anonymousCowardName),
author.getId().get() + "@" + GERRIT_PLACEHOLDER_HOST,
when, serverIdent.getTimeZone());
}
diff --git a/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java b/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java
index 4cd31ab..3e19366 100644
--- a/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java
+++ b/gerrit-server/src/test/java/com/google/gerrit/server/change/IncludedInResolverTest.java
@@ -14,8 +14,6 @@
package com.google.gerrit.server.change;
-import com.google.gerrit.common.data.IncludedInDetail;
-
import org.eclipse.jgit.api.Git;
import org.eclipse.jgit.api.MergeCommand.FastForwardMode;
import org.eclipse.jgit.junit.RepositoryTestCase;
@@ -138,7 +136,7 @@
@Test
public void resolveLatestCommit() throws Exception {
// Check tip commit
- IncludedInDetail detail = resolve(commit_v2_5);
+ IncludedInResolver.Result detail = resolve(commit_v2_5);
// Check that only tags and branches which refer the tip are returned
expTags.add(TAG_2_5);
@@ -152,7 +150,7 @@
@Test
public void resolveFirstCommit() throws Exception {
// Check first commit
- IncludedInDetail detail = resolve(commit_initial);
+ IncludedInResolver.Result detail = resolve(commit_initial);
// Check whether all tags and branches are returned
expTags.add(TAG_1_0);
@@ -176,7 +174,7 @@
@Test
public void resolveBetwixtCommit() throws Exception {
// Check a commit somewhere in the middle
- IncludedInDetail detail = resolve(commit_v1_3);
+ IncludedInResolver.Result detail = resolve(commit_v1_3);
// Check whether all succeeding tags and branches are returned
expTags.add(TAG_1_3);
@@ -190,7 +188,7 @@
assertEquals(expBranches, detail.getBranches());
}
- private IncludedInDetail resolve(RevCommit commit) throws Exception {
+ private IncludedInResolver.Result resolve(RevCommit commit) throws Exception {
return IncludedInResolver.resolve(db, revWalk, commit);
}
diff --git a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
index 1773497..4250ce2 100644
--- a/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
+++ b/polygerrit-ui/app/behaviors/keyboard-shortcut-behavior.html
@@ -56,7 +56,8 @@
target.tagName == 'TEXTAREA' ||
target.tagName == 'SELECT' ||
target.tagName == 'BUTTON' ||
- target.tagName == 'A';
+ target.tagName == 'A' ||
+ target.tagName == 'GR-BUTTON';
},
};
diff --git a/polygerrit-ui/app/elements/gr-account-dropdown.html b/polygerrit-ui/app/elements/gr-account-dropdown.html
index 887cb0c..99850f6 100644
--- a/polygerrit-ui/app/elements/gr-account-dropdown.html
+++ b/polygerrit-ui/app/elements/gr-account-dropdown.html
@@ -16,6 +16,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-dropdown/iron-dropdown.html">
+<link rel="import" href="gr-button.html">
<dom-module id="gr-account-dropdown">
<style>
@@ -23,8 +24,7 @@
display: inline-block;
}
.dropdown-trigger {
- color: #00e;
- cursor: pointer;
+ text-decoration: none;
}
.dropdown-content {
background-color: #fff;
@@ -58,8 +58,8 @@
}
</style>
<template>
- <button class="dropdown-trigger" id="trigger"
- on-tap="_showDropdownTapHandler">[[account.name]]</button>
+ <gr-button link class="dropdown-trigger" id="trigger"
+ on-tap="_showDropdownTapHandler">[[account.name]]</gr-button>
<iron-dropdown id="dropdown"
vertical-align="top"
vertical-offset="25"
diff --git a/polygerrit-ui/app/elements/gr-button.html b/polygerrit-ui/app/elements/gr-button.html
new file mode 100644
index 0000000..2af6a5d
--- /dev/null
+++ b/polygerrit-ui/app/elements/gr-button.html
@@ -0,0 +1,147 @@
+<!--
+Copyright (C) 2016 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.
+-->
+
+<link rel="import" href="../bower_components/polymer/polymer.html">
+<link rel="import" href="../behaviors/keyboard-shortcut-behavior.html">
+
+<dom-module id="gr-button">
+ <template strip-whitespace>
+ <style>
+ :host {
+ background-color: #fff;
+ border: 1px solid #d1d2d3;
+ border-radius: 2px;
+ box-sizing: border-box;
+ color: #333;
+ cursor: pointer;
+ display: inline-block;
+ font-family: var(--font-family);
+ font-size: 13px;
+ font-weight: bold;
+ outline-width: 0;
+ padding: .3em .65em;
+ position: relative;
+ text-align: center;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ -webkit-user-select: none;
+ user-select: none;
+ }
+ :host([hidden]) {
+ display: none;
+ }
+ :host([primary]) {
+ background-color: #4d90fe;
+ border-color: #3079ed;
+ color: #fff;
+ }
+ :host([small]) {
+ font-size: 12px;
+ }
+ :host([link]) {
+ background-color: transparent;
+ border: none;
+ color: #00f;
+ font-size: inherit;
+ font-weight: normal;
+ padding: 0;
+ text-decoration: underline;
+ }
+ :host([loading]),
+ :host([disabled]) {
+ background-color: #efefef;
+ color: #aaa;
+ }
+ :host([disabled]) {
+ cursor: default;
+ pointer-events: none;
+ }
+ :host([loading]),
+ :host([loading][disabled]) {
+ cursor: wait;
+ }
+ :host(:focus),
+ :host(:hover) {
+ border-color: #666;
+ }
+ :host(:active) {
+ border-color: #d1d2d3;
+ color: #aaa;
+ }
+ :host([primary]:focus),
+ :host([primary]:hover) {
+ border-color: #00F;
+ }
+ :host([primary]:active) {
+ border-color: #0c2188;
+ color: #fff;
+ }
+ :host([primary][loading]),
+ :host([primary][disabled]) {
+ background-color: #7caeff;
+ border-color: transparent;
+ color: #fff;
+ }
+ </style>
+ <content></content>
+ </template>
+ <script>
+ (function() {
+ 'use strict';
+
+ Polymer({
+ is: 'gr-button',
+
+ properties: {
+ disabled: {
+ type: Boolean,
+ observer: '_disabledChanged',
+ reflectToAttribute: true,
+ },
+ _enabledTabindex: {
+ type: String,
+ value: '0',
+ },
+ },
+
+ behaviors: [
+ Gerrit.KeyboardShortcutBehavior,
+ ],
+
+ hostAttributes: {
+ role: 'button',
+ tabindex: '0',
+ },
+
+ _disabledChanged: function(disabled) {
+ if (disabled) {
+ this._enabledTabindex = this.getAttribute('tabindex');
+ }
+ this.setAttribute('tabindex', disabled ? '-1' : this._enabledTabindex);
+ },
+
+ _handleKey: function(e) {
+ switch (e.keyCode) {
+ case 32: // 'spacebar'
+ case 13: // 'enter'
+ e.preventDefault();
+ this.click();
+ }
+ },
+ });
+ })();
+ </script>
+</dom-module>
diff --git a/polygerrit-ui/app/elements/gr-change-actions.html b/polygerrit-ui/app/elements/gr-change-actions.html
index 997bfb22..9e9b078 100644
--- a/polygerrit-ui/app/elements/gr-change-actions.html
+++ b/polygerrit-ui/app/elements/gr-change-actions.html
@@ -18,6 +18,7 @@
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-confirm-rebase-dialog.html">
<link rel="import" href="gr-overlay.html">
<link rel="import" href="gr-request.html">
@@ -28,39 +29,12 @@
:host {
display: block;
}
- .primary {
- background-color: #448aff;
- border-color: #448aff;
- color: #fff;
- }
- button:before {
+ gr-button:before {
content: attr(data-label);
}
- button {
- background-color: #f1f2f3;
- border: 1px solid #aaa;
- border-radius: 2px;
- cursor: pointer;
- font: inherit;
- padding: .5em .75em;
- }
- button[loading],
- button[disabled] {
- opacity: .75;
- }
- button[loading] {
- cursor: wait;
- }
- button[loading]:before {
+ gr-button[loading]:before {
content: attr(data-loading-label);
}
- button[disabled] {
- cursor: default;
- }
- button[loading],
- button[loading][disabled] {
- cursor: wait;
- }
</style>
<gr-ajax id="actionsXHR"
url="[[_computeRevisionActionsPath(changeNum, patchNum)]]"
@@ -68,21 +42,21 @@
loading="{{_loading}}"></gr-ajax>
<div>
<template is="dom-repeat" items="[[_computeActionValues(actions, 'change')]]" as="action">
- <button title$="[[action.title]]"
- class$="[[_computeButtonClass(action.__key)]]"
+ <gr-button title$="[[action.title]]"
+ primary$="[[_computePrimary(action.__key)]]"
hidden$="[[!action.enabled]]"
data-action-key$="[[action.__key]]"
data-label$="[[action.label]]"
- on-tap="_handleActionTap"></button>
+ on-tap="_handleActionTap"></gr-button>
</template>
<template is="dom-repeat" items="[[_computeActionValues(_revisionActions, 'revision')]]" as="action">
- <button title$="[[action.title]]"
- class$="[[_computeButtonClass(action.__key)]]"
+ <gr-button title$="[[action.title]]"
+ primary$="[[_computePrimary(action.__key)]]"
disabled$="[[!action.enabled]]"
data-action-key$="[[action.__key]]"
data-label$="[[action.label]]"
data-loading-label$="[[_computeLoadingLabel(action.__key)]]"
- on-tap="_handleActionTap"></button>
+ on-tap="_handleActionTap"></gr-button>
</template>
</div>
<gr-overlay id="overlay" with-backdrop>
@@ -183,6 +157,10 @@
}[action];
},
+ _computePrimary: function(actionKey) {
+ return actionKey == 'submit';
+ },
+
_computeButtonClass: function(action) {
return action == 'submit' ? 'primary' : '';
},
diff --git a/polygerrit-ui/app/elements/gr-change-star.html b/polygerrit-ui/app/elements/gr-change-star.html
index b3ff00d..ad377ef 100644
--- a/polygerrit-ui/app/elements/gr-change-star.html
+++ b/polygerrit-ui/app/elements/gr-change-star.html
@@ -34,7 +34,7 @@
outline: none;
}
.starButton svg {
- fill: #aab8c2;
+ fill: #ccc;
width: 1em;
height: 1em;
}
diff --git a/polygerrit-ui/app/elements/gr-change-view.html b/polygerrit-ui/app/elements/gr-change-view.html
index f16732c..04f52b1 100644
--- a/polygerrit-ui/app/elements/gr-change-view.html
+++ b/polygerrit-ui/app/elements/gr-change-view.html
@@ -19,6 +19,7 @@
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-account-link.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-change-actions.html">
<link rel="import" href="gr-change-star.html">
<link rel="import" href="gr-date-formatter.html">
@@ -199,7 +200,7 @@
permitted-labels="[[_change.permitted_labels]]"
on-send="_handleReplySent"
hidden$="[[!_loggedIn]]">Reply</gr-reply-dropdown>
- <a class="download" href="#" on-tap="_handleDownloadTap">Download</a>
+ <gr-button link class="download" on-tap="_handleDownloadTap">Download</gr-button>
<label class="patchSelectLabel" for="patchSetSelect">Patch set</label>
<select id="patchSetSelect" on-change="_handlePatchChange">
<template is="dom-repeat" items="{{_allPatchSets}}" as="patchNumber">
diff --git a/polygerrit-ui/app/elements/gr-confirm-dialog.html b/polygerrit-ui/app/elements/gr-confirm-dialog.html
index beea8d2..0ba36d6 100644
--- a/polygerrit-ui/app/elements/gr-confirm-dialog.html
+++ b/polygerrit-ui/app/elements/gr-confirm-dialog.html
@@ -15,6 +15,7 @@
-->
<link rel="import" href="../bower_components/polymer/polymer.html">
+<link rel="import" href="gr-button.html">
<dom-module id="gr-confirm-dialog">
<template>
@@ -35,25 +36,12 @@
display: flex;
justify-content: space-between;
}
- button {
- background-color: #f1f2f3;
- border: 1px solid #aaa;
- border-radius: 2px;
- cursor: pointer;
- font: inherit;
- padding: .5em .75em;
- }
- .confirm {
- background-color: #448aff;
- border-color: #448aff;
- color: #fff;
- }
</style>
<div class="header"><content select=".header"></content></div>
<div class="mainContent"><content select=".main"></content></div>
<div class="footer">
- <button class="confirm" on-tap="_handleConfirmTap">[[confirmLabel]]</button>
- <button class="cancel" on-tap="_handleCancelTap">Cancel</button>
+ <gr-button primary on-tap="_handleConfirmTap">[[confirmLabel]]</gr-button>
+ <gr-button on-tap="_handleCancelTap">Cancel</gr-button>
</div>
</template>
<script>
diff --git a/polygerrit-ui/app/elements/gr-diff-comment.html b/polygerrit-ui/app/elements/gr-diff-comment.html
index 82b2ace..c544a8d 100644
--- a/polygerrit-ui/app/elements/gr-diff-comment.html
+++ b/polygerrit-ui/app/elements/gr-diff-comment.html
@@ -16,6 +16,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-autogrow-textarea/iron-autogrow-textarea.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-date-formatter.html">
<link rel="import" href="gr-linked-text.html">
<link rel="import" href="gr-request.html">
@@ -70,9 +71,7 @@
padding-top: 0;
}
.action {
- cursor: pointer;
margin-right: .5em;
- padding: .2em .6em .3em;
}
.danger {
display: flex;
@@ -137,15 +136,15 @@
content="[[comment.message]]"
config="[[projectConfig.commentlinks]]"></gr-linked-text>
<div class="actions" hidden$="[[!showActions]]">
- <button class="action reply" on-tap="_handleReply">Reply</button>
- <button class="action quote" on-tap="_handleQuote">Quote</button>
- <button class="action done" on-tap="_handleDone">Done</button>
- <button class="action edit" on-tap="_handleEdit">Edit</button>
- <button class="action save" on-tap="_handleSave"
- disabled$="[[_computeSaveDisabled(_editDraft)]]">Save</button>
- <button class="action cancel" on-tap="_handleCancel" hidden>Cancel</button>
+ <gr-button class="action reply" on-tap="_handleReply">Reply</gr-button>
+ <gr-button class="action quote" on-tap="_handleQuote">Quote</gr-button>
+ <gr-button class="action done" on-tap="_handleDone">Done</gr-button>
+ <gr-button class="action edit" on-tap="_handleEdit">Edit</gr-button>
+ <gr-button class="action save" on-tap="_handleSave"
+ disabled$="[[_computeSaveDisabled(_editDraft)]]">Save</gr-button>
+ <gr-button class="action cancel" on-tap="_handleCancel" hidden>Cancel</gr-button>
<div class="danger">
- <button class="action discard" on-tap="_handleDiscard">Discard</button>
+ <gr-button class="action discard" on-tap="_handleDiscard">Discard</gr-button>
</div>
</div>
</div>
diff --git a/polygerrit-ui/app/elements/gr-diff-preferences.html b/polygerrit-ui/app/elements/gr-diff-preferences.html
index 7656403..e320620 100644
--- a/polygerrit-ui/app/elements/gr-diff-preferences.html
+++ b/polygerrit-ui/app/elements/gr-diff-preferences.html
@@ -16,6 +16,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-input/iron-input.html">
+<link rel="import" href="gr-button.html">
<dom-module id="gr-diff-preferences">
<template>
@@ -27,7 +28,6 @@
opacity: .5;
pointer-events: none;
}
- button,
input,
select {
font: inherit;
@@ -35,19 +35,6 @@
input[type="number"] {
width: 4em;
}
- button {
- background-color: #f1f2f3;
- border: 1px solid #aaa;
- border-radius: 2px;
- cursor: pointer;
- font: inherit;
- padding: .2em .75em;
- }
- button.primary {
- background: #448aff;
- border: none;
- color: #fff;
- }
.header,
.actions {
padding: 1em 1.5em;
@@ -75,11 +62,7 @@
.actions {
border-top: 1px solid #ddd;
display: flex;
- }
- .cancel {
- display: flex;
- flex: 1;
- justify-content: flex-end;
+ justify-content: space-between;
}
</style>
<div class="header">
@@ -119,10 +102,8 @@
</div>
</div>
<div class="actions">
- <button class="primary" on-tap="_handleSave">Save</button>
- <div class="cancel">
- <button on-tap="_handleCancel">Cancel</button>
- </div>
+ <gr-button primary on-tap="_handleSave">Save</gr-button>
+ <gr-button on-tap="_handleCancel">Cancel</gr-button>
</div>
</template>
<script>
diff --git a/polygerrit-ui/app/elements/gr-diff-view.html b/polygerrit-ui/app/elements/gr-diff-view.html
index 9d30c4a0..1e656ac 100644
--- a/polygerrit-ui/app/elements/gr-diff-view.html
+++ b/polygerrit-ui/app/elements/gr-diff-view.html
@@ -19,6 +19,7 @@
<link rel="import" href="../behaviors/keyboard-shortcut-behavior.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-diff.html">
<link rel="import" href="gr-request.html">
@@ -33,6 +34,11 @@
margin-top: 1em;
padding: .75em var(--default-horizontal-margin);
}
+ .reviewed {
+ display: inline-block;
+ margin: 0 .25em;
+ vertical-align: .15em;
+ }
.jumpToFileContainer {
display: inline-block;
}
@@ -77,11 +83,10 @@
background-color: #fff;
color: #000;
}
- button {
- background: none;
- border: none;
+ gr-button {
font: inherit;
padding: .3em 0;
+ text-decoration: none;
}
</style>
<gr-ajax id="changeDetailXHR"
@@ -100,13 +105,16 @@
<h3>
<a href$="[[_computeChangePath(_changeNum)]]">[[_changeNum]]</a><span>:</span>
<span>[[_change.subject]]</span> —
- <input id="reviewed" type="checkbox" on-change="_handleReviewedChange"
+ <input id="reviewed"
+ class="reviewed"
+ type="checkbox"
+ on-change="_handleReviewedChange"
hidden$="[[!_loggedIn]]" hidden>
<div class="jumpToFileContainer">
- <button class="dropdown-trigger" id="trigger" on-tap="_showDropdownTapHandler">
+ <gr-button link class="dropdown-trigger" id="trigger" on-tap="_showDropdownTapHandler">
<span>[[_path]]</span>
<span class="downArrow">▼</span>
- </button>
+ </gr-button>
<iron-dropdown id="dropdown" vertical-align="top" vertical-offset="25">
<div class="dropdown-content">
<template is="dom-repeat" items="[[_fileList]]" as="path">
diff --git a/polygerrit-ui/app/elements/gr-diff.html b/polygerrit-ui/app/elements/gr-diff.html
index 50dc87f..61cb1c9 100644
--- a/polygerrit-ui/app/elements/gr-diff.html
+++ b/polygerrit-ui/app/elements/gr-diff.html
@@ -17,6 +17,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-diff-preferences.html">
<link rel="import" href="gr-diff-side.html">
<link rel="import" href="gr-overlay.html">
@@ -77,11 +78,11 @@
change-num="[[changeNum]]"
patch-range="[[patchRange]]"
available-patches="[[availablePatches]]"></gr-patch-range-select>
- <a class="prefsButton"
- href="#"
+ <gr-button link
+ class="prefsButton"
on-tap="_handlePrefsTap"
hidden$="[[!prefs]]"
- hidden>Diff View Preferences</a>
+ hidden>Diff View Preferences</gr-button>
</div>
<gr-overlay id="prefsOverlay" with-backdrop>
<gr-diff-preferences
diff --git a/polygerrit-ui/app/elements/gr-download-dialog.html b/polygerrit-ui/app/elements/gr-download-dialog.html
index 533f265..b45c562 100644
--- a/polygerrit-ui/app/elements/gr-download-dialog.html
+++ b/polygerrit-ui/app/elements/gr-download-dialog.html
@@ -17,6 +17,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
+<link rel="import" href="gr-button.html">
<dom-module id="gr-download-dialog">
<template>
@@ -34,7 +35,7 @@
margin: 0;
padding: 0;
}
- li a {
+ li gr-button {
margin-right: 1em;
}
label,
@@ -50,7 +51,7 @@
margin-bottom: .5em;
width: 60em;
}
- li[selected] a {
+ li[selected] gr-button {
color: #000;
font-weight: bold;
text-decoration: none;
@@ -91,14 +92,14 @@
<ul hidden$="[[!_schemes.length]]" hidden>
<template is="dom-repeat" items="[[_schemes]]" as="scheme">
<li selected$="[[_computeSchemeSelected(scheme, _selectedScheme)]]">
- <a href="#" data-scheme$="[[scheme]]" on-tap="_handleSchemeTap">
+ <gr-button link data-scheme$="[[scheme]]" on-tap="_handleSchemeTap">
[[scheme]]
- </a>
+ </gr-button>
</li>
</template>
</ul>
<span class="closeButtonContainer">
- <a href="#" on-tap="_handleCloseTap">Close</a>
+ <gr-button link on-tap="_handleCloseTap">Close</gr-button>
</span>
</div>
<div class="commands" hidden$="[[!_schemes.length]]" hidden>
diff --git a/polygerrit-ui/app/elements/gr-message.html b/polygerrit-ui/app/elements/gr-message.html
index fe94c3c..056546f 100644
--- a/polygerrit-ui/app/elements/gr-message.html
+++ b/polygerrit-ui/app/elements/gr-message.html
@@ -16,6 +16,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="gr-account-link.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-comment-list.html">
<link rel="import" href="gr-date-formatter.html">
<link rel="import" href="gr-linked-text.html">
@@ -91,9 +92,6 @@
.replyContainer {
padding: .5em 0 1em;
}
- .reply {
- padding: .2em .6em .3em;
- }
</style>
<div class$="[[_computeClass(expanded, showAvatar)]]">
<gr-avatar account="[[message.author]]" image-size="100"></gr-avatar>
@@ -115,7 +113,7 @@
</a>
</div>
<div class="replyContainer" hidden$="[[!showReplyButton]]" hidden>
- <button class="reply" on-tap="_handleReplyTap">Reply</button>
+ <gr-button small on-tap="_handleReplyTap">Reply</gr-button>
</div>
</div>
</template>
diff --git a/polygerrit-ui/app/elements/gr-reply-dropdown.html b/polygerrit-ui/app/elements/gr-reply-dropdown.html
index 9562f7f..6f5d6b9 100644
--- a/polygerrit-ui/app/elements/gr-reply-dropdown.html
+++ b/polygerrit-ui/app/elements/gr-reply-dropdown.html
@@ -20,6 +20,7 @@
<link rel="import" href="../bower_components/iron-selector/iron-selector.html">
<link rel="import" href="../behaviors/rest-client-behavior.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-request.html">
<dom-module id="gr-reply-dropdown">
@@ -38,14 +39,6 @@
box-shadow: 0 1px 5px rgba(0, 0, 0, .3);
width: 40em;
}
- button {
- background-color: #f1f2f3;
- border: 1px solid #aaa;
- border-radius: 2px;
- cursor: pointer;
- font: inherit;
- padding: .2em .5em;
- }
section {
border-top: 1px solid #ddd;
padding: .5em .75em;
@@ -73,25 +66,18 @@
iron-selector {
display: inline-flex;
}
- iron-selector > button {
- background-color: #fff;
- border: 1px solid #ddd;
- border-left: none;
- padding: .25em 0;
- cursor: pointer;
- width: 3em;
- text-align: center;
+ iron-selector > gr-button {
+ margin-right: .25em;
}
- iron-selector > button:first-of-type {
+ iron-selector > gr-button:first-of-type {
border-top-left-radius: 2px;
border-bottom-left-radius: 2px;
- border-left: 1px solid #ddd;
}
- iron-selector > button:last-of-type {
+ iron-selector > gr-button:last-of-type {
border-top-right-radius: 2px;
border-bottom-right-radius: 2px;
}
- iron-selector > button.iron-selected {
+ iron-selector > gr-button.iron-selected {
background-color: #ddd;
}
.draftsContainer h3 {
@@ -99,22 +85,18 @@
}
.actionsContainer {
display: flex;
+ justify-content: space-between;
}
.action:link,
.action:visited {
color: #00e;
}
- .danger {
- display: flex;
- flex: 1;
- justify-content: flex-end;
- }
</style>
<template>
<gr-ajax id="draftsXHR"
url="[[_computeDraftsURL(changeNum)]]"
last-response="{{_drafts}}"></gr-ajax>
- <button id="trigger" on-tap="_showPopupTapHandler">Reply</button>
+ <gr-button id="trigger" on-tap="_showPopupTapHandler">Reply</gr-button>
<iron-dropdown id="dropdown"
vertical-align="top"
vertical-offset="25"
@@ -139,7 +121,7 @@
<template is="dom-repeat"
items="[[_computePermittedLabelValues(permittedLabels, label)]]"
as="value">
- <button data-value$="[[value]]">[[value]]</button>
+ <gr-button data-value$="[[value]]">[[value]]</gr-button>
</template>
</iron-selector>
</div>
@@ -153,10 +135,8 @@
patch-num="[[patchNum]]"></gr-comment-list>
</section>
<section class="actionsContainer">
- <button class="action send" on-tap="_sendTapHandler">Send</button>
- <div class="danger">
- <button class="action cancel" on-tap="_cancelTapHandler">Cancel</button>
- </div>
+ <gr-button primary class="action send" on-tap="_sendTapHandler">Send</gr-button>
+ <gr-button class="action cancel" on-tap="_cancelTapHandler">Cancel</gr-button>
</section>
</div>
</iron-dropdown>
diff --git a/polygerrit-ui/app/elements/gr-reviewer-list.html b/polygerrit-ui/app/elements/gr-reviewer-list.html
index 385ffea..8cec337 100644
--- a/polygerrit-ui/app/elements/gr-reviewer-list.html
+++ b/polygerrit-ui/app/elements/gr-reviewer-list.html
@@ -18,6 +18,7 @@
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../behaviors/keyboard-shortcut-behavior.html">
<link rel="import" href="gr-ajax.html">
+<link rel="import" href="gr-button.html">
<link rel="import" href="gr-request.html">
<dom-module id="gr-reviewer-list">
@@ -76,12 +77,12 @@
<template is="dom-repeat" items="[[_reviewers]]" as="reviewer">
<div class="reviewer">
- <gr-account-link account="[[reviewer]]"></gr-account-link>
- <a class="remove"
- href="#"
+ <gr-account-link account="[[reviewer]]" show-email></gr-account-link>
+ <gr-button link
+ class="remove"
data-account-id$="[[reviewer._account_id]]"
on-tap="_handleRemoveTap"
- hidden$="[[_computeCannotRemoveReviewer(reviewer, mutable)]]">remove</a>
+ hidden$="[[_computeCannotRemoveReviewer(reviewer, mutable)]]">remove</gr-buttom>
</div>
</template>
<div class="controlsContainer" hidden$="[[!mutable]]">
@@ -89,7 +90,7 @@
<div class="inputContainer">
<input is="iron-input" id="input"
bind-value="{{_inputVal}}" disabled$="[[disabled]]">
- <a href="#" class="cancel" on-tap="_handleCancelTap">×</a>
+ <gr-button link class="cancel" on-tap="_handleCancelTap">×</gr-button>
</div>
<div class="dropdown" hidden$="[[_hideAutocomplete]]">
<template is="dom-repeat" items="[[_autocompleteData]]" as="reviewer">
@@ -109,8 +110,8 @@
</template>
</div>
</div>
- <a href="#" id="addReviewer" class="addReviewer" on-tap="_handleAddTap"
- hidden$="[[_showInput]]">Add reviewer</a>
+ <gr-button link id="addReviewer" class="addReviewer" on-tap="_handleAddTap"
+ hidden$="[[_showInput]]">Add reviewer</gr-button>
</div>
</template>
<script>
diff --git a/polygerrit-ui/app/elements/gr-search-bar.html b/polygerrit-ui/app/elements/gr-search-bar.html
index a238054..44d1b31 100644
--- a/polygerrit-ui/app/elements/gr-search-bar.html
+++ b/polygerrit-ui/app/elements/gr-search-bar.html
@@ -17,6 +17,7 @@
<link rel="import" href="../bower_components/polymer/polymer.html">
<link rel="import" href="../bower_components/iron-input/iron-input.html">
<link rel="import" href="../behaviors/keyboard-shortcut-behavior.html">
+<link rel="import" href="gr-button.html">
<dom-module id="gr-search-bar">
<template>
@@ -28,17 +29,16 @@
display: flex;
margin-left: 3em;
}
- input,
- button {
- border: 1px solid #aaa;
- font: inherit;
- padding: .2em .5em;
+ input {
+ border: 1px solid #d1d2d3;
+ outline: none;
}
input {
flex: 1;
+ font: inherit;
border-radius: 2px 0 0 2px;
}
- button {
+ gr-button {
background-color: #f1f2f3;
border-radius: 0 2px 2px 0;
border-left-width: 0;
@@ -46,7 +46,7 @@
</style>
<form>
<input is="iron-input" id="searchInput" bind-value="{{_inputVal}}">
- <button type="submit" id="searchButton">Search</button>
+ <gr-button id="searchButton">Search</gr-button>
</form>
</template>
<script>
diff --git a/polygerrit-ui/app/scripts/util.js b/polygerrit-ui/app/scripts/util.js
index c7b5c91..3f806a4 100644
--- a/polygerrit-ui/app/scripts/util.js
+++ b/polygerrit-ui/app/scripts/util.js
@@ -30,11 +30,12 @@
'>': '>',
'"': '"',
'\'': ''',
- '/': '/'
+ '/': '/',
+ '`': '`',
};
util.escapeHTML = function(str) {
- return str.replace(/[&<>"'\/]/g, function(s) {
+ return str.replace(/[&<>"'`\/]/g, function(s) {
return util.htmlEntityMap[s];
});
};
diff --git a/polygerrit-ui/app/test/gr-change-actions-test.html b/polygerrit-ui/app/test/gr-change-actions-test.html
index 3fc5ef1..e510e34 100644
--- a/polygerrit-ui/app/test/gr-change-actions-test.html
+++ b/polygerrit-ui/app/test/gr-change-actions-test.html
@@ -98,7 +98,7 @@
test('submit and rebase buttons show', function(done) {
element.async(function() {
- var buttonEls = Polymer.dom(element.root).querySelectorAll('button');
+ var buttonEls = Polymer.dom(element.root).querySelectorAll('gr-button');
assert.equal(buttonEls.length, 2);
assert.isFalse(element.hidden);
done();
@@ -107,7 +107,7 @@
test('submit change', function(done) {
element.async(function() {
- var submitButton = element.$$('button[data-action-key="submit"]');
+ var submitButton = element.$$('gr-button[data-action-key="submit"]');
assert.ok(submitButton);
MockInteractions.tap(submitButton);
server.respond();
@@ -121,7 +121,7 @@
test('rebase change', function(done) {
element.async(function() {
- var rebaseButton = element.$$('button[data-action-key="rebase"]');
+ var rebaseButton = element.$$('gr-button[data-action-key="rebase"]');
MockInteractions.tap(rebaseButton);
element.$.confirmRebase.base = '1234';
diff --git a/polygerrit-ui/app/test/gr-confirm-dialog-test.html b/polygerrit-ui/app/test/gr-confirm-dialog-test.html
index b61bb17..d19118e 100644
--- a/polygerrit-ui/app/test/gr-confirm-dialog-test.html
+++ b/polygerrit-ui/app/test/gr-confirm-dialog-test.html
@@ -45,8 +45,8 @@
element.addEventListener('confirm', handler);
element.addEventListener('cancel', handler);
- MockInteractions.tap(element.$$('.confirm'));
- MockInteractions.tap(element.$$('.cancel'));
+ MockInteractions.tap(element.$$('gr-button[primary]'));
+ MockInteractions.tap(element.$$('gr-button:not([primary])'));
});
});
diff --git a/polygerrit-ui/app/test/gr-diff-preferences-test.html b/polygerrit-ui/app/test/gr-diff-preferences-test.html
index c689834..9256f2f 100644
--- a/polygerrit-ui/app/test/gr-diff-preferences-test.html
+++ b/polygerrit-ui/app/test/gr-diff-preferences-test.html
@@ -68,8 +68,8 @@
Promise.all([savePromise, cancelPromise]).then(function() {
done();
});
- MockInteractions.tap(element.$$('button.primary'));
- MockInteractions.tap(element.$$('.cancel button'));
+ MockInteractions.tap(element.$$('gr-button[primary]'));
+ MockInteractions.tap(element.$$('gr-button:not([primary])'));
});
});
</script>
diff --git a/polygerrit-ui/app/test/gr-download-dialog-test.html b/polygerrit-ui/app/test/gr-download-dialog-test.html
index 0f674e5..fe26371 100644
--- a/polygerrit-ui/app/test/gr-download-dialog-test.html
+++ b/polygerrit-ui/app/test/gr-download-dialog-test.html
@@ -98,7 +98,7 @@
element.addEventListener('close', function() {
done();
});
- MockInteractions.tap(element.$$('.closeButtonContainer a'));
+ MockInteractions.tap(element.$$('.closeButtonContainer gr-button'));
});
test('tab selection', function() {
diff --git a/polygerrit-ui/app/test/gr-message-test.html b/polygerrit-ui/app/test/gr-message-test.html
index 1bc65f6..503da1b 100644
--- a/polygerrit-ui/app/test/gr-message-test.html
+++ b/polygerrit-ui/app/test/gr-message-test.html
@@ -57,7 +57,7 @@
assert.deepEqual(e.detail.message, element.message);
done();
});
- MockInteractions.tap(element.$$('button.reply'));
+ MockInteractions.tap(element.$$('.replyContainer gr-button'));
});
});
diff --git a/polygerrit-ui/app/test/gr-reply-dropdown-test.html b/polygerrit-ui/app/test/gr-reply-dropdown-test.html
index ca6e541..47fe03d 100644
--- a/polygerrit-ui/app/test/gr-reply-dropdown-test.html
+++ b/polygerrit-ui/app/test/gr-reply-dropdown-test.html
@@ -126,9 +126,11 @@
}
element.draft = 'I wholeheartedly disapprove';
MockInteractions.tap(element.$$(
- 'iron-selector[data-label="Code-Review"] > button[data-value="-1"]'));
+ 'iron-selector[data-label="Code-Review"] > ' +
+ 'gr-button[data-value="-1"]'));
MockInteractions.tap(element.$$(
- 'iron-selector[data-label="Verified"] > button[data-value="-1"]'));
+ 'iron-selector[data-label="Verified"] > ' +
+ 'gr-button[data-value="-1"]'));
// This is needed on non-Blink engines most likely due to the ways in
// which the dom-repeat elements are stamped.