--- Begin Message ---
Package: release.debian.org
Severity: normal
User: release.debian....@packages.debian.org
Usertags: unblock
Please unblock package python-pip
We expect to shortly have a patch to resolve the RC bug #771794. We would
also like to include an additional fix for CVE-2014-8991 (which is not RC)
Please see the attached debdiff. As an aid for review, I'm also attaching
two individual file diffs with the whitespace removed (since this Python,
there are whitespace changes that matter, but it's a lot harder to read).
Please let us know if we can include this.
unblock python-pip/1.5.6-4
*** install.nowhite.diff
--- python-pip-1.5.6/pip/commands/install.py 2014-05-16 22:19:02.000000000
-0400
+++ python-pip-1.5.6.new/pip/commands/install.py 2014-12-03
14:04:16.896561138 -0500
@@ -10,6 +10,7 @@
from pip.index import PackageFinder
from pip.exceptions import InstallationError, CommandError,
PreviousBuildDirError
from pip import cmdoptions
+from pip.util import BuildDirectory
class InstallCommand(Command):
@@ -188,7 +189,7 @@
if (
options.no_install or
options.no_download or
- (options.build_dir != build_prefix) or
+ options.build_dir or
options.no_clean
):
logger.deprecated('1.7', 'DEPRECATION: --no-install,
--no-download, --build, '
@@ -197,7 +198,16 @@
if options.download_dir:
options.no_install = True
options.ignore_installed = True
+
+ # If we have --no-install or --no-download and no --build we use the
+ # legacy static build dir
+ if (options.build_dir is None
+ and (options.no_install or options.no_download)):
+ options.build_dir = build_prefix
+
+ if options.build_dir:
options.build_dir = os.path.abspath(options.build_dir)
+
options.src_dir = os.path.abspath(options.src_dir)
install_options = options.install_options or []
if options.use_user_site:
@@ -237,8 +247,10 @@
finder = self._build_package_finder(options, index_urls, session)
+ build_delete = (not (options.no_clean or options.build_dir))
+ with BuildDirectory(options.build_dir, delete=build_delete) as
build_dir:
requirement_set = RequirementSet(
- build_dir=options.build_dir,
+ build_dir=build_dir,
src_dir=options.src_dir,
download_dir=options.download_dir,
download_cache=options.download_cache,
diff -ruN python-pip-1.5.6/debian/changelog python-pip-1.5.6.new/debian/changelog
--- python-pip-1.5.6/debian/changelog 2014-11-17 14:18:45.000000000 -0500
+++ python-pip-1.5.6.new/debian/changelog 2014-12-03 14:04:16.888561137 -0500
@@ -1,3 +1,12 @@
+python-pip (1.5.6-4) UNRELEASED; urgency=medium
+
+ * Team upload.
+ * Backport upstream fix to use non-predictable download directories
+ - Fixes denial of service vector (CVE-2014-8991) (Closes: #725847)
+ - Fixes retry failures (Closes: #769930)
+
+ -- Scott Kitterman <sc...@kitterman.com> Wed, 03 Dec 2014 13:46:31 -0500
+
python-pip (1.5.6-3) unstable; urgency=medium
* Team upload.
diff -ruN python-pip-1.5.6/debian/patches/random-install-dir.patch python-pip-1.5.6.new/debian/patches/random-install-dir.patch
--- python-pip-1.5.6/debian/patches/random-install-dir.patch 1969-12-31 19:00:00.000000000 -0500
+++ python-pip-1.5.6.new/debian/patches/random-install-dir.patch 2014-12-03 14:04:16.888561137 -0500
@@ -0,0 +1,394 @@
+Description: Use randomized install directory
+ python-pip (1.5.6-4) UNRELEASED; urgency=medium
+ .
+ * Team upload.
+ * Backport upstream fix to use non-predictable download directories
+ - Fixes denial of service vector (CVE-2014-8991) (Closes: #725847)
+ - Fixes retry failures (Closes: #769930)
+Author: Donald Stufft <don...@stufft.io>
+Bug-Debian: http://bugs.debian.org/725847
+Bug-Debian: http://bugs.debian.org/769930
+Origin: https://github.com/pypa/pip/pull/2122
+Forwarded: not-needed
+Reviewed-By: Scott Kitterman <sc...@kitterman.com>
+Last-Update: 2014-12-03
+
+--- python-pip-1.5.6.orig/pip/cmdoptions.py
++++ python-pip-1.5.6/pip/cmdoptions.py
+@@ -9,7 +9,7 @@ To be consistent, all options will follo
+ """
+ import copy
+ from optparse import OptionGroup, SUPPRESS_HELP, Option
+-from pip.locations import build_prefix, default_log_file
++from pip.locations import default_log_file
+
+
+ def make_option_group(group, parser):
+@@ -297,10 +297,8 @@ build_dir = OptionMaker(
+ '-b', '--build', '--build-dir', '--build-directory',
+ dest='build_dir',
+ metavar='dir',
+- default=build_prefix,
+- help='Directory to unpack packages into and build in. '
+- 'The default in a virtualenv is "<venv path>/build". '
+- 'The default for global installs is "<OS temp dir>/pip_build_<username>".')
++ help='Directory to unpack packages into and build in.',
++)
+
+ install_options = OptionMaker(
+ '--install-option',
+--- python-pip-1.5.6.orig/pip/commands/install.py
++++ python-pip-1.5.6/pip/commands/install.py
+@@ -10,6 +10,7 @@ from pip.basecommand import Command
+ from pip.index import PackageFinder
+ from pip.exceptions import InstallationError, CommandError, PreviousBuildDirError
+ from pip import cmdoptions
++from pip.util import BuildDirectory
+
+
+ class InstallCommand(Command):
+@@ -188,7 +189,7 @@ class InstallCommand(Command):
+ if (
+ options.no_install or
+ options.no_download or
+- (options.build_dir != build_prefix) or
++ options.build_dir or
+ options.no_clean
+ ):
+ logger.deprecated('1.7', 'DEPRECATION: --no-install, --no-download, --build, '
+@@ -197,7 +198,16 @@ class InstallCommand(Command):
+ if options.download_dir:
+ options.no_install = True
+ options.ignore_installed = True
+- options.build_dir = os.path.abspath(options.build_dir)
++
++ # If we have --no-install or --no-download and no --build we use the
++ # legacy static build dir
++ if (options.build_dir is None
++ and (options.no_install or options.no_download)):
++ options.build_dir = build_prefix
++
++ if options.build_dir:
++ options.build_dir = os.path.abspath(options.build_dir)
++
+ options.src_dir = os.path.abspath(options.src_dir)
+ install_options = options.install_options or []
+ if options.use_user_site:
+@@ -237,69 +247,71 @@ class InstallCommand(Command):
+
+ finder = self._build_package_finder(options, index_urls, session)
+
+- requirement_set = RequirementSet(
+- build_dir=options.build_dir,
+- src_dir=options.src_dir,
+- download_dir=options.download_dir,
+- download_cache=options.download_cache,
+- upgrade=options.upgrade,
+- as_egg=options.as_egg,
+- ignore_installed=options.ignore_installed,
+- ignore_dependencies=options.ignore_dependencies,
+- force_reinstall=options.force_reinstall,
+- use_user_site=options.use_user_site,
+- target_dir=temp_target_dir,
+- session=session,
+- pycompile=options.compile,
+- )
+- for name in args:
+- requirement_set.add_requirement(
+- InstallRequirement.from_line(name, None))
+- for name in options.editables:
+- requirement_set.add_requirement(
+- InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
+- for filename in options.requirements:
+- for req in parse_requirements(filename, finder=finder, options=options, session=session):
+- requirement_set.add_requirement(req)
+- if not requirement_set.has_requirements:
+- opts = {'name': self.name}
+- if options.find_links:
+- msg = ('You must give at least one requirement to %(name)s '
+- '(maybe you meant "pip %(name)s %(links)s"?)' %
+- dict(opts, links=' '.join(options.find_links)))
+- else:
+- msg = ('You must give at least one requirement '
+- 'to %(name)s (see "pip help %(name)s")' % opts)
+- logger.warn(msg)
+- return
+-
+- try:
+- if not options.no_download:
+- requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
+- else:
+- requirement_set.locate_files()
+-
+- if not options.no_install and not self.bundle:
+- requirement_set.install(install_options, global_options, root=options.root_path)
+- installed = ' '.join([req.name for req in
+- requirement_set.successfully_installed])
+- if installed:
+- logger.notify('Successfully installed %s' % installed)
+- elif not self.bundle:
+- downloaded = ' '.join([req.name for req in
+- requirement_set.successfully_downloaded])
+- if downloaded:
+- logger.notify('Successfully downloaded %s' % downloaded)
+- elif self.bundle:
+- requirement_set.create_bundle(self.bundle_filename)
+- logger.notify('Created bundle in %s' % self.bundle_filename)
+- except PreviousBuildDirError:
+- options.no_clean = True
+- raise
+- finally:
+- # Clean up
+- if (not options.no_clean) and ((not options.no_install) or options.download_dir):
+- requirement_set.cleanup_files(bundle=self.bundle)
++ build_delete = (not (options.no_clean or options.build_dir))
++ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
++ requirement_set = RequirementSet(
++ build_dir=build_dir,
++ src_dir=options.src_dir,
++ download_dir=options.download_dir,
++ download_cache=options.download_cache,
++ upgrade=options.upgrade,
++ as_egg=options.as_egg,
++ ignore_installed=options.ignore_installed,
++ ignore_dependencies=options.ignore_dependencies,
++ force_reinstall=options.force_reinstall,
++ use_user_site=options.use_user_site,
++ target_dir=temp_target_dir,
++ session=session,
++ pycompile=options.compile,
++ )
++ for name in args:
++ requirement_set.add_requirement(
++ InstallRequirement.from_line(name, None))
++ for name in options.editables:
++ requirement_set.add_requirement(
++ InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
++ for filename in options.requirements:
++ for req in parse_requirements(filename, finder=finder, options=options, session=session):
++ requirement_set.add_requirement(req)
++ if not requirement_set.has_requirements:
++ opts = {'name': self.name}
++ if options.find_links:
++ msg = ('You must give at least one requirement to %(name)s '
++ '(maybe you meant "pip %(name)s %(links)s"?)' %
++ dict(opts, links=' '.join(options.find_links)))
++ else:
++ msg = ('You must give at least one requirement '
++ 'to %(name)s (see "pip help %(name)s")' % opts)
++ logger.warn(msg)
++ return
++
++ try:
++ if not options.no_download:
++ requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
++ else:
++ requirement_set.locate_files()
++
++ if not options.no_install and not self.bundle:
++ requirement_set.install(install_options, global_options, root=options.root_path)
++ installed = ' '.join([req.name for req in
++ requirement_set.successfully_installed])
++ if installed:
++ logger.notify('Successfully installed %s' % installed)
++ elif not self.bundle:
++ downloaded = ' '.join([req.name for req in
++ requirement_set.successfully_downloaded])
++ if downloaded:
++ logger.notify('Successfully downloaded %s' % downloaded)
++ elif self.bundle:
++ requirement_set.create_bundle(self.bundle_filename)
++ logger.notify('Created bundle in %s' % self.bundle_filename)
++ except PreviousBuildDirError:
++ options.no_clean = True
++ raise
++ finally:
++ # Clean up
++ if (not options.no_clean) and ((not options.no_install) or options.download_dir):
++ requirement_set.cleanup_files(bundle=self.bundle)
+
+ if options.target_dir:
+ if not os.path.exists(options.target_dir):
+--- python-pip-1.5.6.orig/pip/commands/wheel.py
++++ python-pip-1.5.6/pip/commands/wheel.py
+@@ -8,7 +8,7 @@ from pip.index import PackageFinder
+ from pip.log import logger
+ from pip.exceptions import CommandError, PreviousBuildDirError
+ from pip.req import InstallRequirement, RequirementSet, parse_requirements
+-from pip.util import normalize_path
++from pip.util import BuildDirectory, normalize_path
+ from pip.wheel import WheelBuilder
+ from pip import cmdoptions
+
+@@ -127,6 +127,9 @@ class WheelCommand(Command):
+ "--extra-index-url is suggested.")
+ index_urls += options.mirrors
+
++ if options.build_dir:
++ options.build_dir = os.path.abspath(options.build_dir)
++
+ session = self._build_session(options)
+
+ finder = PackageFinder(find_links=options.find_links,
+@@ -141,59 +144,60 @@ class WheelCommand(Command):
+ session=session,
+ )
+
+- options.build_dir = os.path.abspath(options.build_dir)
+- requirement_set = RequirementSet(
+- build_dir=options.build_dir,
+- src_dir=None,
+- download_dir=None,
+- download_cache=options.download_cache,
+- ignore_dependencies=options.ignore_dependencies,
+- ignore_installed=True,
+- session=session,
+- wheel_download_dir=options.wheel_dir
+- )
+-
+- # make the wheelhouse
+- if not os.path.exists(options.wheel_dir):
+- os.makedirs(options.wheel_dir)
+-
+- #parse args and/or requirements files
+- for name in args:
+- requirement_set.add_requirement(
+- InstallRequirement.from_line(name, None))
+-
+- for filename in options.requirements:
+- for req in parse_requirements(
+- filename,
+- finder=finder,
+- options=options,
+- session=session):
+- if req.editable:
+- logger.notify("ignoring %s" % req.url)
+- continue
+- requirement_set.add_requirement(req)
+-
+- #fail if no requirements
+- if not requirement_set.has_requirements:
+- opts = {'name': self.name}
+- msg = ('You must give at least one requirement '
+- 'to %(name)s (see "pip help %(name)s")' % opts)
+- logger.error(msg)
+- return
++ build_delete = (not (options.no_clean or options.build_dir))
++ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
++ requirement_set = RequirementSet(
++ build_dir=build_dir,
++ src_dir=None,
++ download_dir=None,
++ download_cache=options.download_cache,
++ ignore_dependencies=options.ignore_dependencies,
++ ignore_installed=True,
++ session=session,
++ wheel_download_dir=options.wheel_dir
++ )
+
+- try:
+- #build wheels
+- wb = WheelBuilder(
+- requirement_set,
+- finder,
+- options.wheel_dir,
+- build_options = options.build_options or [],
+- global_options = options.global_options or []
+- )
+- wb.build()
+- except PreviousBuildDirError:
+- options.no_clean = True
+- raise
+- finally:
+- if not options.no_clean:
+- requirement_set.cleanup_files()
++ # make the wheelhouse
++ if not os.path.exists(options.wheel_dir):
++ os.makedirs(options.wheel_dir)
++
++ #parse args and/or requirements files
++ for name in args:
++ requirement_set.add_requirement(
++ InstallRequirement.from_line(name, None))
++
++ for filename in options.requirements:
++ for req in parse_requirements(
++ filename,
++ finder=finder,
++ options=options,
++ session=session):
++ if req.editable:
++ logger.notify("ignoring %s" % req.url)
++ continue
++ requirement_set.add_requirement(req)
++
++ #fail if no requirements
++ if not requirement_set.has_requirements:
++ opts = {'name': self.name}
++ msg = ('You must give at least one requirement '
++ 'to %(name)s (see "pip help %(name)s")' % opts)
++ logger.error(msg)
++ return
++
++ try:
++ #build wheels
++ wb = WheelBuilder(
++ requirement_set,
++ finder,
++ options.wheel_dir,
++ build_options = options.build_options or [],
++ global_options = options.global_options or []
++ )
++ wb.build()
++ except PreviousBuildDirError:
++ options.no_clean = True
++ raise
++ finally:
++ if not options.no_clean:
++ requirement_set.cleanup_files()
+--- python-pip-1.5.6.orig/pip/util.py
++++ python-pip-1.5.6/pip/util.py
+@@ -8,6 +8,7 @@ import zipfile
+ import tarfile
+ import subprocess
+ import textwrap
++import tempfile
+
+ from pip.exceptions import InstallationError, BadCommand, PipError
+ from pip.backwardcompat import(WindowsError, string_types, raw_input,
+@@ -718,3 +719,35 @@ def is_prerelease(vers):
+
+ parsed = version._normalized_key(normalized)
+ return any([any([y in set(["a", "b", "c", "rc", "dev"]) for y in x]) for x in parsed])
++
++
++class BuildDirectory(object):
++
++ def __init__(self, name=None, delete=None):
++ # If we were not given an explicit directory, and we were not given an
++ # explicit delete option, then we'll default to deleting.
++ if name is None and delete is None:
++ delete = True
++
++ if name is None:
++ name = tempfile.mkdtemp(prefix="pip-build-")
++ # If we were not given an explicit directory, and we were not given
++ # an explicit delete option, then we'll default to deleting.
++ if delete is None:
++ delete = True
++
++ self.name = name
++ self.delete = delete
++
++ def __repr__(self):
++ return "<{} {!r}>".format(self.__class__.__name__, self.name)
++
++ def __enter__(self):
++ return self.name
++
++ def __exit__(self, exc, value, tb):
++ self.cleanup()
++
++ def cleanup(self):
++ if self.delete:
++ rmtree(self.name)
diff -ruN python-pip-1.5.6/debian/patches/series python-pip-1.5.6.new/debian/patches/series
--- python-pip-1.5.6/debian/patches/series 2014-11-17 01:59:33.000000000 -0500
+++ python-pip-1.5.6.new/debian/patches/series 2014-12-03 14:04:16.888561137 -0500
@@ -1,3 +1,4 @@
de-vendorize.patch
use-venv-wheels.patch
better-error-message.patch
+random-install-dir.patch
diff -ruN python-pip-1.5.6/.pc/applied-patches python-pip-1.5.6.new/.pc/applied-patches
--- python-pip-1.5.6/.pc/applied-patches 2014-12-03 14:04:39.256562386 -0500
+++ python-pip-1.5.6.new/.pc/applied-patches 2014-12-03 14:04:16.884561137 -0500
@@ -1,3 +1,4 @@
de-vendorize.patch
use-venv-wheels.patch
better-error-message.patch
+random-install-dir.patch
diff -ruN python-pip-1.5.6/pip/cmdoptions.py python-pip-1.5.6.new/pip/cmdoptions.py
--- python-pip-1.5.6/pip/cmdoptions.py 2014-05-16 22:19:02.000000000 -0400
+++ python-pip-1.5.6.new/pip/cmdoptions.py 2014-12-03 14:04:16.896561138 -0500
@@ -9,7 +9,7 @@
"""
import copy
from optparse import OptionGroup, SUPPRESS_HELP, Option
-from pip.locations import build_prefix, default_log_file
+from pip.locations import default_log_file
def make_option_group(group, parser):
@@ -297,10 +297,8 @@
'-b', '--build', '--build-dir', '--build-directory',
dest='build_dir',
metavar='dir',
- default=build_prefix,
- help='Directory to unpack packages into and build in. '
- 'The default in a virtualenv is "<venv path>/build". '
- 'The default for global installs is "<OS temp dir>/pip_build_<username>".')
+ help='Directory to unpack packages into and build in.',
+)
install_options = OptionMaker(
'--install-option',
diff -ruN python-pip-1.5.6/pip/commands/install.py python-pip-1.5.6.new/pip/commands/install.py
--- python-pip-1.5.6/pip/commands/install.py 2014-05-16 22:19:02.000000000 -0400
+++ python-pip-1.5.6.new/pip/commands/install.py 2014-12-03 14:04:16.896561138 -0500
@@ -10,6 +10,7 @@
from pip.index import PackageFinder
from pip.exceptions import InstallationError, CommandError, PreviousBuildDirError
from pip import cmdoptions
+from pip.util import BuildDirectory
class InstallCommand(Command):
@@ -188,7 +189,7 @@
if (
options.no_install or
options.no_download or
- (options.build_dir != build_prefix) or
+ options.build_dir or
options.no_clean
):
logger.deprecated('1.7', 'DEPRECATION: --no-install, --no-download, --build, '
@@ -197,7 +198,16 @@
if options.download_dir:
options.no_install = True
options.ignore_installed = True
- options.build_dir = os.path.abspath(options.build_dir)
+
+ # If we have --no-install or --no-download and no --build we use the
+ # legacy static build dir
+ if (options.build_dir is None
+ and (options.no_install or options.no_download)):
+ options.build_dir = build_prefix
+
+ if options.build_dir:
+ options.build_dir = os.path.abspath(options.build_dir)
+
options.src_dir = os.path.abspath(options.src_dir)
install_options = options.install_options or []
if options.use_user_site:
@@ -237,69 +247,71 @@
finder = self._build_package_finder(options, index_urls, session)
- requirement_set = RequirementSet(
- build_dir=options.build_dir,
- src_dir=options.src_dir,
- download_dir=options.download_dir,
- download_cache=options.download_cache,
- upgrade=options.upgrade,
- as_egg=options.as_egg,
- ignore_installed=options.ignore_installed,
- ignore_dependencies=options.ignore_dependencies,
- force_reinstall=options.force_reinstall,
- use_user_site=options.use_user_site,
- target_dir=temp_target_dir,
- session=session,
- pycompile=options.compile,
- )
- for name in args:
- requirement_set.add_requirement(
- InstallRequirement.from_line(name, None))
- for name in options.editables:
- requirement_set.add_requirement(
- InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
- for filename in options.requirements:
- for req in parse_requirements(filename, finder=finder, options=options, session=session):
- requirement_set.add_requirement(req)
- if not requirement_set.has_requirements:
- opts = {'name': self.name}
- if options.find_links:
- msg = ('You must give at least one requirement to %(name)s '
- '(maybe you meant "pip %(name)s %(links)s"?)' %
- dict(opts, links=' '.join(options.find_links)))
- else:
- msg = ('You must give at least one requirement '
- 'to %(name)s (see "pip help %(name)s")' % opts)
- logger.warn(msg)
- return
-
- try:
- if not options.no_download:
- requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
- else:
- requirement_set.locate_files()
-
- if not options.no_install and not self.bundle:
- requirement_set.install(install_options, global_options, root=options.root_path)
- installed = ' '.join([req.name for req in
- requirement_set.successfully_installed])
- if installed:
- logger.notify('Successfully installed %s' % installed)
- elif not self.bundle:
- downloaded = ' '.join([req.name for req in
- requirement_set.successfully_downloaded])
- if downloaded:
- logger.notify('Successfully downloaded %s' % downloaded)
- elif self.bundle:
- requirement_set.create_bundle(self.bundle_filename)
- logger.notify('Created bundle in %s' % self.bundle_filename)
- except PreviousBuildDirError:
- options.no_clean = True
- raise
- finally:
- # Clean up
- if (not options.no_clean) and ((not options.no_install) or options.download_dir):
- requirement_set.cleanup_files(bundle=self.bundle)
+ build_delete = (not (options.no_clean or options.build_dir))
+ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
+ requirement_set = RequirementSet(
+ build_dir=build_dir,
+ src_dir=options.src_dir,
+ download_dir=options.download_dir,
+ download_cache=options.download_cache,
+ upgrade=options.upgrade,
+ as_egg=options.as_egg,
+ ignore_installed=options.ignore_installed,
+ ignore_dependencies=options.ignore_dependencies,
+ force_reinstall=options.force_reinstall,
+ use_user_site=options.use_user_site,
+ target_dir=temp_target_dir,
+ session=session,
+ pycompile=options.compile,
+ )
+ for name in args:
+ requirement_set.add_requirement(
+ InstallRequirement.from_line(name, None))
+ for name in options.editables:
+ requirement_set.add_requirement(
+ InstallRequirement.from_editable(name, default_vcs=options.default_vcs))
+ for filename in options.requirements:
+ for req in parse_requirements(filename, finder=finder, options=options, session=session):
+ requirement_set.add_requirement(req)
+ if not requirement_set.has_requirements:
+ opts = {'name': self.name}
+ if options.find_links:
+ msg = ('You must give at least one requirement to %(name)s '
+ '(maybe you meant "pip %(name)s %(links)s"?)' %
+ dict(opts, links=' '.join(options.find_links)))
+ else:
+ msg = ('You must give at least one requirement '
+ 'to %(name)s (see "pip help %(name)s")' % opts)
+ logger.warn(msg)
+ return
+
+ try:
+ if not options.no_download:
+ requirement_set.prepare_files(finder, force_root_egg_info=self.bundle, bundle=self.bundle)
+ else:
+ requirement_set.locate_files()
+
+ if not options.no_install and not self.bundle:
+ requirement_set.install(install_options, global_options, root=options.root_path)
+ installed = ' '.join([req.name for req in
+ requirement_set.successfully_installed])
+ if installed:
+ logger.notify('Successfully installed %s' % installed)
+ elif not self.bundle:
+ downloaded = ' '.join([req.name for req in
+ requirement_set.successfully_downloaded])
+ if downloaded:
+ logger.notify('Successfully downloaded %s' % downloaded)
+ elif self.bundle:
+ requirement_set.create_bundle(self.bundle_filename)
+ logger.notify('Created bundle in %s' % self.bundle_filename)
+ except PreviousBuildDirError:
+ options.no_clean = True
+ raise
+ finally:
+ # Clean up
+ if (not options.no_clean) and ((not options.no_install) or options.download_dir):
+ requirement_set.cleanup_files(bundle=self.bundle)
if options.target_dir:
if not os.path.exists(options.target_dir):
diff -ruN python-pip-1.5.6/pip/commands/wheel.py python-pip-1.5.6.new/pip/commands/wheel.py
--- python-pip-1.5.6/pip/commands/wheel.py 2014-12-03 14:04:39.000000000 -0500
+++ python-pip-1.5.6.new/pip/commands/wheel.py 2014-12-03 14:04:16.896561138 -0500
@@ -8,7 +8,7 @@
from pip.log import logger
from pip.exceptions import CommandError, PreviousBuildDirError
from pip.req import InstallRequirement, RequirementSet, parse_requirements
-from pip.util import normalize_path
+from pip.util import BuildDirectory, normalize_path
from pip.wheel import WheelBuilder
from pip import cmdoptions
@@ -127,6 +127,9 @@
"--extra-index-url is suggested.")
index_urls += options.mirrors
+ if options.build_dir:
+ options.build_dir = os.path.abspath(options.build_dir)
+
session = self._build_session(options)
finder = PackageFinder(find_links=options.find_links,
@@ -141,59 +144,60 @@
session=session,
)
- options.build_dir = os.path.abspath(options.build_dir)
- requirement_set = RequirementSet(
- build_dir=options.build_dir,
- src_dir=None,
- download_dir=None,
- download_cache=options.download_cache,
- ignore_dependencies=options.ignore_dependencies,
- ignore_installed=True,
- session=session,
- wheel_download_dir=options.wheel_dir
- )
-
- # make the wheelhouse
- if not os.path.exists(options.wheel_dir):
- os.makedirs(options.wheel_dir)
-
- #parse args and/or requirements files
- for name in args:
- requirement_set.add_requirement(
- InstallRequirement.from_line(name, None))
-
- for filename in options.requirements:
- for req in parse_requirements(
- filename,
- finder=finder,
- options=options,
- session=session):
- if req.editable:
- logger.notify("ignoring %s" % req.url)
- continue
- requirement_set.add_requirement(req)
-
- #fail if no requirements
- if not requirement_set.has_requirements:
- opts = {'name': self.name}
- msg = ('You must give at least one requirement '
- 'to %(name)s (see "pip help %(name)s")' % opts)
- logger.error(msg)
- return
+ build_delete = (not (options.no_clean or options.build_dir))
+ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
+ requirement_set = RequirementSet(
+ build_dir=build_dir,
+ src_dir=None,
+ download_dir=None,
+ download_cache=options.download_cache,
+ ignore_dependencies=options.ignore_dependencies,
+ ignore_installed=True,
+ session=session,
+ wheel_download_dir=options.wheel_dir
+ )
- try:
- #build wheels
- wb = WheelBuilder(
- requirement_set,
- finder,
- options.wheel_dir,
- build_options = options.build_options or [],
- global_options = options.global_options or []
- )
- wb.build()
- except PreviousBuildDirError:
- options.no_clean = True
- raise
- finally:
- if not options.no_clean:
- requirement_set.cleanup_files()
+ # make the wheelhouse
+ if not os.path.exists(options.wheel_dir):
+ os.makedirs(options.wheel_dir)
+
+ #parse args and/or requirements files
+ for name in args:
+ requirement_set.add_requirement(
+ InstallRequirement.from_line(name, None))
+
+ for filename in options.requirements:
+ for req in parse_requirements(
+ filename,
+ finder=finder,
+ options=options,
+ session=session):
+ if req.editable:
+ logger.notify("ignoring %s" % req.url)
+ continue
+ requirement_set.add_requirement(req)
+
+ #fail if no requirements
+ if not requirement_set.has_requirements:
+ opts = {'name': self.name}
+ msg = ('You must give at least one requirement '
+ 'to %(name)s (see "pip help %(name)s")' % opts)
+ logger.error(msg)
+ return
+
+ try:
+ #build wheels
+ wb = WheelBuilder(
+ requirement_set,
+ finder,
+ options.wheel_dir,
+ build_options = options.build_options or [],
+ global_options = options.global_options or []
+ )
+ wb.build()
+ except PreviousBuildDirError:
+ options.no_clean = True
+ raise
+ finally:
+ if not options.no_clean:
+ requirement_set.cleanup_files()
diff -ruN python-pip-1.5.6/pip/util.py python-pip-1.5.6.new/pip/util.py
--- python-pip-1.5.6/pip/util.py 2014-12-03 14:04:39.000000000 -0500
+++ python-pip-1.5.6.new/pip/util.py 2014-12-03 14:04:16.892561137 -0500
@@ -8,6 +8,7 @@
import tarfile
import subprocess
import textwrap
+import tempfile
from pip.exceptions import InstallationError, BadCommand, PipError
from pip.backwardcompat import(WindowsError, string_types, raw_input,
@@ -718,3 +719,35 @@
parsed = version._normalized_key(normalized)
return any([any([y in set(["a", "b", "c", "rc", "dev"]) for y in x]) for x in parsed])
+
+
+class BuildDirectory(object):
+
+ def __init__(self, name=None, delete=None):
+ # If we were not given an explicit directory, and we were not given an
+ # explicit delete option, then we'll default to deleting.
+ if name is None and delete is None:
+ delete = True
+
+ if name is None:
+ name = tempfile.mkdtemp(prefix="pip-build-")
+ # If we were not given an explicit directory, and we were not given
+ # an explicit delete option, then we'll default to deleting.
+ if delete is None:
+ delete = True
+
+ self.name = name
+ self.delete = delete
+
+ def __repr__(self):
+ return "<{} {!r}>".format(self.__class__.__name__, self.name)
+
+ def __enter__(self):
+ return self.name
+
+ def __exit__(self, exc, value, tb):
+ self.cleanup()
+
+ def cleanup(self):
+ if self.delete:
+ rmtree(self.name)
--- python-pip-1.5.6/pip/commands/wheel.py 2014-12-03 14:04:39.000000000 -0500
+++ python-pip-1.5.6.new/pip/commands/wheel.py 2014-12-03 14:04:16.896561138 -0500
@@ -8,7 +8,7 @@
from pip.log import logger
from pip.exceptions import CommandError, PreviousBuildDirError
from pip.req import InstallRequirement, RequirementSet, parse_requirements
-from pip.util import normalize_path
+from pip.util import BuildDirectory, normalize_path
from pip.wheel import WheelBuilder
from pip import cmdoptions
@@ -127,6 +127,9 @@
"--extra-index-url is suggested.")
index_urls += options.mirrors
+ if options.build_dir:
+ options.build_dir = os.path.abspath(options.build_dir)
+
session = self._build_session(options)
finder = PackageFinder(find_links=options.find_links,
@@ -141,9 +144,10 @@
session=session,
)
- options.build_dir = os.path.abspath(options.build_dir)
+ build_delete = (not (options.no_clean or options.build_dir))
+ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
requirement_set = RequirementSet(
- build_dir=options.build_dir,
+ build_dir=build_dir,
src_dir=None,
download_dir=None,
download_cache=options.download_cache,
--- python-pip-1.5.6/pip/commands/install.py 2014-05-16 22:19:02.000000000 -0400
+++ python-pip-1.5.6.new/pip/commands/install.py 2014-12-03 14:04:16.896561138 -0500
@@ -10,6 +10,7 @@
from pip.index import PackageFinder
from pip.exceptions import InstallationError, CommandError, PreviousBuildDirError
from pip import cmdoptions
+from pip.util import BuildDirectory
class InstallCommand(Command):
@@ -188,7 +189,7 @@
if (
options.no_install or
options.no_download or
- (options.build_dir != build_prefix) or
+ options.build_dir or
options.no_clean
):
logger.deprecated('1.7', 'DEPRECATION: --no-install, --no-download, --build, '
@@ -197,7 +198,16 @@
if options.download_dir:
options.no_install = True
options.ignore_installed = True
+
+ # If we have --no-install or --no-download and no --build we use the
+ # legacy static build dir
+ if (options.build_dir is None
+ and (options.no_install or options.no_download)):
+ options.build_dir = build_prefix
+
+ if options.build_dir:
options.build_dir = os.path.abspath(options.build_dir)
+
options.src_dir = os.path.abspath(options.src_dir)
install_options = options.install_options or []
if options.use_user_site:
@@ -237,8 +247,10 @@
finder = self._build_package_finder(options, index_urls, session)
+ build_delete = (not (options.no_clean or options.build_dir))
+ with BuildDirectory(options.build_dir, delete=build_delete) as build_dir:
requirement_set = RequirementSet(
- build_dir=options.build_dir,
+ build_dir=build_dir,
src_dir=options.src_dir,
download_dir=options.download_dir,
download_cache=options.download_cache,
--- End Message ---