Repository: conda/conda

Issue:
Conda 4.3.14 crashes on update or install
Any attempt to install or update a package, or create an environment causes crash after updating conda to 4.3.14.  I used an attempt to downgrade conda to the pervious version that worked to illustrate the crash:
```
$ conda install conda=4.3.13
Fetching package metadata .........
Solving package specifications: .

Package plan for installation in environment /localdisk/work/tmtomash/miniconda3:

The following packages will be DOWNGRADED due to dependency conflicts:

    conda: 4.3.14-py35_0 --> 4.3.13-py35_0

Proceed ([y]/n)? y

An unexpected error has occurred.
Please consider posting the following information to the
conda GitHub issue tracker at:

    https://github.com/conda/conda/issues



Current conda install:

               platform : linux-64
          conda version : 4.3.14
       conda is private : False
      conda-env version : 4.3.14
    conda-build version : 2.1.5
         python version : 3.5.2.final.0
       requests version : 2.12.4
       root environment : /localdisk/work/tmtomash/miniconda3  (writable)
    default environment : /localdisk/work/tmtomash/miniconda3
       envs directories : /localdisk/work/tmtomash/miniconda3/envs
                          /nfs/site/home/tmtomash/.conda/envs
          package cache : /localdisk/work/tmtomash/miniconda3/pkgs
                          /nfs/site/home/tmtomash/.conda/pkgs
           channel URLs : https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/linux-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
            config file : /nfs/site/home/tmtomash/.condarc
           offline mode : False
             user-agent : conda/4.3.14 requests/2.12.4 CPython/3.5.2 Linux/4.4.0-59-generic debian/stretch/sid glibc/2.23
                UID:GID : 11573498:22002



`$ /localdisk/work/tmtomash/miniconda3/bin/conda install conda=4.3.13`




    Traceback (most recent call last):
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/exceptions.py", line 573, in conda_exception_handler
        return_value = func(*args, **kwargs)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/main.py", line 134, in _main
        exit_code = args.func(args, p)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/main_install.py", line 80, in execute
        install(args, parser, 'install')
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/install.py", line 359, in install
        execute_actions(actions, index, verbose=not context.quiet)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 798, in execute_actions
        plan = plan_from_actions(actions, index)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 338, in plan_from_actions
        plan = inject_UNLINKLINKTRANSACTION(plan, index, prefix)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 302, in inject_UNLINKLINKTRANSACTION
        pfe.prepare()
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 465, in prepare
        for dist in self.link_dists)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 465, in <genexpr>
        for dist in self.link_dists)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 388, in make_actions_for_dist
        key=lambda pce: pce and pce.is_extracted and pce.tarball_matches_md5_if(md5)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/_vendor/auxlib/collection.py", line 88, in first
        return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/_vendor/auxlib/collection.py", line 88, in <genexpr>
        return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 387, in <genexpr>
        (PackageCache(pkgs_dir).get(dist) for pkgs_dir in context.pkgs_dirs),
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 347, in get
        return self._packages_map.get(dist, default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 251, in _packages_map
        return self.__packages_map or self._init_packages_map()
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 287, in _init_packages_map
        pkgs_dir_contents = dedupe_pkgs_dir_contents(listdir(pkgs_dir))
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 283, in dedupe_pkgs_dir_contents
        last = reduce(_process, sorted(pkgs_dir_contents))
    TypeError: reduce() of empty sequence with no initial value
```
------------------

The following patch fixes the crash, but the problem may be with the empty list, not when trying to use it:
```
--- package_cache_orig.py	2017-03-09 12:00:58.803996459 -0600
+++ package_cache.py	2017-03-09 12:01:29.467509263 -0600
@@ -279,8 +279,9 @@
                     contents.append(x)
                 return y
 
-            last = reduce(_process, sorted(pkgs_dir_contents))
-            _process(last, contents and contents[-1] or '')
+            if len(pkgs_dir_contents) > 0:
+                last = reduce(_process, sorted(pkgs_dir_contents))
+                _process(last, contents and contents[-1] or '')
             return contents
 
         pkgs_dir_contents = dedupe_pkgs_dir_contents(listdir(pkgs_dir))
```


