public function promise()
    {
        return \GuzzleHttp\Promise\coroutine(function () {
            $objectStats = (yield $this->client->executeAsync(
                $this->client->getCommand('HeadObject', $this->source)
            ));

            if ($objectStats['ContentLength'] > $this->options['mup_threshold']) {
                $mup = new MultipartCopy(
                    $this->client,
                    $this->getSourcePath(),
                    ['source_metadata' => $objectStats, 'acl' => $this->acl]
                        + $this->destination
                        + $this->options
                );

                yield $mup->promise();
            } else {
                $defaults = [
                    'ACL' => $this->acl,
                    'MetadataDirective' => 'COPY',
                    'CopySource' => $this->getSourcePath(),
                ];

                $params = array_diff_key($this->options, self::$defaults)
                    + $this->destination + $defaults + $this->options['params'];

                yield $this->client->executeAsync(
                    $this->client->getCommand('CopyObject', $params)
                );
            }
        });
    }