大学生から始める curl コミュニティ参加生活

(2017/01/17 に **本来書きたかったこと** 以降を追記しました。)

最近 curl を使うことが多くなり、変更を加えることがあったので、
コミュニティ版のビルド・テスト、パッチの投稿を、平均的な情報系大学生が実施できる程度で簡単に記載します。
大学生と書いていますが、英語・C 言語の読み書きが同程度できれば良いです（学生時代の自分がやるとしたら。。。今でもギリギリ）。

以降の説明での環境は以下の通りです。

* Ubuntu 14.04.5 LTS on kvm
* CPU: 2700 MHz x 1
* MEM: 2 GB

# curl のビルド

## コミュニティ版をダウンロード  
curl は github に登録されているので、`git clone` コマンドで取得します。

```
git clone https://github.com/curl/curl.git
```

以下のような結果になれば取得完了です。

```
# git clone https://github.com/curl/curl.git
Cloning into 'curl'...
remote: Counting objects: 122287, done.
remote: Compressing objects: 100% (13/13), done.
remote: Total 122287 (delta 2), reused 0 (delta 0), pack-reused 122274
Receiving objects: 100% (122287/122287), 41.07 MiB | 321.00 KiB/s, done.
Resolving deltas: 100% (94752/94752), done.
Checking connectivity... done.
```

もしくは、ブラウザでアクセスし、"clone or download" ボタンを押した後に現れる "[Download ZIP](https://github.com/curl/curl/archive/master.zip)" で取得します。
なお、この方法で取得すると後の `git` コマンドは使えないのでご注意下さい。

## curl をビルド
`git clone` したディレクトリ(ここでは curl) に移動し、以下の通り `make` まで実施します（全体で 5 ～ 10 分程度掛かります）。
`buildconf` スクリプト実行時にビルドする状態を満たしていない場合、必要なパッケージとそのバージョンを示してくれるので、その指示に従って下さい。

```bash
cd curl
./buildconf
./configure
make
```

