@@ -1035,19 +1035,22 @@ pub trait ObjectStore: std::fmt::Display + Send + Sync + Debug + 'static {
10351035 ///
10361036 /// By default, this is implemented as a copy and then delete source. It may not
10371037 /// check when deleting source that it was the same object that was originally copied.
1038- ///
1039- /// If there exists an object at the destination, it will be overwritten.
1040- async fn rename ( & self , from : & Path , to : & Path ) -> Result < ( ) > {
1041- self . copy ( from, to) . await ?;
1042- self . delete ( from) . await
1043- }
1044-
1045- /// Move an object from one path to another in the same object store.
1046- ///
1047- /// Will return an error if the destination already has an object.
1048- async fn rename_if_not_exists ( & self , from : & Path , to : & Path ) -> Result < ( ) > {
1049- self . copy_if_not_exists ( from, to) . await ?;
1050- self . delete ( from) . await
1038+ async fn rename_opts ( & self , from : & Path , to : & Path , options : RenameOptions ) -> Result < ( ) > {
1039+ let RenameOptions {
1040+ target_mode,
1041+ extensions,
1042+ } = options;
1043+ let copy_mode = match target_mode {
1044+ RenameTargetMode :: Overwrite => CopyMode :: Overwrite ,
1045+ RenameTargetMode :: Create => CopyMode :: Create ,
1046+ } ;
1047+ let copy_options = CopyOptions {
1048+ mode : copy_mode,
1049+ extensions,
1050+ } ;
1051+ self . copy_opts ( from, to, copy_options) . await ?;
1052+ self . delete ( from) . await ?;
1053+ Ok ( ( ) )
10511054 }
10521055}
10531056
@@ -1116,12 +1119,13 @@ macro_rules! as_ref_impl {
11161119 self . as_ref( ) . copy_opts( from, to, options) . await
11171120 }
11181121
1119- async fn rename( & self , from: & Path , to: & Path ) -> Result <( ) > {
1120- self . as_ref( ) . rename( from, to) . await
1121- }
1122-
1123- async fn rename_if_not_exists( & self , from: & Path , to: & Path ) -> Result <( ) > {
1124- self . as_ref( ) . rename_if_not_exists( from, to) . await
1122+ async fn rename_opts(
1123+ & self ,
1124+ from: & Path ,
1125+ to: & Path ,
1126+ options: RenameOptions ,
1127+ ) -> Result <( ) > {
1128+ self . as_ref( ) . rename_opts( from, to, options) . await
11251129 }
11261130 }
11271131 } ;
@@ -1238,6 +1242,19 @@ pub trait ObjectStoreExt: ObjectStore {
12381242 /// If atomic operations are not supported by the underlying object storage (like S3)
12391243 /// it will return an error.
12401244 fn copy_if_not_exists ( & self , from : & Path , to : & Path ) -> impl Future < Output = Result < ( ) > > ;
1245+
1246+ /// Move an object from one path to another in the same object store.
1247+ ///
1248+ /// By default, this is implemented as a copy and then delete source. It may not
1249+ /// check when deleting source that it was the same object that was originally copied.
1250+ ///
1251+ /// If there exists an object at the destination, it will be overwritten.
1252+ fn rename ( & self , from : & Path , to : & Path ) -> impl Future < Output = Result < ( ) > > ;
1253+
1254+ /// Move an object from one path to another in the same object store.
1255+ ///
1256+ /// Will return an error if the destination already has an object.
1257+ fn rename_if_not_exists ( & self , from : & Path , to : & Path ) -> impl Future < Output = Result < ( ) > > ;
12411258}
12421259
12431260impl < T > ObjectStoreExt for T
@@ -1277,6 +1294,16 @@ where
12771294 let options = CopyOptions :: new ( ) . with_mode ( CopyMode :: Create ) ;
12781295 self . copy_opts ( from, to, options) . await
12791296 }
1297+
1298+ async fn rename ( & self , from : & Path , to : & Path ) -> Result < ( ) > {
1299+ let options = RenameOptions :: new ( ) . with_target_mode ( RenameTargetMode :: Overwrite ) ;
1300+ self . rename_opts ( from, to, options) . await
1301+ }
1302+
1303+ async fn rename_if_not_exists ( & self , from : & Path , to : & Path ) -> Result < ( ) > {
1304+ let options = RenameOptions :: new ( ) . with_target_mode ( RenameTargetMode :: Create ) ;
1305+ self . rename_opts ( from, to, options) . await
1306+ }
12801307}
12811308
12821309/// Result of a list call that includes objects, prefixes (directories) and a
@@ -1828,6 +1855,76 @@ impl PartialEq<Self> for CopyOptions {
18281855
18291856impl Eq for CopyOptions { }
18301857
1858+ /// Configure preconditions for the target of rename operation.
1859+ ///
1860+ /// Note though that the source location may or not be deleted at the same time in an atomic operation. There is
1861+ /// currently NO flag to control the atomicity of "delete source at the same time as creating the target".
1862+ #[ derive( Debug , Clone , Copy , PartialEq , Eq , Default ) ]
1863+ pub enum RenameTargetMode {
1864+ /// Perform a write operation on the target, overwriting any object present at the provided path.
1865+ #[ default]
1866+ Overwrite ,
1867+ /// Perform an atomic write operation of the target, returning [`Error::AlreadyExists`] if an
1868+ /// object already exists at the provided path.
1869+ Create ,
1870+ }
1871+
1872+ /// Options for a rename request
1873+ #[ derive( Debug , Clone , Default ) ]
1874+ pub struct RenameOptions {
1875+ /// Configure the [`RenameTargetMode`] for this operation
1876+ pub target_mode : RenameTargetMode ,
1877+ /// Implementation-specific extensions. Intended for use by [`ObjectStore`] implementations
1878+ /// that need to pass context-specific information (like tracing spans) via trait methods.
1879+ ///
1880+ /// These extensions are ignored entirely by backends offered through this crate.
1881+ ///
1882+ /// They are also excluded from [`PartialEq`] and [`Eq`].
1883+ pub extensions : Extensions ,
1884+ }
1885+
1886+ impl RenameOptions {
1887+ /// Create a new [`RenameOptions`]
1888+ pub fn new ( ) -> Self {
1889+ Self :: default ( )
1890+ }
1891+
1892+ /// Sets the `target_mode=.
1893+ ///
1894+ /// See [`RenameOptions::target_mode`].
1895+ #[ must_use]
1896+ pub fn with_target_mode ( mut self , target_mode : RenameTargetMode ) -> Self {
1897+ self . target_mode = target_mode;
1898+ self
1899+ }
1900+
1901+ /// Sets the `extensions`.
1902+ ///
1903+ /// See [`RenameOptions::extensions`].
1904+ #[ must_use]
1905+ pub fn with_extensions ( mut self , extensions : Extensions ) -> Self {
1906+ self . extensions = extensions;
1907+ self
1908+ }
1909+ }
1910+
1911+ impl PartialEq < Self > for RenameOptions {
1912+ fn eq ( & self , other : & Self ) -> bool {
1913+ let Self {
1914+ target_mode,
1915+ extensions : _,
1916+ } = self ;
1917+ let Self {
1918+ target_mode : target_mode_other,
1919+ extensions : _,
1920+ } = other;
1921+
1922+ target_mode == target_mode_other
1923+ }
1924+ }
1925+
1926+ impl Eq for RenameOptions { }
1927+
18311928/// A specialized `Result` for object store-related errors
18321929pub type Result < T , E = Error > = std:: result:: Result < T , E > ;
18331930
0 commit comments