diff --git a/jeepyb/cmd/run_mirror.py b/jeepyb/cmd/run_mirror.py
deleted file mode 100644
index 5e54583..0000000
--- a/jeepyb/cmd/run_mirror.py
+++ /dev/null
@@ -1,373 +0,0 @@
-#! /usr/bin/env python
-# Copyright (C) 2011 OpenStack, LLC.
-# Copyright (C) 2013 Hewlett-Packard Development Company, L.P.
-# Copyright (C) 2013 OpenStack Foundation
-#
-# 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.
-
-# run_mirror reads a YAML config file like:
-# cache-root: /tmp/cache
-#
-# mirrors:
-# - name: openstack
-# projects:
-# - https://github.com/openstack/requirements
-# output: /tmp/mirror/openstack
-#
-# - name: openstack-infra
-# projects:
-# - https://github.com/openstack-infra/config
-# output: /tmp/mirror/openstack-infra
-#
-# The algorithm it attempts to follow is:
-#
-# for each project:
-# clone if necessary and fetch origin
-# for each project-branch:
-# create new virtualenv
-# pip install reqs into virtualenv
-# if installation succeeds:
-# pip freeze > full-reqs
-# create new virtualenv
-# pip install (download only) full-reqs into virtualenv
-#
-# By default only summary information is printed on stdout (see the
-# -d command line option to get more debug info).
-#
-# If "pip install" for a branch's requirements fails to complete
-# (based on parsing of its output), that output will be copied to
-# stderr and the script will skip ahead to the next branch. This
-# makes it suitable for running in a cron job with only stdout
-# redirected to a log, and also avoids one broken project preventing
-# caching of requirements for others.
-from __future__ import print_function
-
-import argparse
-import datetime
-import md5
-import os
-import pkginfo
-import re
-import shlex
-import shutil
-import subprocess
-import sys
-import tempfile
-import urllib
-import yaml
-
-
-class Mirror(object):
- def __init__(self):
- parser = argparse.ArgumentParser(
- description='Build a pypi mirror from requirements')
- parser.add_argument('-b', dest='branch',
- help='restrict run to a specified branch')
- parser.add_argument('-c', dest='config',
- help='specify the config file')
- parser.add_argument('-n', dest='noop', action='store_true',
- help='do not run any commands')
- parser.add_argument('--no-pip', dest='no_pip', action='store_true',
- help='do not run any pip commands')
- parser.add_argument('--verbose', dest='debug', action='store_true',
- help='output verbose debug information')
- parser.add_argument('--no-download', dest='no_download',
- action='store_true',
- help='only process the pip cache into a mirror '
- '(do not download)')
- parser.add_argument('--no-process', dest='no_process',
- action='store_true',
- help='only download into the pip cache '
- '(do not process the cache into a mirror)')
- parser.add_argument('--no-update', dest='no_update',
- action='store_true',
- help='do not update any git repos')
- self.args = parser.parse_args()
- self.config = yaml.load(open(self.args.config))
-
- def run_command(self, cmd):
- cmd_list = shlex.split(str(cmd))
- self.debug("Run: %s" % cmd)
- if self.args.noop:
- return ''
- if self.args.no_pip and cmd_list[0].endswith('pip'):
- return ''
- p = subprocess.Popen(cmd_list, stdout=subprocess.PIPE,
- stderr=subprocess.STDOUT)
- (out, nothing) = p.communicate()
- out = out.strip()
- self.debug(out)
- return out
-
- def run(self):
- for mirror in self.config['mirrors']:
- if not self.args.no_download:
- self.build_mirror(mirror)
- if not self.args.no_process:
- self.process_cache(mirror)
-
- def chdir(self, dest):
- self.debug("cd %s" % dest)
- if not self.args.noop:
- os.chdir(dest)
-
- def debug(self, msg):
- if self.args.debug:
- print(msg)
-
- def process_http_requirements(self, reqlist, pip_cache_dir, pip):
- new_reqs = []
- for reqfile in reqlist:
- for req in open(reqfile):
- req = req.strip()
- # Handle http://, https://, and git+https?://
- if not re.search('https?://', req):
- new_reqs.append(req)
- continue
- target_url = req.split('#', 1)[0]
- target_file = os.path.join(pip_cache_dir,
- urllib.quote(target_url, ''))
- if os.path.exists(target_file):
- self.debug("Unlink: %s" % target_file)
- os.unlink(target_file)
- if os.path.exists(target_file + '.content-type'):
- self.debug("Unlink: %s.content-type" % target_file)
- os.unlink(target_file + '.content-type')
- return new_reqs
-
- def find_pkg_info(self, path):
- versions = set()
- for root, dirs, files in os.walk(path):
- if not root.endswith('.egg'):
- continue
- if not os.path.exists(os.path.join(root, 'EGG-INFO', 'PKG-INFO')):
- continue
- package = pkginfo.Develop(root)
- versions.add('%s==%s' % (package.name, package.version))
- return versions
-
- def build_mirror(self, mirror):
- print("Building mirror: %s" % mirror['name'])
- pip_format = ("%s install -U %s --exists-action=w "
- "--download-cache=%s --build %s -r %s")
- venv_format = ("virtualenv --clear --extra-search-dir=%s %s")
- upgrade_format = ("%s install -U --exists-action=w "
- "--download-cache=%s --build %s %s")
-
- workdir = tempfile.mkdtemp()
- reqs = os.path.join(workdir, "reqs")
- venv = os.path.join(workdir, "venv")
- build = os.path.join(workdir, "build")
- pip = os.path.join(venv, "bin", "pip")
-
- project_cache_dir = os.path.join(self.config['cache-root'],
- 'projects')
- pip_cache_dir = os.path.join(self.config['cache-root'],
- 'pip', mirror['name'])
- if not self.args.noop:
- if not os.path.exists(project_cache_dir):
- os.makedirs(project_cache_dir)
- if not os.path.exists(pip_cache_dir):
- os.makedirs(pip_cache_dir)
-
- for project in mirror['projects']:
- print("Updating repository: %s" % project)
- self.chdir(project_cache_dir)
- short_project = project.split('/')[-1]
- if short_project.endswith('.git'):
- short_project = short_project[:-4]
- if not os.path.isdir(short_project):
- out = self.run_command("git clone %s %s" %
- (project, short_project))
- self.chdir(os.path.join(project_cache_dir,
- short_project))
- out = self.run_command("git fetch -p origin")
-
- if self.args.branch:
- branches = [self.args.branch]
- else:
- branches = self.run_command("git branch -a").split("\n")
- for branch in branches:
- branch = branch.strip()
- if (not branch.startswith("remotes/origin")
- or "origin/HEAD" in branch):
- continue
- print("Fetching pip requires for %s:%s" %
- (project, branch))
- if not self.args.no_update:
- out = self.run_command("git reset --hard %s" % branch)
- out = self.run_command("git clean -x -f -d -q")
- reqlist = []
- if os.path.exists('global-requirements.txt'):
- reqlist.append('global-requirements.txt')
- else:
- for requires_file in ("requirements.txt",
- "test-requirements.txt",
- "tools/pip-requires",
- "tools/test-requires"):
- if os.path.exists(requires_file):
- reqlist.append(requires_file)
- if reqlist:
- out = self.run_command(venv_format %
- (pip_cache_dir, venv))
- out = self.run_command(upgrade_format %
- (pip, pip_cache_dir,
- build, "setuptools"))
- out = self.run_command(upgrade_format %
- (pip, pip_cache_dir,
- build, "pip"))
- out = self.run_command(upgrade_format %
- (pip, pip_cache_dir,
- build, "virtualenv"))
- if os.path.exists(build):
- shutil.rmtree(build)
- new_reqs = self.process_http_requirements(reqlist,
- pip_cache_dir,
- pip)
- (reqfp, reqfn) = tempfile.mkstemp()
- os.write(reqfp, '\n'.join(new_reqs))
- os.close(reqfp)
- out = self.run_command(pip_format %
- (pip, "", pip_cache_dir,
- build, reqfn))
- if "\nSuccessfully installed " not in out:
- sys.stderr.write("Installing pip requires for %s:%s "
- "failed.\n%s\n" %
- (project, branch, out))
- print("pip install did not indicate success")
- else:
- freeze = self.run_command("%s freeze -l" % pip)
- requires = self.find_pkg_info(build)
- reqfd = open(reqs, "w")
- for line in freeze.split("\n"):
- if line.startswith("-e ") or (
- "==" in line and " " not in line):
- requires.add(line)
- for r in requires:
- reqfd.write(r + "\n")
- reqfd.close()
- out = self.run_command(venv_format %
- (pip_cache_dir, venv))
- if os.path.exists(build):
- shutil.rmtree(build)
- out = self.run_command(pip_format %
- (pip, "--no-install",
- pip_cache_dir, build, reqs))
- if "\nSuccessfully downloaded " not in out:
- sys.stderr.write("Downloading pip requires for "
- "%s:%s failed.\n%s\n" %
- (project, branch, out))
- print("pip install did not indicate success")
- print("cached:\n%s" % freeze)
- else:
- print("no requirements")
- shutil.rmtree(workdir)
-
- def process_cache(self, mirror):
- if self.args.noop:
- return
-
- pip_cache_dir = os.path.join(self.config['cache-root'],
- 'pip', mirror['name'])
- destination_mirror = mirror['output']
-
- PACKAGE_VERSION_RE = re.compile(r'(.*)-[0-9]')
- full_html_line = "{name}
\n"
-
- packages = {}
- package_count = 0
-
- if not os.path.exists(destination_mirror):
- os.makedirs(destination_mirror)
-
- for filename in os.listdir(pip_cache_dir):
- if filename.endswith('content-type'):
- continue
-
- realname = urllib.unquote(filename)
- # The ? accounts for sourceforge downloads
- tarball = os.path.basename(realname).split("?")[0]
- name_match = PACKAGE_VERSION_RE.search(tarball)
-
- if name_match is None:
- continue
- package_name = name_match.group(1)
-
- version_list = packages.get(package_name, {})
- version_list[tarball] = filename
- packages[package_name] = version_list
- package_count = package_count + 1
-
- full_html = open(os.path.join(destination_mirror, ".full.html"), 'w')
- simple_html = open(os.path.join(destination_mirror, ".index.html"),
- 'w')
-
- header = ("