gitに新機能を追加してgit masterを目指す(初級編)
学科の実験「大規模ソフトウェアを手探る」でgitを弄って改良しようとしたので、その過程と結果を何回かにわたって書いてみようと思います。
「レポートとしてブログ記事が認められる」という変則的な実験なので、レポートとして書きますが、文体は敬語かつ口語っぽく書かせていただきます。
また、単にハウツーを書くだけではなく、チームや個人としての感想や想いについても書かせていただきます。
というのも、ブログ記事が推奨されている理由が、
今後同じく大規模ソフトウェアやOSS、特に自分の暑かったソフトについて手探ろうとしている人たちの参考となるため
であるためです。
従って、この記事は単なるレポートではなく、他の方に参考にして戴ける記事にしたいと思っているので、質問や意見などがあればコメント欄やはてブコメントなどで仰ってください。
twitterは@showmeearなので、リプを飛ばしていただいても構いません。
ちなみにチームメンバーはtkkとvinterと僕です。
記事内でもこの名前で呼びますが、レポートの中でどう扱われるんでしょうか……?
なお、手探るために用いたgitのバージョンは2.6.0です。
実験「大規模ソフトウェアを手探る」とは
レポートとしては不要かもしれませんが、まずこの実験について簡単に紹介しておきます。
僕の所属する東京大学電子情報工学科(通称eeic)で3年後期に行われる実験の一つで、テーマは
全容を把握できるわけがない程大きなソフトウェアをいかに扱い,必要な動作を理解し,変更するか
だそうです。
サイトは一般に公開されているようなので、ご覧になってみてください。
配布されている資料のpdfがとても参考になるかと思います。
手探る対象ソフトの決定
手探る対象として、私達のチームはgitを選びました。
その主な理由を以下に述べます。
ブラックボックス化の解消
一つ目の理由が、「 普段良く使っているけど、中身がほとんどわからないまま使っているので、手探ることで実態を知りたい 」というものです。
僕自身もかねてから思っていたこととして、「便利なものをブラックボックス化して使っているだけだと、トップダウン的な学習しか出来ずに技術の進歩についていけなくなる」というものがあります。
gitは何も理解しなくても使えて便利なのですが、そのために完全にブラックボックス化して使っていたことの反省として弄ることにしました。
「もともとバージョン管理システムはsvnなどがあったのに、どうしてgitがデファクトスタンダードとなったのか?」とか、「gitで何が出来て何が出来ないのか?」を真に理解しようと思ったら、エンジニアとしては「コードを読む」のが何よりも良いのではないかと思います。
コードの綺麗さ
ふたつめの理由は「gnuplotなどに比べると割と新しめのソフトなので、コードが綺麗そう」というものです。
有名な逸話ですが、創造主Linusは、1週間でgitの元となるものを創りだしたそうです。
安直な考えではありますが、元となるものが1週間で出来たのだったらコードもさほど煩雑ではないだろうし、歴史も長くないので破綻しているところも少ないだろうということで、コードが綺麗で弄りやすいだろうと期待したということです。
実際に見てみると、コードが上手く分割されていたり、変数名や関数名が分かりやすかったりと、かなり綺麗なものでした。
後述しますが、mailing listでmergeしてもらおうとする際には結構厳し目のレビューをされるようなので、そういった開発者コミュニティの努力によって維持された美しさなのかなと思います。
開発とは直接関係はありませんが、こういった綺麗なコードを読む機会は普段一人で開発している時には得難いものなので、そのためにもOSSのコードを読んでみることは良いのではないかと思います。
カッコよさ
「gitにコミットしたんだぜ」って言うとカッコ良さそうですよね。それだけです。
最初の手探り git add
最初に私達のチームでは
- commitメッセージを勝手に変える
git add
とするとgit add .
される
機能を実装することにしました。
あまり重くなさそうなタスクを探した結果、これらになりました。
1つ目はvinter君、2つ目は僕とtkk君が担当したので、僕は後者について解説します。
目的
現状git add
とするとgit add .
の間違いではないかと言われるが、当然その間違いであるので、そのような提案をするのではなく、実際にgit add .
と入力したものとした動きをする。
gitの処理の流れ(怪しい関数の探し方)
まず、git add .
した時の流れをgdbで追いました。
ただ、gdbで追っているだけだとどれが大事な関数なのかわかりづらいので、実際はソースをエディタで見て怪しい関数にめどを付け、その関数にbreakpointを貼るようにしました。
最初のうちは「怪しい関数」と言われてもよくわからなかったのですが、慣れてからの探し方は以下のような流れでした。
- gdbでどのファイルのどの関数に入ったのか見る
- そのファイルをエディタで見て、呼ばれる関数を探す
- その関数の中で、複数の処理をし、複数の関数が呼ばれていくはずなので、その中に怪しい物があるはず
- 引数のない関数は多分準備とか設定に関わっているものなので怪しくない
- 逆に、引数が多くて
run
とかhundle
とかcmd
とかのいかにも実行しそうな名前のついてる関数は怪しい
(gitはこのように命名がわかりやすいので非常に弄りやすい)
- 見つけた関数にbreakpointを設定し、1に戻る
- もし何らかの文章が表示された時は実効が完了してしまった可能性が高いので、飛ばした部分にある関数が怪しいとめどを付けてやり直す
こういった手探りを繰り返して分かったgitの大雑把な処理の流れは以下のとおりです。
- 引数として与えられたコマンドやオプションをparseする
- commandをbuiltinかexternalか判別
- commandに対応した関数を呼ぶ
です。
コードの中での関数の流れ(先述の怪しい関数)は主に以下の通りとなっていました。
main(git.c)
→handle_options(git.c)
→ run_argv(git.c)
→ handle_builtin(git.c)
→ cmd_add(builtin/add.c)
parseについては当然のことだと思われるので省略します。
builtin,externalについて、僕は知らなかったのですが、gitはプラグインを用いて自前のコマンドを用意することが出来ます。
もちろんそれはソースとは別の所にあるので、それらを区別する必要があるわけです。
それがrun_argv()
の中で行われて、builtinコマンドであればhandle_builtin()
が実行されます。
このhandle_builtin()
ではgit.c内で定義されているstruct cmd_struct commands[]
の中から対応する関数を探してきます。
このcommands[]
の定義はgit.c
の中でもひときわ目を引くので、エディタでみてればすぐに怪しいなと分かります。
実際、"add"
に対応しているのは cmd_add()
という関数であることがわかり、テキストエディタでプロジェクト内でこの関数で検索をかけてみると builtin/add.c
にこの関数を見つけることが出来ました。
更に、commands[]
のテーブルとbuiltinフォルダを見比べることで、「builtinコマンドの多くはこの builtin/hoge.c
のなかに cmd_hoge()
として定義されてるっぽい」ということまでわかりました。
add.cの流れ
次に、add
をした時の流れについて詳細に追ってみます。
先ほどの調査でbuiltin/add.c
の cmd_add()
が怪しいということが明らかになりました。
今回の目的はgit add
をgit add .
とすることだったので、まずはgit add
とした時にどこで例外処理されて終了するのかを探してみることにします。
gdbで b cmd_add
とした上で r add
として、n
を連打して飛ばし続けていると、add.c:357
の
if (require_pathspec && argc == 0) { fprintf(stderr, _("Nothing specified, nothing added.\n")); fprintf(stderr, _("Maybe you wanted to say 'git add .'?\n")); return 0; }
の部分で終わっていることが明らかにわかりました。
エラーで吐く文章も一致していることからも明らかですね。
無理矢理addするための二つの方法
今回は Maybe you wanted to say 'git add .'?
との忠告を無視して、無理矢理git add .
であるように振る舞いたいので、そのための方法を探します。
といっても、僕が実装した方法はとても愚直で、
argc==0だったらargv[0]に"."を入れておく
ということで解決しました。
つまり、エラーで提案するのではなく、あたかも最初からgit add .
されていたかのように引数を無理矢理修正したということです。
実際にこれでコンパイルしてみて実行すると、期待通りの挙動をしたので、目標は達成しました。
ただ、この方法は汎用性が低く、汚いという欠点が明らかだったので、どうにか関数を使って上手いことやりたいとも感じました。
それを実際にやってくれたのがtkk君で、彼はargcが0の時にはaddremoveを1にすることで解決していました。
このaddremoveという変数は、git add -A
の時に1になるフラグなので、git add -A
の挙動を示すことになりました。
gitはこのようにフラグでオプションを管理しているところが多いので、困ったら怪しそうなフラグを探すのも手段の一つとして有りうるのではないかと思います。
次回予告
以上、gitを手探った際のファーストステップ、簡単なコマンドを弄ってみた時の手順を解説しました。
次回は、もう少し実用的な修正をした時の記録を書いていこうと思います。
文章をCabochaで解析してグラフにして可視化する(歌詞可視化)
最近どうやら歌詞を可視化するのが流行っているようです。
何がおもしろくて朝の時間をこんなものにつぶしたんだと10時間前の自分を責めたい pic.twitter.com/Y8kffFm8gW
— 御苑トンネル (@Tatawidepine) 2015, 9月 28
自然言語処理をすれば簡単に自動化出来るんじゃないかと思ったので、文章を与えると流れを可視化してくれるプログラムを組んでみました。
出来上がったサンプルがこちら
使ったもの
事前準備
CaboChaのインストール
僕は既にMeCabとかをインストールしてあったので超簡単でした。
$ brew install cabocha $ gem install cabocha-ruby
graphvizのインストール
これもいつだったか使ったことがあったので僕は
$ gem install gviz
するだけでよかったのですが、もしこれからやろうと思った方は柿のサイトが参考になると重います。
Gvizの目次 - Rubyの世界からGraphvizの世界にこんにちは!
かなり親切に解説してありサンプルも豊富なので、rubyがある程度わかれば簡単に使えると思います。
仕様
このブログを書きながら「これもう誰かやってんじゃね?」と思って検索してみたら、2008年時点で先見の明のある方にすでになされていたようです。つらい。
こちらの方は形態素解析を用いているため、文節ではなく形態素(単語)がノードとなっています。 僕は最初に引用したツイートを参考にして作ったため、
- 文節ごとにノードにする
- ノードAからノードBに対する矢印は1本
- bold,solid,dashed,dottedの順で1~4回目の遷移先を指定
- 登場頻度の多いノードは大きくする
という特徴をつけています。
ちなみに、「歌詞の可視化」として曲名を入力すれば勝手に取ってきてくれるようにも出来ると思ったのですが、著作権的にアレなのでやめました。
コードと使い方
githubに上げてます。
mazamachi/sentence2graph
$ ruby generate_graph.rb lyrics.txt (name)
で実行できます。2つめのfilenameは保存するときのファイル名ですが、"."は含まないようにしてください。".png"は勝手につけます。 未指定の場合は、使ったテキストファイル名がlyrics.txtの場合はlyrics.pngとして出力されます。
デフォルトでは階層表示(dot)になっていますが、オプションとして"-n"をつけると、近いもの同士を近づけて(neato)表示されます。
感想
MeCabを用いた形態素解析は575認定などでよく用いていたのですが、そろそろ係り受け解析もしてみたいと思っていたのでちょうどいいタイミングだったと思います。
しかしgraphvizってすごいですね。全然仕組み理解していないけど、どうやらバネのモデルを使ったりしてるらしい?
めっちゃとんでる
「面白さ」という観点で言うと、やはり最初に引用させていただいたツイートは、面白くなるように色分けなどしているので、やはり自動化で面白くするには限界が有るなと感じました。
今後はせっかくだしwebアプリ化してみるなんてのも有りかもしれません。要望があるか暇だったらやってみます。
ちなみに、txtファイルならなんでも良いので、試しに『羅生門』でやってみたのですが、あまりに大きくなりすぎてしまって全く意味が分かりませんでした。 一応貼っときますが、かなり圧縮したので雰囲気だけ伝われば幸いです。
中2の頃から大好きなはてなのインターンで最高の経験をした話
学科内bot作成ハッカソンを開催したので知見を共有します
「学科内 bot作成 ハッカソン」季語: ハッカソン(夏)
学科の希望者を募ってTwitter botを作るハッカソン的なものを開催しました。 ハッカソンと言っても参加者の多くは授業でプログラミングをしているくらいなので大層なものではないのですが、企画者として色々と学びや反省点があったのでノウハウの共有も兼ねてまとめます。
個人的にこれは大事だと思ったことは強調しておくので、参考にしていただければ幸いです。
企画するまで
僕の所属する電子情報工学科では、一応情報系の名を冠する学科ということもあり、学科に配属された当時から「みんなでハッカソンとかしてみたいな」的な話が一部でありました。 が、そもそも全員が実際に開発した経験があるわけではないなどの理由から特に実現することもなくその話は流れて行きました。
しかし、先学期に転機が訪れました。というのもこの学科では、実験の一環として6~7月に学科全員が2人1チームでそれぞれ独自のIP電話を(C言語で)作って発表するという恒例行事があるため、全員が一応開発経験を積むことになります。 作ったものを人前で発表するという経験は僕もなかったのですがとても楽しく、皆も楽しんでいたようなのでまたやってみようと思い、ハッカソンを企画・開催することにしました。
企画段階
参加者はtwitterや学科のslack上で募り、ある程度の人数が集まりそうだということで開催を決定しました。
googleからハッカソン 運営ガイドというものが公開されており、これを読み込むことで企画側としてのイメージを固めていきました。 ハッカソン開催を考えている人は是非読んでみることをオススメします。
教室を借りるための書類が必要だったりしてちょっと面倒だったのですが、お世話になっている先生のご協力を賜ったため割とスムーズに進みました。 開催場所は先述の運営ガイドに則り、
- プロジェクター有り
- 十分なコンセント有り
- 机同士が向かい合った会議室のような部屋ではなく、一つの机に2,3人の教室のような部屋
としました。 チームで開発するハッカソンではこれらが必須条件なのではないかと思います。
準備段階
実際に準備を始めた段階で想定された主な困難は以下のようなものでした。
- 一日で完成させる自信のある人が少ない
- アイディア出しが大変そう
- メンターの数が少ない
- そもそも企画者の僕がハッカソンに参加したことがない
それぞれどう解決したかをまとめます。
一日で完成させる自信のある人が少ない
授業でC言語使った経験しかない人も多かったのですが、とにかく全員が作ってみるのが大事だと思ったので全員に完成を目指してもらうことにしました。 そのために、
と細かい限定をかけることで、全員の足並みをそろえることにしました。 この条件は実は普段僕がbotを作る際にやっているものであり、実際に参加者が作り始める前に僕からノウハウを教えることで、スムーズに開発を開始できたのではないかと思います。
アイディア出しが大変そう
botを作ったことがあればtwitter APIを使って何ができて何ができないのかわかるので作りたいものの困難さも大雑把にイメージできますが、初めてbotを作る際には大変だろうということで、参加者への事前アンケートでアイディアを聞いておくことにしました。
その上で、回答として出てきたアイディアそれぞれに対して「自分だったらこんな感じで作る」「これはちょっと難しいかも」といったアドバイスをこちらから供給してみました。 どれほど参加者の役に立ったのかは分かりませんが、企画者が開発を始める前にアドバイスをすると開発を始めるのが楽になるのではないかと思います。
メンターの数が少ない
僕一人でメンターをするつもりだったのですが、さすがにキツそうなのでB4の先輩に手伝っていただくことにしました。圧倒的感謝。
参加人数が14人だったのでメンターは二人で何とかなりましたが、だいたい5,6人に一人くらいはメンターがいた方が良いのではないかと思います。まだ一回しか開催していないので印象でしかありませんが。
そもそも企画者の僕がハッカソンに参加したことがない
ハッカソンに参加したことがなくても、ハッカソンは開催できるという前例を作ったのでみなさん気軽に開催してみてください。先述のハッカソン運営ガイドは素晴らしいです。読み込みましょう。
開催直前〜当日
事前課題
さすがに当日だけでは間に合わなさそうなので全員に以下の事前課題を課しました。
環境構築段階ではやはり人によってはエラーが出まくっていたようなのでサポートが必須だなと感じました。 だからといって全員揃ってやっているとエラーの出た人が律速段階になってしまいがちなので難しいところです。 今回の場合はslackでエラーコードを貼ってもらいながら解決できたので、そういったコミュニケーションツールの選択も重要だと思います。
herokuへの登録はまぁスムーズだったのですが、最近herokuの無料プランの使用が変更されてしまったので僕も勝手がわからないところがありました。 開催者側は最新の情報にキャッチアップしておくべきであると思います。今回の 反省点の 一つです。
rubyの基礎の勉強についてですが、やはりこれが一番の負担になっていたように感じます。全員に書籍を買わせるわけにも行かなかったのでとりあえずドットインストールを紹介したのですが、後でよく考えてみるとオブジェクト指向プログラミング等は今回のハッカソンにはオーバースペックなところがあったかもしれません。 紹介する教材選びももっと慎重にすべきでした。
スライド・テンプレート・メンタリング
先述したとおり、今回のハッカソンでは僕のノウハウを伝えるべくスライドを作成したのですが、なかなか時間が取れなかったために、メンタリング段階で質問されるまで後回しにしたものも有りました。 当然ですがスライド作成は早めにやりましょう。
スライドを作る際に意識したことは
- 難しそうという意識を取り除く
- 皆が使いそうなものは具体的に教えてしまう(ツイートする方法など)
- 調べ方を教える
です。伝わったかは分かりませんが。 特に3つ目の「調べ方」についてはハッカソンにかぎらず開発の仕方を教えるのであれば必須ですね。すべてを教えることはできません。
ちなみに「難しそうという意識を取り除く」ために、今回僕は「twitter botとはinput/outputのいずれかもしくは両方がtwitterであるプログラムにすぎない」という名言を生み出しました。どうぞ使ってください。
twitter botの場合は特に顕著ですが、認証部分・定期的実行などは誰でもほぼ一致するので、githubでテンプレートとなるものを公開してみんなにpullして貰う形で進めました。 自分でもこれは良い選択だったと思っています。
実際に開発が始まるとやはり同じような質問が頻繁に出てくるので、FAQをタイムリーに更新して共有したほうが良かったかもしれません。
発表
みんな時間がなさそうなので口頭での発表で済ませましたが、後々のことを考えるとその場で終わってしまうのではなく、webとかで公開できるようにスライドを必須にすべきだったかもしれません。 参加者は全員僕が想像していたよりもすごいものを作ってきたので、ただ「楽しかった」で終わるのではなく、その後に繋がるような処置をしておくべきでした。
終了後
Google先生曰く、ハッカソン後の飲み会は必須とのことです。お互いを讃え合いましょう。ちなみに僕は疲れでめっちゃ酔いました。
終了後も質問は受け付けていました。どうやらその後もbot作成を続けてくれている人も多いらしく、嬉しい限りです。
ただ、開催者側に対するフィードバックを得るのを忘れていたので、開催後すぐにでも事後アンケートを行うべきだったと反省しています。 普段授業後のアンケートとか答えるの面倒くさいと思っていましたが、開催側へのフィードバックも大切なんですね。
まとめ
- 参加者のレベルに合わせた準備を行う
- 開催する以上は責任をもって教える
- 双方のフィードバックを大切にする
- 開催するのは楽しい
参加してくれた人達と手伝ってくれた方々、ありがとうございました(o_ _)o