Merge "Stop calling unregisterWorkqueue which was removed in gerrit"
diff --git a/.buckconfig b/.buckconfig
deleted file mode 100644
index 81f137b..0000000
--- a/.buckconfig
+++ /dev/null
@@ -1,16 +0,0 @@
-[alias]
-  webhooks = //:webhooks
-  plugin = //:webhooks
-  src = //:webhooks-sources
-
-[java]
-  jar_spool_mode = direct_to_jar
-  src_roots = java, resources
-
-[project]
-  ignore = .git, eclipse-out/
-  parallel_parsing = true
-
-[cache]
-  mode = dir
-  dir = buck-out/cache
diff --git a/.gitignore b/.gitignore
index c27e17f..8cf583c 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,9 +1,13 @@
-/.buckd/
-/.buckversion
 /.classpath
 /.project
 /.settings/
-/.watchmanconfig
+/.primary_build_tool
+/bazel-bin
+/bazel-genfiles
+/bazel-out
+/bazel-reviewers
+/bazel-testlogs
+/bazel-webhooks
 /buck-out/
 /bucklets
 /eclipse-out/
diff --git a/BUCK b/BUCK
deleted file mode 100644
index f78d670..0000000
--- a/BUCK
+++ /dev/null
@@ -1,70 +0,0 @@
-include_defs('//bucklets/gerrit_plugin.bucklet')
-include_defs('//bucklets/java_sources.bucklet')
-include_defs('//bucklets/maven_jar.bucklet')
-
-SOURCES = glob(['src/main/java/**/*.java'])
-RESOURCES = glob(['src/main/resources/**/*'])
-
-TEST_DEPS = GERRIT_PLUGIN_API + GERRIT_TESTS + [
-  ':webhooks__plugin',
-  ':mockito',
-]
-
-gerrit_plugin(
-  name = 'webhooks',
-  srcs = SOURCES,
-  resources = RESOURCES,
-  manifest_entries = [
-    'Gerrit-PluginName: webhooks',
-    'Gerrit-ApiType: plugin',
-    'Gerrit-Module: com.googlesource.gerrit.plugins.webhooks.Module',
-    'Implementation-Title: webhooks plugin',
-    'Implementation-URL: https://gerrit-review.googlesource.com/#/admin/projects/plugins/webhooks',
-    'Implementation-Vendor: Gerrit Code Review',
-  ],
-  provided_deps = GERRIT_TESTS,
-)
-
-java_sources(
-  name = 'webhooks-sources',
-  srcs = SOURCES + RESOURCES,
-)
-
-java_library(
-  name = 'classpath',
-  deps = TEST_DEPS,
-)
-
-java_test(
-  name = 'webhooks_tests',
-  srcs = glob(['src/test/java/**/*.java']),
-  labels = ['webhooks'],
-  deps = TEST_DEPS,
-)
-
-maven_jar(
-  name = 'mockito',
-  id = 'org.mockito:mockito-core:2.7.21',
-  sha1 = '23e9f7bfb9717e849a05b84c29ee3ac723f1a653',
-  license = 'DO_NOT_DISTRIBUTE',
-  deps = [
-    ':byte-buddy',
-    ':objenesis',
-  ],
-)
-
-maven_jar(
-  name = 'byte-buddy',
-  id = 'net.bytebuddy:byte-buddy:1.6.11',
-  sha1 = '8a8f9409e27f1d62c909c7eef2aa7b3a580b4901',
-  license = 'DO_NOT_DISTRIBUTE',
-  attach_source = False,
-)
-
-maven_jar(
-  name = 'objenesis',
-  id = 'org.objenesis:objenesis:2.5',
-  sha1 = '612ecb799912ccf77cba9b3ed8c813da086076e9',
-  license = 'DO_NOT_DISTRIBUTE',
-  attach_source = False,
-)
diff --git a/BUILD b/BUILD
new file mode 100644
index 0000000..298e4a0
--- /dev/null
+++ b/BUILD
@@ -0,0 +1,44 @@
+load("//tools/bzl:junit.bzl", "junit_tests")
+load(
+    "//tools/bzl:plugin.bzl",
+    "gerrit_plugin",
+    "PLUGIN_DEPS",
+    "PLUGIN_TEST_DEPS",
+)
+
+gerrit_plugin(
+    name = "webhooks",
+    srcs = glob(["src/main/java/**/*.java"]),
+    manifest_entries = [
+        "Gerrit-PluginName: webhooks",
+        "Gerrit-Module: com.googlesource.gerrit.plugins.webhooks.Module",
+        "Implementation-Title: webhooks plugin",
+        "Implementation-URL: https://gerrit-review.googlesource.com/#/admin/projects/plugins/webhooks",
+        "Implementation-Vendor: Gerrit Code Review",
+    ],
+    resources = glob(["src/main/resources/**/*"]),
+)
+
+junit_tests(
+    name = "webhooks_tests",
+    srcs = glob(["src/test/java/**/*.java"]),
+    resources = glob(["src/test/resources/**/*"]),
+    tags = [
+        "webhooks",
+        "local",
+    ],
+    deps = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
+        ":webhooks__plugin_test_deps",
+        ":webhooks__plugin",
+    ],
+)
+
+java_library(
+    name = "webhooks__plugin_test_deps",
+    visibility = ["//visibility:public"],
+    exports = [
+        "@byte-buddy//jar",
+        "@mockito//jar",
+        "@objenesis//jar",
+    ],
+)
diff --git a/WORKSPACE b/WORKSPACE
new file mode 100644
index 0000000..f5f3369
--- /dev/null
+++ b/WORKSPACE
@@ -0,0 +1,44 @@
+workspace(name = "webhooks")
+load("//:bazlets.bzl", "load_bazlets")
+
+load_bazlets(
+    commit = "28aa2290c7f7742261d69b358f3de30d2e87c13b",
+)
+
+#Snapshot Plugin API
+#load(
+#    "@com_googlesource_gerrit_bazlets//:gerrit_api_maven_local.bzl",
+#    "gerrit_api_maven_local",
+#)
+
+# Load snapshot Plugin API
+#gerrit_api_maven_local()
+
+# Release Plugin API
+load(
+   "@com_googlesource_gerrit_bazlets//:gerrit_api.bzl",
+   "gerrit_api",
+)
+
+# Load release Plugin API
+gerrit_api()
+
+load("@com_googlesource_gerrit_bazlets//tools:maven_jar.bzl", "maven_jar")
+
+maven_jar(
+    name = "mockito",
+    artifact = "org.mockito:mockito-core:2.7.21",
+    sha1 = "23e9f7bfb9717e849a05b84c29ee3ac723f1a653",
+)
+
+maven_jar(
+    name = "byte-buddy",
+    artifact = "net.bytebuddy:byte-buddy:1.6.11",
+    sha1 = "8a8f9409e27f1d62c909c7eef2aa7b3a580b4901",
+)
+
+maven_jar(
+    name = "objenesis",
+    artifact = "org.objenesis:objenesis:2.5",
+    sha1 = "612ecb799912ccf77cba9b3ed8c813da086076e9",
+)
diff --git a/bazlets.bzl b/bazlets.bzl
new file mode 100644
index 0000000..e14e488
--- /dev/null
+++ b/bazlets.bzl
@@ -0,0 +1,17 @@
+NAME = "com_googlesource_gerrit_bazlets"
+
+def load_bazlets(
+    commit,
+    local_path = None
+  ):
+  if not local_path:
+      native.git_repository(
+          name = NAME,
+          remote = "https://gerrit.googlesource.com/bazlets",
+          commit = commit,
+      )
+  else:
+      native.local_repository(
+          name = NAME,
+          path = local_path,
+      )
diff --git a/external_plugin_deps.bzl b/external_plugin_deps.bzl
new file mode 100644
index 0000000..12fa6f6
--- /dev/null
+++ b/external_plugin_deps.bzl
@@ -0,0 +1,20 @@
+load("//tools/bzl:maven_jar.bzl", "maven_jar")
+
+def external_plugin_deps():
+  maven_jar(
+    name = "mockito",
+    artifact = "org.mockito:mockito-core:2.7.21",
+    sha1 = "23e9f7bfb9717e849a05b84c29ee3ac723f1a653",
+  )
+
+  maven_jar(
+    name = "byte-buddy",
+    artifact = "net.bytebuddy:byte-buddy:1.6.11",
+    sha1 = "8a8f9409e27f1d62c909c7eef2aa7b3a580b4901",
+  )
+
+  maven_jar(
+    name = "objenesis",
+    artifact = "org.objenesis:objenesis:2.5",
+    sha1 = "612ecb799912ccf77cba9b3ed8c813da086076e9",
+  )
diff --git a/lib/gerrit/BUCK b/lib/gerrit/BUCK
deleted file mode 100644
index 8a21820..0000000
--- a/lib/gerrit/BUCK
+++ /dev/null
@@ -1,22 +0,0 @@
-include_defs('//bucklets/maven_jar.bucklet')
-
-VER = '2.13.6'
-REPO = MAVEN_CENTRAL
-
-maven_jar(
-  name = 'acceptance-framework',
-  id = 'com.google.gerrit:gerrit-acceptance-framework:' + VER,
-  sha1 = '53a5ffbc3ce6842b7145fd11abcc1dc8503b124f',
-  license = 'Apache2.0',
-  attach_source = False,
-  repository = REPO,
-)
-
-maven_jar(
-  name = 'plugin-api',
-  id = 'com.google.gerrit:gerrit-plugin-api:' + VER,
-  sha1 = '1a5d650c72ebc36f4ad522d5481d5ed690bec8bf',
-  license = 'Apache2.0',
-  attach_source = False,
-  repository = REPO,
-)
diff --git a/src/main/resources/Documentation/build.md b/src/main/resources/Documentation/build.md
index 3babed2..176271f 100644
--- a/src/main/resources/Documentation/build.md
+++ b/src/main/resources/Documentation/build.md
@@ -1,94 +1,91 @@
-Build
-=====
+# Build
 
