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 
  4 import itertools
  5 import logging
  6 from itertools import chain
  7 
  8 from pants.core.target_types import ResourcesFieldSet, ResourcesGeneratorFieldSet
  9 from pants.core.util_rules import stripped_source_files
  10 from pants.core.util_rules.source_files import SourceFilesRequest
  11 from pants.core.util_rules.stripped_source_files import StrippedSourceFiles
  12 from pants.core.util_rules.system_binaries import ZipBinary
  13 from pants.engine.fs import Digest, MergeDigests
  14 from pants.engine.internals.selectors import MultiGet
  15 from pants.engine.process import Process, ProcessResult
  16 from pants.engine.rules import Get, collect_rules, rule
  17 from pants.engine.target import SourcesField
  18 from pants.engine.unions import UnionRule
  19 from pants.jvm import compile
  20 from pants.jvm.compile import (
  21     ClasspathDependenciesRequest,
  22     ClasspathEntry,
  23     ClasspathEntryRequest,
  24     ClasspathEntryRequests,
  25     CompileResult,
  26     FallibleClasspathEntries,
  27     FallibleClasspathEntry,
  28 )
  29 from pants.jvm.strip_jar.strip_jar import StripJarRequest
  30 from pants.jvm.subsystems import JvmSubsystem
  31 from pants.util.logging import LogLevel
  32 
  33 logger = logging.getLogger(__name__)
  34 
  35 
  36 class JvmResourcesRequest(ClasspathEntryRequest):
  37     field_sets = (
  38         ResourcesFieldSet,
  39         ResourcesGeneratorFieldSet,
  40     )
  41 
  42 
  43 @rule(desc="Assemble resources")
  44 async def assemble_resources_jar(
  45     zip: ZipBinary,
  46     jvm: JvmSubsystem,
  47     request: JvmResourcesRequest,
  48 ) -> FallibleClasspathEntry:
  49     # Request the component's direct dependency classpath, and additionally any prerequisite.
  50     # Filter out any dependencies that are generated by our current target so that each resource
  51     # only appears in a single input JAR.
  52     # NOTE: Generated dependencies will have the same dependencies as the current target, so we
  53     # don't need to inspect those dependencies.
  54     optional_prereq_request = [*((request.prerequisite,) if request.prerequisite else ())]
  55     fallibles = await MultiGet(
  56         Get(FallibleClasspathEntries, ClasspathEntryRequests(optional_prereq_request)),
  57         Get(FallibleClasspathEntries, ClasspathDependenciesRequest(request, ignore_generated=True)),
  58     )
  59     direct_dependency_classpath_entries = FallibleClasspathEntries(
  60         itertools.chain(*fallibles)
  61     ).if_all_succeeded()
  62 
  63     if direct_dependency_classpath_entries is None:
  64         return FallibleClasspathEntry(
  65             description=str(request.component),
  66             result=CompileResult.DEPENDENCY_FAILED,
  67             output=None,
  68             exit_code=1,
  69         )
  70 
  71     source_files = await Get(
  72         StrippedSourceFiles,
  73         SourceFilesRequest([tgt.get(SourcesField) for tgt in request.component.members]),
  74     )
  75 
  76     output_filename = f"{request.component.representative.address.path_safe_spec}.resources.jar"
  77     output_files = [output_filename]
  78 
  79     resources_jar_input_digest = source_files.snapshot.digest
  80     resources_jar_result = await Get(
  81         ProcessResult,
  82         Process(
  83             argv=[
  84                 zip.path,
  85                 output_filename,
  86                 *source_files.snapshot.files,
  87             ],
  88             description="Build resources JAR for {request.component}",
  89             input_digest=resources_jar_input_digest,
  90             output_files=output_files,
  91             level=LogLevel.DEBUG,
  92         ),
  93     )
  94 
  95     output_digest = resources_jar_result.output_digest
  96     if jvm.reproducible_jars:
  97         output_digest = await Get(Digest, StripJarRequest(output_digest, tuple(output_files)))
  98     cpe = ClasspathEntry(output_digest, output_files, [])
  99 
  100     merged_cpe_digest = await Get(
  101         Digest,
  102         MergeDigests(chain((cpe.digest,), (i.digest for i in direct_dependency_classpath_entries))),
  103     )
  104 
  105     merged_cpe = ClasspathEntry.merge(
  106         digest=merged_cpe_digest, entries=[cpe, *direct_dependency_classpath_entries]
  107     )
  108 
  109     return FallibleClasspathEntry(output_filename, CompileResult.SUCCEEDED, merged_cpe, 0)
  110 
  111 
  112 def rules():
  113     return [
  114         *collect_rules(),
  115         *compile.rules(),
  116         *stripped_source_files.rules(),
  117         UnionRule(ClasspathEntryRequest, JvmResourcesRequest),
  118     ]
  119
  [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
  @@ -4,6 +4,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
  @@ -76,6 +77,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,
  @@ -83,7 +91,7 @@
               argv=[
                   zip.path,
                   output_filename,
  -                *source_files.snapshot.files,
  +                *sorted(input_files),
               ],
               description="Build resources JAR for {request.component}",
               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@@ -4,6 +4,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@@ -76,6 +77,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@@ -83,7 +91,7 @@\n             argv=[\n                 zip.path,\n                 output_filename,\n-                *source_files.snapshot.files,\n+                *sorted(input_files),\n             ],\n             description=\"Build resources JAR for {request.component}\",\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).\n\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)\nfrom pants.jvm.strip_jar.strip_jar import StripJarRequest\nfrom pants.jvm.subsystems import JvmSubsystem\nfrom pants.util.logging import LogLevel\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    jvm: JvmSubsystem,\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 resources JAR for {request.component}\",\n            input_digest=resources_jar_input_digest,\n            output_files=output_files,\n            level=LogLevel.DEBUG,\n        ),\n    )\n\n    output_digest = resources_jar_result.output_digest\n    if jvm.reproducible_jars:\n        output_digest = await Get(Digest, StripJarRequest(output_digest, tuple(output_files)))\n    cpe = ClasspathEntry(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"}]}