prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Not able to load resources when using pants vs sbt
  **Describe the bug**
  When using sbt we are able to call `Thread.currentThread().getContextClassLoader().getResources` and get a list of URLs. When using pants the list is empty. 
  
  This at the moment limits us from using Flyway with pants.
  
  **Pants version**
  2.13.0a1 and main.
  
  **OS**
  MacOS
  
  **Additional info**
  Example repo to reproduce the issue:
  https://github.com/somdoron/test-pants-resources
  
  I think the issue is, that pants only compress files in the resources zip file and not the directories.
  
  </issue>
  <code>
  [start of src/python/pants/jvm/resources.py]
  1 # Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).
  2 # Licensed under the Apache License, Version 2.0 (see LICENSE).
  3 import itertools
  4 import logging
  5 from itertools import chain
  6 
  7 from pants.core.target_types import ResourcesFieldSet, ResourcesGeneratorFieldSet
  8 from pants.core.util_rules import stripped_source_files
  9 from pants.core.util_rules.source_files import SourceFilesRequest
  10 from pants.core.util_rules.stripped_source_files import StrippedSourceFiles
  11 from pants.core.util_rules.system_binaries import ZipBinary
  12 from pants.engine.fs import Digest, MergeDigests
  13 from pants.engine.internals.selectors import MultiGet
  14 from pants.engine.process import Process, ProcessResult
  15 from pants.engine.rules import Get, collect_rules, rule
  16 from pants.engine.target import SourcesField
  17 from pants.engine.unions import UnionRule
  18 from pants.jvm import compile
  19 from pants.jvm.compile import (
  20     ClasspathDependenciesRequest,
  21     ClasspathEntry,
  22     ClasspathEntryRequest,
  23     ClasspathEntryRequests,
  24     CompileResult,
  25     FallibleClasspathEntries,
  26     FallibleClasspathEntry,
  27 )
  28 
  29 logger = logging.getLogger(__name__)
  30 
  31 
  32 class JvmResourcesRequest(ClasspathEntryRequest):
  33     field_sets = (
  34         ResourcesFieldSet,
  35         ResourcesGeneratorFieldSet,
  36     )
  37 
  38 
  39 @rule(desc="Assemble resources")
  40 async def assemble_resources_jar(
  41     zip: ZipBinary,
  42     request: JvmResourcesRequest,
  43 ) -> FallibleClasspathEntry:
  44     # Request the component's direct dependency classpath, and additionally any prerequisite.
  45     # Filter out any dependencies that are generated by our current target so that each resource
  46     # only appears in a single input JAR.
  47     # NOTE: Generated dependencies will have the same dependencies as the current target, so we
  48     # don't need to inspect those dependencies.
  49     optional_prereq_request = [*((request.prerequisite,) if request.prerequisite else ())]
  50     fallibles = await MultiGet(
  51         Get(FallibleClasspathEntries, ClasspathEntryRequests(optional_prereq_request)),
  52         Get(FallibleClasspathEntries, ClasspathDependenciesRequest(request, ignore_generated=True)),
  53     )
  54     direct_dependency_classpath_entries = FallibleClasspathEntries(
  55         itertools.chain(*fallibles)
  56     ).if_all_succeeded()
  57 
  58     if direct_dependency_classpath_entries is None:
  59         return FallibleClasspathEntry(
  60             description=str(request.component),
  61             result=CompileResult.DEPENDENCY_FAILED,
  62             output=None,
  63             exit_code=1,
  64         )
  65 
  66     source_files = await Get(
  67         StrippedSourceFiles,
  68         SourceFilesRequest([tgt.get(SourcesField) for tgt in request.component.members]),
  69     )
  70 
  71     output_filename = f"{request.component.representative.address.path_safe_spec}.resources.jar"
  72     output_files = [output_filename]
  73 
  74     resources_jar_input_digest = source_files.snapshot.digest
  75     resources_jar_result = await Get(
  76         ProcessResult,
  77         Process(
  78             argv=[
  79                 zip.path,
  80                 output_filename,
  81                 *source_files.snapshot.files,
  82             ],
  83             description="Build partial JAR containing resources files",
  84             input_digest=resources_jar_input_digest,
  85             output_files=output_files,
  86         ),
  87     )
  88 
  89     cpe = ClasspathEntry(resources_jar_result.output_digest, output_files, [])
  90 
  91     merged_cpe_digest = await Get(
  92         Digest,
  93         MergeDigests(chain((cpe.digest,), (i.digest for i in direct_dependency_classpath_entries))),
  94     )
  95 
  96     merged_cpe = ClasspathEntry.merge(
  97         digest=merged_cpe_digest, entries=[cpe, *direct_dependency_classpath_entries]
  98     )
  99 
  100     return FallibleClasspathEntry(output_filename, CompileResult.SUCCEEDED, merged_cpe, 0)
  101 
  102 
  103 def rules():
  104     return [
  105         *collect_rules(),
  106         *compile.rules(),
  107         *stripped_source_files.rules(),
  108         UnionRule(ClasspathEntryRequest, JvmResourcesRequest),
  109     ]
  110
  [end of src/python/pants/jvm/resources.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/src/python/pants/jvm/resources.py b/src/python/pants/jvm/resources.py
  --- a/src/python/pants/jvm/resources.py
  +++ b/src/python/pants/jvm/resources.py
  @@ -3,6 +3,7 @@
   import itertools
   import logging
   from itertools import chain
  +from pathlib import Path
   
   from pants.core.target_types import ResourcesFieldSet, ResourcesGeneratorFieldSet
   from pants.core.util_rules import stripped_source_files
  @@ -71,6 +72,13 @@
       output_filename = f"{request.component.representative.address.path_safe_spec}.resources.jar"
       output_files = [output_filename]
   
  +    # #16231: Valid JAR files need the directories of each resource file as well as the files
  +    # themselves.
  +
  +    paths = {Path(filename) for filename in source_files.snapshot.files}
  +    directories = {parent for path in paths for parent in path.parents}
  +    input_files = {str(path) for path in chain(paths, directories)}
  +
       resources_jar_input_digest = source_files.snapshot.digest
       resources_jar_result = await Get(
           ProcessResult,
  @@ -78,7 +86,7 @@
               argv=[
                   zip.path,
                   output_filename,
  -                *source_files.snapshot.files,
  +                *sorted(input_files),
               ],
               description="Build partial JAR containing resources files",
               input_digest=resources_jar_input_digest,
  
verification_info: {"golden_diff": "diff --git a/src/python/pants/jvm/resources.py b/src/python/pants/jvm/resources.py\n--- a/src/python/pants/jvm/resources.py\n+++ b/src/python/pants/jvm/resources.py\n@@ -3,6 +3,7 @@\n import itertools\n import logging\n from itertools import chain\n+from pathlib import Path\n \n from pants.core.target_types import ResourcesFieldSet, ResourcesGeneratorFieldSet\n from pants.core.util_rules import stripped_source_files\n@@ -71,6 +72,13 @@\n     output_filename = f\"{request.component.representative.address.path_safe_spec}.resources.jar\"\n     output_files = [output_filename]\n \n+    # #16231: Valid JAR files need the directories of each resource file as well as the files\n+    # themselves.\n+\n+    paths = {Path(filename) for filename in source_files.snapshot.files}\n+    directories = {parent for path in paths for parent in path.parents}\n+    input_files = {str(path) for path in chain(paths, directories)}\n+\n     resources_jar_input_digest = source_files.snapshot.digest\n     resources_jar_result = await Get(\n         ProcessResult,\n@@ -78,7 +86,7 @@\n             argv=[\n                 zip.path,\n                 output_filename,\n-                *source_files.snapshot.files,\n+                *sorted(input_files),\n             ],\n             description=\"Build partial JAR containing resources files\",\n             input_digest=resources_jar_input_digest,\n", "issue": "Not able to load resources when using pants vs sbt\n**Describe the bug**\r\nWhen using sbt we are able to call `Thread.currentThread().getContextClassLoader().getResources` and get a list of URLs. When using pants the list is empty. \r\n\r\nThis at the moment limits us from using Flyway with pants.\r\n\r\n**Pants version**\r\n2.13.0a1 and main.\r\n\r\n**OS**\r\nMacOS\r\n\r\n**Additional info**\r\nExample repo to reproduce the issue:\r\nhttps://github.com/somdoron/test-pants-resources\r\n\r\nI think the issue is, that pants only compress files in the resources zip file and not the directories.\n", "before_files": [{"content": "# Copyright 2021 Pants project contributors (see CONTRIBUTORS.md).\n# Licensed under the Apache License, Version 2.0 (see LICENSE).\nimport itertools\nimport logging\nfrom itertools import chain\n\nfrom pants.core.target_types import ResourcesFieldSet, ResourcesGeneratorFieldSet\nfrom pants.core.util_rules import stripped_source_files\nfrom pants.core.util_rules.source_files import SourceFilesRequest\nfrom pants.core.util_rules.stripped_source_files import StrippedSourceFiles\nfrom pants.core.util_rules.system_binaries import ZipBinary\nfrom pants.engine.fs import Digest, MergeDigests\nfrom pants.engine.internals.selectors import MultiGet\nfrom pants.engine.process import Process, ProcessResult\nfrom pants.engine.rules import Get, collect_rules, rule\nfrom pants.engine.target import SourcesField\nfrom pants.engine.unions import UnionRule\nfrom pants.jvm import compile\nfrom pants.jvm.compile import (\n    ClasspathDependenciesRequest,\n    ClasspathEntry,\n    ClasspathEntryRequest,\n    ClasspathEntryRequests,\n    CompileResult,\n    FallibleClasspathEntries,\n    FallibleClasspathEntry,\n)\n\nlogger = logging.getLogger(__name__)\n\n\nclass JvmResourcesRequest(ClasspathEntryRequest):\n    field_sets = (\n        ResourcesFieldSet,\n        ResourcesGeneratorFieldSet,\n    )\n\n\n@rule(desc=\"Assemble resources\")\nasync def assemble_resources_jar(\n    zip: ZipBinary,\n    request: JvmResourcesRequest,\n) -> FallibleClasspathEntry:\n    # Request the component's direct dependency classpath, and additionally any prerequisite.\n    # Filter out any dependencies that are generated by our current target so that each resource\n    # only appears in a single input JAR.\n    # NOTE: Generated dependencies will have the same dependencies as the current target, so we\n    # don't need to inspect those dependencies.\n    optional_prereq_request = [*((request.prerequisite,) if request.prerequisite else ())]\n    fallibles = await MultiGet(\n        Get(FallibleClasspathEntries, ClasspathEntryRequests(optional_prereq_request)),\n        Get(FallibleClasspathEntries, ClasspathDependenciesRequest(request, ignore_generated=True)),\n    )\n    direct_dependency_classpath_entries = FallibleClasspathEntries(\n        itertools.chain(*fallibles)\n    ).if_all_succeeded()\n\n    if direct_dependency_classpath_entries is None:\n        return FallibleClasspathEntry(\n            description=str(request.component),\n            result=CompileResult.DEPENDENCY_FAILED,\n            output=None,\n            exit_code=1,\n        )\n\n    source_files = await Get(\n        StrippedSourceFiles,\n        SourceFilesRequest([tgt.get(SourcesField) for tgt in request.component.members]),\n    )\n\n    output_filename = f\"{request.component.representative.address.path_safe_spec}.resources.jar\"\n    output_files = [output_filename]\n\n    resources_jar_input_digest = source_files.snapshot.digest\n    resources_jar_result = await Get(\n        ProcessResult,\n        Process(\n            argv=[\n                zip.path,\n                output_filename,\n                *source_files.snapshot.files,\n            ],\n            description=\"Build partial JAR containing resources files\",\n            input_digest=resources_jar_input_digest,\n            output_files=output_files,\n        ),\n    )\n\n    cpe = ClasspathEntry(resources_jar_result.output_digest, output_files, [])\n\n    merged_cpe_digest = await Get(\n        Digest,\n        MergeDigests(chain((cpe.digest,), (i.digest for i in direct_dependency_classpath_entries))),\n    )\n\n    merged_cpe = ClasspathEntry.merge(\n        digest=merged_cpe_digest, entries=[cpe, *direct_dependency_classpath_entries]\n    )\n\n    return FallibleClasspathEntry(output_filename, CompileResult.SUCCEEDED, merged_cpe, 0)\n\n\ndef rules():\n    return [\n        *collect_rules(),\n        *compile.rules(),\n        *stripped_source_files.rules(),\n        UnionRule(ClasspathEntryRequest, JvmResourcesRequest),\n    ]\n", "path": "src/python/pants/jvm/resources.py"}]}