2013年12月30日(Mon) 炎の九日間3日目 [長年日記]
● [Android] GitHubのアンドロイドアプリにプルリクエストを出してみる
GitHubのアンドロイドアプリに期待とは違う動作をみつけたのでプルリクエストを出してみました。 検討してもらえるとうれしいな。 それはそれとして、恥をしのんで今回の思考の過程を記録公開しておきます。
体調が悪くて夜眠れない時には時々GitHubのアプリを眺めてます。 るびまの編集作業とか手動かしたいんだけどまだちょっとまとめて時間を確保できる自信が無いので指をくわえて見てるわけです。 そこでIssueから辿るURLのパス部にスラッシュが無い時に、そのURLではなくてパス部をユーザー名としてそのユーザーの情報を表示しようとすることに気づきました。
さてどうやって中身を見ようか。 GitHubでレポジトリをforkしつつ まずはlogcatの出力を見てみるのかな。 ActivityManagerの知らせてくれるIntentはすぐに見ることができました。
うまくURLを辿れた時は、例えば、
だめだった時はUserViewActivityが呼ばれてしまっています。
ビルド環境を整えて、 LogCatデバグをしたり、 KMC Staff Blog:AndroidのJavaアプリからスタックトレースをログに出す簡単な方法を参考にさせていただいて、 スタックトレースデバグをしたりして、 結局のところ、UrlLauncher#convert()があやしそうだということになりました。
convert()の動作を追います。 渡ってきているURLを見てみると、期待どおりの模様。 convert()後半で パスにスラッシュの無いURLがすべからくGitHubユーザーのページと思われていることがわかりました。
どう変更すれば期待している動作になるか。 convert()の中盤を見ると、 スキームやホストの無いURLにも対応しようとしている。 根本的にはここで@付きの文字列をGitHubのユーザーに対応させられれば良いのだろうけれど、 どうもHTMLへの変換はこのアプリのコードのそとでおこなわれているようでした。
表示内容がどこで作られているのか、スタックトレースからは追えませんでした。 例えば、class CommitViewAcivityはPagerActivityを継承していて、 PagerActivity#onCreate()からスタックトレースを眺めると Issueを眺める時にこのメソッドが呼ばれることはわかりましたが、 スタックはすぐにアプリの外に出てしまいます。
じゃあレイアウトから…。 issue_header.xmlの@+id/tv_issue_bodyのTextViewに本文が入りそうなことは想像できましたが、 これを参照している IssueFragment.javaには 内容を設定しているコードが見つけられないのです。 それじゃあIssueFragment#onActivityCreated()の 中は… やっとこ、IssueFragment#updateHeaderを呼んでいるコードを発見しました。 しかしここまで。 updateHeader()から呼ばれているIssue#getBodyHtml()を定義しているコードは見つけられなかったのでした。
そういうわけで、ここでは、 やはりタップされた後のconvert()の動作を変更することにします。
GitHub Enterpriseのユーザーへのリンクがある可能性を考えると、 ホスト名を決めうちにするのは避けた方が良いかとも思うのですが、 パス内に特徴的な文字列を含む他のマッチャと違い、 今回のようにGitHubユーザーのURLへのマッチはマッチしすぎるようなので、 ホスト名で制限をかけることにしましょう。
このアプリの中でgithub.comのホスト名はどうやって定義されているか。
いろいろですねw urlLauncher.javaでは、
よりLogCatによるとHOST_DEFAULTが「github.com」として使われていたので倣うことにします。 変更は簡単。 URLのホスト部とHOST_DEFAULTが一致するかを確認するだけ。
そうそう、テストも書きかけたのですが、
するとログイン画面から進めなくなるテストがあったり、 新規に作ったテストのうち変更前に通りはずのものが通らなかったりで、 今回は諦めました。
デバッグビルドしたものを端末に入れて試してみて満足したら、 Pull requestをするまでのgitコマンドのメモ に従ってpull requestを作成しました。 cherry-pick便利!! 今回は、ここまでの作業で、3日間ほど使ったようです。
そうそう、後日、 convert()内ではそれ以降参照されないIntentへの代入を消したのを 巻き戻しました。 メソッドが返ってからこのIntentが参照される可能性がありましたよね。 Pull request用のブランチにこの変更(の取り消し)をmergeしてpushしたところ、 Pull requestにも そのまま反映されました。便利だねえ。
というわけで、今回は、Androidアプリに期待と異なる動作を見つけて、
- LogCatでIntentとスタックトレースを見て動作を理解
- findとgrepを使って根本的な解決が難しいことを把握
- テストケースの追加を失敗
- 最小の変更とプルリクエスト
と作業が進みました。次の機会にはもう少しちゃっちゃと進められるといいな。
最近のツッコまれどころ