0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

chezmoi でローカルとソースの差分を対話的に解消するシェルスクリプト

0
Posted at

chezmoi でローカル側とソースディレクトリ側の差分を解消するときに、1 ファイルずつ差分を表示した上で「ローカル側を登録するか / ソース側を適用するか / 保留するか」を訊いて対応してくれるラッパーシェルスクリプトを書きました。

恒常的に PC 2 台以上で作業するケースで役立つと思います (PC 移行時に個人設定を運搬するのみの場合や、メイン PC 以外で個人設定を変更しない場合は役立たないと思います)。

chezmoi v2.69.3 での動作を確認しています。特に次に依存します。

  • chezmoi diff の結果が diff --git a/.bashrc b/.bashrc といった行を含む (3 番目の要素の先頭 a/ を削るとホームからのパスになる) ことを期待します。
  • chezmoi managed --include=templates ~/.bashrc の結果、そのファイルがテンプレート化されて登録されていたらそのファイルを表示、そうでなければ何も表示しないことを期待します (--include=encrypted も同様)。

シェルスクリプト本体

以下の helper.sh をソースディレクトリ ~/.local/share/chezmoi/ に配置し、ソースディレクトリでこれを実行する想定です (このスクリプト自体はローカルに反映されるべきではないので .chezmoiignore に記述します)。

~/.local/share/chezmoi/helper.sh
#!/usr/bin/bash
while IFS= read -r line; do
  filename="${line:2}"
  echo "----- ローカルとソースディレクトリに差分があります -----"
  echo "${HOME}/${filename}"
  chezmoi diff "${HOME}/${filename}"

  tmpl=0
  encrypt=0
  count=$(chezmoi managed --include=templates "${HOME}/${filename}" | wc -l)
  [ "$count" -gt 0 ] && { tmpl=1; echo "※ テンプレート化されて登録されています"; }
  count=$(chezmoi managed --include=encrypted "${HOME}/${filename}" | wc -l)
  [ "$count" -gt 0 ] && { encrypt=1; echo "※ 暗号化されて登録されています"; }

  echo "${HOME}/${filename} への操作を選択してください"
  read -p "l=ローカルを登録, s=ソースを適用, n=何もしない, q=終了 > " key < /dev/tty
  if [ "$tmpl" -eq 1 ] && [ "$key" == "l" ]; then
    echo "[ERROR] テンプレートファイルはローカルから登録できません"
    exit 0
  fi
  if [ "$key" == "s" ]; then
    echo "本当にソースを適用してローカルを上書きしてよいですか?"
    echo "(サブ機への同期、テンプレートでソース編集したときのみ想定される操作)"
    read -p "l=ローカルを登録, s=ソースを適用, n=何もしない, q=終了 > " key < /dev/tty
  fi
  case "$key" in
    q) exit 0 ;;
    n) : ;;
    l)
      echo "ローカルを登録します"
      [ "$encrypt" -eq 0 ] && chezmoi add "${HOME}/${filename}"
      [ "$encrypt" -eq 1 ] && chezmoi add --encrypt "${HOME}/${filename}"
      ;;
    s)
      echo "ソースを適用します"
      chezmoi apply "${HOME}/${filename}"
      ;;
  esac
done < <(chezmoi diff | grep "^diff " | awk "{print \$3}")

echo
git status -s

基本的な流れ

このシェルスクリプトの基本的な流れは以下です。

  • ローカルとソースディレクトリで差分がある各ファイルについて、
    • 差分を提示します。
    • どうするか訊きます。
      • l=ローカルを登録, s=ソースを適用, n=何もしない, q=終了
    • ls が選択されたら登録か適用を実行します。n が選択されたら何もせず次のファイルにいきます。q が選択されたらこのスクリプト実行自体を終了します。
  • 最後にソースディレクトリでの git status -s の結果を表示します (Git へのコミットが必要なファイルを確認する用)。

注意点

  • s が選択されたときは再確認します。
    • もし意図せずソースを適用すると、ローカル変更が失われるためです。
    • ただし、実際ローカルが新しい場合は chezmoi も再確認するため 2 重確認になり、またこの場合は chezmoi の上書き後に再度エンターを打たないと進まないことがあります。煩わしいならこの再確認の if ブロックは撤去してよいかもしれないです。
  • l が選択され、もしそのファイルが暗号化されて登録されている場合は、再登録も暗号化して実施します (chezmoi add --encrypt)。
  • l が選択され、もしそのファイルがテンプレート化されて登録されている場合は、登録を拒否してスクリプト実行自体を終了します。
    • chezmoi add --template でローカルを登録してしまうと再度くり抜きが必要になるため、テンプレート化ファイルはソースディレクトリ側の編集を想定しています。
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?