Create a binary packager for Bazel

This packager can be called by the release scripts to generate
a self-extractable bash installer for Bazel. This script was
tested by hand as extra arguments can be specified to change
the default install of Bazel (default is system-wide and
with the argument you can make a user install).

This will be the only packager for now since GitHub is offering
the possibility to download the source tree as a ZIP. Hopefully,
before the end of the year we could build some more package kind.

--
Change-Id: I1a2d0cd39b9e4adcaf6c984ec4c855a04213b61a
Reviewed-on: https://bazel-review.googlesource.com/1581
MOS_MIGRATED_REVID=99258828
diff --git a/scripts/packages/self_extract_binary.bzl b/scripts/packages/self_extract_binary.bzl
new file mode 100644
index 0000000..60928f6
--- /dev/null
+++ b/scripts/packages/self_extract_binary.bzl
@@ -0,0 +1,87 @@
+# Copyright 2015 Google Inc. All rights reserved.
+#
+# 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.
+"""Self-extracting binary.
+
+Generate a binary suitable for self-extraction:
+
+self_extract_binary(
+  name = "install.sh",
+  launcher = "launcher.sh",
+  resources = ["path1/file1", "path2/file2"],
+  flatten_ressources = ["path3/file3"],
+)
+
+will generate a file 'install.sh' with a header (launcher.sh)
+and a ZIP footer with the following entries:
+  path1/
+  path1/file1
+  path2/
+  path2/file2
+  file3
+
+"""
+
+def _self_extract_binary(ctx):
+  """Implementation for the self_extract_binary rule."""
+  # This is a bit complex for stripping out timestamps
+  zip_artifact = ctx.new_file(ctx.label.name + ".zip")
+  cp_resources = [
+      ("mkdir -p $(dirname ${tmpdir}/%s)\n" % r.short_path +
+       "cp %s ${tmpdir}/%s" % (r.path, r.short_path))
+      for r in ctx.files.resources
+      ]
+  cp_flatten_resources = [
+      "cp %s ${tmpdir}/%s" % (r.path, r.basename)
+      for r in ctx.files.flatten_resources
+      ]
+  ctx.action(
+      inputs = ctx.files.resources + ctx.files.flatten_resources,
+      outputs = [zip_artifact],
+      command = "\n".join([
+          "tmpdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXX)",
+          "trap \"rm -fr ${tmpdir}\" EXIT"
+          ] + cp_resources + cp_flatten_resources + [
+              "find ${tmpdir} -exec touch -t 198001010000.00 '{}' ';'",
+              "(d=${PWD}; cd ${tmpdir}; zip -rq ${d}/%s *)" % zip_artifact.path,
+              ]),
+      mnemonic = "ZipBin",
+  )
+  ctx.action(
+      inputs = [ctx.file.launcher, zip_artifact],
+      outputs = [ctx.outputs.executable],
+      command = "\n".join([
+          "cat %s %s > %s" % (ctx.file.launcher.path,
+                              zip_artifact.path,
+                              ctx.outputs.executable.path),
+          "zip -qA %s" % ctx.outputs.executable.path
+      ]),
+      mnemonic = "BuildSelfExtractable",
+  )
+
+self_extract_binary = rule(
+    _self_extract_binary,
+    executable = True,
+    attrs = {
+        "launcher": attr.label(
+            mandatory=True,
+            allow_files=True,
+            single_file=True),
+        "resources": attr.label_list(
+            default=[],
+            allow_files=True),
+        "flatten_resources": attr.label_list(
+            default=[],
+            allow_files=True),
+        },
+    )