$ git clone git://github.com/clojure/clojure.git
$ cd clojure
Clojureにパッチを提供したり、貢献することに興味がある場合は、開発概要をご覧ください。
コーディングを始める前に以下の項目を検討することで、評価しやすく、受け入れられやすいパッチを作成できます。
解決しようとしている問題は何か? パッチを作成する前に、問題点を明確にして、パッチの説明に含める必要があります。
解決策のアプローチは何か? コードから推測する必要がないように、説明の中で明確にしてください。
コミュニティでアイデアを検証したか? 可能であれば、Slackまたはメーリングリストでコアチームのメンバーと話し合ってください。(タイプミスなど、すべての場合に必要ではありません。)
検討した代替案とそのトレードオフを表にしてください。選択した解決策が最良の選択である理由を説明してください。
パッチが動作することをどのように証明するか? テストを含めるように計画してください。例に基づくテストも可能ですが、生成的テストが推奨されます。
チケットにパッチの変更点を文書化してください。変更内容とその理由を審査担当者が理解するのに役立つ情報は、審査担当者の作業を容易にします。
やり過ぎない! 特定の問題に対処する小さなパッチを提出してください。余分なものは追加しないでください。近くのコードの「クリーンアップ」でさえ(特に!)追加しないでください。これはパッチの意図を混乱させるだけです。
コメントが寄せられたら、説明を最新の状態に保ってください。コメントスレッドを読んでチケットの現在の状態を再構築するのは非常に時間がかかります。
支持を集める。投票は良いことであり、チケットをレビューしている他のユーザーからのコメントはさらに優れています。
チケットが大きくなったら、どのパッチがアクティブであるかを明確に文書化してください。古いパッチを削除するのではなく、コメントでパッチを名前で参照してください。
コードを作成する準備ができたら、まずClojureまたは適切なリポジトリのクローンが必要です。以下の例はClojureプロジェクト、つまりClojure自体への提出用です。
$ git clone git://github.com/clojure/clojure.git
$ cd clojure
次に、自分のための新しいブランチを作成します。
$ git checkout -b fixbug42
Switched to a new branch "fixbug42"
これでハッキングの準備ができました。作業を開始する前に、既存のすべての回帰テストがまだパスすることを確認してください。たとえば、Clojureの場合はMavenを使用します。
$ mvn clean test
...lots of output...
test:
[INFO] Executed tasks
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 01:26 min
[INFO] Finished at: 2018-12-05T14:36:54-06:00
[INFO] ------------------------------------------------------------------------
変更が完了したら、コミットする必要があります。コミットメッセージの先頭にJIRA番号(CLJ-xyz)を付け、変更が対応する問題または機能拡張に関する記述を含めてください!
$ git commit -a -m "CLJ-932 fixed annoying bug"
Created commit 8f7c712: fixed annoying bug
1 files changed, 0 insertions(+), 1 deletions(-)
変更を行ったので、パッチに適用する必要があります。リポジトリを更新し、発生した競合を修正する必要があります。
$ git checkout master
Switched to branch "master"
$ git pull
...
$ git checkout fixbug42
Switched to branch "fixbug42"
$ git rebase master
競合を修正したら、パッチを作成する準備ができました。
$ git format-patch master --stdout -U8 > clj-932-1.patch
これで、そのパッチファイルをJIRAチケットに添付できます。ページ上部付近の[その他のアクション]メニューで、[ファイルの添付]を選択します。添付したパッチについてコメントを書く際には、以下の推奨事項を読んで従ってください。審査担当者は審査に使える時間が限られています。できるだけ明確で、審査担当者の時間を効率的に使えるようにすることで、パッチが承認される可能性が高くなります。
パッチファイルの接尾辞として、.txtではなく.patchまたは.diffを使用してください。
添付する前にパッチファイルを読んでください。変更しているコードの部分とは関係のない空白の変更などが見つかった場合は、編集して削除し、パッチを再生成してください。また、開発中は複数のコミットを順番に行い、各コミットの説明を付けるのは良いことですが、パッチのレビュー担当者は通常、レビューのためにすべての変更を1つのコミットにまとめることを好みます。
'git add --patch'を使用して変更をステージングすると、無関係な変更をコミットしにくくなります。
チケットに既存の添付ファイルとは異なる名前を使用してください。JIRAでは、同じ名前で複数の添付ファイルを追加できますが、後から追加したファイルは以前のファイルを置き換えません。これは、パッチを名前で参照するときに混乱を招く可能性があります。
パッチを参照するコメントには、ファイル名と日付を含めてください。日付と時刻に基づいてコメントとパッチを照合することは可能ですが、面倒でエラーが発生しやすいです。
チケットが更新されるたびにメールを受信するには、ページの右上にある「ウォッチ」をクリックしてください。これは、他の誰かがパッチにコメントしたり、新しいパッチを作成したりした場合などに役立ちます。チケットの更新メールを停止したい場合は、「ウォッチ中」をクリックしてください。自動メールがスパムフィルターを通過することを確認することをお勧めします。メールはJIRAアカウントに関連付けられたアドレスに送信され、jira@dev.clojure.orgのアドレスから送信されます。
1つ以上の以前のパッチを組み込んだ新しいパッチを作成する場合は、すべてを1つのパッチファイルにまとめて、コメントにその旨を記載してください(置き換えるパッチのファイル名と日付を付けて)。この例外は、複数の人からの大幅に独立した貢献(たとえば、1人がコードを変更し、もう1人がテストを書いた)があり、両方がクレジットを希望する場合です。その場合は、複数のコミットを含む単一のパッチファイルで問題ありません。ただし、同じコードを繰り返し変更する複数のパッチは避けたいです。
「パッチ」フィールドを編集して、審査の準備ができているパッチがあることをチケットに示します。チケットのページの左上付近にある[編集]ボタンをクリックします。次のページで、横にポップアップメニューがある「パッチ」という見出しを探します。そのメニューから「コード」または「コードとテスト」を選択し、ページ下部にある[更新]ボタンをクリックします。チケットのページに[編集]ボタンが表示されず、CAに署名している場合は、開発者メーリングリストまたはClojurians Slackの#clojure-devで、Jiraチケットを編集する権限を要求してください。
パッチを削除するには(例:パッチが不要になったため)、チケットのページに移動し、「説明」テキストの下にある「添付ファイル」の見出しを探します。右端にはプラス記号と三角形があります。三角形をクリックし、メニューから「添付ファイルを管理」を選択します。削除するものを慎重に考え、その横にあるゴミ箱アイコンをクリックします。注:ほとんどの人は自分の添付ファイルを削除する権限を持っていますが、他の人が追加した添付ファイルは削除できません。
一般的に、古いパッチを削除する必要はありません。そのままにしておき、チケットの説明で最も関連性の高いパッチを追跡してください。
古いパッチとは、以前は最新のClojureマスターバージョンに正常に適用されていましたが、パッチの作成後にコミットが行われたため、適用できなくなったパッチのことです。特に、このコマンドの出力
$ git am --keep-cr -s --ignore-whitespace < patch_file.patch
に「パッチに失敗しました」と「元のブランチを復元してパッチ適用を停止するには、「git am --abort」を実行してください」が含まれています。上記のコマンドによって残された失敗したパッチ適用試行の状態を取り除くには、「git am --abort」を実行する必要があります。
「git am」は非常に「壊れやすい」です。つまり、patch_fileが特定のバージョンのソースコードで作成された場合、コマンドが失敗するのに必要なのは、パッチファイルに存在するコンテキスト行のいずれかが変更されることだけです。パッチによって変更されている行の1つではない場合でもです。これは、ユニットテストを含むファイルで特に一般的です。人々は通常、そのようなファイルの最後に新しいテストを追加するため、2つの異なるパッチが同じファイルの最後に新しいテストを追加した場合、新しいテストの前のコンテキスト行が変わります。
このようなパッチを適用するには、--rejectフラグを使用します
$ git apply --reject patch_file.patch
出力は、パッチファイルの各「ハンク」が成功したか失敗したかについてのヒントを提供します。すべて成功した場合、パッチファイルの問題は、いくつかのコンテキスト行が変更されたことだけである可能性があります。ハンクが失敗した場合、パッチは適用されなかった拒否されたハンクを含む「.rej」で終わるファイルを作成し、ソースコードがより大幅に変更された可能性のある場所としてそれらに焦点を当てることができます。このようなコマンドは、それらをすべて見つけます
$ find . -name '*.rej'
これらの拒否されたハンクを確認し、おそらくそれらがまだ適用されるかどうか、どのように適用されるかについて少し考えて、ソースコードを手動で編集して適用する必要があります。
新しいgitパッチを作成する場合
$ git format-patch master --stdout -U8 > patch_file.patch
ファイルの上部付近に名前と現在の日付が配置されます。変更がコンテキスト行のみの場合、開始した元のパッチから名前と日付をコピーして元の作成者のクレジットをそのままにしてから、アップロードしてください。
元のパッチにユニットテストがなかった場所にユニットテストを作成したが、それ以外は元のパッチを変更せず、作業のコミットログに自分の名前を付けたい場合は、更新されたパッチに元の作成者の名前を残したまま、自分の名前を付けたテスト追加の別々のパッチを作成してください。
パッチをテストする審査担当者の場合、新しいブランチを作成し、パッチを適用して作業を開始できます。
$ git checkout -b testxyz
$ git am --keep-cr -s --ignore-whitespace < patch_file.patch
作業が完了したら、そのブランチは破棄できます。
$ git checkout master
$ git branch -D testxyz
$ mvn clean test
擬似乱数生成のジェネレーティブテストの所要時間を60秒から1秒(例えば)に短縮するには、src/script/run_test_generative.cljファイルを編集し、60000の数値を変更します。ただし、提出するパッチにこのような変更を含めないように注意してください。(Clojure 1.6.0以前では、ファイル名はsrc/scripts/run_tests.cljでした)
まず、テストを実行せずに最新のClojureをビルドします。
$ mvn -Dmaven.test.skip=true clean package
# If no compilation errors, mvn command above creates target/clojure-VERSION-master-SNAPSHOT.jar
上記のコマンドはClojureのjarファイルを作成しますが、テストのコンパイルも実行もしません。
必要な依存関係を記述したdeps.ednファイルを作成します。
{:paths ["test"]
:deps
{org.clojure/clojure {:mvn/version "RELEASE"}
org.clojure/test.check {:mvn/version "0.9.0"}
org.clojure/test.generative {:mvn/version "0.5.2"}}
:aliases
{:dbg {:classpath-overrides {org.clojure/clojure "target/classes"}
:extra-deps {criterium/criterium {:mvn/version "0.4.4"}}}}}
cljを使用してREPLを起動し、そこから個々のテストを実行します。
$ clj -A:dbg
Clojure ...
;; We're testing with clojure.test
=> (require 'clojure.test)
nil
;; Load a test file
user=> (require 'clojure.test-clojure.data)
nil
;; Run it
user=> (clojure.test/run-tests 'clojure.test-clojure.data)
Testing clojure.test-clojure.data
Ran 1 tests containing 17 assertions.
0 failures, 0 errors.
{:type :summary, :pass 17, :test 1, :error 0, :fail 0}
REPLを起動し、そこからジェネレーティブテストを実行します。
ジェネレーティブテストは、追加のテストjar(./antsetup.shを実行するとインストールされます)を使用します。そのため、antsetup.shがmaven-classpathファイルに残す追加のクラスパスが必要になります。 *nixを使用している場合、このファイルを利用する最も簡単な方法は次のとおりです。
$ clj -A:dbg
Clojure ...
;; Install some clojure.test extensions
user=> (require 'clojure.test-helper)
nil
;; Load a test file that uses test.generative
user=> (require 'clojure.test-clojure.reader)
nil
;; Load the test.generative runner ns
user=> (use 'clojure.test.generative.runner)
nil
;; Test a specification on 1 thread for 200 ms
user=> (run 1 200 #'clojure.test-clojure.reader/types-that-should-roundtrip)
{:iter 60, :seed 1255541066, :test clojure.test-clojure.reader/types-that-should-roundtrip}
nil
デフォルトでは、Clojureは直接リンクが有効になってビルドされます。これはパフォーマンスを向上させますが、関数Aが関数Bを呼び出す場合(どちらもClojure内)、specを使用してBをインストルメント化しても、Aはインストルメント化されたバージョンではなく、元の関数Bを呼び出し続けることを意味します。 Bをインストルメント化し、Clojureの他の関数がインストルメント化されたバージョンを呼び出すようにするには、直接リンクを無効にしてClojureをビルドする方法があります。
'target name="compile-clojure"'で始まるセクション内にある、build.xmlファイルの次の行で「true」を「false」に置き換えます。
<sysproperty key="clojure.compiler.direct-linking" value="true"/>
次に、ソースからClojureをビルドする preferred な方法を使用します。例:
$ mvn -Dmaven.test.skip=true clean install