<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>emre şahin's digital garden 🍃 - Storage</title>
    <link>https://emresahin.net/categories/storage/</link>
    <description>Posts in the Storage category</description>
    <language>en</language>
    <managingEditor>contact@emresahin.net (Emre Şahin)</managingEditor>
    <lastBuildDate>Tue, 15 Sep 2026 19:46:32 +0000</lastBuildDate>
    <atom:link href="https://emresahin.net/categories/storage/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>devlog 29</title>
      <published>2025-04-24T03:29:07+00:00</published>
      <updated>2025-04-24T03:29:07+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Thu, 24 Apr 2025 03:29:07 +0000</pubDate>
      <link>https://emresahin.net/devlog-29/</link>
      <guid isPermaLink="true">https://emresahin.net/devlog-29/</guid>
      <description>🐢 As the new version is updated, we can go back to the project. What’s the next step? 🐇 We can continue working on rclone. 🐢 Umm, ok. Let’s try to focus on adding another storage type. ✅ #🌻 ADD rclone storage type (2025-04-24 06:27) 🐢 I think the first option is to run the commands from the comma...</description>
      <category>XVC</category>
      <category>Storage</category>
      <category>rclone</category>
      <category>xvc storage new generic</category>
      <category>rclone alias</category>
      <category>Rust</category>
      <category>Development</category>
      <content:encoded><![CDATA[<p>🐢 As the new version is updated, we can go back to the project. What’s the next step?</p>
<p>🐇 We can continue working on rclone.</p>
<p>🐢 Umm, ok. Let’s try to focus on adding another storage type.</p>
<ul>
<li>✅ #🌻 ADD rclone storage type (2025-04-24 06:27)</li>
</ul>
<p>🐢 I think the first option is to run the commands from the command line. We can just use a modified generic storage type without trying to make it fast.</p>
<p>🐇 Let’s make it run first, you say?</p>
<p>🐢 Yes, let’s make it run first and then we can think about making it run fast.</p>
<p>🐇 You’re right!</p>
<ul>
<li>✅ #🌻 ADD generic rclone tests (2025-04-24 06:27)</li>
</ul>
<p>It’s possible to use the <a href="https://www.reddit.com/r/rclone/comments/qu5l5k/how_to_specify_local_directory_as_a_remote/">alias</a> remote with a local path.</p>]]></content:encoded>
    </item>
    <item>
      <title>devlog 28</title>
      <published>2025-04-24T03:20:52+00:00</published>
      <updated>2025-04-24T03:20:52+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Thu, 24 Apr 2025 03:20:52 +0000</pubDate>
      <link>https://emresahin.net/devlog-28/</link>
      <guid isPermaLink="true">https://emresahin.net/devlog-28/</guid>
      <description>🐢 We can start adding an 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 c...</description>
      <category>XVC</category>
      <category>Storage</category>
      <category>rclone</category>
      <category>librclone</category>
      <category>Rust</category>
      <category>celeste</category>
      <category>cloud-storage</category>
      <content:encoded><![CDATA[<p>🐢 We can start adding an rclone remote as well.</p>
<p>🐢 Created the PR, waiting for the tests.</p>
<p>🦊 Let’s search if there is a crate to manage rclone. Maybe it will be easier that way.</p>
<p>🐇 It will add another dependency though.</p>
<p>🦊 We can always add a feature flag for this.</p>
<p>🐢 There is a <a href="https://github.com/trevyn/librclone">librclone</a> crate that can be used to call rclone commands like https://rclone.org/rc/#supported-commands</p>
<p>🦊 We can test it from the command line perhaps.</p>
<pre><code class="language-bash">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
</code></pre>
<p>🐇 It requires the backend to be running in the background.</p>
<p>🦊 There may be examples in the repository.</p>
<p>🐢 There are none. We can search GH for this crate though.</p>
<p>🦊 It’s also possible to search for dependents in crates.io.</p>
<p>🐢 I think Xvc will be the first dependent of this crate: https://crates.io/crates/librclone/reverse_dependencies</p>
<p>🐇 The following two projects depend on librclone:</p>
<ul>
<li>https://github.com/Sh3mm/WarpDrive/tree/master</li>
<li>https://github.com/hwittenborn/celeste</li>
</ul>
<p>🐢 Let’s clone Celeste. It uses librclone and looks like it’s a user interface for rclone written in Rust.</p>
<p>🐇 The examples are in <code>celeste/src/rclone.rs</code>.</p>
<p>🐢 Cool. Let’s take a look at how commands are run:</p>
<pre><code class="language-rust">    /// Common function for some of the below command.
    fn common(command: &amp;str, remote_name: &amp;str, path: &amp;str) -&gt; Result&lt;(), RcloneError&gt; {
        let resp = run(
            command,
            &amp;json!({
                "fs": get_remote_name(remote_name),
                "remote": util::strip_slashes(path),
            })
            .to_string(),
        );

        match resp {
            Ok(_) =&gt; Ok(()),
            Err(json_str) =&gt; Err(serde_json::from_str(&amp;json_str).unwrap()),
        }
    }</code></pre>
<p>All commands are run like <code>librclone::rpc(method, input))</code> and the commands are like:</p>
<pre><code class="language-rust">    /// make a directory on the remote.
    pub fn mkdir(remote_name: &amp;str, path: &amp;str) -&gt; Result&lt;(), RcloneError&gt; {
        common("operations/mkdir", remote_name, path)
    }</code></pre>
<p>🐇 We have all commands in this file that are relevant to Xvc. Let’s list them here:</p>
<ul>
<li>make directory: <code>common("operations/mkdir", remote_name, path)</code></li>
<li>delete file: <code>common("operations/delete", remote_name, path)</code></li>
<li>remove a dir and all of its contents: <code>common("operations/purge", remote_name, path)</code></li>
<li>copy file:</li>
</ul>
<pre><code class="language-rust">run( "operations/copyfile",
            &amp;json!({
                "srcFs": src_fs,
                "srcRemote": util::strip_slashes(src_remote),
                "dstFs": dst_fs,
                "dstRemote": util::strip_slashes(dst_remote)
            })</code></pre>
<p>and</p>
<pre><code class="language-rust">
    /// Copy a file from the local machine to the remote.
    pub fn copy_to_remote(
        local_file: &amp;str,
        remote_name: &amp;str,
        remote_destination: &amp;str,
    ) -&gt; Result&lt;(), RcloneError&gt; {
        copy(
            "/",
            local_file,
            &amp;get_remote_name(remote_name),
            remote_destination,
        )
    }

    /// Copy a file from the remote to the local machine.
    pub fn copy_to_local(
        local_destination: &amp;str,
        remote_name: &amp;str,
        remote_file: &amp;str,
    ) -&gt; Result&lt;(), RcloneError&gt; {
        copy(
            &amp;get_remote_name(remote_name),
            remote_file,
            "/",
            local_destination,
        )
    }</code></pre>
<p>🐇 It looks like that’s all we need. We can organize the commands differently, but these examples are enough to use <code>librclone</code>. It seems rather straightforward.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
