Merge "Documentation/replace_macros: support --site-search option"
diff --git a/Documentation/dev-plugins.txt b/Documentation/dev-plugins.txt
index 1e54cbf..a3166b7 100644
--- a/Documentation/dev-plugins.txt
+++ b/Documentation/dev-plugins.txt
@@ -34,10 +34,10 @@
== Getting started
To get started with the development of a plugin clone the sample
-plugin:
+plugins:
----
-$ git clone https://gerrit.googlesource.com/plugins/cookbook-plugin
+$ git clone https://gerrit.googlesource.com/plugins/examples
----
This is a project that demonstrates the various features of the
diff --git a/WORKSPACE b/WORKSPACE
index b4b1a64..0aa31f6 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -14,9 +14,9 @@
http_archive(
name = "io_bazel_rules_closure",
- sha256 = "0e6de40666f2ebb2b30dc0339745a274d9999334a249b05a3b1f46462e489adf",
- strip_prefix = "rules_closure-87d24b1df8b62405de8dd059cb604fd9d4b1e395",
- urls = ["https://github.com/bazelbuild/rules_closure/archive/87d24b1df8b62405de8dd059cb604fd9d4b1e395.tar.gz"],
+ sha256 = "ddce3b3a3909f99b28b25071c40b7fec7e2e1d1d1a4b2e933f3082aa99517105",
+ strip_prefix = "rules_closure-316e6133888bfc39fb860a4f1a31cfcbae485aef",
+ urls = ["https://github.com/bazelbuild/rules_closure/archive/316e6133888bfc39fb860a4f1a31cfcbae485aef.tar.gz"],
)
# File is specific to Polymer and copied from the Closure Github -- should be
@@ -69,12 +69,6 @@
# Dependencies for PolyGerrit local dev server.
go_repository(
- name = "com_github_robfig_soy",
- commit = "82face14ebc0883b4ca9c901b5aaf3738b9f6a24",
- importpath = "github.com/robfig/soy",
-)
-
-go_repository(
name = "com_github_howeyc_fsnotify",
commit = "441bbc86b167f3c1f4786afae9931403b99fdacf",
importpath = "github.com/howeyc/fsnotify",
diff --git a/antlr3/BUILD b/antlr3/BUILD
index fc96715..2d3050e 100644
--- a/antlr3/BUILD
+++ b/antlr3/BUILD
@@ -20,7 +20,8 @@
name = "query_parser",
srcs = [":query"],
visibility = [
- "//java/com/google/gerrit/index:__pkg__",
+ "//java/com/google/gerrit/index:__subpackages__",
+ "//javatests/com/google/gerrit:__subpackages__",
"//javatests/com/google/gerrit/index:__pkg__",
"//plugins:__pkg__",
],
diff --git a/antlr3/com/google/gerrit/index/query/Query.g b/antlr3/com/google/gerrit/index/query/Query.g
index 953a473..1bf20aa 100644
--- a/antlr3/com/google/gerrit/index/query/Query.g
+++ b/antlr3/com/google/gerrit/index/query/Query.g
@@ -120,12 +120,24 @@
;
conditionBase
: '('! conditionOr ')'!
- | (FIELD_NAME ':') => FIELD_NAME^ ':'! fieldValue
+ | (FIELD_NAME COLON) => FIELD_NAME^ COLON! fieldValue
| fieldValue -> ^(DEFAULT_FIELD fieldValue)
;
fieldValue
- : n=FIELD_NAME -> SINGLE_WORD[n]
+ // Rewrite by invoking SINGLE_WORD fragment lexer rule, passing the field name as an argument.
+ : n=FIELD_NAME -> SINGLE_WORD[n]
+
+ // Allow field values to contain a colon. We can't do this at the lexer level, because we need to
+ // emit a separate token for the field name. If we were to allow ':' in SINGLE_WORD, then
+ // everything would just lex as DEFAULT_FIELD.
+ //
+ // Field values with a colon may be lexed either as <field>:<rest> or <word>:<rest>, depending on
+ // whether the part before the colon looks like a field name.
+ // TODO(dborowitz): Field values ending in colon still don't work.
+ | (FIELD_NAME COLON) => n=FIELD_NAME COLON fieldValue -> SINGLE_WORD[n] COLON fieldValue
+ | (SINGLE_WORD COLON) => SINGLE_WORD COLON fieldValue
+
| SINGLE_WORD
| EXACT_PHRASE
;
@@ -134,6 +146,8 @@
OR: 'OR' ;
NOT: 'NOT' ;
+COLON: ':' ;
+
WS
: ( ' ' | '\r' | '\t' | '\n' ) { $channel=HIDDEN; }
;
@@ -172,7 +186,7 @@
// '-' permit
// '.' permit
// '/' permit
- | ':'
+ | COLON
| ';'
// '<' permit
// '=' permit
diff --git a/contrib/mitm-ui/README.md b/contrib/mitm-ui/README.md
index ad23140..1ec8dd4 100644
--- a/contrib/mitm-ui/README.md
+++ b/contrib/mitm-ui/README.md
@@ -8,7 +8,10 @@
cd ~/gerrit
~/mitm-gerrit/mitm-serve-app-dev.sh
```
-3. Install MITM certificates
+3. Make sure that the browser uses the proxy provided by the command line,
+ e.g. if you are a Googler check that the BeyondCorp extension uses the
+ "System/Alternative" proxy.
+4. Install MITM certificates
- Open http://mitm.it in the proxied browser window
- Follow the instructions to install MITM certs
diff --git a/contrib/mitm-ui/mitm-docker.sh b/contrib/mitm-ui/mitm-docker.sh
index 77f209e..a1206f7 100755
--- a/contrib/mitm-ui/mitm-docker.sh
+++ b/contrib/mitm-ui/mitm-docker.sh
@@ -36,6 +36,7 @@
-v ~/.mitmproxy:/home/mitmproxy/.mitmproxy \
-v ${mitm_dir}:${mitm_dir} \
-v ${gerrit_dir}:${gerrit_dir} \
+ -v ${gerrit_dir}/bazel-out:${gerrit_dir}/bazel-out \
-v ${extra_volume} \
-p 8888:8888 \
mitmproxy/mitmproxy:2.0.2 \
diff --git a/contrib/mitm-ui/mitm-serve-app-dev.sh b/contrib/mitm-ui/mitm-serve-app-dev.sh
index 4fa8958..d4c72cc 100755
--- a/contrib/mitm-ui/mitm-serve-app-dev.sh
+++ b/contrib/mitm-ui/mitm-serve-app-dev.sh
@@ -8,6 +8,8 @@
mitm_dir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null && pwd )"
+bazel build //polygerrit-ui/app:test_components &
+
${mitm_dir}/dev-chrome.sh &
-${mitm_dir}/mitm-docker.sh "serve-app-dev.py --app $(pwd)/polygerrit-ui/app/"
+${mitm_dir}/mitm-docker.sh "serve-app-dev.py --app $(pwd)/polygerrit-ui/app/ --components $(pwd)/bazel-bin/polygerrit-ui/app/"
diff --git a/contrib/mitm-ui/serve-app-dev.py b/contrib/mitm-ui/serve-app-dev.py
index 18e9de1..cdf7bfc 100644
--- a/contrib/mitm-ui/serve-app-dev.py
+++ b/contrib/mitm-ui/serve-app-dev.py
@@ -28,16 +28,19 @@
from mitmproxy import http
from mitmproxy.script import concurrent
-import re
import argparse
-import os.path
import json
import mimetypes
+import os.path
+import re
+import zipfile
class Server:
- def __init__(self, devpath, plugins, pluginroot, assets, strip_assets, theme):
+ def __init__(self, devpath, components, plugins, pluginroot, assets, strip_assets, theme):
if devpath:
print("Serving app from " + devpath)
+ if components:
+ print("Serving components from " + components)
if pluginroot:
print("Serving plugins from " + pluginroot)
if assets:
@@ -52,6 +55,7 @@
else:
self.plugins = {}
self.devpath = devpath
+ self.components = components
self.pluginroot = pluginroot
self.strip_assets = strip_assets
self.theme = theme
@@ -92,6 +96,7 @@
m = re.match(".+polygerrit_ui/\d+\.\d+/(.+)", flow.request.path)
pluginmatch = re.match("^/plugins/(.+)", flow.request.path)
localfile = ""
+ content = ""
if flow.request.path == "/config/server/info":
config = json.loads(flow.response.content[5:].decode('utf8'))
if server.theme:
@@ -105,6 +110,9 @@
flow.response.content = str.encode(")]}'\n" + json.dumps(config))
if m is not None:
filepath = m.groups()[0]
+ if (filepath.startswith("bower_components/")):
+ with zipfile.ZipFile(server.components + "test_components.zip") as bower_zip:
+ content = bower_zip.read(filepath)
localfile = server.devpath + filepath
elif pluginmatch is not None:
pluginfile = flow.request.path_components[-1]
@@ -131,7 +139,10 @@
if localfile and os.path.isfile(localfile):
if pluginmatch is not None:
print("Serving " + flow.request.path + " from " + localfile)
- flow.response.content = server.readfile(localfile)
+ content = server.readfile(localfile)
+
+ if content:
+ flow.response.content = content
flow.response.status_code = 200
localtype = mimetypes.guess_type(localfile)
if localtype and localtype[0]:
@@ -142,13 +153,15 @@
parser = argparse.ArgumentParser()
parser.add_argument("--app", type=str, default="", help="Path to /polygerrit-ui/app/")
+parser.add_argument("--components", type=str, default="", help="Path to test_components.zip")
parser.add_argument("--plugins", type=str, default="", help="Comma-separated list of plugin files to add/replace")
parser.add_argument("--plugin_root", type=str, default="", help="Path containing individual plugin files to replace")
parser.add_argument("--assets", type=str, default="", help="Path containing assets file to import.")
parser.add_argument("--strip_assets", action="store_true", help="Strip plugin bundles from the response.")
-parser.add_argument("--theme", type=str, help="Path to the default site theme to be used.")
+parser.add_argument("--theme", default="", type=str, help="Path to the default site theme to be used.")
args = parser.parse_args()
server = Server(expandpath(args.app) + '/',
+ expandpath(args.components) + '/',
args.plugins,
expandpath(args.plugin_root) + '/',
args.assets and expandpath(args.assets),
diff --git a/java/com/google/gerrit/common/data/testing/GroupReferenceSubject.java b/java/com/google/gerrit/common/data/testing/GroupReferenceSubject.java
index 1988d66..265d590 100644
--- a/java/com/google/gerrit/common/data/testing/GroupReferenceSubject.java
+++ b/java/com/google/gerrit/common/data/testing/GroupReferenceSubject.java
@@ -20,14 +20,17 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.common.data.GroupReference;
import com.google.gerrit.reviewdb.client.AccountGroup;
public class GroupReferenceSubject extends Subject<GroupReferenceSubject, GroupReference> {
public static GroupReferenceSubject assertThat(GroupReference group) {
- return assertAbout(GroupReferenceSubject::new).that(group);
+ return assertAbout(groupReferences()).that(group);
+ }
+
+ public static Subject.Factory<GroupReferenceSubject, GroupReference> groupReferences() {
+ return GroupReferenceSubject::new;
}
private GroupReferenceSubject(FailureMetadata metadata, GroupReference group) {
@@ -37,12 +40,12 @@
public ComparableSubject<?, AccountGroup.UUID> groupUuid() {
isNotNull();
GroupReference group = actual();
- return Truth.assertThat(group.getUUID()).named("groupUuid");
+ return check("groupUuid()").that(group.getUUID());
}
public StringSubject name() {
isNotNull();
GroupReference group = actual();
- return Truth.assertThat(group.getName()).named("name");
+ return check("name()").that(group.getName());
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/BUILD b/java/com/google/gerrit/extensions/common/testing/BUILD
index 6679104..7092d21 100644
--- a/java/com/google/gerrit/extensions/common/testing/BUILD
+++ b/java/com/google/gerrit/extensions/common/testing/BUILD
@@ -6,6 +6,7 @@
deps = [
"//java/com/google/gerrit/extensions:api",
"//java/com/google/gerrit/truth",
+ "//lib:guava",
"//lib/jgit/org.eclipse.jgit:jgit",
"//lib/truth",
],
diff --git a/java/com/google/gerrit/extensions/common/testing/CommitInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/CommitInfoSubject.java
index 6dd5ce4..f0f5516 100644
--- a/java/com/google/gerrit/extensions/common/testing/CommitInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/CommitInfoSubject.java
@@ -15,18 +15,23 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.extensions.common.testing.GitPersonSubject.gitPersons;
+import static com.google.gerrit.truth.ListSubject.elements;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.CommitInfo;
import com.google.gerrit.truth.ListSubject;
public class CommitInfoSubject extends Subject<CommitInfoSubject, CommitInfo> {
public static CommitInfoSubject assertThat(CommitInfo commitInfo) {
- return assertAbout(CommitInfoSubject::new).that(commitInfo);
+ return assertAbout(commits()).that(commitInfo);
+ }
+
+ public static Subject.Factory<CommitInfoSubject, CommitInfo> commits() {
+ return CommitInfoSubject::new;
}
private CommitInfoSubject(FailureMetadata failureMetadata, CommitInfo commitInfo) {
@@ -36,31 +41,30 @@
public StringSubject commit() {
isNotNull();
CommitInfo commitInfo = actual();
- return Truth.assertThat(commitInfo.commit).named("commit");
+ return check("commit()").that(commitInfo.commit);
}
public ListSubject<CommitInfoSubject, CommitInfo> parents() {
isNotNull();
CommitInfo commitInfo = actual();
- return ListSubject.assertThat(commitInfo.parents, CommitInfoSubject::assertThat)
- .named("parents");
+ return check("parents()").about(elements()).thatCustom(commitInfo.parents, commits());
}
public GitPersonSubject committer() {
isNotNull();
CommitInfo commitInfo = actual();
- return GitPersonSubject.assertThat(commitInfo.committer).named("committer");
+ return check("committer()").about(gitPersons()).that(commitInfo.committer);
}
public GitPersonSubject author() {
isNotNull();
CommitInfo commitInfo = actual();
- return GitPersonSubject.assertThat(commitInfo.author).named("author");
+ return check("author()").about(gitPersons()).that(commitInfo.author);
}
public StringSubject message() {
isNotNull();
CommitInfo commitInfo = actual();
- return Truth.assertThat(commitInfo.message).named("message");
+ return check("message").that(commitInfo.message);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/ContentEntrySubject.java b/java/com/google/gerrit/extensions/common/testing/ContentEntrySubject.java
index 5fc8ba6..25750c1 100644
--- a/java/com/google/gerrit/extensions/common/testing/ContentEntrySubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/ContentEntrySubject.java
@@ -14,21 +14,27 @@
package com.google.gerrit.extensions.common.testing;
+import static com.google.common.truth.Fact.simpleFact;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.truth.ListSubject.elements;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IntegerSubject;
import com.google.common.truth.IterableSubject;
+import com.google.common.truth.StandardSubjectBuilder;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.DiffInfo.ContentEntry;
import com.google.gerrit.truth.ListSubject;
public class ContentEntrySubject extends Subject<ContentEntrySubject, ContentEntry> {
public static ContentEntrySubject assertThat(ContentEntry contentEntry) {
- return assertAbout(ContentEntrySubject::new).that(contentEntry);
+ return assertAbout(contentEntries()).that(contentEntry);
+ }
+
+ public static Subject.Factory<ContentEntrySubject, ContentEntry> contentEntries() {
+ return ContentEntrySubject::new;
}
private ContentEntrySubject(FailureMetadata failureMetadata, ContentEntry contentEntry) {
@@ -38,54 +44,54 @@
public void isDueToRebase() {
isNotNull();
ContentEntry contentEntry = actual();
- Truth.assertWithMessage("Entry should be marked 'dueToRebase'")
- .that(contentEntry.dueToRebase)
- .named("dueToRebase")
- .isTrue();
+ if (contentEntry.dueToRebase == null || !contentEntry.dueToRebase) {
+ failWithActual(simpleFact("expected entry to be marked 'dueToRebase'"));
+ }
}
public void isNotDueToRebase() {
isNotNull();
ContentEntry contentEntry = actual();
- Truth.assertWithMessage("Entry should not be marked 'dueToRebase'")
- .that(contentEntry.dueToRebase)
- .named("dueToRebase")
- .isNull();
+ if (contentEntry.dueToRebase != null && contentEntry.dueToRebase) {
+ failWithActual(simpleFact("expected entry not to be marked 'dueToRebase'"));
+ }
}
public ListSubject<StringSubject, String> commonLines() {
isNotNull();
ContentEntry contentEntry = actual();
- return ListSubject.assertThat(contentEntry.ab, Truth::assertThat).named("common lines");
+ return check("commonLines()")
+ .about(elements())
+ .that(contentEntry.ab, StandardSubjectBuilder::that);
}
public ListSubject<StringSubject, String> linesOfA() {
isNotNull();
ContentEntry contentEntry = actual();
- return ListSubject.assertThat(contentEntry.a, Truth::assertThat).named("lines of 'a'");
+ return check("linesOfA()").about(elements()).that(contentEntry.a, StandardSubjectBuilder::that);
}
public ListSubject<StringSubject, String> linesOfB() {
isNotNull();
ContentEntry contentEntry = actual();
- return ListSubject.assertThat(contentEntry.b, Truth::assertThat).named("lines of 'b'");
+ return check("linesOfB()").about(elements()).that(contentEntry.b, StandardSubjectBuilder::that);
}
public IterableSubject intralineEditsOfA() {
isNotNull();
ContentEntry contentEntry = actual();
- return Truth.assertThat(contentEntry.editA).named("intraline edits of 'a'");
+ return check("intralineEditsOfA()").that(contentEntry.editA);
}
public IterableSubject intralineEditsOfB() {
isNotNull();
ContentEntry contentEntry = actual();
- return Truth.assertThat(contentEntry.editB).named("intraline edits of 'b'");
+ return check("intralineEditsOfB()").that(contentEntry.editB);
}
public IntegerSubject numberOfSkippedLines() {
isNotNull();
ContentEntry contentEntry = actual();
- return Truth.assertThat(contentEntry.skip).named("number of skipped lines");
+ return check("numberOfSkippedLines()").that(contentEntry.skip);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
index 057a1a2..ee37bde 100644
--- a/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/DiffInfoSubject.java
@@ -15,11 +15,12 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.extensions.common.testing.FileMetaSubject.fileMetas;
+import static com.google.gerrit.truth.ListSubject.elements;
import com.google.common.truth.ComparableSubject;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.ChangeType;
import com.google.gerrit.extensions.common.DiffInfo;
import com.google.gerrit.extensions.common.DiffInfo.ContentEntry;
@@ -38,25 +39,26 @@
public ListSubject<ContentEntrySubject, ContentEntry> content() {
isNotNull();
DiffInfo diffInfo = actual();
- return ListSubject.assertThat(diffInfo.content, ContentEntrySubject::assertThat)
- .named("content");
+ return check("content()")
+ .about(elements())
+ .thatCustom(diffInfo.content, ContentEntrySubject.contentEntries());
}
public ComparableSubject<?, ChangeType> changeType() {
isNotNull();
DiffInfo diffInfo = actual();
- return Truth.assertThat(diffInfo.changeType).named("changeType");
+ return check("changeType()").that(diffInfo.changeType);
}
public FileMetaSubject metaA() {
isNotNull();
DiffInfo diffInfo = actual();
- return FileMetaSubject.assertThat(diffInfo.metaA).named("metaA");
+ return check("metaA()").about(fileMetas()).that(diffInfo.metaA);
}
public FileMetaSubject metaB() {
isNotNull();
DiffInfo diffInfo = actual();
- return FileMetaSubject.assertThat(diffInfo.metaB).named("metaB");
+ return check("metaB()").about(fileMetas()).that(diffInfo.metaB);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/EditInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/EditInfoSubject.java
index 84ad61c..1c99141 100644
--- a/java/com/google/gerrit/extensions/common/testing/EditInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/EditInfoSubject.java
@@ -15,11 +15,11 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.commits;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.EditInfo;
import com.google.gerrit.truth.OptionalSubject;
import java.util.Optional;
@@ -27,12 +27,16 @@
public class EditInfoSubject extends Subject<EditInfoSubject, EditInfo> {
public static EditInfoSubject assertThat(EditInfo editInfo) {
- return assertAbout(EditInfoSubject::new).that(editInfo);
+ return assertAbout(edits()).that(editInfo);
+ }
+
+ private static Subject.Factory<EditInfoSubject, EditInfo> edits() {
+ return EditInfoSubject::new;
}
public static OptionalSubject<EditInfoSubject, EditInfo> assertThat(
Optional<EditInfo> editInfoOptional) {
- return OptionalSubject.assertThat(editInfoOptional, EditInfoSubject::assertThat);
+ return OptionalSubject.assertThat(editInfoOptional, edits());
}
private EditInfoSubject(FailureMetadata failureMetadata, EditInfo editInfo) {
@@ -42,12 +46,12 @@
public CommitInfoSubject commit() {
isNotNull();
EditInfo editInfo = actual();
- return CommitInfoSubject.assertThat(editInfo.commit).named("commit");
+ return check("commit()").about(commits()).that(editInfo.commit);
}
public StringSubject baseRevision() {
isNotNull();
EditInfo editInfo = actual();
- return Truth.assertThat(editInfo.baseRevision).named("baseRevision");
+ return check("baseRevision()").that(editInfo.baseRevision);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/FileInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/FileInfoSubject.java
index b088016..3ebf838 100644
--- a/java/com/google/gerrit/extensions/common/testing/FileInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/FileInfoSubject.java
@@ -20,7 +20,6 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IntegerSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.FileInfo;
public class FileInfoSubject extends Subject<FileInfoSubject, FileInfo> {
@@ -36,18 +35,18 @@
public IntegerSubject linesInserted() {
isNotNull();
FileInfo fileInfo = actual();
- return Truth.assertThat(fileInfo.linesInserted).named("linesInserted");
+ return check("linesInserted()").that(fileInfo.linesInserted);
}
public IntegerSubject linesDeleted() {
isNotNull();
FileInfo fileInfo = actual();
- return Truth.assertThat(fileInfo.linesDeleted).named("linesDeleted");
+ return check("linesDeleted()").that(fileInfo.linesDeleted);
}
public ComparableSubject<?, Character> status() {
isNotNull();
FileInfo fileInfo = actual();
- return Truth.assertThat(fileInfo.status).named("status");
+ return check("status()").that(fileInfo.status);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java b/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java
index e77eef1..d1b2031 100644
--- a/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/FileMetaSubject.java
@@ -19,13 +19,16 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IntegerSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.DiffInfo.FileMeta;
public class FileMetaSubject extends Subject<FileMetaSubject, FileMeta> {
public static FileMetaSubject assertThat(FileMeta fileMeta) {
- return assertAbout(FileMetaSubject::new).that(fileMeta);
+ return assertAbout(fileMetas()).that(fileMeta);
+ }
+
+ public static Subject.Factory<FileMetaSubject, FileMeta> fileMetas() {
+ return FileMetaSubject::new;
}
private FileMetaSubject(FailureMetadata failureMetadata, FileMeta fileMeta) {
@@ -35,6 +38,6 @@
public IntegerSubject totalLineCount() {
isNotNull();
FileMeta fileMeta = actual();
- return Truth.assertThat(fileMeta.lines).named("total line count");
+ return check("totalLineCount()").that(fileMeta.lines);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/FixReplacementInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/FixReplacementInfoSubject.java
index b56d399..6ba5f8b 100644
--- a/java/com/google/gerrit/extensions/common/testing/FixReplacementInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/FixReplacementInfoSubject.java
@@ -15,18 +15,22 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.extensions.common.testing.RangeSubject.ranges;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.FixReplacementInfo;
public class FixReplacementInfoSubject
extends Subject<FixReplacementInfoSubject, FixReplacementInfo> {
public static FixReplacementInfoSubject assertThat(FixReplacementInfo fixReplacementInfo) {
- return assertAbout(FixReplacementInfoSubject::new).that(fixReplacementInfo);
+ return assertAbout(fixReplacements()).that(fixReplacementInfo);
+ }
+
+ public static Subject.Factory<FixReplacementInfoSubject, FixReplacementInfo> fixReplacements() {
+ return FixReplacementInfoSubject::new;
}
private FixReplacementInfoSubject(
@@ -35,14 +39,17 @@
}
public StringSubject path() {
- return Truth.assertThat(actual().path).named("path");
+ isNotNull();
+ return check("path()").that(actual().path);
}
public RangeSubject range() {
- return RangeSubject.assertThat(actual().range).named("range");
+ isNotNull();
+ return check("range()").about(ranges()).that(actual().range);
}
public StringSubject replacement() {
- return Truth.assertThat(actual().replacement).named("replacement");
+ isNotNull();
+ return check("replacement()").that(actual().replacement);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/FixSuggestionInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/FixSuggestionInfoSubject.java
index 7a6da9c..98dac38 100644
--- a/java/com/google/gerrit/extensions/common/testing/FixSuggestionInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/FixSuggestionInfoSubject.java
@@ -15,6 +15,8 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.extensions.common.testing.FixReplacementInfoSubject.fixReplacements;
+import static com.google.gerrit.truth.ListSubject.elements;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
@@ -27,7 +29,11 @@
public class FixSuggestionInfoSubject extends Subject<FixSuggestionInfoSubject, FixSuggestionInfo> {
public static FixSuggestionInfoSubject assertThat(FixSuggestionInfo fixSuggestionInfo) {
- return assertAbout(FixSuggestionInfoSubject::new).that(fixSuggestionInfo);
+ return assertAbout(fixSuggestions()).that(fixSuggestionInfo);
+ }
+
+ public static Subject.Factory<FixSuggestionInfoSubject, FixSuggestionInfo> fixSuggestions() {
+ return FixSuggestionInfoSubject::new;
}
private FixSuggestionInfoSubject(
@@ -40,8 +46,10 @@
}
public ListSubject<FixReplacementInfoSubject, FixReplacementInfo> replacements() {
- return ListSubject.assertThat(actual().replacements, FixReplacementInfoSubject::assertThat)
- .named("replacements");
+ isNotNull();
+ return check("replacements()")
+ .about(elements())
+ .thatCustom(actual().replacements, fixReplacements());
}
public FixReplacementInfoSubject onlyReplacement() {
@@ -49,6 +57,7 @@
}
public StringSubject description() {
- return Truth.assertThat(actual().description).named("description");
+ isNotNull();
+ return check("description()").that(actual().description);
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java b/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
index cdbef34..dee0636 100644
--- a/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/GitPersonSubject.java
@@ -14,6 +14,7 @@
package com.google.gerrit.extensions.common.testing;
+import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.truth.Truth.assertAbout;
import com.google.common.truth.ComparableSubject;
@@ -21,7 +22,6 @@
import com.google.common.truth.IntegerSubject;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.common.GitPerson;
import java.sql.Timestamp;
import java.util.Date;
@@ -30,7 +30,11 @@
public class GitPersonSubject extends Subject<GitPersonSubject, GitPerson> {
public static GitPersonSubject assertThat(GitPerson gitPerson) {
- return assertAbout(GitPersonSubject::new).that(gitPerson);
+ return assertAbout(gitPersons()).that(gitPerson);
+ }
+
+ public static Factory<GitPersonSubject, GitPerson> gitPersons() {
+ return GitPersonSubject::new;
}
private GitPersonSubject(FailureMetadata failureMetadata, GitPerson gitPerson) {
@@ -40,30 +44,30 @@
public StringSubject name() {
isNotNull();
GitPerson gitPerson = actual();
- return Truth.assertThat(gitPerson.name).named("name");
+ return check("name()").that(gitPerson.name);
}
public StringSubject email() {
isNotNull();
GitPerson gitPerson = actual();
- return Truth.assertThat(gitPerson.email).named("email");
+ return check("email()").that(gitPerson.email);
}
public ComparableSubject<?, Timestamp> date() {
isNotNull();
GitPerson gitPerson = actual();
- return Truth.assertThat(gitPerson.date).named("date");
+ return check("date()").that(gitPerson.date);
}
public IntegerSubject tz() {
isNotNull();
GitPerson gitPerson = actual();
- return Truth.assertThat(gitPerson.tz).named("tz");
+ return check("tz()").that(gitPerson.tz);
}
public void hasSameDateAs(GitPerson other) {
+ checkNotNull(other, "'other' GitPerson must not be null");
isNotNull();
- assertThat(other).named("other").isNotNull();
date().isEqualTo(other.date);
tz().isEqualTo(other.tz);
}
@@ -72,9 +76,7 @@
isNotNull();
name().isEqualTo(ident.getName());
email().isEqualTo(ident.getEmailAddress());
- Truth.assertThat(new Date(actual().date.getTime()))
- .named("rounded date")
- .isEqualTo(ident.getWhen());
+ check("roundedDate()").that(new Date(actual().date.getTime())).isEqualTo(ident.getWhen());
tz().isEqualTo(ident.getTimeZoneOffset());
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/RangeSubject.java b/java/com/google/gerrit/extensions/common/testing/RangeSubject.java
index db7f0d1..12acb8d 100644
--- a/java/com/google/gerrit/extensions/common/testing/RangeSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/RangeSubject.java
@@ -14,19 +14,22 @@
package com.google.gerrit.extensions.common.testing;
-import static com.google.common.truth.Fact.fact;
+import static com.google.common.truth.Fact.simpleFact;
import static com.google.common.truth.Truth.assertAbout;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IntegerSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.client.Comment;
public class RangeSubject extends Subject<RangeSubject, Comment.Range> {
public static RangeSubject assertThat(Comment.Range range) {
- return assertAbout(RangeSubject::new).that(range);
+ return assertAbout(ranges()).that(range);
+ }
+
+ public static Subject.Factory<RangeSubject, Comment.Range> ranges() {
+ return RangeSubject::new;
}
private RangeSubject(FailureMetadata failureMetadata, Comment.Range range) {
@@ -34,32 +37,32 @@
}
public IntegerSubject startLine() {
- return Truth.assertThat(actual().startLine).named("startLine");
+ return check("startLine()").that(actual().startLine);
}
public IntegerSubject startCharacter() {
- return Truth.assertThat(actual().startCharacter).named("startCharacter");
+ return check("startCharacter()").that(actual().startCharacter);
}
public IntegerSubject endLine() {
- return Truth.assertThat(actual().endLine).named("endLine");
+ return check("endLine()").that(actual().endLine);
}
public IntegerSubject endCharacter() {
- return Truth.assertThat(actual().endCharacter).named("endCharacter");
+ return check("endCharacter()").that(actual().endCharacter);
}
public void isValid() {
isNotNull();
if (!actual().isValid()) {
- failWithoutActual(fact("expected", "valid"));
+ failWithActual(simpleFact("expected to be valid"));
}
}
public void isInvalid() {
isNotNull();
if (actual().isValid()) {
- failWithoutActual(fact("expected", "not valid"));
+ failWithActual(simpleFact("expected to be invalid"));
}
}
}
diff --git a/java/com/google/gerrit/extensions/common/testing/RobotCommentInfoSubject.java b/java/com/google/gerrit/extensions/common/testing/RobotCommentInfoSubject.java
index c2bed86..033f54b 100644
--- a/java/com/google/gerrit/extensions/common/testing/RobotCommentInfoSubject.java
+++ b/java/com/google/gerrit/extensions/common/testing/RobotCommentInfoSubject.java
@@ -15,6 +15,7 @@
package com.google.gerrit.extensions.common.testing;
import static com.google.common.truth.Truth.assertAbout;
+import static com.google.gerrit.truth.ListSubject.elements;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
@@ -27,12 +28,15 @@
public static ListSubject<RobotCommentInfoSubject, RobotCommentInfo> assertThatList(
List<RobotCommentInfo> robotCommentInfos) {
- return ListSubject.assertThat(robotCommentInfos, RobotCommentInfoSubject::assertThat)
- .named("robotCommentInfos");
+ return ListSubject.assertThat(robotCommentInfos, robotComments()).named("robotCommentInfos");
}
public static RobotCommentInfoSubject assertThat(RobotCommentInfo robotCommentInfo) {
- return assertAbout(RobotCommentInfoSubject::new).that(robotCommentInfo);
+ return assertAbout(robotComments()).that(robotCommentInfo);
+ }
+
+ private static Factory<RobotCommentInfoSubject, RobotCommentInfo> robotComments() {
+ return RobotCommentInfoSubject::new;
}
private RobotCommentInfoSubject(
@@ -41,8 +45,9 @@
}
public ListSubject<FixSuggestionInfoSubject, FixSuggestionInfo> fixSuggestions() {
- return ListSubject.assertThat(actual().fixSuggestions, FixSuggestionInfoSubject::assertThat)
- .named("fixSuggestions");
+ return check("fixSuggestions()")
+ .about(elements())
+ .thatCustom(actual().fixSuggestions, FixSuggestionInfoSubject.fixSuggestions());
}
public FixSuggestionInfoSubject onlyFixSuggestion() {
diff --git a/java/com/google/gerrit/extensions/restapi/testing/BinaryResultSubject.java b/java/com/google/gerrit/extensions/restapi/testing/BinaryResultSubject.java
index 1867308..5109205 100644
--- a/java/com/google/gerrit/extensions/restapi/testing/BinaryResultSubject.java
+++ b/java/com/google/gerrit/extensions/restapi/testing/BinaryResultSubject.java
@@ -20,7 +20,6 @@
import com.google.common.truth.PrimitiveByteArraySubject;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.restapi.BinaryResult;
import com.google.gerrit.truth.OptionalSubject;
import java.io.ByteArrayOutputStream;
@@ -30,12 +29,16 @@
public class BinaryResultSubject extends Subject<BinaryResultSubject, BinaryResult> {
public static BinaryResultSubject assertThat(BinaryResult binaryResult) {
- return assertAbout(BinaryResultSubject::new).that(binaryResult);
+ return assertAbout(binaryResults()).that(binaryResult);
+ }
+
+ private static Subject.Factory<BinaryResultSubject, BinaryResult> binaryResults() {
+ return BinaryResultSubject::new;
}
public static OptionalSubject<BinaryResultSubject, BinaryResult> assertThat(
Optional<BinaryResult> binaryResultOptional) {
- return OptionalSubject.assertThat(binaryResultOptional, BinaryResultSubject::assertThat);
+ return OptionalSubject.assertThat(binaryResultOptional, binaryResults());
}
private BinaryResultSubject(FailureMetadata failureMetadata, BinaryResult binaryResult) {
@@ -48,7 +51,7 @@
// be used afterwards. Besides, closing it doesn't have an effect for most
// implementations of a BinaryResult.
BinaryResult binaryResult = actual();
- return Truth.assertThat(binaryResult.asString());
+ return check("asString()").that(binaryResult.asString());
}
public PrimitiveByteArraySubject bytes() throws IOException {
@@ -60,6 +63,6 @@
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
binaryResult.writeTo(byteArrayOutputStream);
byte[] bytes = byteArrayOutputStream.toByteArray();
- return Truth.assertThat(bytes);
+ return check("bytes()").that(bytes);
}
}
diff --git a/java/com/google/gerrit/git/testing/CommitSubject.java b/java/com/google/gerrit/git/testing/CommitSubject.java
index 198ddff..0873107 100644
--- a/java/com/google/gerrit/git/testing/CommitSubject.java
+++ b/java/com/google/gerrit/git/testing/CommitSubject.java
@@ -19,7 +19,6 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import java.sql.Timestamp;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.revwalk.RevCommit;
@@ -69,9 +68,7 @@
public void hasCommitMessage(String expectedCommitMessage) {
isNotNull();
RevCommit commit = actual();
- Truth.assertThat(commit.getFullMessage())
- .named("commit message")
- .isEqualTo(expectedCommitMessage);
+ check("commitMessage()").that(commit.getFullMessage()).isEqualTo(expectedCommitMessage);
}
/**
@@ -84,7 +81,7 @@
RevCommit commit = actual();
long timestampDiffMs =
Math.abs(commit.getCommitTime() * 1000L - expectedCommitTimestamp.getTime());
- Truth.assertThat(timestampDiffMs).named("commit timestamp diff").isAtMost(SECONDS.toMillis(1));
+ check("commitTimestampDiff()").that(timestampDiffMs).isAtMost(SECONDS.toMillis(1));
}
/**
@@ -95,6 +92,6 @@
public void hasSha1(ObjectId expectedSha1) {
isNotNull();
RevCommit commit = actual();
- Truth.assertThat(commit).named("SHA1").isEqualTo(expectedSha1);
+ check("sha1()").that(commit).isEqualTo(expectedSha1);
}
}
diff --git a/java/com/google/gerrit/git/testing/ObjectIdSubject.java b/java/com/google/gerrit/git/testing/ObjectIdSubject.java
index 0fd3b73..5fe91f9 100644
--- a/java/com/google/gerrit/git/testing/ObjectIdSubject.java
+++ b/java/com/google/gerrit/git/testing/ObjectIdSubject.java
@@ -18,12 +18,15 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import org.eclipse.jgit.lib.ObjectId;
public class ObjectIdSubject extends Subject<ObjectIdSubject, ObjectId> {
public static ObjectIdSubject assertThat(ObjectId objectId) {
- return assertAbout(ObjectIdSubject::new).that(objectId);
+ return assertAbout(objectIds()).that(objectId);
+ }
+
+ public static Factory<ObjectIdSubject, ObjectId> objectIds() {
+ return ObjectIdSubject::new;
}
private ObjectIdSubject(FailureMetadata metadata, ObjectId actual) {
@@ -33,6 +36,6 @@
public void hasName(String expectedName) {
isNotNull();
ObjectId objectId = actual();
- Truth.assertThat(objectId.getName()).named("name").isEqualTo(expectedName);
+ check("name()").that(objectId.getName()).isEqualTo(expectedName);
}
}
diff --git a/java/com/google/gerrit/git/testing/PushResultSubject.java b/java/com/google/gerrit/git/testing/PushResultSubject.java
index 929e182..724ca17 100644
--- a/java/com/google/gerrit/git/testing/PushResultSubject.java
+++ b/java/com/google/gerrit/git/testing/PushResultSubject.java
@@ -16,7 +16,6 @@
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.truth.Truth.assertAbout;
-import static java.util.stream.Collectors.joining;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Splitter;
@@ -25,11 +24,10 @@
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.StreamSubject;
import com.google.common.truth.Subject;
import com.google.common.truth.Truth;
-import com.google.common.truth.Truth8;
import com.google.gerrit.common.Nullable;
-import java.util.Arrays;
import org.eclipse.jgit.transport.PushResult;
import org.eclipse.jgit.transport.RemoteRefUpdate;
@@ -43,7 +41,8 @@
}
public void hasNoMessages() {
- Truth.assertWithMessage("expected no messages")
+ check()
+ .withMessage("expected no messages")
.that(Strings.nullToEmpty(trimMessages()))
.isEqualTo("");
}
@@ -51,14 +50,14 @@
public void hasMessages(String... expectedLines) {
checkArgument(expectedLines.length > 0, "use hasNoMessages()");
isNotNull();
- Truth.assertThat(trimMessages()).isEqualTo(Arrays.stream(expectedLines).collect(joining("\n")));
+ check("messages()").that(trimMessages()).isEqualTo(String.join("\n", expectedLines));
}
public void containsMessages(String... expectedLines) {
checkArgument(expectedLines.length > 0, "use hasNoMessages()");
isNotNull();
Iterable<String> got = Splitter.on("\n").split(trimMessages());
- Truth.assertThat(got).containsAllIn(expectedLines).inOrder();
+ check("messages()").that(got).containsAllIn(expectedLines).inOrder();
}
private String trimMessages() {
@@ -90,10 +89,7 @@
messages, Throwables.getStackTraceAsString(e));
return;
}
- Truth.assertThat(actual)
- .named("processed commands")
- .containsExactlyEntriesIn(expected)
- .inOrder();
+ check("processedCommands()").that(actual).containsExactlyEntriesIn(expected).inOrder();
}
@VisibleForTesting
@@ -129,7 +125,9 @@
}
public RemoteRefUpdateSubject onlyRef(String refName) {
- Truth8.assertThat(actual().getRemoteUpdates().stream().map(RemoteRefUpdate::getRemoteName))
+ check("setOfRefs()")
+ .about(StreamSubject.streams())
+ .that(actual().getRemoteUpdates().stream().map(RemoteRefUpdate::getRemoteName))
.named("set of refs")
.containsExactly(refName);
return ref(refName);
diff --git a/java/com/google/gerrit/httpd/WebSessionManager.java b/java/com/google/gerrit/httpd/WebSessionManager.java
index cb1e965..d09b4dd 100644
--- a/java/com/google/gerrit/httpd/WebSessionManager.java
+++ b/java/com/google/gerrit/httpd/WebSessionManager.java
@@ -215,7 +215,15 @@
return expiresAt;
}
- Account.Id getAccountId() {
+ /**
+ * Parse an Account.Id.
+ *
+ * <p>This is public so that plugins that implement a web session, can also implement a way to
+ * clear per user sessions.
+ *
+ * @return account ID.
+ */
+ public Account.Id getAccountId() {
return accountId;
}
diff --git a/java/com/google/gerrit/index/query/QueryBuilder.java b/java/com/google/gerrit/index/query/QueryBuilder.java
index 12d1dd6..04a77ca 100644
--- a/java/com/google/gerrit/index/query/QueryBuilder.java
+++ b/java/com/google/gerrit/index/query/QueryBuilder.java
@@ -18,6 +18,7 @@
import static com.google.gerrit.index.query.Predicate.not;
import static com.google.gerrit.index.query.Predicate.or;
import static com.google.gerrit.index.query.QueryParser.AND;
+import static com.google.gerrit.index.query.QueryParser.COLON;
import static com.google.gerrit.index.query.QueryParser.DEFAULT_FIELD;
import static com.google.gerrit.index.query.QueryParser.EXACT_PHRASE;
import static com.google.gerrit.index.query.QueryParser.FIELD_NAME;
@@ -217,41 +218,41 @@
return defaultField(onlyChildOf(r));
case FIELD_NAME:
- return operator(r.getText(), onlyChildOf(r));
+ return operator(r.getText(), concatenateChildText(r));
default:
throw error("Unsupported operator: " + r);
}
}
- private Predicate<T> operator(String name, Tree val) throws QueryParseException {
- switch (val.getType()) {
- // Expand multiple values, "foo:(a b c)", as though they were written
- // out with the longer form, "foo:a foo:b foo:c".
- //
- case AND:
- case OR:
- {
- List<Predicate<T>> p = new ArrayList<>(val.getChildCount());
- for (int i = 0; i < val.getChildCount(); i++) {
- final Tree c = val.getChild(i);
- if (c.getType() != DEFAULT_FIELD) {
- throw error("Nested operator not expected: " + c);
- }
- p.add(operator(name, onlyChildOf(c)));
- }
- return val.getType() == AND ? and(p) : or(p);
- }
+ private static String concatenateChildText(Tree r) throws QueryParseException {
+ if (r.getChildCount() == 0) {
+ throw error("Expected children under: " + r);
+ }
+ if (r.getChildCount() == 1) {
+ return getFieldValue(r.getChild(0));
+ }
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < r.getChildCount(); i++) {
+ sb.append(getFieldValue(r.getChild(i)));
+ }
+ return sb.toString();
+ }
+ private static String getFieldValue(Tree r) throws QueryParseException {
+ if (r.getChildCount() != 0) {
+ throw error("Expected no children under: " + r);
+ }
+ switch (r.getType()) {
case SINGLE_WORD:
+ case COLON:
case EXACT_PHRASE:
- if (val.getChildCount() != 0) {
- throw error("Expected no children under: " + val);
- }
- return operator(name, val.getText());
-
+ return r.getText();
default:
- throw error("Unsupported node in operator " + name + ": " + val);
+ throw error(
+ String.format(
+ "Unsupported %s node in operator %s: %s",
+ QueryParser.tokenNames[r.getType()], r.getParent(), r));
}
}
diff --git a/java/com/google/gerrit/index/query/testing/BUILD b/java/com/google/gerrit/index/query/testing/BUILD
new file mode 100644
index 0000000..030b327
--- /dev/null
+++ b/java/com/google/gerrit/index/query/testing/BUILD
@@ -0,0 +1,16 @@
+package(
+ default_testonly = True,
+ default_visibility = ["//visibility:public"],
+)
+
+java_library(
+ name = "testing",
+ srcs = glob(["*.java"]),
+ deps = [
+ "//antlr3:query_parser",
+ "//java/com/google/gerrit/index",
+ "//lib:guava",
+ "//lib/antlr:java-runtime",
+ "//lib/truth",
+ ],
+)
diff --git a/java/com/google/gerrit/index/query/testing/TreeSubject.java b/java/com/google/gerrit/index/query/testing/TreeSubject.java
new file mode 100644
index 0000000..c60b363
--- /dev/null
+++ b/java/com/google/gerrit/index/query/testing/TreeSubject.java
@@ -0,0 +1,73 @@
+// Copyright (C) 2019 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.index.query.testing;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.truth.Truth.assertAbout;
+import static java.util.Objects.requireNonNull;
+
+import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.Subject;
+import com.google.gerrit.index.query.QueryParser;
+import org.antlr.runtime.tree.Tree;
+
+public class TreeSubject extends Subject<TreeSubject, Tree> {
+ public static TreeSubject assertThat(Tree actual) {
+ return assertAbout(TreeSubject::new).that(actual);
+ }
+
+ private TreeSubject(FailureMetadata failureMetadata, Tree tree) {
+ super(failureMetadata, tree);
+ }
+
+ public void hasType(int expectedType) {
+ isNotNull();
+ check("getType()").that(typeName(actual().getType())).isEqualTo(typeName(expectedType));
+ }
+
+ public void hasText(String expectedText) {
+ requireNonNull(expectedText);
+ isNotNull();
+ check("getText()").that(actual().getText()).isEqualTo(expectedText);
+ }
+
+ public void hasNoChildren() {
+ isNotNull();
+ check("getChildCount()").that(actual().getChildCount()).isEqualTo(0);
+ }
+
+ public void hasChildCount(int expectedChildCount) {
+ checkArgument(
+ expectedChildCount > 0, "expected child count must be positive: %s", expectedChildCount);
+ isNotNull();
+ check("getChildCount()").that(actual().getChildCount()).isEqualTo(expectedChildCount);
+ }
+
+ public TreeSubject child(int childIndex) {
+ isNotNull();
+ return check("getChild(%s)", childIndex)
+ .about(TreeSubject::new)
+ .that(actual().getChild(childIndex));
+ }
+
+ private static String typeName(int type) {
+ checkArgument(
+ type >= 0 && type < QueryParser.tokenNames.length,
+ "invalid token type %s, max is %s",
+ type,
+ QueryParser.tokenNames.length - 1);
+ return QueryParser.tokenNames[type];
+ }
+}
diff --git a/java/com/google/gerrit/proto/testing/SerializedClassSubject.java b/java/com/google/gerrit/proto/testing/SerializedClassSubject.java
index a5cf3ca..546ff89 100644
--- a/java/com/google/gerrit/proto/testing/SerializedClassSubject.java
+++ b/java/com/google/gerrit/proto/testing/SerializedClassSubject.java
@@ -15,9 +15,8 @@
package com.google.gerrit.proto.testing;
import static com.google.common.collect.ImmutableMap.toImmutableMap;
+import static com.google.common.truth.Fact.simpleFact;
import static com.google.common.truth.Truth.assertAbout;
-import static com.google.common.truth.Truth.assertThat;
-import static com.google.common.truth.Truth.assertWithMessage;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.Subject;
@@ -67,21 +66,22 @@
public void isAbstract() {
isNotNull();
- assertWithMessage("expected class %s to be abstract", actual().getName())
- .that(Modifier.isAbstract(actual().getModifiers()))
- .isTrue();
+ if (!Modifier.isAbstract(actual().getModifiers())) {
+ failWithActual(simpleFact("expected class to be abstract"));
+ }
}
public void isConcrete() {
isNotNull();
- assertWithMessage("expected class %s to be concrete", actual().getName())
- .that(!Modifier.isAbstract(actual().getModifiers()))
- .isTrue();
+ if (Modifier.isAbstract(actual().getModifiers())) {
+ failWithActual(simpleFact("expected class to be concrete"));
+ }
}
public void hasFields(Map<String, Type> expectedFields) {
isConcrete();
- assertThat(
+ check("fields()")
+ .that(
FieldUtils.getAllFieldsList(actual()).stream()
.filter(f -> !Modifier.isStatic(f.getModifiers()))
.collect(toImmutableMap(Field::getName, Field::getGenericType)))
@@ -91,20 +91,20 @@
public void hasAutoValueMethods(Map<String, Type> expectedMethods) {
// Would be nice if we could check clazz is an @AutoValue, but the retention is not RUNTIME.
isAbstract();
- assertThat(
+ check("noArgumentAbstractMethodsOn(%s)", actual().getName())
+ .that(
Arrays.stream(actual().getDeclaredMethods())
.filter(m -> !Modifier.isStatic(m.getModifiers()))
.filter(m -> Modifier.isAbstract(m.getModifiers()))
.filter(m -> m.getParameters().length == 0)
.collect(toImmutableMap(Method::getName, Method::getGenericReturnType)))
- .named("no-argument abstract methods on %s", actual().getName())
.isEqualTo(expectedMethods);
}
public void extendsClass(Type superclassType) {
isNotNull();
- assertThat(actual().getGenericSuperclass())
- .named("superclass of %s", actual().getName())
+ check("superclass(%s)", actual().getName())
+ .that(actual().getGenericSuperclass())
.isEqualTo(superclassType);
}
}
diff --git a/java/com/google/gerrit/server/CommentsUtil.java b/java/com/google/gerrit/server/CommentsUtil.java
index 39df152..1229df1 100644
--- a/java/com/google/gerrit/server/CommentsUtil.java
+++ b/java/com/google/gerrit/server/CommentsUtil.java
@@ -50,13 +50,9 @@
import java.util.Collection;
import java.util.List;
import java.util.Optional;
-import org.eclipse.jgit.lib.BatchRefUpdate;
-import org.eclipse.jgit.lib.NullProgressMonitor;
import org.eclipse.jgit.lib.ObjectId;
import org.eclipse.jgit.lib.Ref;
import org.eclipse.jgit.lib.Repository;
-import org.eclipse.jgit.revwalk.RevWalk;
-import org.eclipse.jgit.transport.ReceiveCommand;
/** Utility functions to manipulate Comments. */
@Singleton
@@ -293,26 +289,6 @@
update.deleteCommentByRewritingHistory(commentKey.uuid, newMessage);
}
- public void deleteAllDraftsFromAllUsers(Change.Id changeId) throws IOException {
- try (Repository repo = repoManager.openRepository(allUsers);
- RevWalk rw = new RevWalk(repo)) {
- BatchRefUpdate bru = repo.getRefDatabase().newBatchUpdate();
- for (Ref ref : getDraftRefs(repo, changeId)) {
- bru.addCommand(new ReceiveCommand(ref.getObjectId(), ObjectId.zeroId(), ref.getName()));
- }
- bru.setRefLogMessage("Delete drafts from NoteDb", false);
- bru.execute(rw, NullProgressMonitor.INSTANCE);
- for (ReceiveCommand cmd : bru.getCommands()) {
- if (cmd.getResult() != ReceiveCommand.Result.OK) {
- throw new IOException(
- String.format(
- "Failed to delete draft comment ref %s at %s: %s (%s)",
- cmd.getRefName(), cmd.getOldId(), cmd.getResult(), cmd.getMessage()));
- }
- }
- }
- }
-
private static List<Comment> commentsOnFile(Collection<Comment> allComments, String file) {
List<Comment> result = new ArrayList<>(allComments.size());
for (Comment c : allComments) {
diff --git a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
index e0eb3f2..66e66ca 100644
--- a/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
+++ b/java/com/google/gerrit/server/git/receive/AsyncReceiveCommits.java
@@ -115,17 +115,25 @@
private class Worker implements ProjectRunnable {
final MultiProgressMonitor progress;
+ final String name;
private final Collection<ReceiveCommand> commands;
- private Worker(Collection<ReceiveCommand> commands) {
+ private Worker(Collection<ReceiveCommand> commands, String name) {
this.commands = commands;
+ this.name = name;
progress = new MultiProgressMonitor(new MessageSenderOutputStream(), "Processing changes");
}
@Override
public void run() {
- receiveCommits.processCommands(commands, progress);
+ String oldName = Thread.currentThread().getName();
+ Thread.currentThread().setName(oldName + "-for-" + name);
+ try {
+ receiveCommits.processCommands(commands, progress);
+ } finally {
+ Thread.currentThread().setName(oldName);
+ }
}
@Override
@@ -334,7 +342,7 @@
}
long startNanos = System.nanoTime();
- Worker w = new Worker(commands);
+ Worker w = new Worker(commands, Thread.currentThread().getName());
try {
w.progress.waitFor(
executor.submit(scopePropagator.wrap(w)), timeoutMillis, TimeUnit.MILLISECONDS);
diff --git a/java/com/google/gerrit/server/group/testing/InternalGroupSubject.java b/java/com/google/gerrit/server/group/testing/InternalGroupSubject.java
index f0ab638..2f91394 100644
--- a/java/com/google/gerrit/server/group/testing/InternalGroupSubject.java
+++ b/java/com/google/gerrit/server/group/testing/InternalGroupSubject.java
@@ -23,7 +23,6 @@
import com.google.common.truth.IterableSubject;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.reviewdb.client.AccountGroup;
import com.google.gerrit.server.group.InternalGroup;
import java.sql.Timestamp;
@@ -32,7 +31,11 @@
public class InternalGroupSubject extends Subject<InternalGroupSubject, InternalGroup> {
public static InternalGroupSubject assertThat(InternalGroup group) {
- return assertAbout(InternalGroupSubject::new).that(group);
+ return assertAbout(internalGroups()).that(group);
+ }
+
+ public static Subject.Factory<InternalGroupSubject, InternalGroup> internalGroups() {
+ return InternalGroupSubject::new;
}
private InternalGroupSubject(FailureMetadata metadata, InternalGroup actual) {
@@ -42,66 +45,66 @@
public ComparableSubject<?, AccountGroup.UUID> groupUuid() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getGroupUUID()).named("groupUuid");
+ return check("groupUuid()").that(group.getGroupUUID());
}
public ComparableSubject<?, AccountGroup.NameKey> nameKey() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getNameKey()).named("nameKey");
+ return check("nameKey()").that(group.getNameKey());
}
public StringSubject name() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getName()).named("name");
+ return check("name()").that(group.getName());
}
- public DefaultSubject id() {
+ public Subject<DefaultSubject, Object> id() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getId()).named("id");
+ return check("id()").that(group.getId());
}
public StringSubject description() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getDescription()).named("description");
+ return check("description()").that(group.getDescription());
}
public ComparableSubject<?, AccountGroup.UUID> ownerGroupUuid() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getOwnerGroupUUID()).named("ownerGroupUuid");
+ return check("ownerGroupUuid()").that(group.getOwnerGroupUUID());
}
public BooleanSubject visibleToAll() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.isVisibleToAll()).named("visibleToAll");
+ return check("visibleToAll()").that(group.isVisibleToAll());
}
public ComparableSubject<?, Timestamp> createdOn() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getCreatedOn()).named("createdOn");
+ return check("createdOn()").that(group.getCreatedOn());
}
public IterableSubject members() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getMembers()).named("members");
+ return check("members()").that(group.getMembers());
}
public IterableSubject subgroups() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getSubgroups()).named("subgroups");
+ return check("subgroups()").that(group.getSubgroups());
}
public ComparableSubject<?, ObjectId> refState() {
isNotNull();
InternalGroup group = actual();
- return Truth.assertThat(group.getRefState()).named("refState");
+ return check("refState()").that(group.getRefState());
}
}
diff --git a/java/com/google/gerrit/truth/ListSubject.java b/java/com/google/gerrit/truth/ListSubject.java
index bd9df30..9a839dd 100644
--- a/java/com/google/gerrit/truth/ListSubject.java
+++ b/java/com/google/gerrit/truth/ListSubject.java
@@ -18,28 +18,34 @@
import static com.google.common.truth.Fact.fact;
import static com.google.common.truth.Truth.assertAbout;
+import com.google.common.collect.Iterables;
+import com.google.common.truth.CustomSubjectBuilder;
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.IterableSubject;
+import com.google.common.truth.StandardSubjectBuilder;
import com.google.common.truth.Subject;
import java.util.List;
-import java.util.function.Function;
+import java.util.function.BiFunction;
public class ListSubject<S extends Subject<S, E>, E> extends IterableSubject {
- private final Function<E, S> elementAssertThatFunction;
+ private final BiFunction<StandardSubjectBuilder, E, S> elementSubjectCreator;
- @SuppressWarnings("unchecked")
public static <S extends Subject<S, E>, E> ListSubject<S, E> assertThat(
- List<E> list, Function<E, S> elementAssertThatFunction) {
- // The ListSubjectFactory always returns ListSubjects. -> Casting is appropriate.
- return (ListSubject<S, E>)
- assertAbout(new ListSubjectFactory<>(elementAssertThatFunction)).that(list);
+ List<E> list, Subject.Factory<S, E> subjectFactory) {
+ return assertAbout(elements()).thatCustom(list, subjectFactory);
+ }
+
+ public static CustomSubjectBuilder.Factory<ListSubjectBuilder> elements() {
+ return ListSubjectBuilder::new;
}
private ListSubject(
- FailureMetadata failureMetadata, List<E> list, Function<E, S> elementAssertThatFunction) {
+ FailureMetadata failureMetadata,
+ List<E> list,
+ BiFunction<StandardSubjectBuilder, E, S> elementSubjectCreator) {
super(failureMetadata, list);
- this.elementAssertThatFunction = elementAssertThatFunction;
+ this.elementSubjectCreator = elementSubjectCreator;
}
public S element(int index) {
@@ -49,20 +55,21 @@
if (index >= list.size()) {
failWithoutActual(fact("expected to have element at index", index));
}
- return elementAssertThatFunction.apply(list.get(index));
+ return elementSubjectCreator.apply(check("element(%s)", index), list.get(index));
}
public S onlyElement() {
isNotNull();
hasSize(1);
- return element(0);
+ List<E> list = getActualList();
+ return elementSubjectCreator.apply(check("onlyElement()"), Iterables.getOnlyElement(list));
}
public S lastElement() {
isNotNull();
isNotEmpty();
List<E> list = getActualList();
- return element(list.size() - 1);
+ return elementSubjectCreator.apply(check("lastElement()"), Iterables.getLast(list));
}
@SuppressWarnings("unchecked")
@@ -78,20 +85,20 @@
return (ListSubject<S, E>) super.named(s, objects);
}
- private static class ListSubjectFactory<S extends Subject<S, T>, T>
- implements Subject.Factory<IterableSubject, Iterable<?>> {
+ public static class ListSubjectBuilder extends CustomSubjectBuilder {
- private Function<T, S> elementAssertThatFunction;
-
- ListSubjectFactory(Function<T, S> elementAssertThatFunction) {
- this.elementAssertThatFunction = elementAssertThatFunction;
+ ListSubjectBuilder(FailureMetadata failureMetadata) {
+ super(failureMetadata);
}
- @SuppressWarnings("unchecked")
- @Override
- public ListSubject<S, T> createSubject(FailureMetadata failureMetadata, Iterable<?> objects) {
- // The constructor of ListSubject only accepts lists. -> Casting is appropriate.
- return new ListSubject<>(failureMetadata, (List<T>) objects, elementAssertThatFunction);
+ public <S extends Subject<S, E>, E> ListSubject<S, E> thatCustom(
+ List<E> list, Subject.Factory<S, E> subjectFactory) {
+ return that(list, (builder, element) -> builder.about(subjectFactory).that(element));
+ }
+
+ public <S extends Subject<S, E>, E> ListSubject<S, E> that(
+ List<E> list, BiFunction<StandardSubjectBuilder, E, S> elementSubjectCreator) {
+ return new ListSubject<>(metadata(), list, elementSubjectCreator);
}
}
}
diff --git a/java/com/google/gerrit/truth/OptionalSubject.java b/java/com/google/gerrit/truth/OptionalSubject.java
index d91f07b..b5fc5d0 100644
--- a/java/com/google/gerrit/truth/OptionalSubject.java
+++ b/java/com/google/gerrit/truth/OptionalSubject.java
@@ -17,41 +17,52 @@
import static com.google.common.truth.Fact.fact;
import static com.google.common.truth.Truth.assertAbout;
+import com.google.common.truth.CustomSubjectBuilder;
import com.google.common.truth.DefaultSubject;
import com.google.common.truth.FailureMetadata;
+import com.google.common.truth.StandardSubjectBuilder;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import java.util.Optional;
+import java.util.function.BiFunction;
import java.util.function.Function;
public class OptionalSubject<S extends Subject<S, ? super T>, T>
extends Subject<OptionalSubject<S, T>, Optional<T>> {
- private final Function<? super T, ? extends S> valueAssertThatFunction;
+ private final BiFunction<StandardSubjectBuilder, ? super T, ? extends S> valueSubjectCreator;
- public static <S extends Subject<S, ? super T>, T> OptionalSubject<S, T> assertThat(
+ // TODO(aliceks): Remove when all relevant usages are adapted to new check()/factory approach.
+ public static <S extends Subject<S, T>, T> OptionalSubject<S, T> assertThat(
Optional<T> optional, Function<? super T, ? extends S> elementAssertThatFunction) {
- OptionalSubjectFactory<S, T> optionalSubjectFactory =
- new OptionalSubjectFactory<>(elementAssertThatFunction);
- return assertAbout(optionalSubjectFactory).that(optional);
+ Subject.Factory<S, T> valueSubjectFactory =
+ (metadata, value) -> elementAssertThatFunction.apply(value);
+ return assertThat(optional, valueSubjectFactory);
+ }
+
+ public static <S extends Subject<S, T>, T> OptionalSubject<S, T> assertThat(
+ Optional<T> optional, Subject.Factory<S, T> valueSubjectFactory) {
+ return assertAbout(optionals()).thatCustom(optional, valueSubjectFactory);
}
public static OptionalSubject<DefaultSubject, ?> assertThat(Optional<?> optional) {
- // Unfortunately, we need to cast to DefaultSubject as Truth.assertThat()
+ // Unfortunately, we need to cast to DefaultSubject as StandardSubjectBuilder#that
// only returns Subject<DefaultSubject, Object>. There shouldn't be a way
// for that method not to return a DefaultSubject because the generic type
// definitions of a Subject are quite strict.
- Function<Object, DefaultSubject> valueAssertThatFunction =
- value -> (DefaultSubject) Truth.assertThat(value);
- return assertThat(optional, valueAssertThatFunction);
+ return assertAbout(optionals())
+ .that(optional, (builder, value) -> (DefaultSubject) builder.that(value));
+ }
+
+ public static CustomSubjectBuilder.Factory<OptionalSubjectBuilder> optionals() {
+ return OptionalSubjectBuilder::new;
}
private OptionalSubject(
FailureMetadata failureMetadata,
Optional<T> optional,
- Function<? super T, ? extends S> valueAssertThatFunction) {
+ BiFunction<StandardSubjectBuilder, ? super T, ? extends S> valueSubjectCreator) {
super(failureMetadata, optional);
- this.valueAssertThatFunction = valueAssertThatFunction;
+ this.valueSubjectCreator = valueSubjectCreator;
}
public void isPresent() {
@@ -78,22 +89,28 @@
isNotNull();
isPresent();
Optional<T> optional = actual();
- return valueAssertThatFunction.apply(optional.get());
+ return valueSubjectCreator.apply(check("value()"), optional.get());
}
- private static class OptionalSubjectFactory<S extends Subject<S, ? super T>, T>
- implements Subject.Factory<OptionalSubject<S, T>, Optional<T>> {
+ public static class OptionalSubjectBuilder extends CustomSubjectBuilder {
- private Function<? super T, ? extends S> valueAssertThatFunction;
-
- OptionalSubjectFactory(Function<? super T, ? extends S> valueAssertThatFunction) {
- this.valueAssertThatFunction = valueAssertThatFunction;
+ OptionalSubjectBuilder(FailureMetadata failureMetadata) {
+ super(failureMetadata);
}
- @Override
- public OptionalSubject<S, T> createSubject(
- FailureMetadata failureMetadata, Optional<T> optional) {
- return new OptionalSubject<>(failureMetadata, optional, valueAssertThatFunction);
+ public <S extends Subject<S, T>, T> OptionalSubject<S, T> thatCustom(
+ Optional<T> optional, Subject.Factory<S, T> valueSubjectFactory) {
+ return that(optional, (builder, value) -> builder.about(valueSubjectFactory).that(value));
+ }
+
+ public OptionalSubject<DefaultSubject, ?> that(Optional<?> optional) {
+ return that(optional, (builder, value) -> (DefaultSubject) builder.that(value));
+ }
+
+ public <S extends Subject<S, ? super T>, T> OptionalSubject<S, T> that(
+ Optional<T> optional,
+ BiFunction<StandardSubjectBuilder, ? super T, ? extends S> valueSubjectCreator) {
+ return new OptionalSubject<>(metadata(), optional, valueSubjectCreator);
}
}
}
diff --git a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
index 5aed312..e638e9c 100644
--- a/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/change/ChangeIT.java
@@ -77,6 +77,7 @@
import com.google.gerrit.extensions.api.changes.AddReviewerResult;
import com.google.gerrit.extensions.api.changes.DeleteReviewerInput;
import com.google.gerrit.extensions.api.changes.DeleteVoteInput;
+import com.google.gerrit.extensions.api.changes.DraftInput;
import com.google.gerrit.extensions.api.changes.NotifyHandling;
import com.google.gerrit.extensions.api.changes.NotifyInfo;
import com.google.gerrit.extensions.api.changes.RebaseInput;
@@ -1214,6 +1215,36 @@
}
@Test
+ public void deleteChangeRemovesDraftComment() throws Exception {
+ PushOneCommit.Result r = createChange();
+
+ requestScopeOperations.setApiUser(user.getId());
+
+ DraftInput dri = new DraftInput();
+ dri.message = "hello";
+ dri.path = "a.txt";
+ dri.line = 1;
+
+ gApi.changes().id(r.getChangeId()).current().createDraft(dri);
+ Change.Id num = r.getChange().getId();
+
+ try (Repository repo = repoManager.openRepository(allUsers)) {
+ assertThat(
+ repo.getRefDatabase().getRefsByPrefix(RefNames.refsDraftComments(num, user.getId())))
+ .isNotEmpty();
+ }
+
+ requestScopeOperations.setApiUser(admin.getId());
+
+ gApi.changes().id(r.getChangeId()).delete();
+ try (Repository repo = repoManager.openRepository(allUsers)) {
+ assertThat(
+ repo.getRefDatabase().getRefsByPrefix(RefNames.refsDraftComments(num, user.getId())))
+ .isEmpty();
+ }
+ }
+
+ @Test
public void rebaseUpToDateChange() throws Exception {
PushOneCommit.Result r = createChange();
exception.expect(ResourceConflictException.class);
diff --git a/javatests/com/google/gerrit/acceptance/api/group/GroupIndexerIT.java b/javatests/com/google/gerrit/acceptance/api/group/GroupIndexerIT.java
index a664869..3f09db9 100644
--- a/javatests/com/google/gerrit/acceptance/api/group/GroupIndexerIT.java
+++ b/javatests/com/google/gerrit/acceptance/api/group/GroupIndexerIT.java
@@ -15,6 +15,7 @@
package com.google.gerrit.acceptance.api.group;
import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.gerrit.server.group.testing.InternalGroupSubject.internalGroups;
import static com.google.gerrit.truth.ListSubject.assertThat;
import static com.google.gerrit.truth.OptionalSubject.assertThat;
@@ -163,11 +164,11 @@
private static OptionalSubject<InternalGroupSubject, InternalGroup> assertThatGroup(
Optional<InternalGroup> updatedGroup) {
- return assertThat(updatedGroup, InternalGroupSubject::assertThat);
+ return assertThat(updatedGroup, internalGroups());
}
private static ListSubject<InternalGroupSubject, InternalGroup> assertThatGroups(
List<InternalGroup> parentGroups) {
- return assertThat(parentGroups, InternalGroupSubject::assertThat);
+ return assertThat(parentGroups, internalGroups());
}
}
diff --git a/javatests/com/google/gerrit/index/BUILD b/javatests/com/google/gerrit/index/BUILD
index e3436bc..a1f60de 100644
--- a/javatests/com/google/gerrit/index/BUILD
+++ b/javatests/com/google/gerrit/index/BUILD
@@ -9,6 +9,7 @@
"//antlr3:query_parser",
"//java/com/google/gerrit/index",
"//java/com/google/gerrit/index:query_exception",
+ "//java/com/google/gerrit/index/query/testing",
"//java/com/google/gerrit/testing:gerrit-test-util",
"//lib:guava",
"//lib:junit",
diff --git a/javatests/com/google/gerrit/index/query/QueryBuilderTest.java b/javatests/com/google/gerrit/index/query/QueryBuilderTest.java
new file mode 100644
index 0000000..d275fa8
--- /dev/null
+++ b/javatests/com/google/gerrit/index/query/QueryBuilderTest.java
@@ -0,0 +1,125 @@
+// Copyright (C) 2019 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.index.query;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.common.truth.ThrowableSubject;
+import com.google.gerrit.testing.GerritBaseTests;
+import java.util.Collection;
+import java.util.Objects;
+import org.junit.Test;
+
+public class QueryBuilderTest extends GerritBaseTests {
+ private static class TestPredicate extends Predicate<Object> {
+ private final String field;
+ private final String value;
+
+ TestPredicate(String field, String value) {
+ this.field = field;
+ this.value = value;
+ }
+
+ @Override
+ public Predicate<Object> copy(Collection<? extends Predicate<Object>> children) {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(field, value);
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (!(o instanceof TestPredicate)) {
+ return false;
+ }
+ TestPredicate p = (TestPredicate) o;
+ return Objects.equals(field, p.field) && Objects.equals(value, p.value);
+ }
+ }
+
+ private static class TestQueryBuilder extends QueryBuilder<Object> {
+ TestQueryBuilder() {
+ super(new QueryBuilder.Definition<>(TestQueryBuilder.class));
+ }
+
+ @Operator
+ public Predicate<Object> a(String value) {
+ return new TestPredicate("a", value);
+ }
+ }
+
+ @Test
+ public void fieldNameAndValue() throws Exception {
+ assertThat(parse("a:foo")).isEqualTo(new TestPredicate("a", "foo"));
+ }
+
+ @Test
+ public void fieldWithParenthesizedValues() throws Exception {
+ assertThatParseException("a:(foo bar)")
+ .hasMessageThat()
+ .isEqualTo("line 1:2 no viable alternative at input '('");
+ }
+
+ @Test
+ public void fieldNameAndValueThatLooksLikeFieldNameColonValue() throws Exception {
+ assertThat(parse("a:foo:bar")).isEqualTo(new TestPredicate("a", "foo:bar"));
+ }
+
+ @Test
+ public void fieldNameAndValueThatLooksLikeWordColonValue() throws Exception {
+ assertThat(parse("a:*:bar")).isEqualTo(new TestPredicate("a", "*:bar"));
+ }
+
+ @Test
+ public void fieldNameAndValueWithMultipleColons() throws Exception {
+ assertThat(parse("a:*:*:*")).isEqualTo(new TestPredicate("a", "*:*:*"));
+ }
+
+ @Test
+ public void exactPhraseWithQuotes() throws Exception {
+ assertThat(parse("a:\"foo bar\"")).isEqualTo(new TestPredicate("a", "foo bar"));
+ }
+
+ @Test
+ public void exactPhraseWithQuotesAndColon() throws Exception {
+ assertThat(parse("a:\"foo:bar\"")).isEqualTo(new TestPredicate("a", "foo:bar"));
+ }
+
+ @Test
+ public void exactPhraseWithBraces() throws Exception {
+ assertThat(parse("a:{foo bar}")).isEqualTo(new TestPredicate("a", "foo bar"));
+ }
+
+ @Test
+ public void exactPhraseWithBracesAndColon() throws Exception {
+ assertThat(parse("a:{foo:bar}")).isEqualTo(new TestPredicate("a", "foo:bar"));
+ }
+
+ private static Predicate<Object> parse(String query) throws Exception {
+ return new TestQueryBuilder().parse(query);
+ }
+
+ private static ThrowableSubject assertThatParseException(String query) {
+ try {
+ new TestQueryBuilder().parse(query);
+ throw new AssertionError("expected QueryParseException for " + query);
+ } catch (QueryParseException e) {
+ return assertThat(e);
+ }
+ }
+}
diff --git a/javatests/com/google/gerrit/index/query/QueryParserTest.java b/javatests/com/google/gerrit/index/query/QueryParserTest.java
index 2175f7d..250c40c 100644
--- a/javatests/com/google/gerrit/index/query/QueryParserTest.java
+++ b/javatests/com/google/gerrit/index/query/QueryParserTest.java
@@ -14,7 +14,13 @@
package com.google.gerrit.index.query;
-import static org.junit.Assert.assertEquals;
+import static com.google.common.truth.Truth.assert_;
+import static com.google.gerrit.index.query.QueryParser.AND;
+import static com.google.gerrit.index.query.QueryParser.COLON;
+import static com.google.gerrit.index.query.QueryParser.FIELD_NAME;
+import static com.google.gerrit.index.query.QueryParser.SINGLE_WORD;
+import static com.google.gerrit.index.query.QueryParser.parse;
+import static com.google.gerrit.index.query.testing.TreeSubject.assertThat;
import com.google.gerrit.testing.GerritBaseTests;
import org.antlr.runtime.tree.Tree;
@@ -22,27 +28,172 @@
public class QueryParserTest extends GerritBaseTests {
@Test
- public void projectBare() throws QueryParseException {
- Tree r;
-
- r = parse("project:tools/gerrit");
- assertSingleWord("project", "tools/gerrit", r);
-
- r = parse("project:tools/*");
- assertSingleWord("project", "tools/*", r);
+ public void fieldNameAndValue() throws Exception {
+ Tree r = parse("project:tools/gerrit");
+ assertThat(r).hasType(FIELD_NAME);
+ assertThat(r).hasText("project");
+ assertThat(r).hasChildCount(1);
+ assertThat(r).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).hasText("tools/gerrit");
+ assertThat(r).child(0).hasNoChildren();
}
- private static void assertSingleWord(String name, String value, Tree r) {
- assertEquals(QueryParser.FIELD_NAME, r.getType());
- assertEquals(name, r.getText());
- assertEquals(1, r.getChildCount());
- final Tree c = r.getChild(0);
- assertEquals(QueryParser.SINGLE_WORD, c.getType());
- assertEquals(value, c.getText());
- assertEquals(0, c.getChildCount());
+ @Test
+ public void fieldNameAndValueThatLooksLikeFieldNameColon() throws Exception {
+ // This should work, but doesn't due to a known issue.
+ assertParseFails("project:foo:");
}
- private static Tree parse(String str) throws QueryParseException {
- return QueryParser.parse(str);
+ @Test
+ public void fieldNameAndValueThatLooksLikeFieldNameColonValue() throws Exception {
+ Tree r = parse("project:foo:bar");
+ assertThat(r).hasType(FIELD_NAME);
+ assertThat(r).hasText("project");
+ assertThat(r).hasChildCount(3);
+ assertThat(r).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).hasText("foo");
+ assertThat(r).child(0).hasNoChildren();
+ assertThat(r).child(1).hasType(COLON);
+ assertThat(r).child(1).hasText(":");
+ assertThat(r).child(1).hasNoChildren();
+ assertThat(r).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(2).hasText("bar");
+ assertThat(r).child(2).hasNoChildren();
+ }
+
+ @Test
+ public void fieldNameAndValueThatLooksLikeWordColonValue() throws Exception {
+ Tree r = parse("project:x*y:a*b");
+ assertThat(r).hasType(FIELD_NAME);
+ assertThat(r).hasText("project");
+ assertThat(r).hasChildCount(3);
+ assertThat(r).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).hasText("x*y");
+ assertThat(r).child(0).hasNoChildren();
+ assertThat(r).child(1).hasType(COLON);
+ assertThat(r).child(1).hasText(":");
+ assertThat(r).child(1).hasNoChildren();
+ assertThat(r).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(2).hasText("a*b");
+ assertThat(r).child(2).hasNoChildren();
+ }
+
+ @Test
+ public void fieldNameAndValueThatLooksLikeWordColon() throws Exception {
+ // This should work, but doesn't due to a known issue.
+ assertParseFails("project:x*y:");
+ }
+
+ @Test
+ public void fieldNameAndValueWithMultipleColons() throws Exception {
+ Tree r = parse("project:*:*:*");
+ assertThat(r).hasType(FIELD_NAME);
+ assertThat(r).hasText("project");
+ assertThat(r).hasChildCount(5);
+ assertThat(r).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).hasText("*");
+ assertThat(r).child(0).hasNoChildren();
+ assertThat(r).child(1).hasType(COLON);
+ assertThat(r).child(1).hasText(":");
+ assertThat(r).child(1).hasNoChildren();
+ assertThat(r).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(2).hasText("*");
+ assertThat(r).child(2).hasNoChildren();
+ assertThat(r).child(3).hasType(COLON);
+ assertThat(r).child(3).hasText(":");
+ assertThat(r).child(3).hasNoChildren();
+ assertThat(r).child(4).hasType(SINGLE_WORD);
+ assertThat(r).child(4).hasText("*");
+ assertThat(r).child(4).hasNoChildren();
+ }
+
+ @Test
+ public void fieldNameAndValueWithColonFollowedByAnotherField() throws Exception {
+ Tree r = parse("project:foo:bar file:baz");
+ assertThat(r).hasType(AND);
+ assertThat(r).hasChildCount(2);
+
+ assertThat(r).child(0).hasType(FIELD_NAME);
+ assertThat(r).child(0).hasText("project");
+ assertThat(r).child(0).hasChildCount(3);
+ assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(0).hasText("foo");
+ assertThat(r).child(0).child(0).hasNoChildren();
+ assertThat(r).child(0).child(1).hasType(COLON);
+ assertThat(r).child(0).child(1).hasText(":");
+ assertThat(r).child(0).child(1).hasNoChildren();
+ assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(2).hasText("bar");
+ assertThat(r).child(0).child(2).hasNoChildren();
+
+ assertThat(r).child(1).hasType(FIELD_NAME);
+ assertThat(r).child(1).hasText("file");
+ assertThat(r).child(1).hasChildCount(1);
+ assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(1).child(0).hasText("baz");
+ assertThat(r).child(1).child(0).hasNoChildren();
+ }
+
+ @Test
+ public void fieldNameAndValueWithColonFollowedByOpenParen() throws Exception {
+ Tree r = parse("project:foo:bar (file:baz)");
+ assertThat(r).hasType(AND);
+ assertThat(r).hasChildCount(2);
+
+ assertThat(r).child(0).hasType(FIELD_NAME);
+ assertThat(r).child(0).hasText("project");
+ assertThat(r).child(0).hasChildCount(3);
+ assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(0).hasText("foo");
+ assertThat(r).child(0).child(0).hasNoChildren();
+ assertThat(r).child(0).child(1).hasType(COLON);
+ assertThat(r).child(0).child(1).hasText(":");
+ assertThat(r).child(0).child(1).hasNoChildren();
+ assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(2).hasText("bar");
+ assertThat(r).child(0).child(2).hasNoChildren();
+
+ assertThat(r).child(1).hasType(FIELD_NAME);
+ assertThat(r).child(1).hasText("file");
+ assertThat(r).child(1).hasChildCount(1);
+ assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(1).child(0).hasText("baz");
+ assertThat(r).child(1).child(0).hasNoChildren();
+ }
+
+ @Test
+ public void fieldNameAndValueWithColonFollowedByCloseParen() throws Exception {
+ Tree r = parse("(project:foo:bar) file:baz");
+ assertThat(r).hasType(AND);
+ assertThat(r).hasChildCount(2);
+
+ assertThat(r).child(0).hasType(FIELD_NAME);
+ assertThat(r).child(0).hasText("project");
+ assertThat(r).child(0).hasChildCount(3);
+ assertThat(r).child(0).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(0).hasText("foo");
+ assertThat(r).child(0).child(0).hasNoChildren();
+ assertThat(r).child(0).child(1).hasType(COLON);
+ assertThat(r).child(0).child(1).hasText(":");
+ assertThat(r).child(0).child(1).hasNoChildren();
+ assertThat(r).child(0).child(2).hasType(SINGLE_WORD);
+ assertThat(r).child(0).child(2).hasText("bar");
+ assertThat(r).child(0).child(2).hasNoChildren();
+
+ assertThat(r).child(1).hasType(FIELD_NAME);
+ assertThat(r).child(1).hasText("file");
+ assertThat(r).child(1).hasChildCount(1);
+ assertThat(r).child(1).child(0).hasType(SINGLE_WORD);
+ assertThat(r).child(1).child(0).hasText("baz");
+ assertThat(r).child(1).child(0).hasNoChildren();
+ }
+
+ private static void assertParseFails(String query) {
+ try {
+ parse(query);
+ assert_().fail("expected parse to fail: %s", query);
+ } catch (QueryParseException e) {
+ // Expected.
+ }
}
}
diff --git a/javatests/com/google/gerrit/server/edit/tree/ChangeFileContentModificationSubject.java b/javatests/com/google/gerrit/server/edit/tree/ChangeFileContentModificationSubject.java
index 574c795..265b24e 100644
--- a/javatests/com/google/gerrit/server/edit/tree/ChangeFileContentModificationSubject.java
+++ b/javatests/com/google/gerrit/server/edit/tree/ChangeFileContentModificationSubject.java
@@ -20,7 +20,6 @@
import com.google.common.truth.FailureMetadata;
import com.google.common.truth.StringSubject;
import com.google.common.truth.Subject;
-import com.google.common.truth.Truth;
import com.google.gerrit.extensions.restapi.RawInput;
import java.io.IOException;
import java.io.InputStreamReader;
@@ -41,16 +40,16 @@
public StringSubject filePath() {
isNotNull();
- return Truth.assertThat(actual().getFilePath()).named("filePath");
+ return check("filePath()").that(actual().getFilePath());
}
public StringSubject newContent() throws IOException {
isNotNull();
RawInput newContent = actual().getNewContent();
- Truth.assertThat(newContent).named("newContent").isNotNull();
+ check("newContent()").that(newContent).isNotNull();
String contentString =
CharStreams.toString(
new InputStreamReader(newContent.getInputStream(), StandardCharsets.UTF_8));
- return Truth.assertThat(contentString).named("newContent");
+ return check("newContent()").that(contentString);
}
}
diff --git a/javatests/com/google/gerrit/server/edit/tree/TreeModificationSubject.java b/javatests/com/google/gerrit/server/edit/tree/TreeModificationSubject.java
index 59ee2b7..bd9d4df 100644
--- a/javatests/com/google/gerrit/server/edit/tree/TreeModificationSubject.java
+++ b/javatests/com/google/gerrit/server/edit/tree/TreeModificationSubject.java
@@ -24,12 +24,17 @@
public class TreeModificationSubject extends Subject<TreeModificationSubject, TreeModification> {
public static TreeModificationSubject assertThat(TreeModification treeModification) {
- return assertAbout(TreeModificationSubject::new).that(treeModification);
+ return assertAbout(treeModifications()).that(treeModification);
+ }
+
+ private static Factory<TreeModificationSubject, TreeModification> treeModifications() {
+ return TreeModificationSubject::new;
}
public static ListSubject<TreeModificationSubject, TreeModification> assertThatList(
List<TreeModification> treeModifications) {
- return ListSubject.assertThat(treeModifications, TreeModificationSubject::assertThat)
+ return assertAbout(ListSubject.elements())
+ .thatCustom(treeModifications, treeModifications())
.named("treeModifications");
}
diff --git a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
index 6f43380..c9ba72e 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupConfigTest.java
@@ -16,6 +16,7 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assertWithMessage;
+import static com.google.gerrit.server.group.testing.InternalGroupSubject.internalGroups;
import static com.google.gerrit.truth.OptionalSubject.assertThat;
import static org.hamcrest.CoreMatchers.instanceOf;
@@ -1673,6 +1674,6 @@
private static OptionalSubject<InternalGroupSubject, InternalGroup> assertThatGroup(
Optional<InternalGroup> loadedGroup) {
- return assertThat(loadedGroup, InternalGroupSubject::assertThat);
+ return assertThat(loadedGroup, internalGroups());
}
}
diff --git a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
index cff8189..55eb0a8 100644
--- a/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
+++ b/javatests/com/google/gerrit/server/group/db/GroupNameNotesTest.java
@@ -16,7 +16,9 @@
import static com.google.common.truth.Truth.assertThat;
import static com.google.common.truth.Truth.assert_;
+import static com.google.gerrit.common.data.testing.GroupReferenceSubject.groupReferences;
import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.assertThat;
+import static com.google.gerrit.extensions.common.testing.CommitInfoSubject.commits;
import static com.google.gerrit.reviewdb.client.RefNames.REFS_GROUPNAMES;
import static com.google.gerrit.truth.OptionalSubject.assertThat;
import static java.nio.charset.StandardCharsets.UTF_8;
@@ -584,11 +586,11 @@
private static OptionalSubject<GroupReferenceSubject, GroupReference> assertThatGroup(
Optional<GroupReference> group) {
- return assertThat(group, GroupReferenceSubject::assertThat);
+ return assertThat(group, groupReferences());
}
private static ListSubject<CommitInfoSubject, CommitInfo> assertThatCommits(
List<CommitInfo> commits) {
- return ListSubject.assertThat(commits, CommitInfoSubject::assertThat);
+ return ListSubject.assertThat(commits, commits());
}
}
diff --git a/polygerrit-ui/BUILD b/polygerrit-ui/BUILD
index 3988f95..0e9b4bb 100644
--- a/polygerrit-ui/BUILD
+++ b/polygerrit-ui/BUILD
@@ -57,11 +57,8 @@
data = [
":fonts.zip",
"//polygerrit-ui/app:test_components.zip",
- "//resources/com/google/gerrit/httpd/raw",
],
deps = [
- "@com_github_robfig_soy//:go_default_library",
- "@com_github_robfig_soy//soyhtml:go_default_library",
"@org_golang_x_tools//godoc/vfs/httpfs:go_default_library",
"@org_golang_x_tools//godoc/vfs/zipfs:go_default_library",
],
diff --git a/polygerrit-ui/app/embed/gr-diff.html b/polygerrit-ui/app/embed/gr-diff.html
new file mode 100644
index 0000000..6aa9370
--- /dev/null
+++ b/polygerrit-ui/app/embed/gr-diff.html
@@ -0,0 +1,25 @@
+<!--
+@license
+Copyright (C) 2019 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.
+-->
+<script>
+ // Needed for JSCompiler to understand it's global.
+ // eslint-disable-next-line no-unused-vars, prefer-const
+ let Gerrit = window.Gerrit || {};
+ window.Gerrit = Gerrit;
+</script>
+<link rel="import" href="../styles/themes/app-theme.html">
+<link rel="import" href="../elements/diff/gr-diff/gr-diff.html">
+<link rel="import" href="../elements/diff/gr-diff-cursor/gr-diff-cursor.html">
diff --git a/polygerrit-ui/server.go b/polygerrit-ui/server.go
index ba685184..2f5df90 100644
--- a/polygerrit-ui/server.go
+++ b/polygerrit-ui/server.go
@@ -17,6 +17,7 @@
import (
"archive/zip"
"bufio"
+ "bytes"
"compress/gzip"
"encoding/json"
"errors"
@@ -32,20 +33,16 @@
"regexp"
"strings"
- "github.com/robfig/soy"
- "github.com/robfig/soy/soyhtml"
"golang.org/x/tools/godoc/vfs/httpfs"
"golang.org/x/tools/godoc/vfs/zipfs"
)
var (
- plugins = flag.String("plugins", "", "comma seperated plugin paths to serve")
- port = flag.String("port", ":8081", "Port to serve HTTP requests on")
- prod = flag.Bool("prod", false, "Serve production assets")
- restHost = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to")
- scheme = flag.String("scheme", "https", "URL scheme")
-
- tofu *soyhtml.Tofu
+ plugins = flag.String("plugins", "", "comma seperated plugin paths to serve")
+ port = flag.String("port", ":8081", "Port to serve HTTP requests on")
+ host = flag.String("host", "gerrit-review.googlesource.com", "Host to proxy requests to")
+ scheme = flag.String("scheme", "https", "URL scheme")
+ cdnPattern = regexp.MustCompile("https://cdn.googlesource.com/polygerrit_ui/[0-9.]*")
)
func main() {
@@ -61,55 +58,35 @@
log.Fatal(err)
}
- tofu, err = resolveIndexTemplate()
- if err != nil {
- log.Fatal(err)
- }
-
workspace := os.Getenv("BUILD_WORKSPACE_DIRECTORY")
if err := os.Chdir(filepath.Join(workspace, "polygerrit-ui")); err != nil {
log.Fatal(err)
}
- http.HandleFunc("/index.html", handleIndex)
-
- if *prod {
- http.Handle("/", http.FileServer(http.Dir("dist")))
- } else {
- http.Handle("/", http.FileServer(http.Dir("app")))
- }
-
+ http.Handle("/", http.FileServer(http.Dir("app")))
http.Handle("/bower_components/",
http.FileServer(httpfs.New(zipfs.New(componentsArchive, "bower_components"))))
http.Handle("/fonts/",
http.FileServer(httpfs.New(zipfs.New(fontsArchive, "fonts"))))
- http.HandleFunc("/changes/", handleRESTProxy)
- http.HandleFunc("/accounts/", handleRESTProxy)
- http.HandleFunc("/config/", handleRESTProxy)
- http.HandleFunc("/projects/", handleRESTProxy)
+ http.HandleFunc("/index.html", handleIndex)
+ http.HandleFunc("/changes/", handleProxy)
+ http.HandleFunc("/accounts/", handleProxy)
+ http.HandleFunc("/config/", handleProxy)
+ http.HandleFunc("/projects/", handleProxy)
http.HandleFunc("/accounts/self/detail", handleAccountDetail)
+
if len(*plugins) > 0 {
http.Handle("/plugins/", http.StripPrefix("/plugins/",
http.FileServer(http.Dir("../plugins"))))
log.Println("Local plugins from", "../plugins")
} else {
- http.HandleFunc("/plugins/", handleRESTProxy)
+ http.HandleFunc("/plugins/", handleProxy)
}
log.Println("Serving on port", *port)
log.Fatal(http.ListenAndServe(*port, &server{}))
}
-func resolveIndexTemplate() (*soyhtml.Tofu, error) {
- basePath, err := resourceBasePath()
- if err != nil {
- return nil, err
- }
- return soy.NewBundle().
- AddTemplateFile(basePath + ".runfiles/gerrit/resources/com/google/gerrit/httpd/raw/PolyGerritIndexHtml.soy").
- CompileToTofu()
-}
-
func openDataArchive(path string) (*zip.ReadCloser, error) {
absBinPath, err := resourceBasePath()
if err != nil {
@@ -122,40 +99,40 @@
return filepath.Abs(os.Args[0])
}
-func handleIndex(w http.ResponseWriter, r *http.Request) {
- var obj = map[string]interface{}{
- "canonicalPath": "",
- "staticResourcePath": "",
+func handleIndex(writer http.ResponseWriter, originalRequest *http.Request) {
+ fakeRequest := &http.Request{
+ URL: &url.URL{
+ Path: "/",
+ },
}
- w.Header().Set("Content-Type", "text/html")
- tofu.Render(w, "com.google.gerrit.httpd.raw.Index", obj)
+ handleProxy(writer, fakeRequest)
}
-func handleRESTProxy(w http.ResponseWriter, r *http.Request) {
- req := &http.Request{
+func handleProxy(writer http.ResponseWriter, originalRequest *http.Request) {
+ patchedRequest := &http.Request{
Method: "GET",
URL: &url.URL{
Scheme: *scheme,
- Host: *restHost,
- Opaque: r.URL.EscapedPath(),
- RawQuery: r.URL.RawQuery,
+ Host: *host,
+ Opaque: originalRequest.URL.EscapedPath(),
+ RawQuery: originalRequest.URL.RawQuery,
},
}
- res, err := http.DefaultClient.Do(req)
+ response, err := http.DefaultClient.Do(patchedRequest)
if err != nil {
- http.Error(w, err.Error(), http.StatusInternalServerError)
+ http.Error(writer, err.Error(), http.StatusInternalServerError)
return
}
- defer res.Body.Close()
- for name, values := range res.Header {
+ defer response.Body.Close()
+ for name, values := range response.Header {
for _, value := range values {
if name != "Content-Length" {
- w.Header().Add(name, value)
+ writer.Header().Add(name, value)
}
}
}
- w.WriteHeader(res.StatusCode)
- if _, err := io.Copy(w, patchResponse(r, res)); err != nil {
+ writer.WriteHeader(response.StatusCode)
+ if _, err := io.Copy(writer, patchResponse(originalRequest, response)); err != nil {
log.Println("Error copying response to ResponseWriter:", err)
return
}
@@ -188,8 +165,10 @@
}
}
-func patchResponse(r *http.Request, res *http.Response) io.Reader {
- switch r.URL.EscapedPath() {
+func patchResponse(req *http.Request, res *http.Response) io.Reader {
+ switch req.URL.EscapedPath() {
+ case "/":
+ return replaceCdn(res.Body)
case "/config/server/info":
return injectLocalPlugins(res.Body)
default:
@@ -197,13 +176,23 @@
}
}
-func injectLocalPlugins(r io.Reader) io.Reader {
+func replaceCdn(reader io.Reader) io.Reader {
+ buf := new(bytes.Buffer)
+ buf.ReadFrom(reader)
+ original := buf.String()
+
+ replaced := cdnPattern.ReplaceAllString(original, "")
+
+ return strings.NewReader(replaced)
+}
+
+func injectLocalPlugins(reader io.Reader) io.Reader {
if len(*plugins) == 0 {
- return r
+ return reader
}
// Skip escape prefix
- io.CopyN(ioutil.Discard, r, 5)
- dec := json.NewDecoder(r)
+ io.CopyN(ioutil.Discard, reader, 5)
+ dec := json.NewDecoder(reader)
var response map[string]interface{}
err := dec.Decode(&response)