😽

mercurial 半自動リポジトリサーバCGI

2021/09/07に公開

hgwebdir.cgi

mercurialでは、数行のスクリプトを書くだけで、CGIで簡単にリポジトリサーバを動かすことができる。

https://www.mercurial-scm.org/wiki/HgWebDirStepByStep

前述のURLに従い、スクリプトを写経していけば完成してしまうが、肝心のリポジトリの所在は別途 ini ファイルに書いてから読み込ませる必要がある。

from mercurial.hgweb.hgweb_mod import hgweb
from mercurial.hgweb.hgwebdir_mod import hgwebdir

from mercurial import demandimport; demandimport.enable()
from mercurial.hgweb.hgwebdir_mod import hgwebdir
import mercurial.hgweb.wsgicgi as wsgicgi
application = hgwebdir('hgweb.config')
wsgicgi.launch(application)

iniファイルは例えば次の通りだ。

[paths]
repo1 = c:/webdata/repos.merc/images
repo2 = c:/webdata/repos.merc/web/htdocs/

内蔵機能だけでできてしまう件

PublishingRepositories - Mercurial

[paths]
/ = /home/user/hg/*
The ** wildcard exposes subrepositories (repositories within repositories) whereas * merely finds repositories within a directory. However, this behaviour is modified by the descend setting as described below.

というのを知らなくて自力で頑張ってしまった件....

mercurial.hgweb.hgweb(tuple)

前述のソースに注目。mercurial.hgwebdir_mod.hgwebdir はiniのファイル名を受け付けるが、より別のAPIを探してみると、mercurial.hgweb.hgweb APIが見つかった。

これは、ディレクトリのリストを直接 tuple で受け付けるようだ。 形式は ( 名称, ディレクトリ ) であり、INIファイルのpathsセクションの中身に一致する。

であれば、ランタイムでこの List[tuple] を作成すれば良い。

後はリポジトリを何処に置くか、だが、一般的にはこのCGIとは別の場所に集めるだろう。
hgweb.configファイルの代わりに、幾つかのシンボリックリンクを置いて、それをhgリポジトリへの指標とする。

ディレクトリを検索しつつ、hg リポジトリっぽいものを抽出して tuple を作って、 hgweb() にそのまま突っ込めば良い。

#!/usr/bin/python3
#
# An example hgweb CGI script, edit as necessary
# See also http://mercurial.selenic.com/wiki/PublishingRepositories
from mercurial import demandimport
import cgitb
from mercurial.hgweb import hgweb, wsgicgi
import os.path
import glob
import os
import sys
os.environ["HGENCODING"] = "UTF-8"

syms = [
        xx for xx in glob.glob("*")
        if os.path.islink(xx) and os.path.isdir(xx)
]
##print(syms)

dirs = []
for ROOT in syms:
    dir0 = [
        ( ( ROOT + "@" + os.path.basename(xx)).encode(), xx.encode())
        for xx in glob.glob(ROOT + "/*")
        if os.path.isdir(xx + "/.hg")
    ]
    dirs += dir0

config = dirs

demandimport.enable()
app = hgweb(config)
#print(dir(app))
app.run()

このスクリプトの場合、今の所 ini ファイルを読み込ませる手段がないため、web独自の設定を使うことができなくなる。 仕方ないので、$HOME/.hgrc に webdir用設定も書くことにする。

[subrepos]
git:allowed=true
[web]
push_ssl=False
allow_push=*

Discussion