c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

OSXでGitの罠を回避しつつ更新されたPNGを圧縮するスクリプト

画像の圧縮自体はImageOptimと云ふプログラムをコマンドで呼んでゐる丈だ。お終い。
HomebrewではCaskroom/cask/imageoptimに在る。

そこでGitの話に成る。
利用シーンはご想像にお任せするが、gitでpullした後に、其のpullで更新されたPNGファイルをlosslessで最適化する。最適化するコードだけ抜き出すと以下に成る。

#!/usr/bin/env ruby
require 'shellwords'

targets = ...
system "ImageOptim #{Shellwords.shelljoin(targets)}"

targetsに指定すべきファイルを一覧するにはだうしたらいいだらうか。pullした時に更新したコミット番号がわかるので、diffをとり、削除された差分ではないファイルを一覧し、PNGを抽出する。簡単なシェルのスクリプトだ。git diff --name-statusを使へる。

#!/usr/bin/env ruby
require 'shellwords'

revisions = ARGV[1] || (print 'revisions> '; gets.strip)
targets = `git diff --name-status #{revisions}`.
  each_line.
  collect(&:strip).
  reject{|line| line.start_with?('D') }.
  collect{|line| line.sub(/\A\S+\s+/, '') }.
  select{|line| line.end_with?('.png') }
system "ImageOptim #{Shellwords.shelljoin(targets)}"

此れをImageOptimと云ふ名前で保存しておけば、./ImageOptim -- 64e88f6..2be0234等と呼び出せる。
餘談だが此の偽のコミット番号はruby -rsecurerandom -e"puts SecureRandom.uuid[0..6]"で作れる。
上で標準ライブラリのShellwordsを使ってゐるのは、空白を含んだファイル名が沢山転がってゐるからだ。そもそも此れが、bashスクリプトではなく面倒に成ってRubyを書いた理由だった。
次に現れたのは日本語ファイル名だった。OSXのgitはとうに日本語のファイル名を扱へるやうにはなってゐるが、親切にもエスケープして表示してくれる。\001\002…のやうな。
面倒だ。調べると此のエスケープをオフにするオプションがある。git config core.quotepathだ。此れをfalseにすればUnicodeのまま印字される。常にオフにするのも氣がひけるので、スクリプトの終了時に元の設定に戻すコードを書いた。Ruby的なブロック引數だ。

#!/usr/bin/env ruby
require 'shellwords'

def git_quotepath?
  case `git config --local core.quotepath`
  when ""        then nil
  when "false\n" then false
  when "true\n"  then true
  end
end

def set_git_quotepath config
  case config
  when nil
    `git config --local --unset core.quotepath`
  when false
    `git config --local core.quotepath false`
  when true
    `git config --local core.quotepath true`
  end
end

def without_git_quotepath &block
  config = git_quotepath?
  set_git_quotepath false
  block.call
ensure
  set_git_quotepath config
end

revisions = ARGV[1] || (print 'revisions> '; gets.strip)
targets = without_git_quotepath{ `git diff --name-status #{revisions}` }.
  each_line.
  collect(&:strip).
  reject{|line| line.start_with?('D') }.
  collect{|line| line.sub(/\A\S+\s+/, '') }.
  select{|line| line.end_with?('.png') }
system "ImageOptim #{Shellwords.shelljoin(targets)}"

# vim: set ft=ruby:

疲れた。