Ruby の 定番対話ツール pry 徹底攻略 | 番外編 攻略記事作成中に見つけた pry のバグのプルリクエスト作成への道
概要
攻略記事作成中に見つけた pry のバグのプルリクエスト作成への道
経緯
ここ最近 pry の基本操作に関する連載記事を作成しています。
Ruby の 定番対話ツール pry 徹底攻略
履歴に関する記事を作成した際に、 pry のバグを踏みました。
Ruby の 定番対話ツール pry 徹底攻略 | Managing History
具体的にはこんな感じのエラーになります。
$ pry
[1] pry(main)> "hoge"
=> "hoge"
[2] pry(main)> hist --clear
History cleared.
[3] pry(main)> hist
ArgumentError: negative array size
from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.10.1/lib/pry/commands/hist.rb:171:in `last'
原因調査
エラー行を確認
hist.rb の 171 行目がエラーというログに従い、該当行を確認。
エラーメッセージの ArgumentError: negative array size と合わせて判断すると
Pry.history.session_line_count
がマイナスを返しているようです。
※ Array.last は負の値を受け取ると ArgumentError になる
def find_history
h = if opts.present?(:all)
Pry.history.to_a
else
# ここが 171 行目
Pry.history.to_a.last(Pry.history.session_line_count)
end
# The last value in history will be the 'hist' command itself.
Pry::Code(h[0..-2])
end
Pry.history.session_line_count のソースコードを確認
さて、はじめてのコードベースを探索する必要があるようです。
つまり pry の出番です。
pry のバグ修正に pry を活用します。
Pry.history.session_line_count
のソースコードを確認します。
[1] pry(main)> show-source -l Pry.history.session_line_count
From: /path/to/gems/pry-0.10.1/lib/pry/history.rb @ line 70:
Owner: Pry::History
Visibility: public
Number of lines: 3
70: def session_line_count
71: @history.count - @original_lines
72: end
[2] pry(main)>
Pry のインスタンス変数の内容を確認
Pry.history.session_line_count
と Pry.history.original_lines
の値を
バグを再現する操作の中で確認してみます。
$ pry
[1] pry(main)> "hoge"
=> "hoge"
[2] pry(main)> hist
1: "hoge"
[3] pry(main)> hist --clear
History cleared.
[4] pry(main)> hist
ArgumentError: negative array size
from /home/user/.rbenv/versions/2.0.0-p0/lib/ruby/gems/2.0.0/gems/pry-0.10.1/lib/pry/commands/hist.rb:171:in `last'
[4] pry(main)> Pry.history.original_lines
=> 693
[5] pry(main)> Pry.history.session_line_count
=> -690
原因判明
hist --clear
は履歴をクリアする機能です。
履歴には、
- 以前の履歴 ( .pry_history で管理)
- カレントセッションの履歴
があり、それぞれ
- 以前の履歴 => @original_lines
- カレントセッションの履歴 => @history
に紐付いています。
hist --clear
時に、以前の履歴にあたる @original_lines
の値をクリアしていないため、
@original_lines
の行数分だけマイナスになってしまっているのです。
そのため、 hist --clear
時に @original_lines
もクリアする処理を実装します
pry をフォーク
GitHub の pry/pry のリポジトリ から
プロジェクトをフォークします。
フォークしたプロジェクトをローカル環境に clone します
$ git clone git@github.com:tbpgr/pry.git
※実際は ghq を使ってます
$ ghq get git@github.com:tbpgr/pry.git
トピックブランチの作成
説明的な名前のブランチを作って、該当ブランチで作業をします。
$ git checkout -b fix_hist_clear_negative_array_size
TDD で直す。エラーのテストケースを追加
まずはエラーを再現させるテストコードを追加します。
pry --clear
の処理本体である Pry::History#clear
のテストケースに original_lines が
0 になっていることを確認するテストケースを追加します。
it "clears this session's history" do
Pry.history.to_a.size.should > 0
Pry.history.clear
Pry.history.to_a.size.should == 0
# この1行を追加
Pry.history.original_lines.should == 0
end
- テストがエラーになることを確認します
1) Pry#clear clears this session's history
Failure/Error: Pry.history.original_lines.should == 0
expected: 0
got: 6 (using ==)
# ./spec/history_spec.rb:56:in `block (3 levels) in <top (required)>'
TDD で直す。テストケースをパスする実装を行う
テストをパスするように Pry::History#clear
を実装します。
# Clear this session's history. This won't affect the contents of the
# history file.
def clear
@clearer.call
# この 1 行を追加
@original_lines = 0
@history = []
end
テストを実行します
$bundle exec rspec spec/history_spec.rb
Finished in 0.07801 seconds (files took 0.39155 seconds to load)
14 examples, 0 failure
直りました。
修正内容を push します
$ git push origin fix_hist_clear_negative_array_size
ブラウザでプルリクエストを作成します
- バグの原因の再現
- バグの原因
- バグ修正後の操作例
をソースコードの例示を主に説明しました。
英語力が低いのを補う手法。
ついでに emoji も織り交ぜたり。
以上でプルリクエストが完了しました。