It's raining cats and dogs.

無駄なことなんてないはず

githubにブランチをpushしたら ERROR: Repository not found. と怒られた

今日も怒られました。
とあるプロダクトのgithubリポジトリにアカウントを追加してもらって、masterをcloneして、ローカルでブランチ切って、アレコレ修正してコミットした。
問題無さそうなのでgithubのリポジトリにリモートブランチ作って、pull reqするかと思ってpushしたら表題の通り怒られた。

$ git clone <URL>
$ git checkout -b hotfix_hogehoge
...修正...
$ git add .
$ git commit -m "コメント" 
$ git push origin hotfix_hogehoge
ERROR: Repository not found.
fatal: The remote end hung up unexpectedly

リポジトリが見つからないとか...
念のためgit remote -vで確認

$ git remote -v
origin  <URL> (fetch)
origin  <URL> (push)

うん、ちゃんとoriginは登録されてる。タイポとかないよなーとか30分くらいいろいろ見て回ったけど特にコレと言って問題はない。

そういえば、アカウント登録してもらうときに「guest」ってチームに登録してたよな?と思い出す。
もしかしてと思って担当の方に相談しに行ったら、案の定、僕に付与されていたのはpull only。

pull & pushの権限をもらって試したらpushできましたとさ。

$ git push origin hotfix_hogehoge
Counting objects: 97, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (47/47), done.
Writing objects: 100% (51/51), 5.66 KiB, done.
Total 51 (delta 37), reused 0 (delta 0)
To <URL>
 * [new branch]      hotfix_hogehoge -> hotfix_hogehoge

それにしてもpushの権限がないだけで、

ERROR: Repository not found.

とか言われてもなー。権限がないっていってくれよ。

error: SSL certificate problem, verify that the CA cert is OK.

ちょっと古い環境(CentOS5以下)でgit cloneでとあるプロジェクトをhttps経由で持ってこようとしたら表題のようなエラーがでた。

$ git clone https://github.com/sampleProject/hoge.git .
Cloning into ....
error: SSL certificate problem, verify that the CA cert is OK. Details:
error:14090086:SSL routines:SSL3_GET_SERVER_CERTIFICATE:certificate verify failed while accessing https://github.com/sampleProject/hoge.git/info/refs

fatal: HTTP request failed

URLはダミーです

とりあえずググるとそれらしきページが。

http://d.hatena.ne.jp/tetsuyai/20110924/1316877887

要はCentOSに入っているルート証明書が古いから新しいものを追加しないとダメだと。
正しくやるなら上記リンクのようにルート証明書を入れるのが良いのだけど、とりあえずの環境だし、インフラチーム頼まないといけないのでちょっとそこまでは...

で、やっつけで、証明書のチェックをスルーするやり方を発見

http://project-p.jp/halt/?p=1688

$ export GIT_SSL_NO_VERIFY=true

なるほど、こんな環境変数が設定できるのか。

取り急ぎコレで。

というかこの古い環境では開発しないのだけど...

git clone で error: The requested URL returned error: 401 Authorization Required while accessing と怒られた

今新しく環境を作っていて、githubからとあるプロジェクトをcloneしようとしたら、表題の件で怒られた。

$ git clone https://github.com/sampleProject/hoge.git
Initialized empty Git repository in /path/to/hoge/.git/
error: The requested URL returned error: 401 Authorization Required while accessing https://github.com/sampleProject/hoge.git/info/refs

URLはダミーです

うちはセキュリティ上の制限で外に対してsshは開けていないのでhttpsでアクセスした。

調べてみると

https://help.github.com/articles/https-cloning-errors#check-your-git-version

が見つかる。
1.7.10以上必要です。なので、gitのバージョンを調べてみなさいと。

$ git --version
git version 1.7.1

バージョンが古いことはわかった。
が、この環境はインフラチームが用意してくれた環境で、OSはScientific Linux release 6.4、gitのインストールはyumを使っている。SL6.4のディストリビューションが提供しているyumのgitのバージョンは1.7.1のようだ。
パッケージ管理の都合上yumを使う必要があるのと、追加でyumリポジトリを追加するのはちょいと面倒。(ゴネればなんとかなるかもしれないが、多忙な彼らに頼むのは忍びない)

