List all provenance graph hashes the remote holds. This mirrors the `.change` sync model: the server advertises a flat inventory of content-addressed objects, the client computes the delta by presence (`has_provenance_graph`), and pulls missing objects by hash via [`download_provenance`](Self::download_provenance). Deliberately NOT a per-change relationship query ("which provenance explains chan
(&self)
| 397 | /// |
| 398 | /// Base32-encoded provenance graph hashes, one per line, in server order. |
| 399 | pub async fn get_provenance_list(&self) -> RemoteResult<Vec<String>> { |
| 400 | let url = format!("{}?provenance-list", self.base_url); |
| 401 | debug!("GET provenance-list: {}", url); |
| 402 | |
| 403 | let response = self |
| 404 | .client |
| 405 | .get(&url) |
| 406 | .send() |
| 407 | .await |
| 408 | .map_err(|e| RemoteError::connection_failed(&url, e))?; |
| 409 | |
| 410 | crate::check_min_version_header(response.headers()); |
| 411 | let status = response.status(); |
| 412 | |
| 413 | match status { |
| 414 | StatusCode::OK => { |
| 415 | let text = response |
| 416 | .text() |
| 417 | .await |
| 418 | .map_err(|e| RemoteError::connection_failed(&url, e))?; |
| 419 | Ok(text |
| 420 | .lines() |
| 421 | .map(str::trim) |
| 422 | .filter(|line| !line.is_empty()) |
| 423 | .map(|line| line.to_string()) |
| 424 | .collect()) |
| 425 | } |
| 426 | StatusCode::NOT_FOUND => Ok(Vec::new()), |
| 427 | StatusCode::UNAUTHORIZED | StatusCode::FORBIDDEN => { |
| 428 | let msg = response.text().await.unwrap_or_default(); |
| 429 | Err(RemoteError::auth_failed(&url, msg)) |
| 430 | } |
| 431 | _ => { |
| 432 | let msg = response.text().await.unwrap_or_default(); |
| 433 | Err(RemoteError::http(status.as_u16(), msg)) |
| 434 | } |
| 435 | } |
| 436 | } |
| 437 | |
| 438 | /// Download a provenance graph from the remote server. |
| 439 | /// |