diff options
-rw-r--r-- | doc/source/index.rst | 8 | ||||
-rw-r--r-- | doc/source/packagers.rst | 59 | ||||
-rw-r--r-- | pbr/extra_files.py | 35 | ||||
-rw-r--r-- | pbr/hooks/commands.py | 1 | ||||
-rw-r--r-- | pbr/packaging.py | 189 | ||||
-rw-r--r-- | pbr/tests/test_core.py | 27 | ||||
-rw-r--r-- | pbr/tests/test_packaging.py | 106 | ||||
-rw-r--r-- | pbr/tests/testpackage/git-extra-file.txt | 0 | ||||
-rw-r--r-- | pbr/util.py | 23 | ||||
-rw-r--r-- | requirements.txt | 1 | ||||
-rw-r--r-- | tools/integration.sh | 40 |
11 files changed, 426 insertions, 63 deletions
diff --git a/doc/source/index.rst b/doc/source/index.rst index d3761d7..d05657b 100644 --- a/doc/source/index.rst +++ b/doc/source/index.rst @@ -191,6 +191,14 @@ installed for `pbr.config.drivers`, one called `plain` which maps to the `Plain` class in `pbr.cfg.driver` and one called `fancy` which maps to the `Fancy` class in `pbr.cfg.driver`. +Packager Notes +============== + +.. toctree:: + :maxdepth: 1 + + packagers + Indices and tables ================== diff --git a/doc/source/packagers.rst b/doc/source/packagers.rst new file mode 100644 index 0000000..b1ee358 --- /dev/null +++ b/doc/source/packagers.rst @@ -0,0 +1,59 @@ +===================== + Notes for Packagers +===================== + +If you are maintaining packages of software that uses `pbr`, there are some +features you probably want to be aware of that can make your life easier. +They are exposed by environment variables, so adding them to rules or spec +files should be fairly easy. + +Versioning +========== + +`pbr`, when run in a git repo, derives the version of a package from the +git tags. When run in a tarball with a proper egg-info dir, it will happily +pull the version from that. So for the most part, the packager shouldn't need +to care. However, if you are doing something like keeping a git repo with +the sources and the packaging intermixed and it's causing pbr to get confused +about whether its in its own git repo or not, you can set `PBR_VERSION`: + +:: + + PBR_VERSION=1.2.3 + +and all version calculation logic will be completely skipped and the supplied +version will be considered absolute. + +Dependencies +============ + +`pbr` overrides almost everything having to do with python dependency +resolution and calls out to `pip`. In the python source package world this +leads to a more consistent experience. However, in the distro packaging world, +dependencies are handled by the distro. Setting `SKIP_PIP_INSTALL`: + +:: + + SKIP_PIP_INSTALL=1 + +will cause all logic around use of `pip` to be skipped, including the logic +that includes pip as a dependency of `pbr` itself. + +Tarballs +======== + +`pbr` includes everything in a source tarball that is in the original `git` +repository. This can again cause havoc if a packager is doing fancy things +with combined `git` repos, and is generating a source tarball using `python +setup.py sdist` from that repo. If that is the workflow the packager is using, +setting `SKIP_GIT_SDIST`: + +:: + + SKIP_GIT_SDIST=1 + +will cause all logic around using git to find the files that should be in the +source tarball to be skipped. Beware though, that because `pbr` packages +automatically find all of the files, most of them do not have a complete +`MANIFEST.in` file, so its possible that a tarball produced in that way will +be missing files. diff --git a/pbr/extra_files.py b/pbr/extra_files.py new file mode 100644 index 0000000..a72db0c --- /dev/null +++ b/pbr/extra_files.py @@ -0,0 +1,35 @@ +# Copyright (c) 2013 Hewlett-Packard Development Company, L.P. +# +# 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 distutils import errors +import os + +_extra_files = [] + + +def get_extra_files(): + global _extra_files + return _extra_files + + +def set_extra_files(extra_files): + # Let's do a sanity check + for filename in extra_files: + if not os.path.exists(filename): + raise errors.DistutilsFileError( + '%s from the extra_files option in setup.cfg does not ' + 'exist' % filename) + global _extra_files + _extra_files[:] = extra_files[:] diff --git a/pbr/hooks/commands.py b/pbr/hooks/commands.py index 0171d0d..b4206ed 100644 --- a/pbr/hooks/commands.py +++ b/pbr/hooks/commands.py @@ -39,6 +39,7 @@ class CommandsConfig(base.BaseConfig): self.commands = "%s\n%s" % (self.commands, command) def hook(self): + self.add_command('pbr.packaging.LocalEggInfo') self.add_command('pbr.packaging.LocalSDist') self.add_command('pbr.packaging.LocalInstallScripts') if os.name != 'nt': diff --git a/pbr/packaging.py b/pbr/packaging.py index 526b5c3..a97880c 100644 --- a/pbr/packaging.py +++ b/pbr/packaging.py @@ -31,6 +31,7 @@ import distutils.errors from distutils import log import pkg_resources from setuptools.command import easy_install +from setuptools.command import egg_info from setuptools.command import install from setuptools.command import install_scripts from setuptools.command import sdist @@ -40,6 +41,8 @@ try: except ImportError: import io +from pbr import extra_files + log.set_verbosity(log.INFO) TRUE_VALUES = ('true', '1', 'yes') REQUIREMENTS_FILES = ('requirements.txt', 'tools/pip-requires') @@ -49,6 +52,13 @@ TEST_REQUIREMENTS_FILES = ('test-requirements.txt', 'tools/test-requires') BROKEN_ON_27 = ('argparse', 'importlib') +def get_requirements_files(): + files = os.environ.get("PBR_REQUIREMENTS_FILES") + if files: + return tuple(f.strip() for f in files.split(',')) + return REQUIREMENTS_FILES + + def append_text_list(config, key, text_list): """Append a \n separated list to possibly existing value.""" new_value = [] @@ -79,8 +89,9 @@ def _make_links_args(links): return ["-f '%s'" % link for link in links] -def _pip_install(links, requires, root=None): - if str(os.getenv('SKIP_PIP_INSTALL', '')).lower() in TRUE_VALUES: +def _pip_install(links, requires, root=None, option_dict=dict()): + if get_boolean_option( + option_dict, 'skip_pip_install', 'SKIP_PIP_INSTALL'): return root_cmd = "" if root: @@ -129,11 +140,7 @@ def get_reqs_from_files(requirements_files): def parse_requirements(requirements_files=None): if requirements_files is None: - files = os.environ.get("PBR_REQUIREMENTS_FILES") - if files: - requirements_files = tuple(f.strip() for f in files.split(',')) - else: - requirements_files = REQUIREMENTS_FILES + requirements_files = get_requirements_files() def egg_fragment(match): # take a versioned egg fragment and return a @@ -176,7 +183,9 @@ def parse_requirements(requirements_files=None): return requirements -def parse_dependency_links(requirements_files=REQUIREMENTS_FILES): +def parse_dependency_links(requirements_files=None): + if requirements_files is None: + requirements_files = get_requirements_files() dependency_links = [] # dependency_links inject alternate locations to find packages listed # in requirements @@ -214,7 +223,7 @@ def _run_shell_command(cmd, throw_on_error=False, buffer=True): raise distutils.errors.DistutilsError( "%s returned %d" % (cmd, output.returncode)) if len(out) == 0 or not out[0] or not out[0].strip(): - return None + return '' return out[0].strip().decode('utf-8') @@ -267,27 +276,53 @@ def generate_authors(git_dir=None, dest_dir='.', option_dict=dict()): if git_dir is None: git_dir = _get_git_directory() if git_dir: + authors = [] + # don't include jenkins email address in AUTHORS file git_log_cmd = ("git --git-dir=" + git_dir + - " log --format='%aN <%aE>' | sort -u | " - "egrep -v '" + ignore_emails + "'") - changelog = _run_shell_command(git_log_cmd) - signed_cmd = ("git log --git-dir=" + git_dir + - " | grep -i Co-authored-by: | sort -u") - signed_entries = _run_shell_command(signed_cmd) - if signed_entries: - new_entries = "\n".join( - [signed.split(":", 1)[1].strip() - for signed in signed_entries.split("\n") if signed]) - changelog = "\n".join((changelog, new_entries)) + " log --format='%aN <%aE>'" + " | egrep -v '" + ignore_emails + "'") + authors += _run_shell_command(git_log_cmd).split('\n') + + # get all co-authors from commit messages + co_authors_cmd = ("git log --git-dir=" + git_dir + + " | grep -i Co-authored-by:") + co_authors = _run_shell_command(co_authors_cmd) + + co_authors = [signed.split(":", 1)[1].strip() + for signed in co_authors.split('\n') if signed] + + authors += co_authors + + # canonicalize emails, remove duplicates and sort + mailmap = read_git_mailmap(git_dir) + authors = canonicalize_emails('\n'.join(authors), mailmap) + authors = authors.split('\n') + authors = sorted(set(authors)) - mailmap = read_git_mailmap() with open(new_authors, 'wb') as new_authors_fh: if os.path.exists(old_authors): with open(old_authors, "rb") as old_authors_fh: new_authors_fh.write(old_authors_fh.read()) - new_authors_fh.write(canonicalize_emails( - changelog, mailmap).encode('utf-8')) + new_authors_fh.write(('\n'.join(authors) + '\n') + .encode('utf-8')) + + +def _find_git_files(dirname='', git_dir=None): + """Behave like a file finder entrypoint plugin. + + We don't actually use the entrypoints system for this because it runs + at absurd times. We only want to do this when we are building an sdist. + """ + file_list = [] + if git_dir is None: + git_dir = _get_git_directory() + if git_dir: + log.info("[pbr] In git context, generating filelist from git") + git_ls_cmd = "git --git-dir=%s ls-files -z" % git_dir + file_list = _run_shell_command(git_ls_cmd) + file_list = file_list.split(b'\x00'.decode('utf-8')) + return [f for f in file_list if f] _rst_template = """%(heading)s @@ -326,17 +361,20 @@ class LocalInstall(install.install): command_name = 'install' def run(self): + option_dict = self.distribution.get_option_dict('pbr') if (not self.single_version_externally_managed and self.distribution.install_requires): links = _make_links_args(self.distribution.dependency_links) - _pip_install(links, self.distribution.install_requires, self.root) + _pip_install( + links, self.distribution.install_requires, self.root, + option_dict=option_dict) return du_install.install.run(self) def _newer_requires_files(egg_info_dir): """Check to see if any of the requires files are newer than egg-info.""" - for target, sources in (('requires.txt', REQUIREMENTS_FILES), + for target, sources in (('requires.txt', get_requirements_files()), ('test-requires.txt', TEST_REQUIREMENTS_FILES)): target_path = os.path.join(egg_info_dir, target) for src in _any_existing(sources): @@ -362,7 +400,10 @@ class _PipInstallTestRequires(object): links = _make_links_args( parse_dependency_links(TEST_REQUIREMENTS_FILES)) if self.distribution.tests_require: - _pip_install(links, self.distribution.tests_require) + option_dict = self.distribution.get_option_dict('pbr') + _pip_install( + links, self.distribution.tests_require, + option_dict=option_dict) def pre_run(self): self.egg_name = pkg_resources.safe_name(self.distribution.get_name()) @@ -447,7 +488,7 @@ def override_get_script_args( import_target=ep.attrs[0], invoke_target='.'.join(ep.attrs), ) - yield (name, header+script_text) + yield (name, header + script_text) class LocalInstallScripts(install_scripts.install_scripts): @@ -488,6 +529,65 @@ class LocalInstallScripts(install_scripts.install_scripts): self.write_script(*args) +class LocalManifestMaker(egg_info.manifest_maker): + """Add any files that are in git and some standard sensible files.""" + + def _add_pbr_defaults(self): + for template_line in [ + 'include AUTHORS', + 'include ChangeLog', + 'exclude .gitignore', + 'exclude .gitreview', + 'global-exclude *.pyc' + ]: + self.filelist.process_template_line(template_line) + + def add_defaults(self): + option_dict = self.distribution.get_option_dict('pbr') + + sdist.sdist.add_defaults(self) + self.filelist.append(self.template) + self.filelist.append(self.manifest) + self.filelist.extend(extra_files.get_extra_files()) + should_skip = get_boolean_option(option_dict, 'skip_git_sdist', + 'SKIP_GIT_SDIST') + if not should_skip: + rcfiles = _find_git_files() + if rcfiles: + self.filelist.extend(rcfiles) + elif os.path.exists(self.manifest): + self.read_manifest() + ei_cmd = self.get_finalized_command('egg_info') + self._add_pbr_defaults() + self.filelist.include_pattern("*", prefix=ei_cmd.egg_info) + + +class LocalEggInfo(egg_info.egg_info): + """Override the egg_info command to regenerate SOURCES.txt sensibly.""" + + command_name = 'egg_info' + + def find_sources(self): + """Generate SOURCES.txt only if there isn't one already. + + If we are in an sdist command, then we always want to update + SOURCES.txt. If we are not in an sdist command, then it doesn't + matter one flip, and is actually destructive. + """ + manifest_filename = os.path.join(self.egg_info, "SOURCES.txt") + if not os.path.exists(manifest_filename) or 'sdist' in sys.argv: + log.info("[pbr] Processing SOURCES.txt") + mm = LocalManifestMaker(self.distribution) + mm.manifest = manifest_filename + mm.run() + self.filelist = mm.filelist + else: + log.info("[pbr] Reusing existing SOURCES.txt") + self.filelist = egg_info.FileList() + for entry in open(manifest_filename, 'r').read().split('\n'): + self.filelist.append(entry) + + class LocalSDist(sdist.sdist): """Builds the ChangeLog and Authors files from VC first.""" @@ -501,6 +601,7 @@ class LocalSDist(sdist.sdist): sdist.sdist.run(self) try: + from sphinx import apidoc from sphinx import application from sphinx import config from sphinx import setup_command @@ -510,17 +611,21 @@ try: command_name = 'build_sphinx' builders = ['html', 'man'] - def generate_autoindex(self): + def _get_source_dir(self): option_dict = self.distribution.get_option_dict('build_sphinx') - log.info("[pbr] Autodocumenting from %s" - % os.path.abspath(os.curdir)) - modules = {} if 'source_dir' in option_dict: source_dir = os.path.join(option_dict['source_dir'][1], 'api') else: source_dir = 'doc/source/api' if not os.path.exists(source_dir): os.makedirs(source_dir) + return source_dir + + def generate_autoindex(self): + log.info("[pbr] Autodocumenting from %s" + % os.path.abspath(os.curdir)) + modules = {} + source_dir = self._get_source_dir() for pkg in self.distribution.packages: if '.' not in pkg: for dirpath, dirnames, files in os.walk(pkg): @@ -547,6 +652,10 @@ try: output_file.write(_rst_template % values) autoindex.write(" %s.rst\n" % module) + def _sphinx_tree(self): + source_dir = self._get_source_dir() + apidoc.main(['apidoc', '.', '-H', 'Modules', '-o', source_dir]) + def _sphinx_run(self): if not self.verbose: status_stream = io.StringIO() @@ -587,11 +696,19 @@ try: def run(self): option_dict = self.distribution.get_option_dict('pbr') - if ('autodoc_index_modules' in option_dict and - option_dict.get( - 'autodoc_index_modules')[1].lower() in TRUE_VALUES and - not os.getenv('SPHINX_DEBUG')): - self.generate_autoindex() + tree_index = get_boolean_option(option_dict, + 'autodoc_tree_index_modules', + 'AUTODOC_TREE_INDEX_MODULES') + auto_index = get_boolean_option(option_dict, + 'autodoc_index_modules', + 'AUTODOC_INDEX_MODULES') + if not os.getenv('SPHINX_DEBUG'): + #NOTE(afazekas): These options can be used together, + # but they do a very similar thing in a difffernet way + if tree_index: + self._sphinx_tree() + if auto_index: + self.generate_autoindex() for builder in self.builders: self.builder = builder diff --git a/pbr/tests/test_core.py b/pbr/tests/test_core.py index a7376eb..dd21e6f 100644 --- a/pbr/tests/test_core.py +++ b/pbr/tests/test_core.py @@ -90,7 +90,7 @@ class TestCore(tests.BaseTestCase): tf = tarfile.open(tf_path) names = ['/'.join(p.split('/')[1:]) for p in tf.getnames()] - assert 'extra-file.txt' in names + self.assertIn('extra-file.txt', names) def test_console_script_install(self): """Test that we install a non-pkg-resources console script.""" @@ -120,3 +120,28 @@ class TestCore(tests.BaseTestCase): 'develop', '--install-dir=%s' % self.temp_dir) self.check_script_install(stdout) + + +class TestGitSDist(tests.BaseTestCase): + + def setUp(self): + super(TestGitSDist, self).setUp() + + stdout, _, return_code = self._run_cmd('git', ('init',)) + if return_code: + self.skipTest("git not installed") + + stdout, _, return_code = self._run_cmd('git', ('add', '.')) + stdout, _, return_code = self._run_cmd( + 'git', ('commit', '-m', 'Turn this into a git repo')) + + stdout, _, return_code = self.run_setup('sdist', '--formats=gztar') + + def test_sdist_git_extra_files(self): + """Test that extra files found in git are correctly added.""" + # There can be only one + tf_path = glob.glob(os.path.join('dist', '*.tar.gz'))[0] + tf = tarfile.open(tf_path) + names = ['/'.join(p.split('/')[1:]) for p in tf.getnames()] + + self.assertIn('git-extra-file.txt', names) diff --git a/pbr/tests/test_packaging.py b/pbr/tests/test_packaging.py new file mode 100644 index 0000000..562b10e --- /dev/null +++ b/pbr/tests/test_packaging.py @@ -0,0 +1,106 @@ +# Copyright (c) 2013 New Dream Network, LLC (DreamHost) +# +# 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. +# +# Copyright (C) 2013 Association of Universities for Research in Astronomy +# (AURA) +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions are met: +# +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# +# 2. Redistributions in binary form must reproduce the above +# copyright notice, this list of conditions and the following +# disclaimer in the documentation and/or other materials provided +# with the distribution. +# +# 3. The name of AURA and its representatives may not be used to +# endorse or promote products derived from this software without +# specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY AURA ``AS IS'' AND ANY EXPRESS OR IMPLIED +# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +# DISCLAIMED. IN NO EVENT SHALL AURA BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, +# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + +import os + +from pbr import tests + + +class TestPackagingInGitRepoWithCommit(tests.BaseTestCase): + + def setUp(self): + super(TestPackagingInGitRepoWithCommit, self).setUp() + self._run_cmd('git', ['init', '.']) + self._run_cmd('git', ['add', '.']) + self._run_cmd('git', ['commit', '-m', 'test commit']) + self.run_setup('sdist') + return + + def test_authors(self): + # One commit, something should be in the authors list + with open(os.path.join(self.package_dir, 'AUTHORS'), 'r') as f: + body = f.read() + self.assertNotEqual(body, '') + + def test_changelog(self): + with open(os.path.join(self.package_dir, 'ChangeLog'), 'r') as f: + body = f.read() + # One commit, something should be in the ChangeLog list + self.assertNotEqual(body, '') + + +class TestPackagingInGitRepoWithoutCommit(tests.BaseTestCase): + + def setUp(self): + super(TestPackagingInGitRepoWithoutCommit, self).setUp() + self._run_cmd('git', ['init', '.']) + self._run_cmd('git', ['add', '.']) + self.run_setup('sdist') + return + + def test_authors(self): + # No commits, no authors in list + with open(os.path.join(self.package_dir, 'AUTHORS'), 'r') as f: + body = f.read() + self.assertEqual(body, '\n') + + def test_changelog(self): + # No commits, nothing should be in the ChangeLog list + with open(os.path.join(self.package_dir, 'ChangeLog'), 'r') as f: + body = f.read() + self.assertEqual(body, '') + + +class TestPackagingInPlainDirectory(tests.BaseTestCase): + + def setUp(self): + super(TestPackagingInPlainDirectory, self).setUp() + self.run_setup('sdist') + return + + def test_authors(self): + # Not a git repo, no AUTHORS file created + filename = os.path.join(self.package_dir, 'AUTHORS') + self.assertFalse(os.path.exists(filename)) + + def test_changelog(self): + # Not a git repo, no ChangeLog created + filename = os.path.join(self.package_dir, 'ChangeLog') + self.assertFalse(os.path.exists(filename)) diff --git a/pbr/tests/testpackage/git-extra-file.txt b/pbr/tests/testpackage/git-extra-file.txt new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/pbr/tests/testpackage/git-extra-file.txt diff --git a/pbr/util.py b/pbr/util.py index 6339116..1682b66 100644 --- a/pbr/util.py +++ b/pbr/util.py @@ -77,6 +77,7 @@ try: except ImportError: import configparser +from pbr import extra_files import pbr.hooks # A simplified RE for this; just checks that the line ends with version @@ -222,7 +223,7 @@ def cfg_to_args(path='setup.cfg'): if setup_hooks: setup_hooks = [ hook for hook in split_multiline(setup_hooks) - if hook != 'pbr.hook.setup_hook'] + if hook != 'pbr.hooks.setup_hook'] for hook in setup_hooks: hook_fn = resolve_name(hook) try : @@ -258,23 +259,9 @@ def cfg_to_args(path='setup.cfg'): wrap_commands(kwargs) # Handle the [files]/extra_files option - extra_files = has_get_option(config, 'files', 'extra_files') - if extra_files: - extra_files = split_multiline(extra_files) - # Let's do a sanity check - for filename in extra_files: - if not os.path.exists(filename): - raise DistutilsFileError( - '%s from the extra_files option in setup.cfg does not ' - 'exist' % filename) - # Unfortunately the only really sensible way to do this is to - # monkey-patch the manifest_maker class - @monkeypatch_method(manifest_maker) - def add_defaults(self, extra_files=extra_files, log=log): - log.info('[pbr] running patched manifest_maker command ' - 'with extra_files support') - add_defaults._orig(self) - self.filelist.extend(extra_files) + files_extra_files = has_get_option(config, 'files', 'extra_files') + if files_extra_files: + extra_files.set_extra_files(split_multiline(files_extra_files)) finally: # Perform cleanup if any paths were added to sys.path diff --git a/requirements.txt b/requirements.txt index da917d5..4627de5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,2 +1 @@ -setuptools_git>=0.4 pip>=1.0 diff --git a/tools/integration.sh b/tools/integration.sh index b32b303..8f7b46f 100644 --- a/tools/integration.sh +++ b/tools/integration.sh @@ -17,9 +17,6 @@ function mkvenv { $venv/bin/pip install $pip } -# PROJECTS is a list of projects that we're testing -PROJECTS=$* - # BASE should be a directory with a subdir called "new" and in that # dir, there should be a git repository for every entry in PROJECTS BASE=${BASE:-/opt/stack} @@ -29,9 +26,9 @@ REPODIR=${REPODIR:-$BASE/new} # TODO: Figure out how to get this on to the box properly sudo apt-get install -y --force-yes libxml2-dev libxslt-dev libmysqlclient-dev libpq-dev libnspr4-dev pkg-config libsqlite3-dev libzmq-dev libffi-dev -tmpdir=`mktemp -d` +tmpdir=$(mktemp -d) -whoami=`whoami` +whoami=$(whoami) tmpdownload=$tmpdir/download mkdir -p $tmpdownload @@ -40,9 +37,11 @@ mkdir -p $pypidir jeepybvenv=$tmpdir/jeepyb +sudo touch $HOME/pip.log +sudo chown $USER $HOME/pip.log + rm -f ~/.pip/pip.conf ~/.pydistutils.cfg mkdir -p ~/.pip - cat <<EOF > ~/.pip/pip.conf [global] log = $HOME/pip.log @@ -64,6 +63,24 @@ mirrors: output: $pypidir EOF +# Default to using pypi.openstack.org as an easy_install mirror +if [ "$1" == "--no-mirror" ] ; then + shift +else + cat <<EOF > ~/.pydistutils.cfg +[easy_install] +index_url = http://pypi.openstack.org/openstack +EOF + cat <<EOF > ~/.pip/pip.conf +[global] +index-url = http://pypi.openstack.org/openstack +log = $HOME/pip.log +EOF +fi + +# PROJECTS is a list of projects that we're testing +PROJECTS=$* + pbrsdistdir=$tmpdir/pbrsdist git clone $REPODIR/pbr $pbrsdistdir cd $pbrsdistdir @@ -77,6 +94,8 @@ $jeepybvenv/bin/python setup.py sdist -d $tmpdownload/pip/openstack $jeepybvenv/bin/run-mirror -b remotes/origin/master --verbose -c $tmpdir/mirror.yaml --no-download +find $pypidir + # Make pypi thing pypiurl=file://$pypidir @@ -139,7 +158,7 @@ projectdir=$tmpdir/projects mkdir -p $projectdir for PROJECT in $PROJECTS ; do - SHORT_PROJECT=`basename $PROJECT` + SHORT_PROJECT=$(basename $PROJECT) if ! grep 'pbr' $REPODIR/$SHORT_PROJECT/requirements.txt >/dev/null 2>&1 then # project doesn't use pbr @@ -154,6 +173,13 @@ for PROJECT in $PROJECTS ; do continue fi shortprojectdir=$projectdir/$SHORT_PROJECT + sudo chown -R $USER $REPODIR/$SHORT_PROJECT + (cd $REPODIR/requirements && python update.py $REPODIR/$SHORT_PROJECT) + pushd $REPODIR/$SHORT_PROJECT + if ! git diff --quiet ; then + git commit -a -m'Update requirements' + fi + popd git clone $REPODIR/$SHORT_PROJECT $shortprojectdir sdistvenv=$tmpdir/sdist |