We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
`venv create` no longer includes `--sources-directory` contents when all files are nested
It seems like there was a regression from 2.1.148 -> 2.1.149 with the behaviour of `venv create` with a `--pex-repository` that was created with `--sources-directory`: those sources aren't included in the final venv.

Reproducer:

```shell
cd $(mktemp -d)

# create our dummy file
mkdir -p source_files/foo
touch source_files/foo/bar.py # NB.1
# touch source_files/qux.py # NB.2

for version in v2.1.148 v2.1.149; do
    curl -s -L https://github.com/pantsbuild/pex/releases/download/$version/pex > pex-$version
    chmod +x pex-$version

    # NB.3
    ./pex-$version --output-file=repository-$version.pex --sources-directory=source_files

    # NB.4
    PEX_SCRIPT=pex3 ./pex-$version venv create --dest-dir=dest-$version --pex-repository=repository-$version.pex --layout=flat

    # what was included?
    tree dest-$version
done
```

Running that shows that the contents of the `dest-...` directory depends on the version, without the `bar.py` file when using v2.1.149, but should be the same:

```
dest-v2.1.148
└── foo
    └── bar.py

1 directory, 1 file
dest-v2.1.149

0 directories, 0 files
```

Ablative studies:

- uncommenting `NB.2` line (to have two files) passes ✅ (both versions have both `foo/bar.py` and `qux.py`)
- _replacing_ the `NB.1` with `NB.2` (to just `qux.py` at the top level) passes ✅ 
- _always_ using v2.1.148 on line `NB.3` (create the pex) and v2.1.149 on line `NB.4` (create the venv) passes ✅ 
- v2.1.149 for `NB.3` and v2.1.148 for `NB.4` fails ❌ 
- I think third-party dependencies work okay, but haven't confirmed in this reduced setting
- This reproduces without `--layout`, but the output is simpler with `--layout=flat`

