Skip to content

Commit e3c4140

Browse files
authored
Merge pull request #14391 from lovesegfault/nix-s3-complete-multipart
feat(libstore/s3-binary-cache-store): implement `completeMultipartUpload()`
2 parents 00f4a86 + c77317b commit e3c4140

File tree

1 file changed

+42
-0
lines changed

1 file changed

+42
-0
lines changed

src/libstore/s3-binary-cache-store.cc

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
#include <cassert>
66
#include <ranges>
77
#include <regex>
8+
#include <span>
89

910
namespace nix {
1011

@@ -46,6 +47,19 @@ class S3BinaryCacheStore : public virtual HttpBinaryCacheStore
4647
*/
4748
std::string uploadPart(std::string_view key, std::string_view uploadId, uint64_t partNumber, std::string data);
4849

50+
struct UploadedPart
51+
{
52+
uint64_t partNumber;
53+
std::string etag;
54+
};
55+
56+
/**
57+
* Completes a multipart upload by combining all uploaded parts.
58+
* @see
59+
* https://docs.aws.amazon.com/AmazonS3/latest/API/API_CompleteMultipartUpload.html#API_CompleteMultipartUpload_RequestSyntax
60+
*/
61+
void completeMultipartUpload(std::string_view key, std::string_view uploadId, std::span<const UploadedPart> parts);
62+
4963
/**
5064
* Abort a multipart upload
5165
*
@@ -133,6 +147,34 @@ void S3BinaryCacheStore::abortMultipartUpload(std::string_view key, std::string_
133147
getFileTransfer()->enqueueFileTransfer(req).get();
134148
}
135149

150+
void S3BinaryCacheStore::completeMultipartUpload(
151+
std::string_view key, std::string_view uploadId, std::span<const UploadedPart> parts)
152+
{
153+
auto req = makeRequest(key);
154+
req.setupForS3();
155+
156+
auto url = req.uri.parsed();
157+
url.query["uploadId"] = uploadId;
158+
req.uri = VerbatimURL(url);
159+
req.method = HttpMethod::POST;
160+
161+
std::string xml = "<CompleteMultipartUpload>";
162+
for (const auto & part : parts) {
163+
xml += "<Part>";
164+
xml += "<PartNumber>" + std::to_string(part.partNumber) + "</PartNumber>";
165+
xml += "<ETag>" + part.etag + "</ETag>";
166+
xml += "</Part>";
167+
}
168+
xml += "</CompleteMultipartUpload>";
169+
170+
debug("S3 CompleteMultipartUpload XML (%d parts): %s", parts.size(), xml);
171+
172+
req.data = xml;
173+
req.mimeType = "text/xml";
174+
175+
getFileTransfer()->enqueueFileTransfer(req).get();
176+
}
177+
136178
StringSet S3BinaryCacheStoreConfig::uriSchemes()
137179
{
138180
return {"s3"};

0 commit comments

Comments
 (0)