Initial commit
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..8dc9c2c
--- /dev/null
+++ b/README.md
@@ -0,0 +1,46 @@
+infra_virtualenv README
+=======================
+
+This repository provides a common Python virtualenv interface that
+infra code (such as chromite) can depend on.  At this point, it is
+experimental and not yet used in production.
+
+Virtualenv users should create a `requirements.txt` file listing the
+packages that they need and use the wrapper scripts (described below)
+to create the virtualenv and run commands within it.
+
+To add packages to this repository, run:
+
+    $ pip wheel -w path/to/pip_packages -r path/to/requirements.txt
+
+Commit the changes and make a CL.
+
+For example for chromite, from within `chromite/virtualenv`, run:
+
+    $ pip wheel -w pip_packages -r requirements.txt
+
+Wrapper scripts
+---------------
+
+This repository contains two scripts for working with Python virtualenvs.
+
+`venv_command` runs a command in a virtualenv environment.  This is more
+convenient than having to start a shell and source `bin/activate`.
+For example, to start Python inside the virtualenv:
+
+    $ venv_command path/to/venv python
+
+`create_venv` creates or updates a virtualenv using a `requirements.txt` file.
+
+    $ create_venv path/to/venv path/to/requirements.txt
+
+Here’s a complete example:
+
+    $ echo mock=2.0.0 > requirements.txt
+    $ ./create_venv venv requirements.txt
+    $ ./venv_command venv python
+    Python 2.7.6 (default, Jun 22 2015, 17:58:13)
+    [GCC 4.8.2] on linux2
+    Type "help", "copyright", "credits" or "license" for more information.
+    >>> import mock
+    >>>
diff --git a/create_venv b/create_venv
new file mode 100755
index 0000000..bc7934e
--- /dev/null
+++ b/create_venv
@@ -0,0 +1,78 @@
+#!/bin/bash
+# Copyright 2016 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Create or update a virtualenv.
+#
+# $ create_venv path/to/venv path/to/requirements.txt
+set -eu
+
+basedir=$(readlink -f "$(dirname "${BASH_SOURCE[0]}" )")
+pkgdir="$basedir/pip_packages"
+
+main() {
+  if [[ $# -ne 2 ]]; then
+    print_help >&2
+    exit 1
+  fi
+
+  local venv_dir=$1
+  local requirements=$2
+  local lock="$venv_dir/.create_venv.lock"
+
+  mkdir -p "$venv_dir"
+  (
+    # Try to acquire a lock for 90 seconds.
+    if ! flock -w 90 9; then
+      echo 'Failed to acquire lock on virtualenv' >&2
+      exit 1
+    fi
+    if up_to_date "$venv_dir" "$requirements"; then
+      echo "Existing virtualenv $venv_dir is already up to date"
+    else
+      echo "Creating or updating virtualenv in $venv_dir"
+      init_venv "$venv_dir"
+      install_packages_in_venv "$venv_dir" "$requirements"
+      mark_up_to_date "$venv_dir" "$requirements"
+    fi
+  ) 9>"$lock"
+}
+
+print_help() {
+  echo "Usage: $0 path/to/venv path/to/requirements.txt
+
+Create or update a Python virtualenv."
+}
+
+up_to_date() {
+  local venv_dir=$1
+  local requirements=$2
+  local installed="$venv_dir/.installed.txt"
+  cmp -s "$requirements" "$installed"
+}
+
+mark_up_to_date() {
+  local venv_dir=$1
+  local requirements=$2
+  local installed="$venv_dir/.installed.txt"
+  cp "$requirements" "$installed"
+}
+
+init_venv() {
+  local venv_dir=$1
+  virtualenv "$venv_dir" --extra-search-dir="$pkgdir"
+}
+
+install_packages_in_venv() {
+  local venv_dir=$1
+  local requirements=$2
+  venv_command "$venv_dir" \
+               pip install --no-index -f "$pkgdir" -r "$requirements"
+}
+
+venv_command() {
+  "$basedir/venv_command" "$@"
+}
+
+main "$@"
diff --git a/pip_packages/MySQL_python-1.2.5-cp27-cp27mu-linux_x86_64.whl b/pip_packages/MySQL_python-1.2.5-cp27-cp27mu-linux_x86_64.whl
new file mode 100644
index 0000000..6bcf4a7
--- /dev/null
+++ b/pip_packages/MySQL_python-1.2.5-cp27-cp27mu-linux_x86_64.whl
Binary files differ
diff --git a/pip_packages/PyYAML-3.12-cp27-cp27mu-linux_x86_64.whl b/pip_packages/PyYAML-3.12-cp27-cp27mu-linux_x86_64.whl
new file mode 100644
index 0000000..2abaf75
--- /dev/null
+++ b/pip_packages/PyYAML-3.12-cp27-cp27mu-linux_x86_64.whl
Binary files differ
diff --git a/pip_packages/SQLAlchemy-1.0.15-cp27-cp27mu-linux_x86_64.whl b/pip_packages/SQLAlchemy-1.0.15-cp27-cp27mu-linux_x86_64.whl
new file mode 100644
index 0000000..aacd359
--- /dev/null
+++ b/pip_packages/SQLAlchemy-1.0.15-cp27-cp27mu-linux_x86_64.whl
Binary files differ
diff --git a/pip_packages/enum34-1.1.6-py2-none-any.whl b/pip_packages/enum34-1.1.6-py2-none-any.whl
new file mode 100644
index 0000000..12be7c7
--- /dev/null
+++ b/pip_packages/enum34-1.1.6-py2-none-any.whl
Binary files differ
diff --git a/pip_packages/funcsigs-1.0.2-py2.py3-none-any.whl b/pip_packages/funcsigs-1.0.2-py2.py3-none-any.whl
new file mode 100644
index 0000000..ec5973f
--- /dev/null
+++ b/pip_packages/funcsigs-1.0.2-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/future-0.15.2-cp27-none-any.whl b/pip_packages/future-0.15.2-cp27-none-any.whl
new file mode 100644
index 0000000..765327e
--- /dev/null
+++ b/pip_packages/future-0.15.2-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/futures-3.0.5-py2-none-any.whl b/pip_packages/futures-3.0.5-py2-none-any.whl
new file mode 100644
index 0000000..48f6293
--- /dev/null
+++ b/pip_packages/futures-3.0.5-py2-none-any.whl
Binary files differ
diff --git a/pip_packages/gax_google_logging_v2-0.8.1-cp27-none-any.whl b/pip_packages/gax_google_logging_v2-0.8.1-cp27-none-any.whl
new file mode 100644
index 0000000..7c3d4aa
--- /dev/null
+++ b/pip_packages/gax_google_logging_v2-0.8.1-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/gax_google_pubsub_v1-0.8.1-cp27-none-any.whl b/pip_packages/gax_google_pubsub_v1-0.8.1-cp27-none-any.whl
new file mode 100644
index 0000000..b46c7d2
--- /dev/null
+++ b/pip_packages/gax_google_pubsub_v1-0.8.1-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/gcloud-0.18.1-cp27-none-any.whl b/pip_packages/gcloud-0.18.1-cp27-none-any.whl
new file mode 100644
index 0000000..f17309b
--- /dev/null
+++ b/pip_packages/gcloud-0.18.1-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/google_gax-0.12.5-cp27-none-any.whl b/pip_packages/google_gax-0.12.5-cp27-none-any.whl
new file mode 100644
index 0000000..1ebbf6b
--- /dev/null
+++ b/pip_packages/google_gax-0.12.5-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/googleapis_common_protos-1.3.3-cp27-none-any.whl b/pip_packages/googleapis_common_protos-1.3.3-cp27-none-any.whl
new file mode 100644
index 0000000..d8c6ca2
--- /dev/null
+++ b/pip_packages/googleapis_common_protos-1.3.3-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/grpc_google_logging_v2-0.8.1-cp27-none-any.whl b/pip_packages/grpc_google_logging_v2-0.8.1-cp27-none-any.whl
new file mode 100644
index 0000000..6d3223c
--- /dev/null
+++ b/pip_packages/grpc_google_logging_v2-0.8.1-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/grpc_google_pubsub_v1-0.8.1-cp27-none-any.whl b/pip_packages/grpc_google_pubsub_v1-0.8.1-cp27-none-any.whl
new file mode 100644
index 0000000..4b1f606
--- /dev/null
+++ b/pip_packages/grpc_google_pubsub_v1-0.8.1-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/grpcio-1.0.0-cp27-cp27mu-manylinux1_x86_64.whl b/pip_packages/grpcio-1.0.0-cp27-cp27mu-manylinux1_x86_64.whl
new file mode 100644
index 0000000..776ee27
--- /dev/null
+++ b/pip_packages/grpcio-1.0.0-cp27-cp27mu-manylinux1_x86_64.whl
Binary files differ
diff --git a/pip_packages/httplib2-0.9.2-cp27-none-any.whl b/pip_packages/httplib2-0.9.2-cp27-none-any.whl
new file mode 100644
index 0000000..e323831
--- /dev/null
+++ b/pip_packages/httplib2-0.9.2-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/mock-2.0.0-py2.py3-none-any.whl b/pip_packages/mock-2.0.0-py2.py3-none-any.whl
new file mode 100644
index 0000000..25c9874
--- /dev/null
+++ b/pip_packages/mock-2.0.0-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/mox-0.5.3-cp27-none-any.whl b/pip_packages/mox-0.5.3-cp27-none-any.whl
new file mode 100644
index 0000000..21eedc1
--- /dev/null
+++ b/pip_packages/mox-0.5.3-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/numpy-1.11.1-cp27-cp27mu-manylinux1_x86_64.whl b/pip_packages/numpy-1.11.1-cp27-cp27mu-manylinux1_x86_64.whl
new file mode 100644
index 0000000..805115c
--- /dev/null
+++ b/pip_packages/numpy-1.11.1-cp27-cp27mu-manylinux1_x86_64.whl
Binary files differ
diff --git a/pip_packages/oauth2client-3.0.0-cp27-none-any.whl b/pip_packages/oauth2client-3.0.0-cp27-none-any.whl
new file mode 100644
index 0000000..18b80c2
--- /dev/null
+++ b/pip_packages/oauth2client-3.0.0-cp27-none-any.whl
Binary files differ
diff --git a/pip_packages/pbr-1.10.0-py2.py3-none-any.whl b/pip_packages/pbr-1.10.0-py2.py3-none-any.whl
new file mode 100644
index 0000000..be5b24e
--- /dev/null
+++ b/pip_packages/pbr-1.10.0-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/pip-8.1.2-py2.py3-none-any.whl b/pip_packages/pip-8.1.2-py2.py3-none-any.whl
new file mode 100644
index 0000000..cc49227
--- /dev/null
+++ b/pip_packages/pip-8.1.2-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/ply-3.8-py2.py3-none-any.whl b/pip_packages/ply-3.8-py2.py3-none-any.whl
new file mode 100644
index 0000000..d22c1b3
--- /dev/null
+++ b/pip_packages/ply-3.8-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/protobuf-3.0.0-py2.py3-none-any.whl b/pip_packages/protobuf-3.0.0-py2.py3-none-any.whl
new file mode 100644
index 0000000..f46d007
--- /dev/null
+++ b/pip_packages/protobuf-3.0.0-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/psutil-4.3.1-cp27-cp27mu-linux_x86_64.whl b/pip_packages/psutil-4.3.1-cp27-cp27mu-linux_x86_64.whl
new file mode 100644
index 0000000..a4189cb
--- /dev/null
+++ b/pip_packages/psutil-4.3.1-cp27-cp27mu-linux_x86_64.whl
Binary files differ
diff --git a/pip_packages/pyasn1-0.1.9-py2.py3-none-any.whl b/pip_packages/pyasn1-0.1.9-py2.py3-none-any.whl
new file mode 100644
index 0000000..d690e39
--- /dev/null
+++ b/pip_packages/pyasn1-0.1.9-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/pyasn1_modules-0.0.8-py2.py3-none-any.whl b/pip_packages/pyasn1_modules-0.0.8-py2.py3-none-any.whl
new file mode 100644
index 0000000..3164490
--- /dev/null
+++ b/pip_packages/pyasn1_modules-0.0.8-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/pyparsing-2.1.8-py2.py3-none-any.whl b/pip_packages/pyparsing-2.1.8-py2.py3-none-any.whl
new file mode 100644
index 0000000..b27167b
--- /dev/null
+++ b/pip_packages/pyparsing-2.1.8-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/rsa-3.4.2-py2.py3-none-any.whl b/pip_packages/rsa-3.4.2-py2.py3-none-any.whl
new file mode 100644
index 0000000..d4834c4
--- /dev/null
+++ b/pip_packages/rsa-3.4.2-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/setuptools-27.1.2-py2.py3-none-any.whl b/pip_packages/setuptools-27.1.2-py2.py3-none-any.whl
new file mode 100644
index 0000000..de213bb
--- /dev/null
+++ b/pip_packages/setuptools-27.1.2-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/setuptools-28.2.0-py2.py3-none-any.whl b/pip_packages/setuptools-28.2.0-py2.py3-none-any.whl
new file mode 100644
index 0000000..d583238
--- /dev/null
+++ b/pip_packages/setuptools-28.2.0-py2.py3-none-any.whl
Binary files differ
diff --git a/pip_packages/six-1.10.0-py2.py3-none-any.whl b/pip_packages/six-1.10.0-py2.py3-none-any.whl
new file mode 100644
index 0000000..0887261
--- /dev/null
+++ b/pip_packages/six-1.10.0-py2.py3-none-any.whl
Binary files differ
diff --git a/venv_command b/venv_command
new file mode 100755
index 0000000..b99c0bf
--- /dev/null
+++ b/venv_command
@@ -0,0 +1,38 @@
+#!/bin/bash
+# Copyright 2016 The Chromium OS Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+#
+# Run a command in a virtualenv environment.
+#
+# $ venv_command path/to/venv command [args...]
+set -eu
+
+main() {
+  if [[ $# -lt 2 ]]; then
+    print_help >&2
+    exit 1
+  fi
+
+  local venv_dir=$1
+  shift 1
+
+  activate_venv "$venv_dir"
+  exec "$@"
+}
+
+print_help() {
+  echo "Usage: $0 path/to/venv command [args...]
+
+Run a command in a Python virtualenv environment."
+}
+
+activate_venv() {
+  local venv_dir=$1
+  set +u  # activate script relies on unset variables.
+  # shellcheck source=/dev/null
+  . "$venv_dir/bin/activate"
+  set -u
+}
+
+main "$@"