We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Regression] Conda create environment fails on lock if root environment is not under user control
This issue is introduced in Conda 4.1.0 (Conda 4.0.8 works fine).

```
$ conda create -n root2 python=2                                                                                                                                                                   [123/1811]
Fetching package metadata .......
Solving package specifications .............

Package plan for installation in environment /home/frol/.conda/envs/root2:

The following NEW packages will be INSTALLED:

    openssl:    1.0.2h-1      (soft-link)
    pip:        8.1.2-py27_0  (soft-link)
    python:     2.7.11-0      (soft-link)
    readline:   6.2-2         (soft-link)
    setuptools: 23.0.0-py27_0 (soft-link)
    sqlite:     3.13.0-0      (soft-link)
    tk:         8.5.18-0      (soft-link)
    wheel:      0.29.0-py27_0 (soft-link)
    zlib:       1.2.8-3       (soft-link)

Proceed ([y]/n)?

Linking packages ...
An unexpected error has occurred, please consider sending the
following traceback to the conda GitHub issue tracker at:

    https://github.com/conda/conda/issues

Include the output of the command 'conda info' in your report.


Traceback (most recent call last):
  File "/usr/local/miniconda/bin/conda", line 6, in <module>
    sys.exit(main())
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main.py", line 120, in main
    args_func(args, p)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main.py", line 127, in args_func
    args.func(args, p)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main_create.py", line 57, in execute
    install(args, parser, 'create')
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/install.py", line 407, in install
    execute_actions(actions, index, verbose=not args.quiet)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/plan.py", line 566, in execute_actions
    inst.execute_instructions(plan, index, verbose)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/instructions.py", line 137, in execute_instructions
    cmd(state, arg)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/instructions.py", line 80, in LINK_CMD
    link(state['prefix'], dist, lt, index=state['index'], shortcuts=shortcuts)
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/install.py", line 1035, in link
    with Locked(prefix), Locked(pkgs_dir):
  File "/usr/local/miniconda/lib/python2.7/site-packages/conda/lock.py", line 60, in __enter__
    os.makedirs(self.lock_path)
  File "/usr/local/miniconda/lib/python2.7/os.py", line 157, in makedirs
    mkdir(name, mode)
OSError: [Errno 13] Permission denied: '/usr/local/miniconda/pkgs/.conda_lock-949'
```

`/usr/local/miniconda/` is a system-wide installation of miniconda, so obviously, users cannot create lock files there.

P.S. I have a dream that updating conda software won't break things on every release...


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `conda/lock.py`
Content:
```
1 # (c) 2012-2013 Continuum Analytics, Inc. / http://continuum.io
2 # All Rights Reserved
3 #
4 # conda is distributed under the terms of the BSD 3-clause license.
5 # Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause.
6 
7 """
8 Tools for working with locks
9 
10 A lock is just an empty directory. We use directories because this lets us use
11 the race condition-proof os.makedirs.
12 
13 For now, there is one global lock for all of conda, because some things happen
14 globally (such as downloading packages).
15 
16 We don't raise an error if the lock is named with the current PID
17 """
18 from __future__ import absolute_import, division, print_function
19 
20 import logging
21 import os
22 import time
23 
24 from .exceptions import LockError
25 
26 LOCKFN = '.conda_lock'
27 
28 
29 stdoutlog = logging.getLogger('stdoutlog')
30 
31 
32 class Locked(object):
33     """
34     Context manager to handle locks.
35     """
36     def __init__(self, path, retries=10):
37         self.path = path
38         self.end = "-" + str(os.getpid())
39         self.lock_path = os.path.join(self.path, LOCKFN + self.end)
40         self.retries = retries
41 
42     def __enter__(self):
43         # Keep the string "LOCKERROR" in this string so that external
44         # programs can look for it.
45         lockstr = ("""\
46     LOCKERROR: It looks like conda is already doing something.
47     The lock %s was found. Wait for it to finish before continuing.
48     If you are sure that conda is not running, remove it and try again.
49     You can also use: $ conda clean --lock\n""")
50         sleeptime = 1
51 
52         for _ in range(self.retries):
53             if os.path.isdir(self.lock_path):
54                 stdoutlog.info(lockstr % self.lock_path)
55                 stdoutlog.info("Sleeping for %s seconds\n" % sleeptime)
56 
57                 time.sleep(sleeptime)
58                 sleeptime *= 2
59             else:
60                 os.makedirs(self.lock_path)
61                 return self
62 
63         stdoutlog.error("Exceeded max retries, giving up")
64         raise LockError(lockstr % self.lock_path)
65 
66     def __exit__(self, exc_type, exc_value, traceback):
67         try:
68             os.rmdir(self.lock_path)
69             os.rmdir(self.path)
70         except OSError:
71             pass
72
```