-This plugin is built with Buck.
+This plugin can be built with Bazel, and two build modes are supported:
 
-Two build modes are supported: Standalone and in Gerrit tree. Standalone
-build mode is recommended, as this mode doesn't require local Gerrit
-tree to exist.
+* Standalone
+* In Gerrit tree
 
-Build standalone
-----------------
+Standalone build mode is recommended, as this mode doesn't require local Gerrit
+tree to exist. Moreover, there are some limitations and additional manual steps
+required when building in Gerrit tree mode (see corresponding sections).
 
-Clone bucklets library:
-
-```
-  git clone https://gerrit.googlesource.com/bucklets
-
-```
-and link it to @PLUGIN@ directory:
-
-```
-  cd @PLUGIN@ && ln -s ../bucklets .
-```
-
-Add link to the .buckversion file:
-
-```
-  cd @PLUGIN@ && ln -s bucklets/buckversion .buckversion
-```
-
-Add link to the .watchmanconfig file:
-
-```
-  cd @PLUGIN@ && ln -s bucklets/watchmanconfig .watchmanconfig
-```
+## Build standalone
 
 To build the plugin, issue the following command:
 
 ```
-  buck build plugin
+  bazel build @PLUGIN@
+```
+
+The output is created in
+
+```
+  bazel-genfiles/@PLUGIN@.jar
+```
+
+To package the plugin sources run:
+
+```
+  bazel build lib@PLUGIN@__plugin-src.jar
 ```
 
 The output is created in:
 
 ```
-  buck-out/gen/@PLUGIN@.jar
-```
-
-This project can be imported into the Eclipse IDE:
-
-```
-  ./bucklets/tools/eclipse.py
+  bazel-bin/lib@PLUGIN@__plugin-src.jar
 ```
 
 To execute the tests run:
 
 ```
-  buck test
-```
-
-To build plugin sources run:
-
-```
-  buck build src
-```
-
-The output is created in:
-
-```
-  buck-out/gen/@PLUGIN@-sources.jar
-```
-
-Build in Gerrit tree
---------------------
-
-Clone or link this plugin to the plugins directory of Gerrit's source
-tree, and issue the command:
-
-```
-  buck build plugins/@PLUGIN@
-```
-
-The output is created in:
-
-```
-  buck-out/gen/plugins/@PLUGIN@/@PLUGIN@.jar
+  bazel test webhooks_tests
 ```
 
 This project can be imported into the Eclipse IDE:
 
 ```
+  ./tools/eclipse.py
+```
+
+## Build in Gerrit tree
+
+Clone or link this plugin to the plugins directory of Gerrit's
+source tree. Put the external dependency Bazel build file into
+the Gerrit /plugins directory, replacing the existing empty one.
+
+```
+  cd gerrit/plugins
+  rm external_plugin_deps.bzl
+  ln -s @PLUGIN@/external_plugin_deps.bzl .
+```
+
+From Gerrit source tree issue the command:
+
+```
+  bazel build plugins/@PLUGIN@
+```
+
+Note that due to a [known issue in Bazel][bazelissue], if the plugin
+has previously been built in standalone mode, it is necessary to clean
+the workspace before building in-tree:
+
+```
+  cd plugins/@PLUGIN@
+  bazel clean --expunge
+```
+
+The output is created in
+
+```
+  bazel-genfiles/plugins/@PLUGIN@/@PLUGIN@.jar
+```
+
+This project can be imported into the Eclipse IDE:
+Add the plugin name to the `CUSTOM_PLUGINS` and to the
+`CUSTOM_PLUGINS_TEST_DEPS` set in Gerrit core in
+`tools/bzl/plugins.bzl`, and execute:
+
+```
   ./tools/eclipse/project.py
 ```
 
