11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

WindowsでRhodeCode

Last updated at Posted at 2012-12-26

2015.4.21 WindowsでKallitheaを動かす の方に現時点でのセットアップ手順をまとめました。


Mercurial Advent Calender 22日目のエントリです。

RhodeCodeというのは、MercurialとGitに対応したGitHubライクなリポジトリブラウザ(hg serve相当のサーバ機能もあり)な訳ですが、このRhodeCodeをWindowsで動かした時の手順とか設定とかの話です。
基本的には ここ に書いてある通りなんですが。

前提条件とか

  • アクセスするのは25人くらい。
  • 既存の環境はできる限り汚したくない。
  • リポジトリ内のファイルはUTF8とshift_jisが混在している。
  • 今のところ日本語パスはないけど、一応日本語パスでも問題ないようにしておきたい。
  • クライアントはすべてWindows。
  • RhodeCodeとTracを同じポートで動かして、外からのアクセスはApacheでリバースプロキシを設定する。
  • 認証はApache側で。
  • Windowsサービス化する。

virtualenv環境の準備

既存の環境に影響が出ないように、すべてvirtualenv内にインストールするようにします。

console
C:\.virtualenvs>virtualenv galahad
C:\.virtualenvs>cd galahad
C:\.virtualenvs\galahad>Script\activate.bat

virtualenv内だけで有効な環境変数を設定するために、Lib\site-packages\sitecustomize.py を作成します。
Windows環境下で日本語パスをちゃんと扱うには HGENCODING = cp932 としておく必要があるのと、RhodeCode用に個別のhgrcを読み込ませるために HOME を設定しています。

sitecustomize.py
import os
os.environ["HGENCODING"] = "cp932"
os.environ["HOME"] = "C:/.virtualenvs/garahad/HOME"
os.environ["PYTHON_EGG_CACHE"] = "C:/.virtualenvs/garahad/.egg-cache"

モジュールのインストール

インストール自体は pip install rhodecode でほぼ終わり。
non-asciiなファイルを扱うには追加で chardet が必要なのでそれも一緒に。

console
(galahad)C:\.virtualenvs\galahad>pip install rhodecode
(galahad)C:\.virtualenvs\galahad>pip install chardet

サービス化するために、Python win32 extensionが必要になりますが、これはpypiにはないのでここからインストーラをダウンロードして、 easy_install でvirtualenvにインストールします。
http://sourceforge.net/projects/pywin32/files/pywin32/Build%20218/

console
(galahad)C:\.virtualenvs\galahad>easy_install pywin32-218.win32-py2.7.exe

ちなみに、Mercurialをvirtualenv環境下にインストールするとそのままではhgコマンドが動かないので、 Script\hg.bat を少し修正しておきましょう。

hg.bat.patch
@@ -8,5 +8,5 @@
 rem install does not put python.exe on the PATH...
 rem %~dp0 is the directory of this script
 
-"%~dp0..\python" "%~dp0hg" %*
+"%~dp0python" "%~dp0hg" %*
 endlocal

RhodeCode環境の構築

paster make-configpaster setup-rhodecode で、環境を構築します。
アクセスするのが高々25人程度ということで、とりあえずsqliteのままで。

console
(galahad)C:\.virtualenvs\galahad>mkdir repositories
(galahad)C:\.virtualenvs\galahad>mkdir environ && cd environ
(galahad)C:\.virtualenvs\galahad\environ>paster make-config RhodeCode rhodecode.ini
(galahad)C:\.virtualenvs\galahad\environ>paster setup-rhodecode rhodecode.ini
...
Are you sure to destroy old database ? [y/n] y
...
Enter a valid absolute path to store repositories. All repositories in that path
will be added automatically: C:\.virtualenvs\garahad\repositories
...
Specify admin username:iwata
...
Specify admin password (min 6 chars):XXXXXX
Confirm password:XXXXXX
...
Specify admin email:iwata@dummy.local
...

ここでいったん、ちゃんと動くかどうか確認します。

console
(galahad)C:\.virtualenvs\galahad\environ>paster serve rhodecode.ini

rhodecode-initial

日本語パスのための設定

日本語パスを扱うために、以下の設定が必要です。

  1. win32mbcs エクステンションをインストールする
    RhodeCode環境にもwin32mbcsエクステンションが必要になります。
    適当な場所に win32mbcs.py を置いて、 $HOME\hgrc に記述してください。

  2. default_encodingの設定
    RhodeCodeのコンフィグファイル内で、 default_encoding = cp932 に設定します。

rhodecode.ini
[app:main]
use = egg:rhodecode
# 中略
default_encoding = cp932

日本語(というかnon-ascii文字)を含むファイルについては、基本的に chardet がよろしく処理してくれるのであまり気にする必要はありません。
cp932でもUTF8でも特に問題は無いと思います。

サービス化

とりあえず、wsgi applicationにします。

rhodecodeapp.py
import os

home = os.path.dirname(__file__)
CONFIG_FILE = os.path.join(home, 'rhodecode.ini')

from paste.deploy import loadapp
from paste.script.util.logging_config import fileConfig