Path: `conda/exceptions.py`
Content:
```
1 from __future__ import absolute_import, division, print_function
2 
3 class CondaException(Exception):
4     pass
5 
6 
7 class InvalidInstruction(CondaException):
8     def __init__(self, instruction, *args, **kwargs):
9         msg = "No handler for instruction: %r" % instruction
10         super(InvalidInstruction, self).__init__(msg, *args, **kwargs)
11 
12 class LockError(RuntimeError, CondaException):
13     pass
14
```

Path: `conda/egg_info.py`
Content:
```
1 """
2 Functions related to core conda functionality that relates to manually
3 installed Python packages, e.g. using "python setup.py install", or "pip".
4 """
5 from __future__ import absolute_import, division, print_function
6 
7 from io import open
8 import os
9 import re
10 import sys
11 from os.path import isdir, isfile, join
12 
13 from .compat import itervalues
14 from .install import linked_data
15 from .misc import rel_path
16 
17 
18 def get_site_packages_dir(installed_pkgs):
19     for info in itervalues(installed_pkgs):
20         if info['name'] == 'python':
21             if sys.platform == 'win32':
22                 stdlib_dir = 'Lib'
23             else:
24                 py_ver = info['version'][:3]
25                 stdlib_dir = 'lib/python%s' % py_ver
26             return join(stdlib_dir, 'site-packages')
27     return None
28 
29 
30 def get_egg_info_files(sp_dir):
31     for fn in os.listdir(sp_dir):
32         if not fn.endswith(('.egg', '.egg-info', '.dist-info')):
33             continue
34         path = join(sp_dir, fn)
35         if isfile(path):
36             yield path
37         elif isdir(path):
38             for path2 in [join(path, 'PKG-INFO'),
39                           join(path, 'EGG-INFO', 'PKG-INFO'),
40                           join(path, 'METADATA')]:
41                 if isfile(path2):
42                     yield path2
43 
44 
45 pat = re.compile(r'(\w+):\s*(\S+)', re.I)
46 def parse_egg_info(path):
47     """
48     Parse an .egg-info file and return its canonical distribution name
49     """
50     info = {}
51     for line in open(path, encoding='utf-8'):
52         line = line.strip()
53         m = pat.match(line)
54         if m:
55             key = m.group(1).lower()
56             info[key] = m.group(2)
57         try:
58             return '%(name)s-%(version)s-<pip>' % info
59         except KeyError:
60             pass
61     return None
62 
63 
64 def get_egg_info(prefix, all_pkgs=False):
65     """
66     Return a set of canonical names of all Python packages (in `prefix`),
67     by inspecting the .egg-info files inside site-packages.
68     By default, only untracked (not conda installed) .egg-info files are
69     considered.  Setting `all_pkgs` to True changes this.
70     """
71     installed_pkgs = linked_data(prefix)
72     sp_dir = get_site_packages_dir(installed_pkgs)
73     if sp_dir is None:
74         return set()
75 
76     conda_files = set()
77     for info in itervalues(installed_pkgs):
78         conda_files.update(info.get('files', []))
79 
80     res = set()
81     for path in get_egg_info_files(join(prefix, sp_dir)):
82         f = rel_path(prefix, path)
83         if all_pkgs or f not in conda_files:
84             try:
85                 dist = parse_egg_info(path)
86             except UnicodeDecodeError:
87                 dist = None
88             if dist:
89                 res.add(dist)
90     return res
91 
92 
93 if __name__ == '__main__':
94     from pprint import pprint
95     pprint(get_egg_info(sys.prefix))
96
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/conda/egg_info.py b/conda/egg_info.py
--- a/conda/egg_info.py
+++ b/conda/egg_info.py
@@ -15,6 +15,7 @@
 from .misc import rel_path
 
 
+
 def get_site_packages_dir(installed_pkgs):
     for info in itervalues(installed_pkgs):
         if info['name'] == 'python':
diff --git a/conda/exceptions.py b/conda/exceptions.py
--- a/conda/exceptions.py
+++ b/conda/exceptions.py
@@ -8,6 +8,3 @@
     def __init__(self, instruction, *args, **kwargs):
         msg = "No handler for instruction: %r" % instruction
         super(InvalidInstruction, self).__init__(msg, *args, **kwargs)
-
-class LockError(RuntimeError, CondaException):
-    pass
diff --git a/conda/lock.py b/conda/lock.py
--- a/conda/lock.py
+++ b/conda/lock.py
@@ -17,11 +17,11 @@
 """
 from __future__ import absolute_import, division, print_function
 
-import logging
 import os
-import time
-
-from .exceptions import LockError
+import logging
+from os.path import join
+import glob
+from time import sleep
 
 LOCKFN = '.conda_lock'
 
@@ -33,13 +33,15 @@
     """
     Context manager to handle locks.
     """
-    def __init__(self, path, retries=10):
+    def __init__(self, path):
         self.path = path
         self.end = "-" + str(os.getpid())
-        self.lock_path = os.path.join(self.path, LOCKFN + self.end)
-        self.retries = retries
+        self.lock_path = join(self.path, LOCKFN + self.end)
+        self.pattern = join(self.path, LOCKFN + '-*')
+        self.remove = True
 
     def __enter__(self):
+        retries = 10
         # Keep the string "LOCKERROR" in this string so that external
         # programs can look for it.
         lockstr = ("""\
@@ -48,24 +50,33 @@
     If you are sure that conda is not running, remove it and try again.
     You can also use: $ conda clean --lock\n""")
         sleeptime = 1
-
-        for _ in range(self.retries):
-            if os.path.isdir(self.lock_path):
-                stdoutlog.info(lockstr % self.lock_path)
+        files = None
+        while retries:
+            files = glob.glob(self.pattern)
+            if files and not files[0].endswith(self.end):
+                stdoutlog.info(lockstr % str(files))
                 stdoutlog.info("Sleeping for %s seconds\n" % sleeptime)
-
-                time.sleep(sleeptime)
+                sleep(sleeptime)
                 sleeptime *= 2
+                retries -= 1
             else:
-                os.makedirs(self.lock_path)
-                return self
+                break
+        else:
+            stdoutlog.error("Exceeded max retries, giving up")
+            raise RuntimeError(lockstr % str(files))
 
-        stdoutlog.error("Exceeded max retries, giving up")
-        raise LockError(lockstr % self.lock_path)
+        if not files:
+            try:
+                os.makedirs(self.lock_path)
+            except OSError:
+                pass
+        else:  # PID lock already here --- someone else will remove it.
+            self.remove = False
 
     def __exit__(self, exc_type, exc_value, traceback):
-        try:
-            os.rmdir(self.lock_path)
-            os.rmdir(self.path)
-        except OSError:
-            pass
+        if self.remove:
+            for path in self.lock_path, self.path:
+                try:
+                    os.rmdir(path)
+                except OSError:
+                    pass

{"golden_diff": "diff --git a/conda/egg_info.py b/conda/egg_info.py\n--- a/conda/egg_info.py\n+++ b/conda/egg_info.py\n@@ -15,6 +15,7 @@\n from .misc import rel_path\n \n \n+\n def get_site_packages_dir(installed_pkgs):\n     for info in itervalues(installed_pkgs):\n         if info['name'] == 'python':\ndiff --git a/conda/exceptions.py b/conda/exceptions.py\n--- a/conda/exceptions.py\n+++ b/conda/exceptions.py\n@@ -8,6 +8,3 @@\n     def __init__(self, instruction, *args, **kwargs):\n         msg = \"No handler for instruction: %r\" % instruction\n         super(InvalidInstruction, self).__init__(msg, *args, **kwargs)\n-\n-class LockError(RuntimeError, CondaException):\n-    pass\ndiff --git a/conda/lock.py b/conda/lock.py\n--- a/conda/lock.py\n+++ b/conda/lock.py\n@@ -17,11 +17,11 @@\n \"\"\"\n from __future__ import absolute_import, division, print_function\n \n-import logging\n import os\n-import time\n-\n-from .exceptions import LockError\n+import logging\n+from os.path import join\n+import glob\n+from time import sleep\n \n LOCKFN = '.conda_lock'\n \n@@ -33,13 +33,15 @@\n     \"\"\"\n     Context manager to handle locks.\n     \"\"\"\n-    def __init__(self, path, retries=10):\n+    def __init__(self, path):\n         self.path = path\n         self.end = \"-\" + str(os.getpid())\n-        self.lock_path = os.path.join(self.path, LOCKFN + self.end)\n-        self.retries = retries\n+        self.lock_path = join(self.path, LOCKFN + self.end)\n+        self.pattern = join(self.path, LOCKFN + '-*')\n+        self.remove = True\n \n     def __enter__(self):\n+        retries = 10\n         # Keep the string \"LOCKERROR\" in this string so that external\n         # programs can look for it.\n         lockstr = (\"\"\"\\\n@@ -48,24 +50,33 @@\n     If you are sure that conda is not running, remove it and try again.\n     You can also use: $ conda clean --lock\\n\"\"\")\n         sleeptime = 1\n-\n-        for _ in range(self.retries):\n-            if os.path.isdir(self.lock_path):\n-                stdoutlog.info(lockstr % self.lock_path)\n+        files = None\n+        while retries:\n+            files = glob.glob(self.pattern)\n+            if files and not files[0].endswith(self.end):\n+                stdoutlog.info(lockstr % str(files))\n                 stdoutlog.info(\"Sleeping for %s seconds\\n\" % sleeptime)\n-\n-                time.sleep(sleeptime)\n+                sleep(sleeptime)\n                 sleeptime *= 2\n+                retries -= 1\n             else:\n-                os.makedirs(self.lock_path)\n-                return self\n+                break\n+        else:\n+            stdoutlog.error(\"Exceeded max retries, giving up\")\n+            raise RuntimeError(lockstr % str(files))\n \n-        stdoutlog.error(\"Exceeded max retries, giving up\")\n-        raise LockError(lockstr % self.lock_path)\n+        if not files:\n+            try:\n+                os.makedirs(self.lock_path)\n+            except OSError:\n+                pass\n+        else:  # PID lock already here --- someone else will remove it.\n+            self.remove = False\n \n     def __exit__(self, exc_type, exc_value, traceback):\n-        try:\n-            os.rmdir(self.lock_path)\n-            os.rmdir(self.path)\n-        except OSError:\n-            pass\n+        if self.remove:\n+            for path in self.lock_path, self.path:\n+                try:\n+                    os.rmdir(path)\n+                except OSError:\n+                    pass\n", "issue": "[Regression] Conda create environment fails on lock if root environment is not under user control\nThis issue is introduced in Conda 4.1.0 (Conda 4.0.8 works fine).\n\n```\n$ conda create -n root2 python=2                                                                                                                                                                   [123/1811]\nFetching package metadata .......\nSolving package specifications .............\n\nPackage plan for installation in environment /home/frol/.conda/envs/root2:\n\nThe following NEW packages will be INSTALLED:\n\n    openssl:    1.0.2h-1      (soft-link)\n    pip:        8.1.2-py27_0  (soft-link)\n    python:     2.7.11-0      (soft-link)\n    readline:   6.2-2         (soft-link)\n    setuptools: 23.0.0-py27_0 (soft-link)\n    sqlite:     3.13.0-0      (soft-link)\n    tk:         8.5.18-0      (soft-link)\n    wheel:      0.29.0-py27_0 (soft-link)\n    zlib:       1.2.8-3       (soft-link)\n\nProceed ([y]/n)?\n\nLinking packages ...\nAn unexpected error has occurred, please consider sending the\nfollowing traceback to the conda GitHub issue tracker at:\n\n    https://github.com/conda/conda/issues\n\nInclude the output of the command 'conda info' in your report.\n\n\nTraceback (most recent call last):\n  File \"/usr/local/miniconda/bin/conda\", line 6, in <module>\n    sys.exit(main())\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main.py\", line 120, in main\n    args_func(args, p)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main.py\", line 127, in args_func\n    args.func(args, p)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/main_create.py\", line 57, in execute\n    install(args, parser, 'create')\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/cli/install.py\", line 407, in install\n    execute_actions(actions, index, verbose=not args.quiet)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/plan.py\", line 566, in execute_actions\n    inst.execute_instructions(plan, index, verbose)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/instructions.py\", line 137, in execute_instructions\n    cmd(state, arg)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/instructions.py\", line 80, in LINK_CMD\n    link(state['prefix'], dist, lt, index=state['index'], shortcuts=shortcuts)\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/install.py\", line 1035, in link\n    with Locked(prefix), Locked(pkgs_dir):\n  File \"/usr/local/miniconda/lib/python2.7/site-packages/conda/lock.py\", line 60, in __enter__\n    os.makedirs(self.lock_path)\n  File \"/usr/local/miniconda/lib/python2.7/os.py\", line 157, in makedirs\n    mkdir(name, mode)\nOSError: [Errno 13] Permission denied: '/usr/local/miniconda/pkgs/.conda_lock-949'\n```\n\n`/usr/local/miniconda/` is a system-wide installation of miniconda, so obviously, users cannot create lock files there.\n\nP.S. I have a dream that updating conda software won't break things on every release...\n\n", "before_files": [{"content": "# (c) 2012-2013 Continuum Analytics, Inc. / http://continuum.io\n# All Rights Reserved\n#\n# conda is distributed under the terms of the BSD 3-clause license.\n# Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause.\n\n\"\"\"\nTools for working with locks\n\nA lock is just an empty directory. We use directories because this lets us use\nthe race condition-proof os.makedirs.\n\nFor now, there is one global lock for all of conda, because some things happen\nglobally (such as downloading packages).\n\nWe don't raise an error if the lock is named with the current PID\n\"\"\"\nfrom __future__ import absolute_import, division, print_function\n\nimport logging\nimport os\nimport time\n\nfrom .exceptions import LockError\n\nLOCKFN = '.conda_lock'\n\n\nstdoutlog = logging.getLogger('stdoutlog')\n\n\nclass Locked(object):\n    \"\"\"\n    Context manager to handle locks.\n    \"\"\"\n    def __init__(self, path, retries=10):\n        self.path = path\n        self.end = \"-\" + str(os.getpid())\n        self.lock_path = os.path.join(self.path, LOCKFN + self.end)\n        self.retries = retries\n\n    def __enter__(self):\n        # Keep the string \"LOCKERROR\" in this string so that external\n        # programs can look for it.\n        lockstr = (\"\"\"\\\n    LOCKERROR: It looks like conda is already doing something.\n    The lock %s was found. Wait for it to finish before continuing.\n    If you are sure that conda is not running, remove it and try again.\n    You can also use: $ conda clean --lock\\n\"\"\")\n        sleeptime = 1\n\n        for _ in range(self.retries):\n            if os.path.isdir(self.lock_path):\n                stdoutlog.info(lockstr % self.lock_path)\n                stdoutlog.info(\"Sleeping for %s seconds\\n\" % sleeptime)\n\n                time.sleep(sleeptime)\n                sleeptime *= 2\n            else:\n                os.makedirs(self.lock_path)\n                return self\n\n        stdoutlog.error(\"Exceeded max retries, giving up\")\n        raise LockError(lockstr % self.lock_path)\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        try:\n            os.rmdir(self.lock_path)\n            os.rmdir(self.path)\n        except OSError:\n            pass\n", "path": "conda/lock.py"}, {"content": "from __future__ import absolute_import, division, print_function\n\nclass CondaException(Exception):\n    pass\n\n\nclass InvalidInstruction(CondaException):\n    def __init__(self, instruction, *args, **kwargs):\n        msg = \"No handler for instruction: %r\" % instruction\n        super(InvalidInstruction, self).__init__(msg, *args, **kwargs)\n\nclass LockError(RuntimeError, CondaException):\n    pass\n", "path": "conda/exceptions.py"}, {"content": "\"\"\"\nFunctions related to core conda functionality that relates to manually\ninstalled Python packages, e.g. using \"python setup.py install\", or \"pip\".\n\"\"\"\nfrom __future__ import absolute_import, division, print_function\n\nfrom io import open\nimport os\nimport re\nimport sys\nfrom os.path import isdir, isfile, join\n\nfrom .compat import itervalues\nfrom .install import linked_data\nfrom .misc import rel_path\n\n\ndef get_site_packages_dir(installed_pkgs):\n    for info in itervalues(installed_pkgs):\n        if info['name'] == 'python':\n            if sys.platform == 'win32':\n                stdlib_dir = 'Lib'\n            else:\n                py_ver = info['version'][:3]\n                stdlib_dir = 'lib/python%s' % py_ver\n            return join(stdlib_dir, 'site-packages')\n    return None\n\n\ndef get_egg_info_files(sp_dir):\n    for fn in os.listdir(sp_dir):\n        if not fn.endswith(('.egg', '.egg-info', '.dist-info')):\n            continue\n        path = join(sp_dir, fn)\n        if isfile(path):\n            yield path\n        elif isdir(path):\n            for path2 in [join(path, 'PKG-INFO'),\n                          join(path, 'EGG-INFO', 'PKG-INFO'),\n                          join(path, 'METADATA')]:\n                if isfile(path2):\n                    yield path2\n\n\npat = re.compile(r'(\\w+):\\s*(\\S+)', re.I)\ndef parse_egg_info(path):\n    \"\"\"\n    Parse an .egg-info file and return its canonical distribution name\n    \"\"\"\n    info = {}\n    for line in open(path, encoding='utf-8'):\n        line = line.strip()\n        m = pat.match(line)\n        if m:\n            key = m.group(1).lower()\n            info[key] = m.group(2)\n        try:\n            return '%(name)s-%(version)s-<pip>' % info\n        except KeyError:\n            pass\n    return None\n\n\ndef get_egg_info(prefix, all_pkgs=False):\n    \"\"\"\n    Return a set of canonical names of all Python packages (in `prefix`),\n    by inspecting the .egg-info files inside site-packages.\n    By default, only untracked (not conda installed) .egg-info files are\n    considered.  Setting `all_pkgs` to True changes this.\n    \"\"\"\n    installed_pkgs = linked_data(prefix)\n    sp_dir = get_site_packages_dir(installed_pkgs)\n    if sp_dir is None:\n        return set()\n\n    conda_files = set()\n    for info in itervalues(installed_pkgs):\n        conda_files.update(info.get('files', []))\n\n    res = set()\n    for path in get_egg_info_files(join(prefix, sp_dir)):\n        f = rel_path(prefix, path)\n        if all_pkgs or f not in conda_files:\n            try:\n                dist = parse_egg_info(path)\n            except UnicodeDecodeError:\n                dist = None\n            if dist:\n                res.add(dist)\n    return res\n\n\nif __name__ == '__main__':\n    from pprint import pprint\n    pprint(get_egg_info(sys.prefix))\n", "path": "conda/egg_info.py"}], "after_files": [{"content": "# (c) 2012-2013 Continuum Analytics, Inc. / http://continuum.io\n# All Rights Reserved\n#\n# conda is distributed under the terms of the BSD 3-clause license.\n# Consult LICENSE.txt or http://opensource.org/licenses/BSD-3-Clause.\n\n\"\"\"\nTools for working with locks\n\nA lock is just an empty directory. We use directories because this lets us use\nthe race condition-proof os.makedirs.\n\nFor now, there is one global lock for all of conda, because some things happen\nglobally (such as downloading packages).\n\nWe don't raise an error if the lock is named with the current PID\n\"\"\"\nfrom __future__ import absolute_import, division, print_function\n\nimport os\nimport logging\nfrom os.path import join\nimport glob\nfrom time import sleep\n\nLOCKFN = '.conda_lock'\n\n\nstdoutlog = logging.getLogger('stdoutlog')\n\n\nclass Locked(object):\n    \"\"\"\n    Context manager to handle locks.\n    \"\"\"\n    def __init__(self, path):\n        self.path = path\n        self.end = \"-\" + str(os.getpid())\n        self.lock_path = join(self.path, LOCKFN + self.end)\n        self.pattern = join(self.path, LOCKFN + '-*')\n        self.remove = True\n\n    def __enter__(self):\n        retries = 10\n        # Keep the string \"LOCKERROR\" in this string so that external\n        # programs can look for it.\n        lockstr = (\"\"\"\\\n    LOCKERROR: It looks like conda is already doing something.\n    The lock %s was found. Wait for it to finish before continuing.\n    If you are sure that conda is not running, remove it and try again.\n    You can also use: $ conda clean --lock\\n\"\"\")\n        sleeptime = 1\n        files = None\n        while retries:\n            files = glob.glob(self.pattern)\n            if files and not files[0].endswith(self.end):\n                stdoutlog.info(lockstr % str(files))\n                stdoutlog.info(\"Sleeping for %s seconds\\n\" % sleeptime)\n                sleep(sleeptime)\n                sleeptime *= 2\n                retries -= 1\n            else:\n                break\n        else:\n            stdoutlog.error(\"Exceeded max retries, giving up\")\n            raise RuntimeError(lockstr % str(files))\n\n        if not files:\n            try:\n                os.makedirs(self.lock_path)\n            except OSError:\n                pass\n        else:  # PID lock already here --- someone else will remove it.\n            self.remove = False\n\n    def __exit__(self, exc_type, exc_value, traceback):\n        if self.remove:\n            for path in self.lock_path, self.path:\n                try:\n                    os.rmdir(path)\n                except OSError:\n                    pass\n", "path": "conda/lock.py"}, {"content": "from __future__ import absolute_import, division, print_function\n\nclass CondaException(Exception):\n    pass\n\n\nclass InvalidInstruction(CondaException):\n    def __init__(self, instruction, *args, **kwargs):\n        msg = \"No handler for instruction: %r\" % instruction\n        super(InvalidInstruction, self).__init__(msg, *args, **kwargs)\n", "path": "conda/exceptions.py"}, {"content": "\"\"\"\nFunctions related to core conda functionality that relates to manually\ninstalled Python packages, e.g. using \"python setup.py install\", or \"pip\".\n\"\"\"\nfrom __future__ import absolute_import, division, print_function\n\nfrom io import open\nimport os\nimport re\nimport sys\nfrom os.path import isdir, isfile, join\n\nfrom .compat import itervalues\nfrom .install import linked_data\nfrom .misc import rel_path\n\n\n\ndef get_site_packages_dir(installed_pkgs):\n    for info in itervalues(installed_pkgs):\n        if info['name'] == 'python':\n            if sys.platform == 'win32':\n                stdlib_dir = 'Lib'\n            else:\n                py_ver = info['version'][:3]\n                stdlib_dir = 'lib/python%s' % py_ver\n            return join(stdlib_dir, 'site-packages')\n    return None\n\n\ndef get_egg_info_files(sp_dir):\n    for fn in os.listdir(sp_dir):\n        if not fn.endswith(('.egg', '.egg-info', '.dist-info')):\n            continue\n        path = join(sp_dir, fn)\n        if isfile(path):\n            yield path\n        elif isdir(path):\n            for path2 in [join(path, 'PKG-INFO'),\n                          join(path, 'EGG-INFO', 'PKG-INFO'),\n                          join(path, 'METADATA')]:\n                if isfile(path2):\n                    yield path2\n\n\npat = re.compile(r'(\\w+):\\s*(\\S+)', re.I)\ndef parse_egg_info(path):\n    \"\"\"\n    Parse an .egg-info file and return its canonical distribution name\n    \"\"\"\n    info = {}\n    for line in open(path, encoding='utf-8'):\n        line = line.strip()\n        m = pat.match(line)\n        if m:\n            key = m.group(1).lower()\n            info[key] = m.group(2)\n        try:\n            return '%(name)s-%(version)s-<pip>' % info\n        except KeyError:\n            pass\n    return None\n\n\ndef get_egg_info(prefix, all_pkgs=False):\n    \"\"\"\n    Return a set of canonical names of all Python packages (in `prefix`),\n    by inspecting the .egg-info files inside site-packages.\n    By default, only untracked (not conda installed) .egg-info files are\n    considered.  Setting `all_pkgs` to True changes this.\n    \"\"\"\n    installed_pkgs = linked_data(prefix)\n    sp_dir = get_site_packages_dir(installed_pkgs)\n    if sp_dir is None:\n        return set()\n\n    conda_files = set()\n    for info in itervalues(installed_pkgs):\n        conda_files.update(info.get('files', []))\n\n    res = set()\n    for path in get_egg_info_files(join(prefix, sp_dir)):\n        f = rel_path(prefix, path)\n        if all_pkgs or f not in conda_files:\n            try:\n                dist = parse_egg_info(path)\n            except UnicodeDecodeError:\n                dist = None\n            if dist:\n                res.add(dist)\n    return res\n\n\nif __name__ == '__main__':\n    from pprint import pprint\n    pprint(get_egg_info(sys.prefix))\n", "path": "conda/egg_info.py"}]}