Posted on :: Tags: , , ,

🐢 We can start adding rclone remote as well.

🐢 Created the PR, waiting for the tests.

🦊 Let’s search if there is a crate to manage rclone. Maybe it will be easier that way

🐇 It will add another dependency though

🦊 We can always add a feature flag for this

🐢 There is a librclone crate that can be used to call rclone commands like https://rclone.org/rc/#supported-commands

🦊 We can test it from the command line perhaps.

rclone rc 
2025/03/15 17:41:09 NOTICE: Failed to rc: failed to list: connection failed: Post "http://localhost:5572/rc/list": dial tcp [::1]:5572: connect: connection refused
BASH

🐇 It requires the backend to be running in the background.

🦊 There may be examples in the repository

🐢 There is none. We can search GH for this crate though

🦊 It’s also possible to search for dependents in crates.io

🐢 I think xvc will the first dependent of this crate: https://crates.io/crates/librclone/reverse_dependencies

🐇 The following two projects depend to librclone

  • https://github.com/Sh3mm/WarpDrive/tree/master
  • https://github.com/hwittenborn/celeste

🐢 Let’s clone celeste. It uses librclone and looks like it’s a user interface for rclone written in Rust.

🐇 The examples are in celeste/src/rclone.rs

🐢 Cool. Let’s take a look how commands are run:

    /// Common function for some of the below command.
    fn common(command: &str, remote_name: &str, path: &str) -> Result<(), RcloneError> {
        let resp = run(
            command,
            &json!({
                "fs": get_remote_name(remote_name),
                "remote": util::strip_slashes(path),
            })
            .to_string(),
        );

        match resp {
            Ok(_) => Ok(()),
            Err(json_str) => Err(serde_json::from_str(&json_str).unwrap()),
        }
    }
RUST

All commands are run like librclone::rpc(method, input)) and the commands are like

    /// make a directory on the remote.
    pub fn mkdir(remote_name: &str, path: &str) -> Result<(), RcloneError> {
        common("operations/mkdir", remote_name, path)
    }
RUST

🐇 We have all commands in this file that are relevant to Xvc. Let’s list them here:

  • make directory: common(“operations/mkdir”, remote_name, path)
  • delete file: common(“operations/delete”, remote_name, path)
  • remove a dir and all of its contents: common(“operations/purge”, remote_name, path)
  • copy file:
run( "operations/copyfile",
            &json!({
                "srcFs": src_fs,
                "srcRemote": util::strip_slashes(src_remote),
                "dstFs": dst_fs,
                "dstRemote": util::strip_slashes(dst_remote)
            })
RUST

and


    /// Copy a file from the local machine to the remote.
    pub fn copy_to_remote(
        local_file: &str,
        remote_name: &str,
        remote_destination: &str,
    ) -> Result<(), RcloneError> {
        copy(
            "/",
            local_file,
            &get_remote_name(remote_name),
            remote_destination,
        )
    }

    /// Copy a file from the remote to the local machine.
    pub fn copy_to_local(
        local_destination: &str,
        remote_name: &str,
        remote_file: &str,
    ) -> Result<(), RcloneError> {
        copy(
            &get_remote_name(remote_name),
            remote_file,
            "/",
            local_destination,
        )
    }
RUST

🐇 It looks that’s all we need. We can organize the commands differently but these examples are enough to use librclone. It seems rather straightforward.