Conda 4.3.14 crashes on update or install
Any attempt to install or update a package, or create an environment causes crash after updating conda to 4.3.14.  I used an attempt to downgrade conda to the pervious version that worked to illustrate the crash:
```
$ conda install conda=4.3.13
Fetching package metadata .........
Solving package specifications: .

Package plan for installation in environment /localdisk/work/tmtomash/miniconda3:

The following packages will be DOWNGRADED due to dependency conflicts:

    conda: 4.3.14-py35_0 --> 4.3.13-py35_0

Proceed ([y]/n)? y

An unexpected error has occurred.
Please consider posting the following information to the
conda GitHub issue tracker at:

    https://github.com/conda/conda/issues



Current conda install:

               platform : linux-64
          conda version : 4.3.14
       conda is private : False
      conda-env version : 4.3.14
    conda-build version : 2.1.5
         python version : 3.5.2.final.0
       requests version : 2.12.4
       root environment : /localdisk/work/tmtomash/miniconda3  (writable)
    default environment : /localdisk/work/tmtomash/miniconda3
       envs directories : /localdisk/work/tmtomash/miniconda3/envs
                          /nfs/site/home/tmtomash/.conda/envs
          package cache : /localdisk/work/tmtomash/miniconda3/pkgs
                          /nfs/site/home/tmtomash/.conda/pkgs
           channel URLs : https://repo.continuum.io/pkgs/free/linux-64
                          https://repo.continuum.io/pkgs/free/noarch
                          https://repo.continuum.io/pkgs/r/linux-64
                          https://repo.continuum.io/pkgs/r/noarch
                          https://repo.continuum.io/pkgs/pro/linux-64
                          https://repo.continuum.io/pkgs/pro/noarch
            config file : /nfs/site/home/tmtomash/.condarc
           offline mode : False
             user-agent : conda/4.3.14 requests/2.12.4 CPython/3.5.2 Linux/4.4.0-59-generic debian/stretch/sid glibc/2.23
                UID:GID : 11573498:22002



`$ /localdisk/work/tmtomash/miniconda3/bin/conda install conda=4.3.13`




    Traceback (most recent call last):
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/exceptions.py", line 573, in conda_exception_handler
        return_value = func(*args, **kwargs)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/main.py", line 134, in _main
        exit_code = args.func(args, p)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/main_install.py", line 80, in execute
        install(args, parser, 'install')
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/cli/install.py", line 359, in install
        execute_actions(actions, index, verbose=not context.quiet)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 798, in execute_actions
        plan = plan_from_actions(actions, index)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 338, in plan_from_actions
        plan = inject_UNLINKLINKTRANSACTION(plan, index, prefix)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/plan.py", line 302, in inject_UNLINKLINKTRANSACTION
        pfe.prepare()
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 465, in prepare
        for dist in self.link_dists)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 465, in <genexpr>
        for dist in self.link_dists)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 388, in make_actions_for_dist
        key=lambda pce: pce and pce.is_extracted and pce.tarball_matches_md5_if(md5)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/_vendor/auxlib/collection.py", line 88, in first
        return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/_vendor/auxlib/collection.py", line 88, in <genexpr>
        return next((apply(x) for x in seq if key(x)), default() if callable(default) else default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 387, in <genexpr>
        (PackageCache(pkgs_dir).get(dist) for pkgs_dir in context.pkgs_dirs),
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 347, in get
        return self._packages_map.get(dist, default)
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 251, in _packages_map
        return self.__packages_map or self._init_packages_map()
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 287, in _init_packages_map
        pkgs_dir_contents = dedupe_pkgs_dir_contents(listdir(pkgs_dir))
      File "/localdisk/work/tmtomash/miniconda3/lib/python3.5/site-packages/conda/core/package_cache.py", line 283, in dedupe_pkgs_dir_contents
        last = reduce(_process, sorted(pkgs_dir_contents))
    TypeError: reduce() of empty sequence with no initial value
```
------------------

The following patch fixes the crash, but the problem may be with the empty list, not when trying to use it:
```
--- package_cache_orig.py	2017-03-09 12:00:58.803996459 -0600
+++ package_cache.py	2017-03-09 12:01:29.467509263 -0600
@@ -279,8 +279,9 @@
                     contents.append(x)
                 return y
 
-            last = reduce(_process, sorted(pkgs_dir_contents))
-            _process(last, contents and contents[-1] or '')
+            if len(pkgs_dir_contents) > 0:
+                last = reduce(_process, sorted(pkgs_dir_contents))
+                _process(last, contents and contents[-1] or '')
             return contents
 
         pkgs_dir_contents = dedupe_pkgs_dir_contents(listdir(pkgs_dir))
```




Discussion:
F&(%
F&(%

Resolving patch:
diff --git a/conda/core/package_cache.py b/conda/core/package_cache.py
--- a/conda/core/package_cache.py
+++ b/conda/core/package_cache.py
@@ -272,6 +272,9 @@ def _add_entry(__packages_map, pkgs_dir, package_filename):
         def dedupe_pkgs_dir_contents(pkgs_dir_contents):
             # if both 'six-1.10.0-py35_0/' and 'six-1.10.0-py35_0.tar.bz2' are in pkgs_dir,
             #   only 'six-1.10.0-py35_0.tar.bz2' will be in the return contents
+            if not pkgs_dir_contents:
+                return []
+
             contents = []
 
             def _process(x, y):


Test patch: