|
13 | 13 | use std::ops::{Bound, RangeBounds};
|
14 | 14 |
|
15 | 15 | use anyhow::Result;
|
16 |
| -use futures_lite::{Stream, StreamExt}; |
| 16 | +use futures_lite::{io, Stream, StreamExt}; |
17 | 17 | use quic_rpc::{client::BoxedConnector, Connector, RpcClient};
|
18 | 18 | use serde::{Deserialize, Serialize};
|
19 | 19 |
|
@@ -221,6 +221,20 @@ where
|
221 | 221 | stream.next().await.transpose()
|
222 | 222 | }
|
223 | 223 |
|
| 224 | + /// Rename a tag |
| 225 | + /// |
| 226 | + /// This is done in steps, so it is not atomic! |
| 227 | + pub async fn rename(&self, from: impl AsRef<[u8]>, to: impl AsRef<[u8]>) -> Result<()> { |
| 228 | + let from = from.as_ref(); |
| 229 | + let to = to.as_ref(); |
| 230 | + let Some(old) = self.get(from.as_ref()).await? else { |
| 231 | + return Err(io::Error::new(io::ErrorKind::NotFound, "Tag not found").into()); |
| 232 | + }; |
| 233 | + self.set(to.as_ref(), old.hash_and_format()).await?; |
| 234 | + self.delete(from.as_ref()).await?; |
| 235 | + Ok(()) |
| 236 | + } |
| 237 | + |
224 | 238 | /// List a range of tags
|
225 | 239 | pub async fn list_range<R, E>(&self, range: R) -> Result<impl Stream<Item = Result<TagInfo>>>
|
226 | 240 | where
|
@@ -287,3 +301,13 @@ pub struct TagInfo {
|
287 | 301 | /// Hash of the data
|
288 | 302 | pub hash: Hash,
|
289 | 303 | }
|
| 304 | + |
| 305 | +impl TagInfo { |
| 306 | + /// Get the hash and format of the tag. |
| 307 | + pub fn hash_and_format(&self) -> HashAndFormat { |
| 308 | + HashAndFormat { |
| 309 | + hash: self.hash, |
| 310 | + format: self.format, |
| 311 | + } |
| 312 | + } |
| 313 | +} |
0 commit comments