Date 2025-05-13

dirback - バックアップツールを作った

  tech ,  Rust ,  やった

Dirback

シンプルなディレクトリ単位のバックアップツールを作った。

Dirback

  • シンプルな使い心地
  • GUI / TUI / Command の3形式で利用できる
  • バックアップ対象はディレクトリ単位
  • .tar.gz 形式でバックアップする
  • Linux / Windows に対応
    • Linux は主に X11 環境で実装・動作確認した
      • Wayland 環境でも実行はできた
      • でもあんまりテストしてない
    • Mac は環境を用意できないので試せていない
      • けど動くはず

GitHub の Releases から最新版をダウンロードできる。

ツールとして

ぼく個人としては、 主にゲームデータのバックアップ・リストアの用途に使う予定なので、

  • 複数のタイトル(バックアップ対象)を分かりやすくリストできる
  • サクッとバックアップ・リストアできる

という2点を主軸に実装してある。

動機

最近 Rust が楽しい、何か1つ作ろう、というのが始まり。

  • Tauri も触ってみたいな
  • GUI アプリなんかあるかな
  • そういえば、ゲームデータのバックアップにシンプルなツールが欲しかったんだよな
  • したらそれをお題にしよう

という流れでバックアップツールにした。

また、「クリーンアーキテクチャ、 勉強したり小さく実践したりはしたけど、1からちゃんとやったことないな」 という気持ちがあり、せっかくなのでそれを意識した設計にしてみた。

キレイな設計かどうかは自信ないけど、依存の方向は1方向になっているハズ。

UseCase / Adapter を介して機能を使うデザインのおかげで、 各プレゼンテーション層 (GUI, TUI, Command) の実装は比較的楽だった。

Service を切り替えれば zip などにも対応できる(面倒だからやらないけど)。

技術まわり

Rust で書いた。

Cargo の workspace 機能を使い、 コア部分(ドメイン周りや Infra など)とプレゼンテーション部分で crate を分割した。

lib crate も細かく分割できて、だいぶ開発しやすくて良かった。

反面、 crates.io へ公開するのが難しくなった。

今回は Command としても実装していたし、 サーバで使うときに cargo install で使えたら便利だったんだけど、 最終的には断念した。

具体的には、 Workspace 内の各 lib crate への依存を以下のように記述した場合、 crates.io 上でそれが解決できないため、 publish 時にエラーになる模様。

[workspace.dependencies]
dirback = { path = "crates/lib/dirback" }
jsonfile = { path = "crates/lib/jsonfile" }
mktemp = { path = "crates/lib/mktemp" }
targz = { path = "crates/lib/targz" }

これに対応するには、各 lib crate をそれぞれ crates.io へ公開する必要がある。

各 lib crate を dirback_xxx という名前にして公開することも考えたけど、 面倒になったので中止した。

TUI ... Ratatui.rs

TUI は Ratatui.rs を使った。

簡単に TUI アプリの実装を開始できて、視覚的にも楽しい。

ただ、複雑な UI のものを作ろうとしたら、 GUI まわりの設計をしっかりしないと厳しそうだった。

GUI ... Tauri + Svelte

GUI は、

の構成にした。

Tauri はネイティブの WebView を使用するので、 Web フレームワークは大体なんでも使える。

各コンテンツ (html,js,css など) の WebView への配布はアプリが行う。

いわゆる埋め込みという形になるので、React や Vue よりは、Svelte や Solidjs のほうが相性は良さそう。

今回はデスクトップ向けだけだし、機能的にも複雑なことはしなかったので、特に躓く点もなく開発できた。

おわり

作ってから2週間くらい経ってこれを書いた。 ので、細部を忘れつつある。

個人的にけっこう便利に使ってる。

ちなみに、ロゴ画像は、はじめ ChatGPT に作って貰おうとした。 けど、あんまり良い出力にできなかった。 結局 Inkscake で D の文字を作って Canva で適当なディレクトリ画像と重ねた。

プロンプト力が求められる……。