@@ -104,3 +101,4 @@
 [Back to @PLUGIN@ documentation index][index]
 
 [index]: index.html
+[bazelissue]: https://github.com/bazelbuild/bazel/issues/2797
diff --git a/tools/bazel.rc b/tools/bazel.rc
new file mode 100644
index 0000000..4ed16cf
--- /dev/null
+++ b/tools/bazel.rc
@@ -0,0 +1,2 @@
+build --workspace_status_command=./tools/workspace-status.sh
+test --build_tests_only
diff --git a/tools/bzl/BUILD b/tools/bzl/BUILD
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/tools/bzl/BUILD
diff --git a/tools/bzl/classpath.bzl b/tools/bzl/classpath.bzl
new file mode 100644
index 0000000..dfcbe9c
--- /dev/null
+++ b/tools/bzl/classpath.bzl
@@ -0,0 +1,2 @@
+load("@com_googlesource_gerrit_bazlets//tools:classpath.bzl",
+     "classpath_collector")
diff --git a/tools/bzl/junit.bzl b/tools/bzl/junit.bzl
new file mode 100644
index 0000000..3af7e58
--- /dev/null
+++ b/tools/bzl/junit.bzl
@@ -0,0 +1,4 @@
+load(
+    "@com_googlesource_gerrit_bazlets//tools:junit.bzl",
+    "junit_tests",
+)
diff --git a/tools/bzl/plugin.bzl b/tools/bzl/plugin.bzl
new file mode 100644
index 0000000..a2e438f
--- /dev/null
+++ b/tools/bzl/plugin.bzl
@@ -0,0 +1,6 @@
+load(
+    "@com_googlesource_gerrit_bazlets//:gerrit_plugin.bzl",
+    "gerrit_plugin",
+    "PLUGIN_DEPS",
+    "PLUGIN_TEST_DEPS",
+)
diff --git a/tools/eclipse/BUILD b/tools/eclipse/BUILD
new file mode 100644
index 0000000..8b19f92
--- /dev/null
+++ b/tools/eclipse/BUILD
@@ -0,0 +1,24 @@
+load("//tools/bzl:plugin.bzl", "PLUGIN_DEPS", "PLUGIN_TEST_DEPS")
+load("//tools/bzl:classpath.bzl", "classpath_collector")
+
+java_library(
+    name = "classpath",
+    runtime_deps = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
+        "@wiremock//jar",
+        "@mockito//jar",
+        "@byte-buddy//jar",
+        "@objenesis//jar",
+        "//:webhooks__plugin",
+    ],
+)
+
+classpath_collector(
+    name = "main_classpath_collect",
+    deps = PLUGIN_DEPS + PLUGIN_TEST_DEPS + [
+        "@wiremock//jar",
+        "@mockito//jar",
+        "@byte-buddy//jar",
+        "@objenesis//jar",
+        "//:webhooks__plugin",
+    ],
+)
diff --git a/tools/eclipse/project.py b/tools/eclipse/project.py
new file mode 100755
index 0000000..88ca4b0
--- /dev/null
+++ b/tools/eclipse/project.py
@@ -0,0 +1,179 @@
+#!/usr/bin/env python
+# Copyright (C) 2016 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+from __future__ import print_function
+# TODO(davido): use Google style for importing instead:
+# import optparse
+#
+# optparse.OptionParser
+from optparse import OptionParser
+from os import environ, path, makedirs
+from subprocess import CalledProcessError, check_call, check_output
+from xml.dom import minidom
+import re
+import sys
+
+MAIN = '//tools/eclipse:classpath'
+JRE = '/'.join([
+  'org.eclipse.jdt.launching.JRE_CONTAINER',
+  'org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType',
+  'JavaSE-1.8',
+])
+# Map of targets to corresponding classpath collector rules
+cp_targets = {
+  MAIN: '//tools/eclipse:main_classpath_collect',
+}
+
+ROOT = path.abspath(__file__)
+while not path.exists(path.join(ROOT, 'WORKSPACE')):
+  ROOT = path.dirname(ROOT)
+
+opts = OptionParser()
+opts.add_option('--name', help='name of the generated project',
+                action='store', default='sync-index', dest='project_name')
+args, _ = opts.parse_args()
+
+def retrieve_ext_location():
+  return check_output(['bazel', 'info', 'output_base']).strip()
+
+def gen_primary_build_tool():
+  bazel = check_output(['which', 'bazel']).strip()
+  with open(path.join(ROOT, ".primary_build_tool"), 'w') as fd:
+    fd.write("bazel=%s\n" % bazel)
+    fd.write("PATH=%s\n" % environ["PATH"])
+
+def _query_classpath(target):
+  deps = []
+  t = cp_targets[target]
+  try:
+    check_call(['bazel', 'build', t])
+  except CalledProcessError:
+    exit(1)
+  name = 'bazel-bin/tools/eclipse/' + t.split(':')[1] + '.runtime_classpath'
+  deps = [line.rstrip('\n') for line in open(name)]
+  return deps
+
+def gen_project(name='gerrit', root=ROOT):
+  p = path.join(root, '.project')
+  with open(p, 'w') as fd:
+    print("""\
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+  <name>%(name)s</name>
+  <buildSpec>
+    <buildCommand>
+      <name>org.eclipse.jdt.core.javabuilder</name>
+    </buildCommand>
+  </buildSpec>
+  <natures>
+    <nature>org.eclipse.jdt.core.javanature</nature>
+  </natures>
+</projectDescription>\
+    """ % {"name": name}, file=fd)
+
+def gen_classpath(ext):
+  def make_classpath():
+    impl = minidom.getDOMImplementation()
+    return impl.createDocument(None, 'classpath', None)
+
+  def classpathentry(kind, path, src=None, out=None, exported=None):
+    e = doc.createElement('classpathentry')
+    e.setAttribute('kind', kind)
+    # TODO(davido): Remove this and other exclude BUILD files hack
+    # when this Bazel bug is fixed:
+    # https://github.com/bazelbuild/bazel/issues/1083
+    if kind == 'src':
+      e.setAttribute('excluding', '**/BUILD')
+    e.setAttribute('path', path)
+    if src:
+      e.setAttribute('sourcepath', src)
+    if out:
+      e.setAttribute('output', out)
+    if exported:
+      e.setAttribute('exported', 'true')
+    doc.documentElement.appendChild(e)
+
+  doc = make_classpath()
+  src = set()
+  lib = set()
+
+  # Classpath entries are absolute for cross-cell support
+  java_library = re.compile('bazel-out/local-fastbuild/bin/lib[^/]+[.]jar$')
+  srcs = re.compile('(.*/external/[^/]+)/jar/(.*)[.]jar')
+  for p in _query_classpath(MAIN):
+    m = java_library.match(p)
+    if m:
+      src.add(".")
+    else:
+      if p.startswith("external"):
+        p = path.join(ext, p)
+      lib.add(p)
+
+  for s in sorted(src):
+    out = None
+
+    if s.startswith('lib/'):
+      out = 'eclipse-out/lib'
+
+    p = path.join(s, 'java')
+    if path.exists(p):
+      classpathentry('src', p, out=out)
+      continue
+
+    for env in ['main', 'test']:
+      o = None
+      if out:
+        o = out + '/' + env
+      elif env == 'test':
+        o = 'eclipse-out/test'
+
+      for srctype in ['java', 'resources']:
+        p = path.join(s, 'src', env, srctype)
+        if path.exists(p):
+          classpathentry('src', p, out=o)
+
+  for libs in [lib]:
+    for j in sorted(libs):
+      s = None
+      m = srcs.match(j)
+      if m:
+        prefix = m.group(1)
+        suffix = m.group(2)
+        p = path.join(prefix, "src", "%s-src.jar" % suffix)
+        if path.exists(p):
+          s = p
+      classpathentry('lib', j, s)
+
+  classpathentry('con', JRE)
+  classpathentry('output', 'eclipse-out/classes')
+
+  p = path.join(ROOT, '.classpath')
+  with open(p, 'w') as fd:
+    doc.writexml(fd, addindent='\t', newl='\n', encoding='UTF-8')
+
+try:
+  ext_location = retrieve_ext_location()
+  gen_project(args.project_name)
+  gen_classpath(ext_location)
+  gen_primary_build_tool()
+
+  try:
+    check_call(['bazel', 'build', MAIN])
+  except CalledProcessError:
+    exit(1)
+except KeyboardInterrupt:
+  print('Interrupted by user', file=sys.stderr)
+  exit(1)
diff --git a/tools/workspace-status.sh b/tools/workspace-status.sh
new file mode 100755
index 0000000..8f3390c
--- /dev/null
+++ b/tools/workspace-status.sh
@@ -0,0 +1,17 @@
+#!/bin/bash
+
+# This script will be run by bazel when the build process starts to
+# generate key-value information that represents the status of the
+# workspace. The output should be like
+#
+# KEY1 VALUE1
+# KEY2 VALUE2
+#
+# If the script exits with non-zero code, it's considered as a failure
+# and the output will be discarded.
+
+function rev() {
+  cd $1; git describe --always --match "v[0-9].*" --dirty
+}
+
+echo STABLE_BUILD_WEBHOOKS_LABEL $(rev .)