# Copyright 2019 Pants project contributors (see CONTRIBUTORS.md).
# Licensed under the Apache License, Version 2.0 (see LICENSE).

from dataclasses import dataclass

from pants.build_graph.address import Address
from pants.engine.addressable import BuildFileAddresses
from pants.engine.console import Console
from pants.engine.fs import Digest, DirectoryToMaterialize, Workspace
from pants.engine.goal import Goal, LineOriented
from pants.engine.legacy.graph import HydratedTarget
from pants.engine.rules import console_rule, rule, union
from pants.engine.selectors import Get, MultiGet


@dataclass(frozen=True)
class Binary(LineOriented, Goal):
  """Create a runnable binary."""
  name = 'binary'


@union
class BinaryTarget:
  pass


@union
@dataclass(frozen=True)
class CreatedBinary:
  digest: Digest
  binary_name: str


@console_rule
async def create_binary(addresses: BuildFileAddresses, console: Console, workspace: Workspace, options: Binary.Options) -> Binary:
  with Binary.line_oriented(options, console) as print_stdout:
    print_stdout("Generating binaries in `dist/`")
    binaries = await MultiGet(Get(CreatedBinary, Address, address.to_address()) for address in addresses)
    dirs_to_materialize = tuple(
      DirectoryToMaterialize(binary.digest, path_prefix='dist/') for binary in binaries
    )
    results = workspace.materialize_directories(dirs_to_materialize)
    for result in results.dependencies:
      for path in result.output_paths:
        print_stdout(f"Wrote {path}")
  return Binary(exit_code=0)


@rule
async def coordinator_of_binaries(target: HydratedTarget) -> CreatedBinary:
  binary = await Get(CreatedBinary, BinaryTarget, target.adaptor)
  return binary


def rules():
  return [
    create_binary,
    coordinator_of_binaries,
  ]

@@ -338,16 +338,36 @@
  Digest,
+ DirectoriesToMerge,
  Directo
@@ -879,16 +879,19 @@
 _binary(
+%0A  
 addresse
@@ -976,16 +976,17 @@
 .Options
+%0A
 ) -%3E Bin
@@ -1137,17 +1137,17 @@
 iGet(Get
-(
+%5B
 CreatedB
@@ -1151,18 +1151,18 @@
 edBinary
-, 
+%5D(
 Address,
@@ -1218,101 +1218,87 @@
     
-dirs_to_materialize = tuple(%0A      DirectoryToMaterialize(binary.digest, path_prefix='dist/')
+merged_digest = await Get%5BDigest%5D(%0A      DirectoriesToMerge(tuple(binary.digest
  for
@@ -1316,16 +1316,18 @@
 binaries
+))
 %0A    )%0A 
@@ -1335,17 +1335,16 @@
   result
-s
  = works
@@ -1372,75 +1372,82 @@
 ctor
-ies(dirs_to_materialize)%0A    for result in results.dependencies:%0A  
+y(%0A      DirectoryToMaterialize(merged_digest, path_prefix=%22dist/%22)%0A    )%0A
     
@@ -1479,18 +1479,16 @@
 _paths:%0A
-  
       pr
@@ -1648,17 +1648,17 @@
 wait Get
-(
+%5B
 CreatedB
@@ -1662,18 +1662,18 @@
 edBinary
-, 
+%5D(
 BinaryTa

Fix V2 binary to work with multiple targets (#8781)