2012年12月16日日曜日

phpbrew + Template for Jenkins Jobs for PHP Projects 的なもの

そろそろPHP通算歴が半年くらいになっちゃうんじゃないかなぁ…

今や 継続インテグレーションは強みではなくなった [プログラマー現役続行] らしいですし、
PHPヤダヤダ言っててもしゃーないしで試してみました。

ていうか自動テスト環境すらないもの引き継がせんじゃねぇ糞が

ちなみに強引に動かしてます。


用意した環境
  • Cent0S6.3 64bit的な環境

主な参考サイト
Template for Jenkins Jobs for PHP Projects
c9s/phpbrew

Template for jenkins Jobs for PHP Project のリンク先に Integrating PHP Projects with Jenkinsなんて本がありますね。
2011/09 に出てたっぽいのですね。
うーむ、CIはもう常識なんですね、やばいなぁ…



jdkとかjenkinsはテキトーに入っている前提
jenkinsの導入はこの通りにyumで


phpbrew install

phpbrewのサイトのほぼ指示通りですね
Install phpbrew into system-wide environment の部分を参考にしています。
理由はjenkinsに無理やり使わせるためです

phpbrewで5.3.10を入れている理由は、phpbrew variants でサンプルで出てきたからという理由です。
皆さんお好きな環境でどうぞ。
+iconvしているのは、後々入れるphpmdやらphplocやらが使うからという理由です。
その他yumで入れているものは、カラの環境だと インストール時に怒られるから…という理由から入れています。

なお、自前でオプションを指定したい場合は「--」のあとに続けるとできます

phpbrew install

主に Install phpbrew into system-wide environment 参考

# phpが全く入っていないのはダメ

yum install php php-xml
yum install --enablerepo=rpmforge re2c libmhash

curl -O https://raw.github.com/c9s/phpbrew/master/phpbrew
chmod +x phpbrew
cp phpbrew /usr/bin/phpbrew

phpbrew init

#pythonbrewが入れてくれるやつをパクってみた

cat << _EOS_ >> /etc/profile.d/phpbrew.sh
#begin-phpbrew
if [ -n "${BASH_VERSION:-}" -o -n "${ZSH_VERSION:-}" ] ; then
    export PHPBREW_ROOT=/opt/phpbrew
    source /opt/phpbrew/bashrc
fi
#end-phpbrew
_EOS_

mkdir /opt/phpbrew
cp /root/.phpbrew/bashrc /opt/phpbrew/bashrc
source /etc/bashrc

yum install bison-devel bison libxml2-devel libxslt-devel

phpbrew install php-5.3.10 +default +iconv
# 自分でオプションを指定する場合は
# phpbrew install php-5.3.10 -- --with… みたいな

# 完了したら phpbrew switch/use php-5.3.10
# Dateの設定をしておく
vim /opt/phpbrew/php/php-5.3.13/etc/php.ini
[Date]
date.timezone = "Asia/Tokyo"

phpbrew use php-5.3.10

yum install autoconf
pecl install xdebug
phpbrew enable xdebug

# xdebug.iniを書き換える
vim /opt/phpbrew/php/php-5.3.10/var/db/xdebug.ini 

zend_extension=/opt/phpbrew/php/php-5.3.10/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so
view raw 2.md hosted with ❤ by GitHub



Template for Jenkins Jobs for PHP Projects とビミョーに違うところとか

まあ大体一緒です。
phpdoxじゃなくてphpdoc入れているところとかですかね。(ppwが作るやつがphpdoc使っているし)
あとppwでプロジェクト作るから…とかが差異だったりとか
その他plugin入れたり、テンプレートプロジェクトを入れたりとかは
同じことしているので省略

ビミョーに違うところ

Template for Jenkins Jobs for PHP Projects とビミョーに違うところ

pear config-set auto_discover 1
pear install pear.phpqatools.org/phpqatools 
# phpdoxじゃなくて http://www.phpdoc.org/ を入れた
pear channel-discover pear.phpdoc.org
pear install phpdoc/phpDocumentor-alpha

# php project wizardも必要なら入れておく
# https://github.com/sebastianbergmann/php-project-wizard
pear install phpunit/ppw
view raw 3.md hosted with ❤ by GitHub




jenkins先生に頑張っていただく

まずはプロジェクトを作ります。
テンプレがあるので楽ですね。
Template for Jenkins Jobs for PHP Projects 様様です

