public function canAcquireLeaseOnResource(DrydockBlueprint $blueprint, DrydockResource $resource, DrydockLease $lease)
 {
     // Don't hand out leases on working copies which have not activated, since
     // it may take an arbitrarily long time for them to acquire a host.
     if (!$resource->isActive()) {
         return false;
     }
     $need_map = $lease->getAttribute('repositories.map');
     if (!is_array($need_map)) {
         return false;
     }
     $have_map = $resource->getAttribute('repositories.map');
     if (!is_array($have_map)) {
         return false;
     }
     $have_as = ipull($have_map, 'phid');
     $need_as = ipull($need_map, 'phid');
     foreach ($need_as as $need_directory => $need_phid) {
         if (empty($have_as[$need_directory])) {
             // This resource is missing a required working copy.
             return false;
         }
         if ($have_as[$need_directory] != $need_phid) {
             // This resource has a required working copy, but it contains
             // the wrong repository.
             return false;
         }
         unset($have_as[$need_directory]);
     }
     if ($have_as && $lease->getAttribute('repositories.strict')) {
         // This resource has extra repositories, but the lease is strict about
         // which repositories are allowed to exist.
         return false;
     }
     if (!DrydockSlotLock::isLockFree($this->getLeaseSlotLock($resource))) {
         return false;
     }
     return true;
 }