というわけでインフラチームに頼らずなんとかcloneしたかったのでいろいろ調べてみると

http://stackoverflow.com/questions/12538130/cant-clone-a-github-repo-on-linux-via-https

この辺りが見つかる。ビンゴ。

githubのURLを指定するときにgithubのusernameをURLに含めれば良さそう。

$ git clone https://<githubのユーザーID>@github.com/sampleProject/hoge.git
Initialized empty Git repository in /path/to/hoge/.git/
Password:
remote: Counting objects: 51114, done.
remote: Compressing objects: 100% (11818/11818), done.
remote: Total 51114 (delta 34851), reused 51036 (delta 34775)
Receiving objects: 100% (51114/51114), 37.25 MiB | 1.99 MiB/s, done.
Resolving deltas: 100% (34851/34851), done.

途中でパスワードを求められるので、入力するとcloneができた。
stackoverflowにも書いてあるけど

https://username:password@github.com/sampleProject/hoge.git

でパスワードをURLに含めてもいけそうだけど、historyに残ったりなんやらかんやらして嫌な感じなのでパスワードはURLに含めないようにした。

ちなみに、手元のmacだと、gitのバージョンは1.8.1.3だったので当然問題なくcloneできた。

なぜ1.7.10より古いgitだとうまくいくかはよくわかっていない。

[ruby] omniauth-twitterでOAuth::Unauthorized at /auth/twitter っていうエラーがでる

かなり今更感ありそうなomniauthの話。
omniauthでサクッと認証する部分を作ろうとしたら

OAuth::Unauthorized at /auth/twitter
401 Unauthorized

っていうエラーに遭遇した。

backtraceが出てたけどとりあえずしばらくググったら回答を発見。
OmniAuthのFAQに出てました

https://github.com/intridea/omniauth/wiki/FAQ#how-to-fix-oauthunauthorized-error-for-twitter-provider

twitter開発者向けページでアプリ登録するときにcallback urlは任意だったので、めんどくさくて入力しなかったのが原因みたい。
FAQにある通り、開発者ページで、
callback urlにOmniAuthのtwitter用callback url

http://127.0.0.1:9292/auth/twitter/callback

を設定後、「Recreate my access token」を押して、アプリを動かしてみたら無事動きましたとさ。

※追記
どこかのサイトで見たけど、twitterの開発者ページのoauth settingのaccess levelがread onlyじゃ動かないからread and writeにする的な話は今回の件とは関係ないみたいでした。


以下の手順は完全にメモなので結構どうでもよい(Whatever.)

作業メモ

サンプル用のディレクトリ作ってGemfileをつくる
$ mkdir sample_omniauth
$ cd sample_omniauth
$ bundle init
Gemfileを編集
# A sample Gemfile
source "https://rubygems.org"

gem 'sinatra'
gem 'omniauth-twitter'
bundle install
$ bundle install --path vendor/bundle
sinatraのconfig.ruを作成
# coding: utf-8
require 'rubygems'
require 'bundler'

Bundler.require

require './app.rb'
run Sinatra::Application
app.rbを作成
# coding: utf-8

require 'rubygems'
require 'sinatra'
require 'omniauth'

enable :sessions, :logging

# twitterのkeyとかをomniauthに設定
use OmniAuth::Builder do
  provider :twitter, 'Consumer key', 'Consumer secret'
end

# root
get '/' do
  '<a href="/auth/twitter">twitter</a>'
end

# omniauthのOAuth callback
get '/auth/:name/callback' do
  request.env['omniauth.auth'].inspect
end
アプリをrackup
$ bundle exec rackup config.ru


http://localhost:9292
にアクセスして動作完了

svnでdumpファイルload時に Cannot accept non-LF line endings in 'svn:log' property っていうエラーがでた