さて、Antを実行と見せかけて下記のようにします。
無理やりphpbrewを使うためです。
antもシェル上で叩いていますが、これを分離してしまうと
せっかく無理やり認識させたphpbrewが使えないからです。
うーむ無理やりw
なお、使用しているAntはJenkins先生が自分でインストールしてくる奴のパスを叩いています。
一度はAntタスクを実行しないとインストールされませんので、その辺は適当に。

export PHPBREW_ROOT=/opt/phpbrew
source /opt/phpbrew/bashrc
phpbrew use php-5.3.10
$JENKINS_HOME/tools/Ant/1.8.4/bin/ant


publish HTML report もほんのちょびっとだけいじります
index.xhtml → index.html にするだけ。
実際上記の通り作ると、build/api 以下にそう作られていたから…以上の意味は無いです。




準備ができたらppwでプロジェクトを作ります。
別に自前でant用のbuild.xml書いてもいいですけど、メンドイですよね。

他にもMave for phpなんてのもあるし、
そもそも時代はGradleらしいです。
Ant使っている場合じゃねぇ(AAry

そこはとりあえず置いといて…

ppwがデフォルトで作成してくれる状態に超テキトーにソースを加えたものを実行してみました。
ここに置いときます


テストは通ってないし、警告は出るしで最低ですねw
常にJenkins先生を怒らせないような状態を保つようにすれば、
もしかしたらPHPもゴミクズのように言われない日が来るかもしれませんね。







まあそんな日は来ないだろうけどな





2012年11月5日月曜日

rhodecode1.4.4を試してみた #tokyomercurial

世の中GithubEnterpriseでpullrequest方式での開発が
一部では標準化しているんじゃないかと思われる今日この頃いかがお過ごしでしょうか?

とは言うものの、いくら有用性を語ってもそうそう導入されるような世界じゃないですよね?高いし。
せめてGithub/Bitbucketの有料アカウントを…と思ってもそれもねぇ…って世界ですよね(´;ω;`)

そんな僕達がPullRequest方式で開発したい!!そうだRhodeCodeがあるじゃないか!!
という私やあなたみたいな方にお届けするエントリーですw

あ、ちなみに件名に#tokyomercurial を追記した理由は特にありません。
あえていうなら、このツイートがあったので…ぐらいかな?



あ、ちなみに長いのでご注意ください


試した環境はこんな感じ

  • CentOS6.3 64bit minimal状態から
  • VirtualBox上で

すげー大雑把にやりますので、必要な部分は適宜脳内補完でお願いします

実験用なのでselinux/iptablesは無視

最初は…
とりあえず入れましょう。
使わないのもあるけど。

最初に入れたもの

yum -y install yum-priorities
yum -y install wget
yum -y install vim-enhanced.x86_64

wget http://ftp-srv2.kddilabs.jp/Linux/distributions/fedora/epel/6/x86_64/epel-release-6-7.noarch.rpm
rpm -ivh epel-release-6-7.noarch.rpm

wget http://rpms.famillecollet.com/enterprise/remi-release-6.rpm
rpm -ivh remi-release-6.rpm

vim /etc/yum.repos.d/remi.repo // enableに

yum -y install make
yum -y install gcc-c++
yum -y install kernel-devel-2.6.32-279.el6.x86_64
yum -y install openssl-devel
yum -y install sqlite-devel
yum -y install readline-devel
yum -y install ncurses-devel
yum -y install zlib-devel
yum -y install bzip2-devel
yum -y install git-all
view raw 01.md hosted with ❤ by GitHub


python周り入れましょう。
最初から入っているのは2.6系のはずですし、別にそのまま使ってもいいですが…
pythonbrewという流行りに乗っかっておきましょう。
→ それだったら pythonz で入れろって話しなんでしたっけ?
下記はちょっと時間かかるので、コーヒでも入れましょう。

pythonインストール

curl -kLO https://github.com/utahta/pythonbrew/raw/master/pythonbrew-install
chmod +x pythonbrew-install
./pythonbrew-install

pythonbrew install --configure="--with-zlib \
--with-bz2 \
--with-ssl \
--with-readline \
--with-ncurses \
--with-expat \
--with-sqlite3 \
--with-crypt \
--with-md5 \
--with-sha" 2.7.3
pythonbrew switch 2.7.3

python -V で2.7.3が出ること
python (REPL起動)
> import ssl (でエラーが起きないこと確認)
view raw 02.md hosted with ❤ by GitHub


おまたせ、rhodecodeです。時間かかります。
なぜならいっぱい一緒に入りますから。当然Mercurialもこの時入りますので。
さっき作ったコーヒでも飲みましょう。

rhodecodeインストール

pip install rhodecode
view raw 03.md hosted with ❤ by GitHub


使用するwebサーバでも入れましょう。
rhodecodeのドキュメントにはapacheとnginxのサンプル設定が乗ってますので、テキトーに。
ここではnginx入れます

nginxインストール

nginx.repoを /etc/yum.repos.d に設置後

yum -y install nginx
view raw 04.md hosted with ❤ by GitHub

[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/centos/6/$basearch/
gpgcheck=0
enabled=1
view raw nginx.repo hosted with ❤ by GitHub



さて、rhodecodeの設定をやりましょう。
まあrhodecodeのドキュメントままといえばそれまでですが…

rhodecode 最初の設定

useradd rhodecode -g nginx
su rhodecode
pythonbrew switch 2.7.3
cd ~
paster make-config RhodeCode production.ini

production.iniを書き換え

vim production.ini
# 以下書き換え
host = 0.0.0.0
container_auth_enabled = true
proxypass_auth_enabled = true

書き換えたら

mkdir repos # 実際にrepository格納する場所作成

paster setup-rhodecode production.ini \
--user=adminユーザー名を \
--password=adminユーザのパスワード \
--email=test@sample.com \
--repos=/home/rhodecode/repos

古いDB消すって聞かれるのでyesで
view raw 05.md hosted with ❤ by GitHub


これで設定ファイルができたので…試しに動かしてみます

とりあえず動かす

paster serve production.ini

このあとブラウザでipaddress:5000 に当たりに行ってみる
view raw 06.md hosted with ❤ by GitHub


ブラウザで確認するとこうなっているかと。
/etc/hosts にvm2って名前で仮想マシンのip書いているのでurlはそんな感じ


さっき作ったadminユーザでログインしてみます

とりあえず3名ほどユーザを追加してみましょう
まあLDAPが使えれば、こんなこといらないんだろうけど…
Admin > Users > Add New User




時にログイン画面の下に小さくDon't have an account? という項目ありますが、
こちらから誰でもアカウント作成が可能です。
が、こちらで作ると初期の状態だとログイン出来ません。
 管理者にActiveにしてもらう必要性があります。


 各自が作成した時に最初からActiveにするためには
Adminユーザで
Admin > permissions で Registration を変更すればいけます。


次にとりあえずAdminユーザでrepository groupを作っておきます。
実際に仕事で使う…とかになると、プロジェクト単位で切ることになるのかな?
もちろん作らなくてもOKですが、とりあえず。

Admin > repositories groups > ADD NEW GROUP


作ったらパーミッションを設定します。
ここでは太郎くんにadmin権限を渡してみます。


さて、太郎くんでログインしてテキトーに作ります

ご丁寧にQuick Start ってありますね。



この通りやってみましょう。

QuickStartの通りやってみる

hg clone http://taro_yamada@vm2:5000/HelloGroup/hellorepo
cd hellorepo

# hoge.txtを足す
cat << _EOS_ >> hoge.txt
hello!!
_EOS_

hg ci -A -m"first"
hg push
view raw 07.md hosted with ❤ by GitHub


結果

当然反映してますね。

続いて二郎くんでフォークしてプルリクエストを出してみます。
まず二郎くんでログイン
そしてhellorepoを選択し OptionsからForkを選びます

すると、repositoryを作成した時のような画面になります。

Fork結果

fork-hellorepo-jiroの詳細を見てみるとClone urlってありますね。

手元にcloneして作業してみます。

二郎の作業

hg clone http://jiro_tanaka@vm2:5000/HelloGroup/fork-hellorepo-jiro
cd fork-hellorepo-jiro

# hoge.txtになんか書く

hg branch jirowork
hg ci -A -m"second"
hg push --new-branch
view raw 08.md hosted with ❤ by GitHub


作業に満足したらプルリクエストしましょう
Options > Open new pull request を選択します



結果こんな感じ


ソースにコメントも可


実際にレビューした結果を選択
change status にチェックを入れて、レビュー結果OKかどうか選択しましょう。

全員がレビューしたと仮定


あとは誰かがComment and closeを押せばいいわけですが…
現状で自動でこのリクエストは取り込まれない…よね?
→間違っていたらご指摘ください。
なので手動で太郎くんがpullしてマージしてpushすることになります。

太郎のマージ作業

# 手元のhellorepoでの作業
hg pull http://taro_yamada@vm2:5000/HelloGroup/fork-hellorepo-jiro -b jirowork
hg merge -r jirowork
hg ci -m"merge"
hg push --new-branch
view raw 09.md hosted with ❤ by GitHub


うーん、メンドイ。
何よりせっかくApproved とフラグをつけた内容なのに、結局fork元repository上では当然それがなくなっているわけで…
更にPullRequestを取り込んだからといって、PullRequestが閉じられるわけでもない。
→ Forkしたrepositoryを閉じれば(削除すれば)消えます。
もっというと手動で取り込む=結局approved/reject関係なく取り込む人次第なので、
このへんは運用ルールでどうにかするしか無さそうです。

ちなみに上記はbranch切ってやりましたが、別にbookmarkでもいけます

その辺も運用ルール次第なのかな?

ただBitbucketみたいに、「こう言うふうにコマンド叩いて取り込めるよ!!」とかの表記がないので、
リビジョン指定よりもブランチ/ブックマークで取り込むことを前提とした運用のほうが無難だと思います。


多分gitでもそんなに操作変わらんだろう
ということで次。

まずnginxを使ってアクセスできるようにしましょう

ってもドキュメントのサンプルから大きく逸脱しなければ大丈夫なはずです


あくまで動作確認なので自分は本当にほぼ上記ドキュメントのまま。
upstream rc {
server 127.0.0.1:5000;
# add more instances for load balancing
#server 127.0.0.1:5001;
#server 127.0.0.1:5002;
}
server {
listen 80;
server_name localhost;
access_log /var/log/nginx/rhodecode.access.log;
error_log /var/log/nginx/rhodecode.error.log;
# uncomment if you have nginx with chunking module compiled
# fixes the issues of having to put postBuffer data for large git
# pushes
#chunkin on;
#error_page 411 = @my_411_error;
#location @my_411_error {
# chunkin_resume;
#}
# uncomment if you want to serve static files by nginx
#root /path/to/installation/rhodecode/public;
location / {
try_files $uri @rhode;
}
location @rhode {
proxy_pass http://rc;
include /etc/nginx/proxy.conf;
}
}
view raw default.conf hosted with ❤ by GitHub

proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Url-Scheme $scheme;
proxy_set_header X-Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Proxy-host $proxy_host;
client_max_body_size 400m;
client_body_buffer_size 128k;
proxy_buffering off;
proxy_connect_timeout 7200;
proxy_send_timeout 7200;
proxy_read_timeout 7200;
proxy_buffers 8 32k;
view raw proxy.conf hosted with ❤ by GitHub


このあと service nginx start で ipaddressであたりにいけるはずです


clone url もport番号がなくなったのが確認できるはず。

なおこの段階で、rhodecodeの設定ファイルであるproduction.iniのhostを「127.0.0.1」に直しても問題ありません。
nginxで飛ばすわけだしね。
むしろしたほうが、ipaddress:5000でアクセスできなくなるし、いいんじゃまいか。

ただし
full_stack = false
にすると、repositoryをcloneする際にこの症状にハマります。
まあ httpのままでなければいいのかもしれないけど…

また
static_files = false
にすると、自分の場合web表示が崩れました。



あとはサービス化
このあたりを参考にしました
きっとこんなのを作ればいいんだろう…

# /etc/env.rhodecode
# なんかもっとカッコいい書き方があるんじゃないかな…
PBREWPATH="/usr/local/pythonbrew/pythons/Python-2.7.3/bin"
PATH="$PBREWPATH:$PATH"
PYTHONPATH="/usr/local/pythonbrew/pythons/Python-2.7.3/lib"
view raw env.rhodecode hosted with ❤ by GitHub

#!/bin/sh
#/etc/rc.d/init.d/rhodecode
#
# chkconfig: 345 44 56
# description: rhodecode
. /etc/env.rhodecode
export PBREWPATH PATH PYTHONPATH
case $1 in
start)
$PBREWPATH/paster serve /home/rhodecode/production.ini start
;;
stop)
$PBREWPATH/paster serve /home/rhodecode/production.ini stop
;;
status)
$PBREWPATH/paster serve /home/rhodecode/production.ini status
;;
*)
echo "Usage: test [start|stop|status]"
;;
esac
exit 0
view raw rhodecode hosted with ❤ by GitHub


シェルスクリプトとか詳しくないし、このへんはそんなに突っ込まないでほしいw

あとは
chkconfig rhodecode on
で登録しておけばOKですね。

とりあえずこれで「最低限」使うことは可能になると思います。
ローカル内でしかアクセスされないなら、まあセキュリティとかそこまで考えなくてもいいでしょうし、
レビューツールとしてはありだと思います。

ただ、その他のツールと連携していくこととか考えたらここでAPI見てなんか書いたり、
もしくはincoming hook書いて直接repoの中においてきたり…とかになるんでしょうか。

rhodecodeを使うとなると、issue trackerを外部に依存することになるでしょうし、
それ+CIサーバと連携…とか考えると、ちょっとめんどいですね。
個人でやる分には多少失敗しようがそれなりに動けばいいんですけど…ってか
個人だったらGithub/Bitbucketで事足りるし、ウムム…
この手の構築が好きで得意な人がいるような会社だったら、検討の余地は十分あると思います。

そういえばLDAP連携で @usaturnさんが悩んでいた記憶が…



つまり @usaturnさんがrhodecodeを使った素晴らしい開発環境構築を年内にまとめてくれるはず…!?


Admin > Settings に hgsubversion extension を設定できる箇所が有りました。
これにチェックを入れたら、最初にrepository作るときのclone先にsvnのrepositoryを指定できるかも?




補足 会社でrhodecode使い始めました。
Gitに関して追加設定が必要だったり、HGで日本語コメントがちゃんとrhodecode上で表示されるようにしたり…
みたいな設定をお隣の席の人がやってくれました
詳細は以下
http://htn.to/TAKNVB




2012年11月3日土曜日

自転車買ったよ〜

Wiggle で自転車買いました。

え、購入理由?
1年半共に過ごしたロードがパクられたからだよ(´;ω;`)

で、まあ自転車ないと通勤が必然的に電車になります…
電車辛い…

で、知り合いにWiggle勧められて買いました、と。


届くとこんな感じ



開けてみる



取り出してみる



組み上げて出来上がり






ということで、こいつで今週から通勤しております。
快適快適〜
送料込みで7万ちょっとはお買い得だったと思うなぁ…

次はパクられないように、こいつこいつで地球ロックしてます。

過去にバイク盗まれたときはこいつバッツリ切られてましたけど…
さすがに車両金額的に大丈夫だと思いたい…


しかしお買い得と言えども予定外の出費だったので、予定していたサスペンション購入はまた今度だな。

2012年10月1日月曜日

Playframework2.0 + mongo(salat) でのUnitTestに関するメモ

conf/application.confに書かれた設定値は

FakeApplication(additionalConfiguration = Map("key名" -> "値"))

で置き換えられます
ですので、mongoを使っている場合

FakeApplication(additionalConfiguration = Map("mongodb.default.db" -> "dummy_db_name"))

とかで"mongodb.default.db"を書き変えてテストを実行することで、テスト用のDBが使えます



事の経緯






ということで開催されました、第一回詳しい人が誰もいないScala勉強会@Hangout




こんなかんじで みやびさん まで巻き込まれた結果がこれ。

package models
import play.api.test._
import play.api.test.Helpers._
import org.specs2.mutable._
import org.specs2.specification.Scope
import org.specs2.runner.JUnitRunner
import org.junit.runner.RunWith
import com.mongodb.casbah.MongoConnection
@RunWith(classOf[JUnitRunner])
class TaskSpecs2 extends Specification {
sequential
"using task model" should {
"get all task" in context {
running(context.fakeApp) {
Task.all.size must_== 0
Task.create("hoge")
Task.create("fuga")
Task.all.size must_== 2
}
}
}
object context extends BeforeAfter {
lazy val dummy_db_name = "test_app_db"
lazy val fakeApp = FakeApplication(additionalConfiguration = Map("mongodb.default.db" -> dummy_db_name))
def before = {
implicit val mongoDB = MongoConnection()(dummy_db_name)
mongoDB.dropDatabase()
}
def after = ()
}
}




documentにも
「このフェイクアプリケーションに対して追加の設定値を渡す (または上書きする) したり、プラグインをモックすることも可能です。例えば、 default という名前の インメモリデータベースに接続された FakeApplication を起動する場合は、次のように書きます」

FakeApplication(additionalConfiguration = inMemoryDatabase())

とありますが、inMemoryDatabaseは次のようになっています

  def inMemoryDatabase(name: String = "default"): Map[String, String] = {
    Map(
      ("db." + name + ".driver") -> "org.h2.Driver",
      ("db." + name + ".url") -> ("jdbc:h2:mem:play-test-" + scala.util.Random.nextInt)
    )
  }

早い話がinMemoryDatabaseを使っても、「mongodb.default.db」を書き換えられるわけないってことでした
残念!

なお、database cleaner 的なものがパッと調べた感じでは見つからなかったので、
上記ではbeforeでテスト用のDBごとdropしてます

参考にしたのはこちら

上記のような方法でとりあえずは気兼ねなくテストケースが書けそうで何よりです。
ただ、毎度毎度書くのは面倒なので、「Specification」を拡張してどっかに置いておくとかのほうがいいと思います。




「いやそもそもこういう便利な方法あるしwww m9。゚(゚^Д^゚)゚。プギャーッハハハハヒャヒャヒャヒャ」

的なツッコミありましたら、教えてください♥





参考
http://playdocja.appspot.com/documentation/2.0.3/ScalaTest
http://modalsoul.github.com/Programing/2012/07/31/Getting-Started-with-Play2-Scala-and-Squeryl/
https://github.com/mongodb/casbah/blob/master/casbah-core/src/test/scala/ConversionsSpec.scala
https://github.com/leon/play-salat
http://stackoverflow.com/questions/10760131/using-specs2-and-fakeapplication-to-test-database-fails-evolution-inserts


サンプルとひな形を兼ねて、githubに上げています
g8 daneko/play-salat
で作成した後、play test で動くはずです。



今後も 詳しい人が誰もいないScala勉強会@Hangout をテキトーに開くと思いますw

2012年9月10日月曜日

Scalaのカリー化とか部分適応とかの俺メモ

別になんにも難しい or 怖いお話はありません

// 全部問題ない
def hoge(x:Int, y:Int, f:(Int, Int) => Int) = f(x,y)
// hogeをカリー化
val fuga = hoge _ curried
// hogeを部分適応
val piyo = hoge(3, _:Int, _:(Int, Int) => Int)
// 更に部分適応
val moo = piyo(2, _:(Int, Int) => Int)
def mew(x:Int)(y:Int)(f:(Int, Int) => Int) = f(x,y)
// mewを部分適応
val bow = mew(3)_
view raw memo1.scala hosted with ❤ by GitHub


上記は問題ない。
全く問題ない。

問題は下

/**
* fugaもpiyoもすでに「関数オブジェクト」となっているので
* メソッド _ で関数オブジェクト化してはならない、というか出来ない
**/
// fugaを部分適応
// NG
//val fugafuga = fuga(3)_
// OK
val fugafuga = fuga(3)
// piyoをカリー化
// NG
//val piyopiyo = piyo _ curried
// OK
val piyopiyo = piyo curried
view raw memo2.scala hosted with ❤ by GitHub


一旦部分適応やらで作成したメソッドを再度カリー化したり
一旦カリー化されたメソッドを更に部分適応したりするときは _ が不要
というかつけると怒られる

とりあえずはそういうものって覚えればいい?

環境は
Scala2.9.2
MacOSX10.7


2012/09/12 追記
defで宣言した関数名の後ろに「_」をつけると、「関数オブジェクト」になる
なので、一回関数オブジェクトに変わっている → 次は変える必要はない(というか既に変換済み)
ということでいいんでしょうか?


2012/09/13 追記
http://togetter.com/li/154007
このあたりかな?

2012年9月6日木曜日

Intellij Idea で eclipse の saveアクション的なことをする

参考URLというか答え
http://stackoverflow.com/questions/946993/intellij-reformat-on-file-save

マクロにやりたい処理を追加して、そのマクロにショートカットキーを割り当てるだけ

saveアクション的なことをするためには、
Command+sに保存処理を含んだマクロを割り当てればまさにそれっぽい


でもこれVimPlugin使っている俺はどうやって割り当てればいいんだろうねぇ…
(とりあえずCommand+sに割り当てたけど…)

マクロの存在に気がつけたのでまあいいやw

2012年5月6日日曜日

bitbucketで一人pullrequestとかしてた

bitbucketで遊んでみた

ちなみにGW中bitbucketとずっと戯れていたわけじゃないよ。猫と戯れていただけだよ(´;ω;`)

bitbucket は自分のリポジトリをforkできます。
→確か前々回ぐらいの #TokyoMercurial で @troter さんがそんなことを呟いていましたが、確かにできましたw
githubはしらん。

まあ、普通しないよね。練習以外に何に使うのだろう…

あとpull request そのものについて詳しい訳じゃないので間違っている場合はご指摘ください。
名前からして「ねー、ねー。僕のリポジトリ(ブランチ)pullしてよ〜」なんですよね。



準備

とりあえず適当にリポジトリを作ります

作ったらテキトーにコミットしてpushしておきます

bitbucketに戻ってforkしてみます


普通他の人からforkするときはリポジトリ名はそのままでしょうけど、自分で自分のリポジトリをforkするので名前は変えたほうがいいと思います。

fork結果を見るとこんな感じで、何をforkしたのかという情報とかがオリジナルと違う点のようです。

compare fork というのを選ぶと、hg in/out を実行した結果が見られます。
作ったばっかりなので当然差分はありません。



とりあえずdefaultブランチのままぶん投げてみる

forkした側を適当に修正して、pull requestをしてみます

自分のどのブランチを相手のどのブランチに送り込むのか選択する感じ?

compare forkを見てみたところ
さっきと違ってoriginalとの差分がわかります

pull requestを受け取った側

とりあえず受け入れてみる

フツーにpullした状態が出来ます。

調子に乗って2個コミットした状態でRequestを投げてみます

compare fork だと hg diff -r b68e677f670d とやったような感じ
(2個分まとめての差分)

受け入れた結果。
何も問題なさそうです。



拒否ってみる(拒否られてみる)

テキトーにコミットしてpull Requestしてそれを拒否ってみました

Rejectボタンを押すとこんな画面で、拒否理由を書いてRejectするようです

拒否完了


じゃあ、肝心の拒否られた側ですが…
どうやらInboxにメールが届いているだけで、視覚的にダメだったお!みたいなのはなさそうです。
まあ受け入れられたときもそんな感じですが。
俺が気がついていないだけでもっと視覚的な何かがあるんでしょうか?

ところで拒否られたらどうすればいいんでしょう?
個人的にはstripしてなかったことにしてしまえばいいかと。
もしくは再度forkすればいいんじゃね?


backoutがいいんじゃね?的なこと書いてありますが、forkしたリポジトリが複数人でガンガンコミットしたり…
ってことは無いでしょうし。わかんないけど。
あとこの作業後にbackupファイルがDL出来るみたいです。

ローカル側はまあ適当に直せますしね。



下図みたいにpull requestしようとしたら元側が更新されていた…みたいな場合
まあrebaseしろって話でしょうけど、やってみる



受け入れ側…よく見たら「Accept and merge」になっている…
ということはマージして受け入れるんだろうなぁ

押してみたらコミットメッセージが書けるようになっていた



結果 まあ当然の結果



pull requestを受け入れてもらったわけですが、当然下記のように元リポジトリとfork側で違う歴史になりました
揃えないといけませんがどーしましょう


別にfork側のリポジトリを消して再度forkしてもいいと思いますが、改めてcompareを見てみるとコマンド書いてます。
ので、このまま実行してみます。


cd fork_repo_path
hg pull -r default ssh://hg@bitbucket.org/orginal/orginal_repo
hg update default

hg serve でローカルの状態見てみるとこんな感じになる。
これでfork側がoriginal側を追従できた

あとはpushしてやればOK



ていうかpull requestを取り込むかどうか、ローカルで確認したいんですけど!という受け入れ側(original側)はどうすれば?
というのも実質さっきのやつと一緒

forkした側で見れるcompareのoutgoingに書いてある通りに実行でいいんじゃね


# オリジナル側 forkした側じゃないよ
cd orignal_repo_path
hg pull -r default ssh://hg@bitbucket.org/fork/fork_repo

上記みたいにpull requestしてきた人のデータを直接pullすればローカルでじっくり確認できます。

ちなみにこのrequest結果をローカルでみて、
「いけるいける!!」
と思いオリジナル側がこのままpushしたらどうなるのか…

なんと、受け入れた事になりました!
ちゃんと受け入れたよ!ってメッセージも発行しているし、さすが。





正直ここまで来たらもう先は読めたしやらんでもいい気がするけど、ブランチ切ってpull request も試してみる。
一応下記を試す
すべてRequest側はhogeブランチを切るとして

  • hogeブランチをdefaultに取り込んでもらえるかどうか
  • hogeブランチをhogeブランチとして取り込んでもらえるかどうか

というわけで一つ目。
まあこんな感じでsend requestを投げた



requestを投げた側なんだけど、compare forkに差分表示が無い…
なにかしら表示してくれると思ったんだけど、もしかしてdefault ブランチのみを追従しているのかな?
(だからcompare に表示されるコマンドが -r オプションつけているかも…?)

受け入れる側も差分とかは出るものの、ブランチ切られているってことは
ローカルで確認しようとした時にヤヤコシイよね。
ブランチ名指定しなかったら下手したら腐るほどデータ引っ張ってきちゃうし。

まあとりあえず受け入れて…と思ったら、これはAccept and pull なのか。へ~


っておい、やっぱりマージじゃねーかorz


でもまあpull request的に
「hogeブランチだけどdefaultに取り込んでね!」
って明示してんだから動作的には正しいですよね。

でもマージ時のコミットメッセージ書けなかった…


次、hogeブランチとして取り込んで!!!




フツーにpullして終わりました。めでたしめでたし





pull requestの内容が競合するようなものだったらどうなるのか

いやまあ正直requestする側がrebaseしてくれれば…ね… ってのもあると思うんですけど
pull requestと本家の更新が同時とかってこともあるだろうし、試さずにはいられない

compare forkを見る。もうおもいっきりコンフリクトって書いてある、赤字でw



それでも気にしないで送りつける



受け取った側。
コンフリクトしてるから取り込むなら自分で解消してねってところですかね。


送り手的にはcomapreで事前にコンフリクトがわかるわけですし、やっぱり解消した上で送ったほうがいいとは思います。
けどまあ送ることはできるということで。



競合した上にブランチ切ってあったらどうなるのか?
ブランチ切るとそれはcompareとして表示されなかったので、一見コンフリクトと見なされないのではないか?
(いやもちろんfork側がincomingを見て、差分があったら取り込んだ上でpushすればいいんだけど)

試してみると… なんだちゃんとコンフリクトって出ますね。




わたしoriginal側だけどforkした奴が素敵だから勝手に取り込みたいの!

pull request 出してくれているわけじゃないけど、いい修正だし欲しいなぁ…
みたいなとき

実際そんなパターンがあるのか?と思いますが、あったんですよこれが。

まあ、pull requestを取り込むかどうかローカルで確認したい時と同じでいいハズ
そして今更気がついたけど、コミットする人の名前変えればわかり易かった…


こんな状態で
cd original_repo_path
hg pull -r default ssh://hg@bitbucket.org/fork/fork_repo
#取り込むか確認したら
hg push

で、こうなる。



じゃあ開始時点がこんなだったらどうするか?


まあ諦めてマージな気がするなぁ

とりあえずpullして持ってきた状態


まずマージしてみる

至って普通


続いてrebaseなんだけど…そもそもこの場合ってrebaseは間違っている気がするんだなぁ…
なぜならpullして持ってきた状態って全部のphaseがpublicなので基本rebaseしない前提のはず…

まあでもやってみます

pullして持ってきた方を自分にくっつけることにした場合

cd original_repo_path
hg phase -d -f tip
hg rebase -d 9 -s tip
hg push

結果
一直線になっているし問題なさそうだけど、リビジョン番号が変わってしまうことに注意
まあそれ自体は別にわかりきっていることですが…

それよりもfork側のcompare forkから incomingを見るとこうなる

もちろんoutgoingもある

うーん、びみょー


逆版(自分のcommitをpullして持ってきたcommitにつなげる)ってのはもっとやらない気がする。
だってoriginal側を変更するということはstripしないと見た目おかしくなるし、
何より見ている人、触っている人がそれなりに居るだろうからまずやらないよね?

なので省略


有りなのかどうなのかわかりませんが、マージはしたくないけど取り込みたいし…の場合
「やあやあ、そのコミット リベースした上でpull requestしてくれないか!」と連絡するのが一番よかったりして…


色々とやってみたけど結局どうpull requestするのがいいんだろう?

GitHub的にはこちらのブログを見ると(pull request マナー でググってtopだった)
pull request用のブランチ切ってrebaseしてまとめてそれを投げるのが良いらしい。なるほど。

じゃあbitbucketというかhgの場合は…

適当に幾つか見て回りましたが、ほぼ default -> default だったので
特段pull request用にブランチ等は意識しなくて良いようです。多分。

なので pull request 前にoriginal側との差分を最小限にして(取り込んでrebaseして)から
やればまあいいんじゃないかなぁ…

手順的には

  • forkする
  • 作業する
  • original側をpullしてくる
  • 更新があったらrebase
  • push
  • pull request

みたいな手順になるんでしょうね。きっと。

何れにしても自分で自分のリポジトリをforkできるんで色々と試しておくといいのかもしれません。

あとは実際にpull requestしてダメだったら駄目出ししてくれるはず(他力本願

ついでに言うと #TokyoMercurial に参加すると誰かがやさしく教えてくれるかもしれない?(ステマ