(First observed in https://github.com/pantsbuild/pants/pull/20149.)

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `pex/util.py`
Content:
```
1 # Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).
2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
3 
4 from __future__ import absolute_import
5 
6 import contextlib
7 import hashlib
8 import importlib
9 import os
10 import shutil
11 import tempfile
12 from hashlib import sha1
13 from site import makepath  # type: ignore[attr-defined]
14 
15 from pex import hashing
16 from pex.common import is_pyc_dir, is_pyc_file, safe_mkdir, safe_mkdtemp
17 from pex.compatibility import (  # type: ignore[attr-defined]  # `exec_function` is defined dynamically
18     PY2,
19     exec_function,
20 )
21 from pex.orderedset import OrderedSet
22 from pex.typing import TYPE_CHECKING
23 
24 if TYPE_CHECKING:
25     from typing import IO, Any, Callable, Iterator, Optional, Text
26 
27     from pex.hashing import Hasher
28 
29 
30 class DistributionHelper(object):
31     # TODO(#584: This appears unused, but clients might still use it. We cannot remove until we
32     #  have a deprecation policy.
33     @classmethod
34     def access_zipped_assets(cls, static_module_name, static_path, dir_location=None):
35         # type: (str, str, Optional[str]) -> str
36         """Create a copy of static resource files as we can't serve them from within the pex file.
37 
38         :param static_module_name: Module name containing module to cache in a tempdir
39         :param static_path: Module name, for example 'serverset'
40         :param dir_location: create a new temporary directory inside, or None to have one created
41         :returns temp_dir: Temporary directory with the zipped assets inside
42         """
43         if dir_location is None:
44             temp_dir = safe_mkdtemp()
45         else:
46             temp_dir = dir_location
47 
48         module = importlib.import_module(static_module_name)
49         # N.B.: This handles namespace packages new and old.
50         paths = OrderedSet(os.path.realpath(d) for d in getattr(module, "__path__", []))
51         if module.__file__:
52             # And this handles old-style __init__.py packages.
53             paths.add(os.path.realpath(module.__file__))
54 
55         safe_mkdir(temp_dir)
56         for path in paths:
57             resource_dir = os.path.realpath(os.path.join(path, static_path))
58             if os.path.isdir(resource_dir):
59                 for root, dirs, files in os.walk(resource_dir):
60                     for d in dirs:
61                         safe_mkdir(
62                             os.path.join(
63                                 temp_dir, os.path.relpath(os.path.join(root, d), resource_dir)
64                             )
65                         )
66                     for f in files:
67                         src = os.path.join(root, f)
68                         shutil.copy(src, os.path.join(temp_dir, os.path.relpath(src, resource_dir)))
69         return temp_dir
70 
71 
72 class CacheHelper(object):
73     @classmethod
74     def hash(cls, path, digest=None, hasher=sha1):
75         # type: (Text, Optional[Hasher], Callable[[], Hasher]) -> str
76         """Return the digest of a single file in a memory-efficient manner."""
77         if digest is None:
78             digest = hasher()
79         hashing.file_hash(path, digest)
80         return digest.hexdigest()
81 
82     @classmethod
83     def pex_code_hash(cls, directory):
84         # type: (str) -> str
85         """Return a reproducible hash of the contents of a loose PEX; excluding all `.pyc` files."""
86         digest = hashlib.sha1()
87         hashing.dir_hash(
88             directory=directory,
89             digest=digest,
90             dir_filter=is_pyc_dir,
91             file_filter=lambda file_path: not is_pyc_file(file_path)
92             and not file_path.startswith("."),
93         )
94         return digest.hexdigest()
95 
96     @classmethod
97     def dir_hash(cls, directory, digest=None, hasher=sha1):
98         # type: (str, Optional[Hasher], Callable[[], Hasher]) -> str
99         """Return a reproducible hash of the contents of a directory; excluding all `.pyc` files."""
100         if digest is None:
101             digest = hasher()
102         hashing.dir_hash(
103             directory=directory,
104             digest=digest,
105             dir_filter=lambda d: not is_pyc_dir(d),
106             file_filter=lambda f: not is_pyc_file(f),
107         )
108         return digest.hexdigest()
109 
110     @classmethod
111     def zip_hash(
112         cls,
113         zip_path,  # type: str
114         relpath=None,  # type: Optional[str]
115     ):
116         # type: (...) -> str
117         """Return a reproducible hash of the contents of a zip; excluding all `.pyc` files."""
118         digest = hashlib.sha1()
119         hashing.zip_hash(
120             zip_path=zip_path,
121             digest=digest,
122             relpath=relpath,
123             dir_filter=lambda d: not is_pyc_dir(d),
124             file_filter=lambda f: not is_pyc_file(f),
125         )
126         return digest.hexdigest()
127 
128 
129 @contextlib.contextmanager
130 def named_temporary_file(**kwargs):
131     # type: (**Any) -> Iterator[IO]
132     """Due to a bug in python (https://bugs.python.org/issue14243), we need this to be able to use
133     the temporary file without deleting it."""
134     assert "delete" not in kwargs
135     kwargs["delete"] = False
136     fp = tempfile.NamedTemporaryFile(**kwargs)
137     try:
138         with fp:
139             yield fp
140     finally:
141         os.remove(fp.name)
142
```
--- 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/pex/util.py b/pex/util.py
--- a/pex/util.py
+++ b/pex/util.py
@@ -87,7 +87,7 @@
         hashing.dir_hash(
             directory=directory,
             digest=digest,
-            dir_filter=is_pyc_dir,
+            dir_filter=lambda d: not is_pyc_dir(d),
             file_filter=lambda file_path: not is_pyc_file(file_path)
             and not file_path.startswith("."),
         )

{"golden_diff": "diff --git a/pex/util.py b/pex/util.py\n--- a/pex/util.py\n+++ b/pex/util.py\n@@ -87,7 +87,7 @@\n         hashing.dir_hash(\n             directory=directory,\n             digest=digest,\n-            dir_filter=is_pyc_dir,\n+            dir_filter=lambda d: not is_pyc_dir(d),\n             file_filter=lambda file_path: not is_pyc_file(file_path)\n             and not file_path.startswith(\".\"),\n         )\n", "issue": "`venv create` no longer includes `--sources-directory` contents when all files are nested\nIt seems like there was a regression from 2.1.148 -> 2.1.149 with the behaviour of `venv create` with a `--pex-repository` that was created with `--sources-directory`: those sources aren't included in the final venv.\r\n\r\nReproducer:\r\n\r\n```shell\r\ncd $(mktemp -d)\r\n\r\n# create our dummy file\r\nmkdir -p source_files/foo\r\ntouch source_files/foo/bar.py # NB.1\r\n# touch source_files/qux.py # NB.2\r\n\r\nfor version in v2.1.148 v2.1.149; do\r\n    curl -s -L https://github.com/pantsbuild/pex/releases/download/$version/pex > pex-$version\r\n    chmod +x pex-$version\r\n\r\n    # NB.3\r\n    ./pex-$version --output-file=repository-$version.pex --sources-directory=source_files\r\n\r\n    # NB.4\r\n    PEX_SCRIPT=pex3 ./pex-$version venv create --dest-dir=dest-$version --pex-repository=repository-$version.pex --layout=flat\r\n\r\n    # what was included?\r\n    tree dest-$version\r\ndone\r\n```\r\n\r\nRunning that shows that the contents of the `dest-...` directory depends on the version, without the `bar.py` file when using v2.1.149, but should be the same:\r\n\r\n```\r\ndest-v2.1.148\r\n\u2514\u2500\u2500 foo\r\n    \u2514\u2500\u2500 bar.py\r\n\r\n1 directory, 1 file\r\ndest-v2.1.149\r\n\r\n0 directories, 0 files\r\n```\r\n\r\nAblative studies:\r\n\r\n- uncommenting `NB.2` line (to have two files) passes \u2705 (both versions have both `foo/bar.py` and `qux.py`)\r\n- _replacing_ the `NB.1` with `NB.2` (to just `qux.py` at the top level) passes \u2705 \r\n- _always_ using v2.1.148 on line `NB.3` (create the pex) and v2.1.149 on line `NB.4` (create the venv) passes \u2705 \r\n- v2.1.149 for `NB.3` and v2.1.148 for `NB.4` fails \u274c \r\n- I think third-party dependencies work okay, but haven't confirmed in this reduced setting\r\n- This reproduces without `--layout`, but the output is simpler with `--layout=flat`\r\n\r\n(First observed in https://github.com/pantsbuild/pants/pull/20149.)\n", "before_files": [{"content": "# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import\n\nimport contextlib\nimport hashlib\nimport importlib\nimport os\nimport shutil\nimport tempfile\nfrom hashlib import sha1\nfrom site import makepath  # type: ignore[attr-defined]\n\nfrom pex import hashing\nfrom pex.common import is_pyc_dir, is_pyc_file, safe_mkdir, safe_mkdtemp\nfrom pex.compatibility import (  # type: ignore[attr-defined]  # `exec_function` is defined dynamically\n    PY2,\n    exec_function,\n)\nfrom pex.orderedset import OrderedSet\nfrom pex.typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from typing import IO, Any, Callable, Iterator, Optional, Text\n\n    from pex.hashing import Hasher\n\n\nclass DistributionHelper(object):\n    # TODO(#584: This appears unused, but clients might still use it. We cannot remove until we\n    #  have a deprecation policy.\n    @classmethod\n    def access_zipped_assets(cls, static_module_name, static_path, dir_location=None):\n        # type: (str, str, Optional[str]) -> str\n        \"\"\"Create a copy of static resource files as we can't serve them from within the pex file.\n\n        :param static_module_name: Module name containing module to cache in a tempdir\n        :param static_path: Module name, for example 'serverset'\n        :param dir_location: create a new temporary directory inside, or None to have one created\n        :returns temp_dir: Temporary directory with the zipped assets inside\n        \"\"\"\n        if dir_location is None:\n            temp_dir = safe_mkdtemp()\n        else:\n            temp_dir = dir_location\n\n        module = importlib.import_module(static_module_name)\n        # N.B.: This handles namespace packages new and old.\n        paths = OrderedSet(os.path.realpath(d) for d in getattr(module, \"__path__\", []))\n        if module.__file__:\n            # And this handles old-style __init__.py packages.\n            paths.add(os.path.realpath(module.__file__))\n\n        safe_mkdir(temp_dir)\n        for path in paths:\n            resource_dir = os.path.realpath(os.path.join(path, static_path))\n            if os.path.isdir(resource_dir):\n                for root, dirs, files in os.walk(resource_dir):\n                    for d in dirs:\n                        safe_mkdir(\n                            os.path.join(\n                                temp_dir, os.path.relpath(os.path.join(root, d), resource_dir)\n                            )\n                        )\n                    for f in files:\n                        src = os.path.join(root, f)\n                        shutil.copy(src, os.path.join(temp_dir, os.path.relpath(src, resource_dir)))\n        return temp_dir\n\n\nclass CacheHelper(object):\n    @classmethod\n    def hash(cls, path, digest=None, hasher=sha1):\n        # type: (Text, Optional[Hasher], Callable[[], Hasher]) -> str\n        \"\"\"Return the digest of a single file in a memory-efficient manner.\"\"\"\n        if digest is None:\n            digest = hasher()\n        hashing.file_hash(path, digest)\n        return digest.hexdigest()\n\n    @classmethod\n    def pex_code_hash(cls, directory):\n        # type: (str) -> str\n        \"\"\"Return a reproducible hash of the contents of a loose PEX; excluding all `.pyc` files.\"\"\"\n        digest = hashlib.sha1()\n        hashing.dir_hash(\n            directory=directory,\n            digest=digest,\n            dir_filter=is_pyc_dir,\n            file_filter=lambda file_path: not is_pyc_file(file_path)\n            and not file_path.startswith(\".\"),\n        )\n        return digest.hexdigest()\n\n    @classmethod\n    def dir_hash(cls, directory, digest=None, hasher=sha1):\n        # type: (str, Optional[Hasher], Callable[[], Hasher]) -> str\n        \"\"\"Return a reproducible hash of the contents of a directory; excluding all `.pyc` files.\"\"\"\n        if digest is None:\n            digest = hasher()\n        hashing.dir_hash(\n            directory=directory,\n            digest=digest,\n            dir_filter=lambda d: not is_pyc_dir(d),\n            file_filter=lambda f: not is_pyc_file(f),\n        )\n        return digest.hexdigest()\n\n    @classmethod\n    def zip_hash(\n        cls,\n        zip_path,  # type: str\n        relpath=None,  # type: Optional[str]\n    ):\n        # type: (...) -> str\n        \"\"\"Return a reproducible hash of the contents of a zip; excluding all `.pyc` files.\"\"\"\n        digest = hashlib.sha1()\n        hashing.zip_hash(\n            zip_path=zip_path,\n            digest=digest,\n            relpath=relpath,\n            dir_filter=lambda d: not is_pyc_dir(d),\n            file_filter=lambda f: not is_pyc_file(f),\n        )\n        return digest.hexdigest()\n\n\n@contextlib.contextmanager\ndef named_temporary_file(**kwargs):\n    # type: (**Any) -> Iterator[IO]\n    \"\"\"Due to a bug in python (https://bugs.python.org/issue14243), we need this to be able to use\n    the temporary file without deleting it.\"\"\"\n    assert \"delete\" not in kwargs\n    kwargs[\"delete\"] = False\n    fp = tempfile.NamedTemporaryFile(**kwargs)\n    try:\n        with fp:\n            yield fp\n    finally:\n        os.remove(fp.name)\n", "path": "pex/util.py"}], "after_files": [{"content": "# Copyright 2014 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\n\nfrom __future__ import absolute_import\n\nimport contextlib\nimport hashlib\nimport importlib\nimport os\nimport shutil\nimport tempfile\nfrom hashlib import sha1\nfrom site import makepath  # type: ignore[attr-defined]\n\nfrom pex import hashing\nfrom pex.common import is_pyc_dir, is_pyc_file, safe_mkdir, safe_mkdtemp\nfrom pex.compatibility import (  # type: ignore[attr-defined]  # `exec_function` is defined dynamically\n    PY2,\n    exec_function,\n)\nfrom pex.orderedset import OrderedSet\nfrom pex.typing import TYPE_CHECKING\n\nif TYPE_CHECKING:\n    from typing import IO, Any, Callable, Iterator, Optional, Text\n\n    from pex.hashing import Hasher\n\n\nclass DistributionHelper(object):\n    # TODO(#584: This appears unused, but clients might still use it. We cannot remove until we\n    #  have a deprecation policy.\n    @classmethod\n    def access_zipped_assets(cls, static_module_name, static_path, dir_location=None):\n        # type: (str, str, Optional[str]) -> str\n        \"\"\"Create a copy of static resource files as we can't serve them from within the pex file.\n\n        :param static_module_name: Module name containing module to cache in a tempdir\n        :param static_path: Module name, for example 'serverset'\n        :param dir_location: create a new temporary directory inside, or None to have one created\n        :returns temp_dir: Temporary directory with the zipped assets inside\n        \"\"\"\n        if dir_location is None:\n            temp_dir = safe_mkdtemp()\n        else:\n            temp_dir = dir_location\n\n        module = importlib.import_module(static_module_name)\n        # N.B.: This handles namespace packages new and old.\n        paths = OrderedSet(os.path.realpath(d) for d in getattr(module, \"__path__\", []))\n        if module.__file__:\n            # And this handles old-style __init__.py packages.\n            paths.add(os.path.realpath(module.__file__))\n\n        safe_mkdir(temp_dir)\n        for path in paths:\n            resource_dir = os.path.realpath(os.path.join(path, static_path))\n            if os.path.isdir(resource_dir):\n                for root, dirs, files in os.walk(resource_dir):\n                    for d in dirs:\n                        safe_mkdir(\n                            os.path.join(\n                                temp_dir, os.path.relpath(os.path.join(root, d), resource_dir)\n                            )\n                        )\n                    for f in files:\n                        src = os.path.join(root, f)\n                        shutil.copy(src, os.path.join(temp_dir, os.path.relpath(src, resource_dir)))\n        return temp_dir\n\n\nclass CacheHelper(object):\n    @classmethod\n    def hash(cls, path, digest=None, hasher=sha1):\n        # type: (Text, Optional[Hasher], Callable[[], Hasher]) -> str\n        \"\"\"Return the digest of a single file in a memory-efficient manner.\"\"\"\n        if digest is None:\n            digest = hasher()\n        hashing.file_hash(path, digest)\n        return digest.hexdigest()\n\n    @classmethod\n    def pex_code_hash(cls, directory):\n        # type: (str) -> str\n        \"\"\"Return a reproducible hash of the contents of a loose PEX; excluding all `.pyc` files.\"\"\"\n        digest = hashlib.sha1()\n        hashing.dir_hash(\n            directory=directory,\n            digest=digest,\n            dir_filter=lambda d: not is_pyc_dir(d),\n            file_filter=lambda file_path: not is_pyc_file(file_path)\n            and not file_path.startswith(\".\"),\n        )\n        return digest.hexdigest()\n\n    @classmethod\n    def dir_hash(cls, directory, digest=None, hasher=sha1):\n        # type: (str, Optional[Hasher], Callable[[], Hasher]) -> str\n        \"\"\"Return a reproducible hash of the contents of a directory; excluding all `.pyc` files.\"\"\"\n        if digest is None:\n            digest = hasher()\n        hashing.dir_hash(\n            directory=directory,\n            digest=digest,\n            dir_filter=lambda d: not is_pyc_dir(d),\n            file_filter=lambda f: not is_pyc_file(f),\n        )\n        return digest.hexdigest()\n\n    @classmethod\n    def zip_hash(\n        cls,\n        zip_path,  # type: str\n        relpath=None,  # type: Optional[str]\n    ):\n        # type: (...) -> str\n        \"\"\"Return a reproducible hash of the contents of a zip; excluding all `.pyc` files.\"\"\"\n        digest = hashlib.sha1()\n        hashing.zip_hash(\n            zip_path=zip_path,\n            digest=digest,\n            relpath=relpath,\n            dir_filter=lambda d: not is_pyc_dir(d),\n            file_filter=lambda f: not is_pyc_file(f),\n        )\n        return digest.hexdigest()\n\n\n@contextlib.contextmanager\ndef named_temporary_file(**kwargs):\n    # type: (**Any) -> Iterator[IO]\n    \"\"\"Due to a bug in python (https://bugs.python.org/issue14243), we need this to be able to use\n    the temporary file without deleting it.\"\"\"\n    assert \"delete\" not in kwargs\n    kwargs[\"delete\"] = False\n    fp = tempfile.NamedTemporaryFile(**kwargs)\n    try:\n        with fp:\n            yield fp\n    finally:\n        os.remove(fp.name)\n", "path": "pex/util.py"}]}