copy method

  1. @override
Future<void> copy(
  1. String sourceKey,
  2. String destKey
)
override

Copy an object, including its metadata.

Local: filesystem-level copy. Encrypted: re-encrypts when the destination resolves to a different encryption key. Remote: server- side CopyObject. The metadata travels with the body.

Implementation

@override
Future<void> copy(String sourceKey, String destKey) async {
  checkNotDisposed();
  final info = await _inner.head(sourceKey);
  if (info == null) throw FileNotFoundError(sourceKey);

  if (info.metadata[_metaEncrypted] != 'true') {
    // Not encrypted — simple copy
    return _inner.copy(sourceKey, destKey);
  }

  // Encrypted — re-encrypt with the destination key
  // This ensures cross-profile copies work correctly
  final sourceEncKey = await _keyResolver?.resolveKey(sourceKey);
  final destEncKey = await _keyResolver?.resolveKey(destKey);

  if (sourceEncKey == null && destEncKey == null) {
    // Locked copy — neither side resolves (e.g. a locked profile).
    // A byte copy keeps the object intact and still encrypted with its
    // original key: nothing is exposed, nothing is mis-keyed.
    return _inner.copy(sourceKey, destKey);
  }
  if (sourceEncKey == null || destEncKey == null) {
    // Exactly one side resolves. A byte copy here would stamp the
    // destination with ciphertext its own key can't decrypt (MAC
    // failures later, far from the cause); re-keying silently is worse.
    throw EncryptionKeyMissingError(
      sourceEncKey == null ? sourceKey : destKey,
    );
  }

  // Read-decrypt source → write-encrypt dest, carrying the user metadata
  // across. writeStream re-derives the internal _metaEncrypted/_metaOriginalSize
  // flags for the destination, so passing them straight through is harmless.
  final plainStream = readStream(sourceKey);
  await writeStream(
    destKey,
    plainStream,
    WriteOptions(
      encrypt: true,
      encryptionKey: destEncKey,
      contentType: info.contentType,
      metadata: info.metadata,
    ),
  );
}