MCPcopy Create free account
hub / github.com/atomicdotdev/atomic / upload_change_streamed

Method upload_change_streamed

atomic-remote/src/http/upload.rs:437–504  ·  view source on GitHub ↗

Upload a change file by streaming from disk. Uses reqwest's streaming body support to avoid loading the entire file into memory. The `Content-Length` header is set from file metadata so the server can validate the upload without buffering. # Arguments `hash` - The base32-encoded hash of the change. `view` - The target view name. `path` - Path to the `.change` file on disk. # Errors Returns a

(
        &self,
        hash: &str,
        view: &str,
        path: &std::path::Path,
    )

Source from the content-addressed store, hash-verified

435 /// Returns an error if the file can't be opened, the upload fails, or
436 /// the server rejects the change.
437 pub async fn upload_change_streamed(
438 &self,
439 hash: &str,
440 view: &str,
441 path: &std::path::Path,
442 ) -> RemoteResult<()> {
443 let url = format!("{}?insert={}&view={}", self.base_url, hash, view);
444 debug!("POST insert (streamed): {} from {:?}", url, path);
445
446 let file = tokio::fs::File::open(path).await.map_err(|e| {
447 RemoteError::other(format!("Failed to open change file {:?}: {}", path, e))
448 })?;
449
450 let file_size = file
451 .metadata()
452 .await
453 .map_err(|e| {
454 RemoteError::other(format!("Failed to read metadata for {:?}: {}", path, e))
455 })?
456 .len();
457
458 info!("Streaming upload of change {} ({} bytes)", hash, file_size);
459
460 let stream = ReaderStream::new(file);
461 let body = reqwest::Body::wrap_stream(stream);
462
463 let response = self
464 .client
465 .post(&url)
466 .header(CONTENT_TYPE, "application/octet-stream")
467 .header(CONTENT_LENGTH, file_size)
468 .body(body)
469 .send()
470 .await
471 .map_err(|e| RemoteError::connection_failed(&url, e))?;
472
473 crate::check_min_version_header(response.headers());
474 let status = response.status();
475
476 match status {
477 StatusCode::OK => {
478 debug!("Successfully streamed change {} from file", hash);
479 Ok(())
480 }
481 StatusCode::NOT_FOUND => Err(RemoteError::repo_not_found(&url)),
482 StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => {
483 let msg = response.text().await.unwrap_or_default();
484 Err(RemoteError::auth_failed(&url, msg))
485 }
486 StatusCode::BAD_REQUEST | StatusCode::INTERNAL_SERVER_ERROR => {
487 let msg = response.text().await.unwrap_or_default();
488 if msg.contains("missing") && msg.contains("dependenc") {
489 let hashes = extract_change_hashes(&msg);
490 if hashes.is_empty() {
491 Err(RemoteError::http(status.as_u16(), msg))
492 } else {
493 Err(RemoteError::missing_deps(hashes))
494 }

Callers 1

upload_change_fileMethod · 0.80

Calls 10

check_min_version_headerFunction · 0.85
extract_change_hashesFunction · 0.85
postMethod · 0.80
textMethod · 0.80
lenMethod · 0.45
metadataMethod · 0.45
headerMethod · 0.45
statusMethod · 0.45
containsMethod · 0.45
is_emptyMethod · 0.45

Tested by

no test coverage detected