バックアップ版へ戻すコマンド - revert-from-backup

みんなは毎日バックアップを取っているかな?俺は更新頻度の高い/home以下はちゃんと毎日取っている。

たま〜にだけどファイルを更新してて、動きがおかしくなったからバックアップ版に戻したいということがあるだろう。バージョン管理システムを使えって?もちろん自分が作成したファイルのほぼすべてに使っている。しかし、常用するelispをアップグレードしたら動かなくなったとしたらどうするか?バックアップから書き戻すのが手っ取り早い。

俺の場合ホームディレクトリ /home/rubikitch 以下はDVD-RAMの /d/backup/rubikitch 以下にそのままバックアップされている。たとえば /home/rubikitch/.emacs は /d/backup/rubikitch/.emacs にバックアップされる。しかし、同じパスを二度書くのは面倒だ。そこでこの小さいスクリプトを。

もちろん BACKUP_DIR, HOME_DIR, MOUNT_DIR は環境に応じて書き換えてくれ。

#!/usr/bin/env ruby
BACKUP_DIR = "/d/backup/rubikitch/"
HOME_DIR = ENV['HOME'] + "/"
MOUNT_DIR = "/d"

require 'fileutils'
require 'optparse'
ARGV.options {|o|
  o.banner = "revert-from-backup [-m] files..."
  o.on("-m", "Mount and unmount backup file system.") {|x| @mount = true }
  if ARGV.empty?
    print o
    exit 1
  end
  o.parse!
}


def backup_file(file)
  file = File.expand_path(file)
  if file =~ /^#{Regexp.union(HOME_DIR)}(.+)$/
    BACKUP_DIR + $1
  else
    raise "#{file} is not on home directory."
  end
end

def revert_files(files)
  files.each do |file|
    begin
      FileUtils.cp(backup_file(file), file, :verbose => true)
    rescue => err
      warn err.message
    end
  end
end

system "mount", MOUNT_DIR if @mount
revert_files ARGV
system "umount", MOUNT_DIR if @mount


使い方は簡単で、

revert-from-backup -m ~/emacs/lisp/hogehoge.el ~/emacs/lisp/foo.el

と書いたら

mount /d
cp /d/backup/rubikitch/emacs/lisp/hogehoge.el ~/emacs/lisp/hogehoge.el
cp /d/backup/rubikitch/emacs/lisp/foo.el ~/emacs/lisp/foo.el
umount /d

が実行される。