バージョンの古いsvnリポジトリでdumpしたリポジトリを新しいバージョンのsvnにloadしようとしたら以下のエラーがでた。

Started new transaction, based on original revision 4257
svnadmin: E125005: Invalid property value found in dumpstream; consider repairing the source or using --bypass-prop-validation while loading.
svnadmin: E125005: Cannot accept non-LF line endings in 'svn:log' property

なんのことやらと思ってぐぐってみると、他にも同じようハマっている方がいた。
http://d.hatena.ne.jp/shinsuke789/20120713/1342162178
ブログの記事によれば、svnの1.6からコミットログの文字コードをチェックするようになり、改行コードもLFでなければいけなくなったみたい。

なので今回のエラーを見る限りrev 4257のログが怪しそう。
念のため対象のリポジトリで全ログを出力してみるとCRLFの改行コードが入っていた。

上記のブログ記事に対応方法スクリプトが記載されていて、マルっと直してくれるスクリプトだったんだけど、今回はCRLFの混入したログはrev 4257だけだったので
このリビジョンのログだけ書き換えることにした。

コミットログの改変とか初めてだったので結構ドキドキしながらやったんだけど、さくっとできた。
参考にしたのは↓
http://terai.xrea.jp/Subversion/SetLog.html

svnadminのsetlogというサブコマンドでできるらしい。

ログを書き換えたら、loadできた。めでたしめでたし。

※ちょっとハマったのが、リポジトリの本体が置いてあるディレクトリに書き込み権限がなくて慌ててインフラの部署に対応をお願いした。

svn hook(pre-commit)を使ってコミットを拒否る