参考までに、ビルドするためには少なくとも以下のパッケージをインストールしている必要があります。
詳細は curl の [GIT-INFO](https://github.com/curl/curl/blob/master/GIT-INFO) ファイルを参照して下さい。

* autoconf
* automake
* libtool
* m4

実行時の出力としては以下のようになれば問題ありません。

```
# cd curl
# ./buildconf 
...
buildconf: OK
   ★ OK が表示されている
# ./configure
...
configure: Configured to build curl/libcurl:

  curl version:     7.52.0-DEV
   ★ ビルド時のバージョンや設定が表示されている
...
# make
...
make[1]: Leaving directory '/home/foobar/curl'
   ★ エラーメッセージが表示されていない
```

## ビルドした curl の実行  
動作することを確認するために `src/curl` でバージョンを表示します（適当な URL を渡しても良いです）。

```
src/curl -V
```

バージョンの確認をした場合、以下のように ubuntu 14.04 での curl とは異なるバージョンが表示されます。

```
# src/curl -V
curl 7.52.0-DEV (x86_64-unknown-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3
     ~~~~~~~~~~
...
# curl -V
curl 7.35.0 (x86_64-pc-linux-gnu) libcurl/7.35.0 OpenSSL/1.0.1f zlib/1.2.8 libidn/1.28 librtmp/2.3
     ~~~~~~
...
```

なお、`src/curl` はスクリプトで `src/.libs/lt-curl` を作成し、これを実行しています。

# curl の変更、および、テスト

## 変更を加える
変更を加えたいソースファイルを好きなテキストエディタで開いて編集します。

```
vi <対象のソースファイル>
```

## 再ビルド
変更を加え終わったら、再度ビルドし動作を確認します。
（変更を加えたファイル・機能によっては `configure` から行います。）

```bash
./configure [適切なオプション]
make
src/curl <適切な引数>
```

## テストケースを実施
以下のコマンドを実行すると、コミュニティ提供のテストケースが実行されます（10 〜 20 分程度掛かります）。

```
make test
```

以下のようにテスト結果が表示されます。

```
# make test
...
test 2053...OK (1039 out of 1040, remaining: 00:01)
test 2054...OK (1040 out of 1040, remaining: 00:00)
TESTDONE: 749 tests out of 749 reported OK: 100%
TESTDONE: 1050 tests were considered during 578 seconds.
make[1]: Leaving directory '/home/foobar/curl/tests'
```

失敗したテストがある場合は `TESTFAIL` の行が追加され、そのテスト番号が表示されます。
テスト番号は tests/data ディレクトリにあるファイルから先頭の test を除いた値になります。

```
...
TESTDONE: 748 tests out of 749 reported OK: 99%
TESTFAIL: These test cases failed: 1212 
TESTDONE: 1050 tests were considered during 576 seconds.
```

特定のテストケースを実施する場合は、tests ディレクトリに移動し、以下の perl スクリプトを実行します。

```bash
cd tests
./runtests.pl <テスト番号> ...
```

# コミュニティにパッチを提供する

修正したソースファイルの記述方法に明らかな問題がないかどうかを以下で確認します。

```
make checksrc
```

特に問題がなく、かつ github アカウントがある場合は、pull request を発行します。
その際、変更した内容を英語で詳しく説明します（自分は英語辞書や人と相談しながら、なんとか書いています）。

github アカウントがない場合は、`git format-patch` や `diff` を使用して、
パッチファイルを作成し、curl の開発用メーリングリストに投稿します。

詳細は [curl のコントリビュートのページ](https://curl.haxx.se/dev/contribute.html)を参照して下さい。


# 本来書きたかったこと

この記事では、実際に問題(バグなど)を見つけてコミュニティにマージされるまでの例を記載したかったので追記しました。
(言い訳としては、思いのほか時間が取れなかったり、別問題の修正もしたりで間に合いませんでした。反省。。。) 

取り上げる Pull Request は以下になります。

[url: Fix NO_PROXY env var to work properly with --proxy option. #1140](https://github.com/curl/curl/pull/1140)

## どうやって問題を見つけるのか

古典的な問題の見つけ方(と思っている方法)としては以下があります。

<dl>
<dt>1. curl コマンドの man page や manual を読む。</dt>
<dd>読んだだけでは使い方がわからなければ、説明が不足しています。</dd>

<dt>2. curl コマンドを使ってみる。</dt>
<dd>色んな使い方(オプションを組み合わせてみるなど)をした結果、直感と反する(man page や manual と違う挙動をするなど)なら、文章が間違っているか、不足している、または curl コマンドにバグがあります。</dd>

<dt>3. curl コマンドのソースを読んでみる。</dt>
<dd>セキュリティホールやメモリリークなどになりそうな実装があるかどうか探します。
(多分、大抵の人は検出ツールなどと併用して探すはず。。。)<dd>
</dl>


PR #1140 は、環境変数とオプションを組み合わせて使っているときに見つけました(上記 2つ目)。
なお、環境変数を使っていたのは毎回同じ効果のあるオプションを指定するのが手間だったためです。


## 見つけた問題はどうするのか

他の人が同様の問題を訊いていないか少なくとも以下で確認します。
* [Known Bugs (既知の問題) の一覧](https://curl.haxx.se/docs/knownbugs.html)
* [Mailing Lists のアーカイブ](https://curl.haxx.se/mail/list.cgi?list=curl-library)
* [github 上の curl の issue チケット](https://github.com/curl/curl/issues)

確認の結果、同様のものがない、または、あっても自分の疑問が解決しないならば、以下を行います。

* mailing list 上で訊く
* 同様の問題を訊いている issue があれば、その issue で質問する。もし、なければ、github 上で New issue として発行する

PR #1140 は、New issue を発行せすに、自分で修正を作った上で Pull Request を発行しています。


## どんな内容で報告するのか

他の人に、自分だけの問題でないことを伝える必要があるので、以下を記載するようにします。

* どんな問題が起き、どの程度発生するのか(、またどうしたら発生するのか)。
* 報告する対象の最新の状態がどうなのか。
* 自分はどんな状態を望み、それが他のユーザにどんな利益があるか
* 例を記載する

PR #1140 では、以下のような曖昧な説明で発行したので、内容を再確認されています。

* work と書いたので、どんな動きをするのかわかりづらい(access とか書くべきだった)。
* プロキシ経由する/しないと書くために proxied/non-proxied と書いているが、明に access through proxy/direct access と書くべきだった。

その後は、質問や要望に応えながら、内容を修正していっています。
その結果、PR #1140 では、

* --proxy オプションを使用した場合、NO_PROXY 環境変数で直接アクセスすることを指定したホストにプロキシ経由でアクセスする問題の修正

だけでなく、

* NO_PROXY 環境変数と同じ効果がある --noproxy オプションを使用した場合、NO_PROXY 環境変数で指定したが、--noproxy オプションでは指定しなかったホストにプロキシ経由でアクセスする(オプションが環境変数を上書きしない)問題の修正
* 修正した結果の挙動のドキュメントへの記載

も行っています。

なお、マージ時にコミットをまとめているので、github 上のやり取りと修正内容を比較したい場合は
[まとめる前のブランチのバックアップ](https://github.com/eramoto/curl/commits/backup_fix-noproxy-env-with-proxy-option)を参照してください。