fileConfig(CONFIG_FILE)
application = loadapp("config:" + CONFIG_FILE)

あとはこれを mod_wsgiでApacheに載せればいいんですが、今回は先住民との住み分けの問題でApacheに直接載せられないので、スタンドアロンなサービスにしてApacheからリバースプロキシすることにします。

~/galahad/hg => RhodeCode
~/galahad/trac => Trac
という形でリバースプロキシ設定する予定なので、設定を簡単にするためにこっち側でも同じようにURLをマップしておきます。

で、サービスとして動かすために作ったのが以下のスクリプトです。

service.py
import win32serviceutil
from cherrypy.wsgiserver import WSGIPathInfoDispatcher, CherryPyWSGIServer

class Galahad(win32serviceutil.ServiceFramework):
    _svc_name_ = "Galahad"
    _svc_display_name_ = "Galahad Service"
    _svc_description_ = "Finally, I have long-cherished Ice-sword."
    _svc_deps_ = None

    server = None

    def SvcDoRun(self):
        """サービス開始"""
        from rhodecodeapp import application as rhodecode_app
        # tracapp.py についての説明は省略
        from tracapp import application as trac_app  

        # Routingの設定
        dispatcher = WSGIPathInfoDispatcher({
                "/galahad/hg":    rhodecode_app,
                "/galahad/trac":  trac_app,
            })
        self.server = CherryPyWSGIServer(('127.0.0.1', 5000), dispatcher)
        self.server.start()

    def SvcStop(self):
        """サービス終了"""
        if self.server:
            self.server.stop()

if __name__ == "__main__":
    win32serviceutil.HandleCommandLine(Galahad)

このへん を参考にしました。
取り回しの簡単そうなCherryPyを使うことにしましたが、Werkzeug(何回見てもスペルが憶えられないw)とかでもよかったかも知れません。
※Windowsの場合、こういうときに手っ取り早くwsgiサーバを建てたいと思ったら何を使うのがいいんですかね?

サービスのインストールは以下のコマンドです

console
(galahad)C:\.virtualenvs\galahad\environ>python service.py install

デフォルトの設定だと標準エラー出力にログメッセージが流れるようになっていますが、サービス化すると標準エラー出力が無くてBad File Descriptorになってしまうので、ファイルに出力するように設定を変えておきます。

rhodecode.ini
##############
## HANDLERS ##
##############

[handler_console]
class = handlers.RotatingFileHandler
args = ('C:/.virtualenvs/galahad/environ/log/service.log', 'a', 10000)
level = INFO
formatter = generic

[handler_console_sql]
class = handlers.RotatingFileHandler
args = ('C:/.virtualenvs/galahad/environ/log/service.log', 'a', 10000)
level = WARN
formatter = generic

リバースプロキシと認証

ここ の記述に従って、Apache側で、リバースプロキシと認証の設定を行います。
REMOTE_USERをX-FORWARDED-USERに乗せ替えて飛ばしている訳ですね。

httpd.conf
<Location /galahad>
    SetEnvIf X-Url-Scheme https HTTPS=1

    ProxyPass           http://127.0.0.1:5000/galahad
    ProxyPassReverse    http://127.0.0.1:5000/galahad

    AuthType Digest
    AuthName "Login to Galahad"
    AuthDigestProvider file
    AuthUserFile /path/to/digest/file
    BrowserMatch "MSIE|Chrome" AuthDigestEnableQueryStringHack=On
    Require valid-user
    
    RequestHeader unset X-Forwarded-User
    RewriteEngine On
    RewriteCond %{LA-U:REMOTE_USER} (.+)
    RewriteRule .* - [E=RU:%1]
    RequestHeader set X-Forwarded-User %{RU}e
</Location>

RhodeCode側の設定は以下のようになります。上のURLの記述からは分かりづらいですが、Proxy-Passthroughモードで動かすときは container_auth_enabledproxypass_auth_enabled の両方を true に設定する必要があるようです。

rhodecode.ini
[app:main]
use = egg:rhodecode
# 中略
container_auth_enabled = true
proxypass_auth_enabled = true

これで晴れてRhodeCodeが動くようになりました。
リポジトリの作成と clonepushpullがちゃんと動くことを確認して〆。

いろいろ

Tracと共存させてみたところ、TracのURLに一度でもアクセスするとRhodeCodeがInternal Errorを返すようになるという現象がありました。
調べてみたところ、Tracが内部的に locale.setlocale を実行しているのが問題らしく、Trac側で trac.locale = English を設定することで回避。

RhodeCode上で、ファイルに対してshow as rawdownload as rawを実行すると、cp932のファイルであってもUTF8で返されるみたいです。さすがに download as zip はそんなことないので大した問題ではないですが。

まとめのようなそうでもないような

RhodeCodeは細かいところまでよく出来てて、開発のモチベーションが上がりますね。
別にPull Request運用をする訳じゃないって所でも(うちもそうです)、Mercurial使うならセットアップして損はないんじゃないでしょうか。

でもまあ、こういうのはLinux系の方が楽ですねえ。

11
11
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
11

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?