PCを買い替えて、新しいPCへ移行して古いPCを手放すにあたって、古いPCにしか無いデータのサルベージが問題になる。私の場合、普段使っているPCは常に3種類ぐらいあるけど、Chromebookを中心に使うのもあって大体のデータはクラウドにある。PCのローカルに大事なデータが置いてあるようなことは少ない。プログラムはGitHubに上がっているし、開発環境はDockerなのでローカルに依存する環境設定とかも少ない。しかし、gitignoreされているファイルに記載されているAPIキーのようなsecretファイルは問題になる。

そこで、PC内のGitプロジェクトを洗い出して、その中からgitignoreされている特定パターンのファイルを抽出して集めるやつを作った。

https://github.com/s2terminal/gitignored-list

実装はPythonを使った。単にいちばん使い慣れているからであって、大した理由はない。

uv

今回は環境構築にastral-sh/uvを使った。私が開発する時はだいたいPoetry+Dockerだけど、今回はホストのファイル配置に依存して使う物なので、Dockerみたいな仮想環境と相性が良くないので、最近流行っているのもあってuvを選んだ。

uvはインストールが速かったし、使い勝手が良かった。「uv」という名前が検索しにくいという点だけ悩み。

pydantic-settings

設定の読み込みにはpydantic-settingsを使った。YAMLファイルで動作の設定をしておいて、対象となるパス指定などはコマンドライン引数から受け取るように設定しておいた。必要なパラメータの存在チェックやパースをPydanticで自動でやってくれて、使いやすかった。

gitignoreされたものを出すコマンド

まず指定したパス以下にあるGit管理されたディレクトリを抽出する。これは単に.gitが配置してあるディレクトリを探した。

Git管理されたディレクトリに対して、git ls-filesコマンドを使ってGit管理外にあるファイルを抜き出した。そこからnode_modules/内のような不必要なファイルは除外するようgrep -vした。実際には下記のようなコマンドになる。

$ git ls-files --other --ignored --exclude-standard | grep -v -e node_modules -e dist

正規表現をまとめることで高速化できると思うけど、何度も動かすプログラムではないので書きやすさを重視して-eを続けて繋いでいる。実際にはpydantic-settingsで不必要ファイルのパターンをリストで指定して、grepコマンドを動的に組み立てている。

PyInstaller

今回実行するのはすべて自分のPCなのでPythonの実行環境を用意すれば良いんだけど、普段はDockerしか使っていないのもあってPythonがそもそもインストールされていないPCばかりで少し面倒だった。そこで、Pythonアプリケーションをパッケージ化するPyInstallerがLinuxでも使えるのは知らなかったので、使ってみた。名前からしてWindows専用かと思っていた。

PyInstallerはGitHub Actionsでビルドするようにした。最近パブリックリポジトリでarm64対応したようなので、これを使ってx64とarm64の両方でビルドした。GitHub公式ドキュメントに従って設定すればOK。

    strategy:
      fail-fast: true
      matrix:
        runs-on:
          - "ubuntu-20.04"
          - "ubuntu-22.04-arm"

なおglibcのバージョン揃えるために、Ubuntuのバージョンはlatestを使わず下げている。

余談: zip圧縮時の漏れ

このプログラムを使って収集したファイルをzip圧縮してクラウドにアップロードしたけど、中を見てみたら一部のファイルが含まれていなかった。調べてみると、ChromeOSのファイラーでできる「zip圧縮」で、権限が無いファイルが含まれてるとエラーも警告も無く除外されるという仕様のようで、ファイルが漏れてしまっていた。