引き続きみんな大好きsvnネタ。集中管理バンザイ(泣

やりたいこと

コミット対象のファイルの中に特定の文字列が含まれていた時にコミットを拒否したい

svn hookについて

http://www.asahi-net.or.jp/~iu9m-tcym/svndoc/svn_pre-commit.html
の「設定方法の流れ」がわかりやすい
今回ボクがやりたいことはpre-commitを使うと実現できそう

pre-commitのファイルを作成する

リポジトリが置いてあるディレクトリの下にhooksというディレクトリがあって、その下にpre-commitという実行権限があるスクリプトを置いておけば良いらしい。
bashでもrubyでもperlでもpythonでも実行出来ればなんでもよさそう。
ちなみに僕はbash(sh)で書いた。

$ cd /path/to/repos/hogerepo/hooks
[/path/to/repos/hogerepo/hooks]$ vi pre-commit
#!/bin/sh

# 対象リポジトリ
REPOS="$1"
# トランザクション番号
TXN="$2"

# svnlookのパス
SVNLOOK="/usr/bin/svnlook"

# トランザクション番号とリポジトリ名を使ってコミット対象のリストを取得するためのコマンド
CHANGED_CMD="$SVNLOOK changed -t $TXN $REPOS"
# トランザクション番号とリポジトリ名を使ってコミット対象ファイルの中身を確認(cat)するためのコマンド
CAT_CMD="$SVNLOOK cat -t $TXN $REPOS"

for line in `$CHANGED_CMD`
do
  # .phpのファイル以外は無視
  if ! echo "$line" | grep -E '\.php$' ; then
    continue
  fi

  # ファイル内にhoge, fuga の文字があったらエラー
  if $CAT_CMD $line | grep -E 'hoge|fuga'; then
    echo "NG word error!!! in $line" >&2
    # 途中で終了する場合は0以外を返すらしい
    exit 1
  fi
done

exit 0

こんな感じ。svnlookというコマンドは初めて知った。

svnlook とは

作業コピーではなくリポジトリの中を確認するためのコマンド
http://www.caldron.jp/~nabetaro/svn/svnbook-1.4-final/svn.ref.svnlook.html
サブコマンドと併用して使う。

svnlook changed

svnlookのサブコマンド
トランザクション番号を指定すると、そのコミット(トランザクション)での対象ファイルリストが取れる。
リビジョンを指定するとそのリビジョンでコミットされたファイルリストが取れる。
http://www.caldron.jp/~nabetaro/svn/svnbook-1.4-final/svn.ref.svnlook.c.changed.html

svnlook cat

svnlookのサブコマンド
トランザクション番号を指定すると、そのコミット(トランザクション)の対象となるファイルの中身をコミット前でも見れる
リビジョンを指定するとそのリビジョンでコミットされた時のファイルの中身が見れる。
http://www.caldron.jp/~nabetaro/svn/svnbook-1.4-final/svn.ref.svnlook.c.cat.html

実行権限をつける

最後に、実行権限がないと動かないので実行権限をつけておく
[/path/to/repos/hogerepo/hooks]$ chmod 755 pre-commit


これで完了

svnのリポジトリを統合する

とあるリポジトリを別のリポジトリの配下に移してリポジトリを統合したい。
どういうことかというと

repos1
  └ foo.txt
repos2
  └ bar.txt

これを

repos1
  ├ foo.txt
  └ repos2
      └ bar.txt

のようにrepos1配下にrepos2を移動して統合する。

事前にそれぞれのリポジトリのログを見ておくと、現状は以下のような感じ。

  • repos1のログ
[/path/to/workdir/repos1]$ svn log
------------------------------------------------------------------------
r2 | tadasy | 2013-04-05 16:25:52 +0900 (金, 05  4 2013) | 1 line

repos1 foo.txt add.
------------------------------------------------------------------------
r1 | tadasy | 2013-04-05 16:23:21 +0900 (金, 05  4 2013) | 1 line

repos1 init
------------------------------------------------------------------------
  • repos2のログ
[/path/to/workdir/repos2]$ svn log
------------------------------------------------------------------------
r2 | tadasy | 2013-04-05 16:25:15 +0900 (金, 05  4 2013) | 1 line

repos2 bar.txt add.
------------------------------------------------------------------------
r1 | tadasy | 2013-04-05 16:23:32 +0900 (金, 05  4 2013) | 1 line

repos2 init.
------------------------------------------------------------------------


手順はシンプル

  1. repos2をsvndumpでdumpする
  2. repos1にrepos2用のディレクトリをつくりコミットする
  3. repos2のdumpファイルをrepos2用のディレクトリにloadする

repos2をsvndumpでdumpする

svnadminでdump

$ svnadmin dump /var/repos/repos2 > /var/tmp/repos2_dumpfile

repos1にrepos2用のディレクトリをつくりコミットする

repos1の作業コピーに移動

$ cd /path/to/workdir/repos1

repos2用のディレクトリを作ってコミットする

[/path/to/workdir/repos1]$ svn mkdir repos2
[/path/to/workdir/repos1]$ svn ci -m 'add repos2 dir.' repos2

repos2のdumpファイルをrepos2用のディレクトリにloadする

svnadminでloadする。 --parent-dirにはさっき作ったrepos2用のディレクトリ名を指定する

[/path/to/workdir/repos1]$ svnadmin load --parent-dir repos2 /var/repos/repos1 < /var/tmp/repos2_dumpfile

repos2のsvn logを確認しておく

r4,5にrepos2のログがマージされている

[/path/to/workdir/repos1]$ svn log
------------------------------------------------------------------------
r5 | tadasy | 2013-04-05 16:25:15 +0900 (金, 05  4 2013) | 1 line

repos2 bar.txt add.
------------------------------------------------------------------------
r4 | tadasy | 2013-04-05 16:23:32 +0900 (金, 05  4 2013) | 1 line

repos2 init
------------------------------------------------------------------------
r3 | tadasy | 2013-04-05 16:26:54 +0900 (金, 05  4 2013) | 1 line

add repos2 dir.
------------------------------------------------------------------------
r2 | tadasy | 2013-04-05 16:25:52 +0900 (金, 05  4 2013) | 1 line

repos1 foo.txt add.
------------------------------------------------------------------------
r1 | tadasy | 2013-04-05 16:23:21 +0900 (金, 05  4 2013) | 1 line

repos1 init
------------------------------------------------------------------------