<?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 🍃 - programming</title>
    <link>https://emresahin.net/tags/programming/</link>
    <description>Posts in the programming tag</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/tags/programming/rss.xml" rel="self" type="application/rss+xml"/>
    <item>
      <title>XVC State Machine</title>
      <published>2022-12-10T20:49:21+00:00</published>
      <updated>2022-12-10T20:49:21+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Sat, 10 Dec 2022 20:49:21 +0000</pubDate>
      <link>https://emresahin.net/xvc-state-machine/</link>
      <guid isPermaLink="true">https://emresahin.net/xvc-state-machine/</guid>
      <description>I began writing Xvc’s pipeline and dependency handling. The best way to handle dependency states seems to be through a state machine. A state machine is a simple abstraction that shows state changes with respect to inputs. It can also have outputs for these state changes. There are some varieties...</description>
      <category>development</category>
      <category>xvc</category>
      <category>xvc</category>
      <category>rust</category>
      <category>finite state machines</category>
      <category>state machines</category>
      <category>pipeline</category>
      <category>programming</category>
      <content:encoded><![CDATA[<p>I began writing Xvc’s pipeline and dependency handling.
The best way to handle dependency states seems to be through a state machine.
A state machine is a simple abstraction that shows state changes with respect to inputs.
It can also have outputs for these state changes.
There are some varieties of this, but Xvc’s state machine (SM) is a simple one.</p>
<p>I first tried to use the <a href="https://crates.io/crates/rust-fsm"><code>rust-fsm</code></a> library, but it became apparent that Xvc pipeline steps’ states are tied to <code>XvcRoot</code>. That is, if we are to check the presence of a file or the value of a parameter, we have to do it relative to the repository root.
The root directory should be taken into consideration in every transition.</p>
<p>I checked the code and noticed that the FSM is actually very simple.
I copied it, added <code>&amp;XvcRoot</code> to the <code>transition</code> and <code>output</code> functions in the trait definition, and implemented it for <code>XvcOutput</code>, <code>XvcDependency</code>, and <code>XvcStep</code>.</p>
<p>These are the constituents of a pipeline.
A pipeline is composed of an <code>XvcStep</code> that defines a command, and each step can have multiple <code>XvcDependency</code> and <code>XvcOutput</code> definitions.
For each of these structs, I’ve added fields that represent their current state.</p>
<p>For example, an <code>XvcOutput</code> can be <code>Missing</code>, <code>Found</code>, <code>Old</code>, or <code>Ok</code>.
An <code>XvcStep</code> that produces this <code>XvcOutput</code> doesn’t check the dependency content hash if an output is missing.
However, if an <code>XvcOutput</code> is <code>Found</code>, the <code>XvcStepStateMachine</code> checks the <code>XvcDependency</code> states and their modification times to see if they have changed since the output was generated.
An <code>XvcStep</code> is invalidated when an <code>XvcOutput</code> is <code>Missing</code> or an <code>XvcDependency</code> has changed after the last command run.</p>
<p>Unlike DVC, I added the ability for an <code>XvcStep</code> to depend on other <code>XvcStep</code>s.
They communicate through outputs. I’ve added <code>XvcDependency::Step(XvcStep)</code> to the <code>XvcDependency</code> definition.
I’m also planning <code>XvcDependency::Pipeline(XvcPipeline)</code> to allow steps to depend on other pipelines, so that pipelines can be run in order.</p>
<p>Currently, the following are included as <code>XvcDependency</code>:</p>
<ul>
<li><code>File</code>: A (binary or text) file in the repository. If the metadata (size and modification time) or the content changes, the dependent step becomes invalidated.</li>
<li><code>Directory</code>: A directory that contains files. If a file is added to or removed from the directory, or any of the files are changed, the associated step becomes invalidated.</li>
<li><code>Glob</code>: A glob such as <code>my-data/*.png</code>. If the list of files changes or their content has changed, the associated step becomes invalidated.</li>
<li><code>Parameter</code>: Xvc can parse YAML, TOML, and JSON files and get the values of variables. It’s possible to define these (hyper)parameters as dependencies.</li>
<li><code>URL</code>: An HTTPS URL, which is checked first by metadata and then by content to see whether it has changed.</li>
<li><code>Step</code>: A previously defined step; if it’s invalidated, the depending step also becomes invalidated.</li>
</ul>
<p>Additionally, I’m planning to add the following items to Xvc as dependencies:</p>
<ul>
<li><code>Lines {path, begin, end}</code>: Lines in a text file. This can be used for general-purpose input tracking. If the given lines in a file are changed, the dependent step becomes invalidated.</li>
<li><code>Regex {path, regex}</code>: If the regular expression result on the file changes, the dependent stage becomes invalidated.</li>
<li><code>Pipeline { name }</code>: If any of the steps in a pipeline is invalidated, the pipeline is also invalidated, or the step that depends on this pipeline becomes invalidated.</li>
</ul>
<p>Each of these dependencies is checked minimally; that is, when their size on disk is detected to have changed, they are considered changed without checking the content hash. It needs a very detailed state machine to track the changes without bugs.</p>
<p>I’ve noticed that if I can write such a state machine, most of the I/O operations can be done in parallel. If two steps do not depend on each other in the dependency graph, they can be run in parallel. The state machine’s granularity allows this.</p>]]></content:encoded>
    </item>
    <item>
      <title>Xvc Devlog</title>
      <published>2022-10-27T11:13:00+00:00</published>
      <updated>2022-10-27T11:13:00+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Thu, 27 Oct 2022 11:13:00 +0000</pubDate>
      <link>https://emresahin.net/xvc-devlog/</link>
      <guid isPermaLink="true">https://emresahin.net/xvc-devlog/</guid>
      <description>I’ll start a new series to record my Xvc development progress. I think it’s nice to have a dialogue between 🐢 and 🐇 to explain the decisions and progress. These will be published on my personal blog for now. In the future, we can have a dedicated blog for this. 🐇 LGTM. I think you can also link t...</description>
      <category>xvc</category>
      <category>devlog</category>
      <category>xvc</category>
      <category>cargo-geiger</category>
      <category>unsafe_code</category>
      <category>debug</category>
      <category>rust</category>
      <category>programming</category>
      <content:encoded><![CDATA[<p>I’ll start a new series to record my Xvc development progress. I think it’s nice to have a dialogue between 🐢 and 🐇 to explain the decisions and progress. These will be published on my personal blog for now. In the future, we can have a dedicated blog for this.</p>
<p>🐇 LGTM. I think you can also link to commits here when they occur.</p>
<p>🐢 I think that’s a bit too much work, but PRs may be linked.</p>
<p>🐇 Ok. Let’s start with the PRs. What are you working on these days?</p>
<p>🐢 I started fixing warnings in <a href="https://github.com/iesahin/xvc/issues/3">issue #3</a> and am now fixing missing documentation warnings.</p>
<p>🐇 Do you really think that we’ll have a use for [RMNStore] in the future?</p>
<p>🐢 I’m not sure. Possibly any M-N relationship can be tracked by two 1-N relationships. Under the hood, this is what RMNStore does actually.</p>
<p>🐇 Maybe we should just remove it.</p>
<p>🐢 I want to save it for the time being. If [<code>xvc-ecs</code>] is used in other places, it may be needed.</p>
<p>🐇 Ok. Probably YAGNI, but let’s keep it for the time being.</p>
<hr>
<p>🐢 Writing documentation can be a debugging method, too. I think I’ve found the reason for a <a href="https://github.com/iesahin/xvc/issues/45">bug here</a>.</p>
<p>🐇 Um, how could it lead to a bug?</p>
<p>🐢 Insert means a <em>new event</em> happened. But when converting a <code>VStore</code> to an <code>XvcStore</code>, new events are not happening. We are simply converting from one store to another.</p>
<p>🐇 That means they are added to <code>XvcStore::current</code> events, not <code>XvcStore::previous</code>, and when <code>save_dir</code> is called, they are saved.</p>
<p>🐢 Yeah, that was the bug. From time to time, I was seeing duplicate JSON files.</p>
<p>🐇 Then maybe it’s better to limit all <code>insert</code> usage.</p>
<p>🐢 Yeah, I should review that, too.</p>
<p>🐇 Added a <a href="https://github.com/iesahin/xvc/issues/45">bug report</a>.</p>
<hr>
<p>🐢 I’m installing <code>cargo-geiger</code> to show that there is no <code>unsafe</code> code.</p>
<p>🐇 Do you think you’ll maintain Xvc that way? That it won’t require any unsafe code?</p>
<p>🐢 Maintain the <code>forbidden(unsafe)</code> status? I think so. Xvc doesn’t seem to need any unsafe blocks by itself. Most of the dependencies may need it, though.</p>
<p>🐇 <a href="https://github.com/iesahin/xvc/issues/63">Working on it</a>, and it will be merged today.</p>
<hr>
<p>🐢 I worked on <a href="https://github.com/iesahin/xvc/issues/8">that <code>s3cmd</code> bug</a> yesterday, and it turned out that my modification of the configuration was the cause.</p>
<p>🐇 You were thinking that it’s about R2 all along?</p>
<p>🐢 I should suspect my custom config more.</p>
<p>🐇 Anyway, congratulations 🌠 that Xvc now has Cloudflare R2 support.</p>]]></content:encoded>
    </item>
    <item>
      <title>TIL 10: Structs in Go</title>
      <published>2021-01-10T18:44:55+00:00</published>
      <updated>2021-01-10T18:44:55+00:00</updated>
      <author>Emre Şahin</author>
      <pubDate>Sun, 10 Jan 2021 18:44:55 +0000</pubDate>
      <link>https://emresahin.net/til-10/</link>
      <guid isPermaLink="true">https://emresahin.net/til-10/</guid>
      <description>Structs in Go In Go, it is possible to embed structs within other structs: type person struct { first string last string age int } type employee struct { person employee_id int salary int } We can instantiate the employee type as follows: e := employee{ person: person{ first: "Ali", last: "Yeşil"...</description>
      <category>Golang</category>
      <category>struct</category>
      <category>anonymous struct</category>
      <category>embedded struct</category>
      <category>Go</category>
      <category>programming</category>
      <content:encoded><![CDATA[<h2 id="structs-in-go">Structs in Go</h2>
<p>In Go, it is possible to embed structs within other structs:</p>
<pre><code class="language-go">type person struct {
    first string
    last string
    age   int
}

type employee struct {
    person
    employee_id int
    salary      int
}
</code></pre>
<p>We can instantiate the <code>employee</code> type as follows:</p>
<pre><code class="language-go">e := employee{
    person: person{
        first: "Ali",
        last:  "Yeşil",
        age:   33,
    },
    employee_id: 001,
    salary:      4500,
}
</code></pre>
<p>We can then access the fields of the embedded struct as if they were fields of the outer struct:</p>
<pre><code class="language-go">// e.first is a shorthand for e.person.first
fmt.Println(e.first) 
</code></pre>
<p>One can also use anonymous structs without explicitly defining a type:</p>
<pre><code class="language-go">z := struct {
    a string
    b int
}{
    a: "aaa",
    b: 123,
}
</code></pre>
<p>If these won’t be reused elsewhere, using anonymous structs can keep the code clean.</p>]]></content:encoded>
    </item>
  </channel>
</rss>
