Add Buck build

Change-Id: I0549da0db48aeb1c22360ea0729441e860051b72
Signed-off-by: Edwin Kempin <edwin.kempin@sap.com>
diff --git a/.buckconfig b/.buckconfig
new file mode 100644
index 0000000..9f228b8
--- /dev/null
+++ b/.buckconfig
@@ -0,0 +1,11 @@
+[alias]
+  plugin = //:server-config
+
+[buildfile]
+  includes = //tools/buck.defs
+
+[java]
+  src_roots = java, resources
+
+[project]
+  ignore = .git
diff --git a/.gitignore b/.gitignore
index 80d6257..a45e726 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,3 +1,4 @@
+/buck-out
 /target
 /.classpath
 /.project
diff --git a/BUCK b/BUCK
new file mode 100644
index 0000000..4aaaec6
--- /dev/null
+++ b/BUCK
@@ -0,0 +1,21 @@
+include_defs('//lib/maven.defs')
+
+API_VERSION = '2.9-SNAPSHOT'
+REPO = MAVEN_LOCAL
+
+gerrit_plugin(
+  name = 'server-config',
+  srcs = glob(['src/main/java/**/*.java']),
+  resources = glob(['src/main/resources/**/*']),
+  manifest_entries = [
+    'Gerrit-PluginName: server-config',
+    'Gerrit-HttpModule: com.googlesource.gerrit.plugins.serverconfig.HttpModule',
+  ]
+)
+
+maven_jar(
+  name = 'plugin-lib',
+  id = 'com.google.gerrit:gerrit-plugin-api:' + API_VERSION,
+  repository = REPO,
+  license = 'Apache2.0',
+)
diff --git a/VERSION b/VERSION
new file mode 100644
index 0000000..44ed74b
--- /dev/null
+++ b/VERSION
@@ -0,0 +1 @@
+2.9-SNAPSHOT
diff --git a/lib/build.defs b/lib/build.defs
new file mode 100644
index 0000000..08418d0
--- /dev/null
+++ b/lib/build.defs
@@ -0,0 +1,76 @@
+include_defs('//lib/maven.defs')
+
+def java_library2(
+    name,
+    srcs = [],
+    resources = [],
+    deps = [],
+    compile_deps = [],
+    visibility = []):
+  c = name + '__compile'
+  t = name + '__link'
+  j = 'lib__%s__output/%s.jar' % (c, c)
+  o = 'lib__%s__output/%s.jar' % (name, name)
+  java_library(
+    name = c,
+    srcs = srcs,
+    resources = resources,
+    deps = deps + compile_deps,
+    visibility = visibility,
+  )
+  genrule(
+    name = t,
+    cmd = 'mkdir -p $(dirname $OUT);ln -s $SRCS $OUT',
+    srcs = [genfile(j)],
+    deps = [':' + c],
+    out = o,
+  )
+  prebuilt_jar(
+    name = name,
+    binary_jar = genfile(o),
+    deps = deps + [':' + t],
+    visibility = visibility,
+  )
+
+def gerrit_plugin(
+    name,
+    deps = [],
+    srcs = [],
+    resources = [],
+    manifest_file = None,
+    manifest_entries = [],
+    type = 'plugin',
+    visibility = ['PUBLIC']):
+  mf_cmd = 'v=$(cat VERSION);'
+  if manifest_file:
+    mf_src = [manifest_file]
+    mf_cmd += 'sed "s:@VERSION@:$v:g" $SRCS >$OUT'
+  else:
+    mf_src = []
+    mf_cmd += 'echo "Manifest-Version: 1.0" >$OUT;'
+    mf_cmd += 'echo "Gerrit-ApiType: %s" >>$OUT;' % type
+    mf_cmd += 'echo "Implementation-Version: $v" >>$OUT'
+    for line in manifest_entries:
+      mf_cmd += ';echo "%s" >> $OUT' % line
+  genrule(
+    name = name + '__manifest',
+    cmd = mf_cmd,
+    srcs = mf_src,
+    out = 'MANIFEST.MF',
+  )
+  java_library2(
+    name = name + '__plugin',
+    srcs = srcs,
+    resources = resources,
+    deps = deps,
+    compile_deps = ['//:%s-lib' % type],
+  )
+  java_binary(
+    name = name,
+    manifest_file = genfile('MANIFEST.MF'),
+    deps = [
+      ':%s__plugin' % name,
+      ':%s__manifest' % name,
+    ],
+    visibility = visibility,
+  )
diff --git a/lib/maven.defs b/lib/maven.defs
new file mode 100644
index 0000000..689040a
--- /dev/null
+++ b/lib/maven.defs
@@ -0,0 +1,63 @@
+GERRIT = 'GERRIT:'
+GERRIT_API = 'GERRIT_API:'
+MAVEN_LOCAL = 'MAVEN_LOCAL:'
+
+def maven_jar(
+    name,
+    id,
+    license,
+    deps = [],
+    sha1 = '',
+    bin_sha1 = '',
+    src_sha1 = '',
+    repository = GERRIT,
+    attach_source = True,
+    visibility = ['PUBLIC']):
+  from os import path
+
+  parts = id.split(':')
+  if len(parts) != 3:
+    raise NameError('expected id="groupId:artifactId:version"')
+  group, artifact, version = parts
+
+  file_version = version
+
+  jar = path.join(name, artifact.lower() + '-' + file_version)
+  url = '/'.join([
+    repository,
+    group.replace('.', '/'), artifact, version,
+    artifact + '-' + file_version])
+
+  binjar = jar + '.jar'
+  binurl = url + '.jar'
+
+  srcjar = jar + '-src.jar'
+  srcurl = url + '-sources.jar'
+
+  cmd = ['$(exe //tools:download_file)', '-o', '$OUT', '-u', binurl]
+  if sha1:
+    cmd.extend(['-v', sha1])
+  elif bin_sha1:
+    cmd.extend(['-v', bin_sha1])
+
+  genrule(
+    name = name + '__download_bin',
+    cmd = ' '.join(cmd),
+    deps = ['//tools:download_file'],
+    out = binjar,
+  )
+
+  srcjar = None
+  genrule(
+    name = name + '__download_src',
+    cmd = ':>$OUT',
+    out = '__' + name + '__no_src',
+  )
+
+  prebuilt_jar(
+    name = name,
+    deps = deps + [':' + name + '__download_bin'],
+    binary_jar = genfile(binjar),
+    source_jar = genfile(srcjar) if srcjar else None,
+    visibility = visibility,
+  )
diff --git a/tools/BUCK b/tools/BUCK
new file mode 100644
index 0000000..1b1175c
--- /dev/null
+++ b/tools/BUCK
@@ -0,0 +1,5 @@
+python_binary(
+  name = 'download_file',
+  main = 'download_file.py',
+  visibility = ['PUBLIC'],
+)
diff --git a/tools/buck.defs b/tools/buck.defs
new file mode 100644
index 0000000..41eeeca
--- /dev/null
+++ b/tools/buck.defs
@@ -0,0 +1,67 @@
+# Copyright (C) 2014 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+include_defs('//lib/build.defs')
+
+original_java_library = java_library
+def java_library(
+    name,
+    srcs=[],
+    resources=[],
+    source='7',
+    target='7',
+    proguard_config=None,
+    deps=[],
+    exported_deps=[],
+    visibility=[],
+    ):
+  original_java_library(
+    name=name,
+    srcs=srcs,
+    resources=resources,
+    source=source,
+    target=target,
+    proguard_config=proguard_config,
+    deps=deps,
+    exported_deps=exported_deps,
+    visibility=visibility,
+  )
+
+original_java_test = java_test
+def java_test(
+    name,
+    srcs=[],
+    labels=[],
+    resources=[],
+    source='7',
+    target='7',
+    vm_args=[],
+    source_under_test=[],
+    contacts=[],
+    deps=[],
+    visibility=[],
+    ):
+  original_java_test(
+    name=name,
+    srcs=srcs,
+    labels=labels,
+    resources=resources,
+    source=source,
+    target=target,
+    vm_args=vm_args,
+    source_under_test=source_under_test,
+    contacts=contacts,
+    deps=deps,
+    visibility=visibility,
+  )
diff --git a/tools/download_file.py b/tools/download_file.py
new file mode 100755
index 0000000..d71c3ac
--- /dev/null
+++ b/tools/download_file.py
@@ -0,0 +1,209 @@
+#!/usr/bin/python
+# Copyright (C) 2013 The Android Open Source Project
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import print_function
+
+from hashlib import sha1
+from optparse import OptionParser
+from os import link, makedirs, path, remove
+import shutil
+from subprocess import check_call, CalledProcessError
+from sys import stderr
+from zipfile import ZipFile, BadZipfile, LargeZipFile
+
+REPO_ROOTS = {
+  'GERRIT': 'http://gerrit-maven.storage.googleapis.com',
+  'GERRIT_API': 'https://gerrit-api.commondatastorage.googleapis.com/release',
+  'ECLIPSE': 'https://repo.eclipse.org/content/groups/releases',
+  'MAVEN_CENTRAL': 'http://repo1.maven.org/maven2',
+  'MAVEN_LOCAL': 'file://' + path.expanduser('~/.m2/repository'),
+}
+
+GERRIT_HOME = path.expanduser('~/.gerritcodereview')
+CACHE_DIR = path.join(GERRIT_HOME, 'buck-cache')
+LOCAL_PROPERTIES = 'local.properties'
+
+
+def hashfile(p):
+  d = sha1()
+  with open(p, 'rb') as f:
+    while True:
+      b = f.read(8192)
+      if not b:
+        break
+      d.update(b)
+  return d.hexdigest()
+
+def safe_mkdirs(d):
+  if path.isdir(d):
+    return
+  try:
+    makedirs(d)
+  except OSError as err:
+    if not path.isdir(d):
+      raise err
+
+def download_properties(root_dir):
+  """ Get the download properties.
+
+  First tries to find the properties file in the given root directory,
+  and if not found there, tries in the Gerrit settings folder in the
+  user's home directory.
+
+  Returns a set of download properties, which may be empty.
+
+  """
+  p = {}
+  local_prop = path.join(root_dir, LOCAL_PROPERTIES)
+  if not path.isfile(local_prop):
+    local_prop = path.join(GERRIT_HOME, LOCAL_PROPERTIES)
+  if path.isfile(local_prop):
+    try:
+      with open(local_prop) as fd:
+        for line in fd:
+          if line.startswith('download.'):
+            d = [e.strip() for e in line.split('=', 1)]
+            name, url = d[0], d[1]
+            p[name[len('download.'):]] = url
+    except OSError:
+      pass
+  return p
+
+def cache_entry(args):
+  if args.v:
+    h = args.v
+  else:
+    h = sha1(args.u).hexdigest()
+  name = '%s-%s' % (path.basename(args.o), h)
+  return path.join(CACHE_DIR, name)
+
+def resolve_url(url, redirects):
+  s = url.find(':')
+  if s < 0:
+    return url
+  scheme, rest = url[:s], url[s+1:]
+  if scheme not in REPO_ROOTS:
+    return url
+  if scheme in redirects:
+    root = redirects[scheme]
+  else:
+    root = REPO_ROOTS[scheme]
+  root = root.rstrip('/')
+  rest = rest.lstrip('/')
+  return '/'.join([root, rest])
+
+opts = OptionParser()
+opts.add_option('-o', help='local output file')
+opts.add_option('-u', help='URL to download')
+opts.add_option('-v', help='expected content SHA-1')
+opts.add_option('-x', action='append', help='file to delete from ZIP')
+opts.add_option('--exclude_java_sources', action='store_true')
+opts.add_option('--unsign', action='store_true')
+args, _ = opts.parse_args()
+
+root_dir = args.o
+while root_dir:
+  root_dir, n = path.split(root_dir)
+  if n == 'buck-out':
+    break
+
+redirects = download_properties(root_dir)
+cache_ent = cache_entry(args)
+src_url = resolve_url(args.u, redirects)
+
+if not path.exists(cache_ent):
+  try:
+    safe_mkdirs(path.dirname(cache_ent))
+  except OSError as err:
+    print('error creating directory %s: %s' %
+          (path.dirname(cache_ent), err), file=stderr)
+    exit(1)
+
+  print('Download %s' % src_url, file=stderr)
+  try:
+    check_call(['curl', '--proxy-anyauth', '-sfo', cache_ent, src_url])
+  except OSError as err:
+    print('could not invoke curl: %s\nis curl installed?' % err, file=stderr)
+    exit(1)
+  except CalledProcessError as err:
+    print('error using curl: %s' % err, file=stderr)
+    exit(1)
+
+if args.v:
+  have = hashfile(cache_ent)
+  if args.v != have:
+    print((
+      '%s:\n' +
+      'expected %s\n' +
+      'received %s\n') % (src_url, args.v, have), file=stderr)
+    try:
+      remove(cache_ent)
+    except OSError as err:
+      if path.exists(cache_ent):
+        print('error removing %s: %s' % (cache_ent, err), file=stderr)
+    exit(1)
+
+exclude = []
+if args.x:
+  exclude += args.x
+if args.exclude_java_sources:
+  try:
+    zf = ZipFile(cache_ent, 'r')
+    try:
+      for n in zf.namelist():
+        if n.endswith('.java'):
+          exclude.append(n)
+    finally:
+      zf.close()
+  except (BadZipfile, LargeZipFile) as err:
+    print('error opening %s: %s'  % (cache_ent, err), file=stderr)
+    exit(1)
+
+if args.unsign:
+  try:
+    zf = ZipFile(cache_ent, 'r')
+    try:
+      for n in zf.namelist():
+        if (n.endswith('.RSA')
+            or n.endswith('.SF')
+            or n.endswith('.LIST')):
+          exclude.append(n)
+    finally:
+      zf.close()
+  except (BadZipfile, LargeZipFile) as err:
+    print('error opening %s: %s'  % (cache_ent, err), file=stderr)
+    exit(1)
+
+safe_mkdirs(path.dirname(args.o))
+if exclude:
+  try:
+    shutil.copyfile(cache_ent, args.o)
+  except (shutil.Error, IOError) as err:
+    print('error copying to %s: %s' % (args.o, err), file=stderr)
+    exit(1)
+  try:
+    check_call(['zip', '-d', args.o] + exclude)
+  except CalledProcessError as err:
+    print('error removing files from zip: %s' % err, file=stderr)
+    exit(1)
+else:
+  try:
+    link(cache_ent, args.o)
+  except OSError as err:
+    try:
+      shutil.copyfile(cache_ent, args.o)
+    except (shutil.Error, IOError) as err:
+      print('error copying to %s: %s' % (args.o, err), file=stderr)
+      exit(1)