hg.exe を Python インタプリタにする - Mercurial Advent Calendar 2013

2013 年 12 月 9 日 はてなブックマークへ追加 はてなブックマーク - hg.exe を Python インタプリタにする - Mercurial Advent Calendar 2013 Bookmark this on Delicious

Mercurial Advent Calendar 2013 の 9 日目です。

プログラムのビルドでちょっとしたテキスト処理をしたいことはよくあると思います。 例えば、ビルド日時やリビジョン番号、その日の天気や気分を埋め込みたいとか。
そんな時、 Unix であれば sed, awk, perl など道具はいくらでもありますが、 Windows が絡むと残念な気持ちになりますね。

さて、ここでもし仮に Mercurial でソースコードを管理しているのであれば、 hg.exe を使えるんじゃないでしょうか?

import sys
from mercurial import cmdutil, commands

commands.norepo += ' python'
cmdtable = {}
command = cmdutil.command(cmdtable)

@command('python',
    [('c', 'code', '', 'program passed in as string')],
    '[-c cmd | file] [arg] ...')
def python(ui, *pats, **opts):
    sys.argv = list(pats)
    ns = {'__name__': '__main__'}
    if opts['code']:
        sys.argv.insert(0, '-c')
        exec opts['code'] in ns
    elif pats:
        execfile(pats[0], ns)

このエクステンションは hg python コマンドを提供します。 インストールのために稟議は不要です。

使い方:

# file の SHA-1 ハッシュを生成
hg python -c "import hashlib, sys; print hashlib.sha1(sys.stdin.read()).hexdigest()" < file
# ファイルを選択
hg python -c "from PyQt4.QtGui import *; a = QApplication([]); print QFileDialog.getOpenFileName()"

Makefile には PYTHON = hg python --config extensions.python=path/to/python.py と定義しておけばいいでしょう。 GNU Make が使えるなら、すでに Unix ライクな環境が整ってるかもしれませんけど。

コメント

TortoiseHg のエラーを出そう - TortoiseHg Advent Calendar 2012

2012 年 12 月 19 日 はてなブックマークへ追加 はてなブックマーク - TortoiseHg のエラーを出そう - TortoiseHg Advent Calendar 2012 Bookmark this on Delicious

TortoiseHg Advent Calendar 2012 の 19 日目です。

例外をちょっとだけ楽しくする話をします。

何も言わずに下のコードを itarize エクステンション に貼ってみましょう。

def uisetup(ui):
    if not os.path.basename(sys.argv[0]).startswith('thg'):
        # TortoiseHg以外から読み込まれた場合は何もしない
        return

    ...

    # AnnotateViewを装飾
    from tortoisehg.hgqt.fileview import AnnotateView
    Itarate(AnnotateView)

    # -- ここから --
    from tortoisehg.hgqt import bugreport
    # 念のためサブクラス化
    class BugReportTextBrowser(bugreport.QTextBrowser):
        pass
    bugreport.QTextBrowser = BugReportTextBrowser
    Itarate(BugReportTextBrowser)
    # -- ここまで --

ほら、このとおり。

例外を見るのが楽しくなりますね!

けれど、エラーが起きた時しか表示されなくて残念です。 せっかくなのでいつでもウィンドウを開けるようにしましょう。

    from mercurial import extensions
    from tortoisehg.hgqt import workbench
    def itaraise():
        raise Exception('hello')

    def wbrun(orig, ui, *pats, **opts):
        w = orig(ui, *pats, **opts)
        if not isinstance(w, workbench.Workbench):
            return w
        a = QtGui.QAction(u'エラーを起こす', w.menuHelp)
        a.setShortcut('F1')
        a.triggered.connect(itaraise)
        w.menuHelp.insertAction(w.menuHelp.actions()[0], a)
        return w

    extensions.wrapfunction(workbench, 'run', wbrun)

じゃん。

F1 キーを押すだけでエラーが起きるようになりました。

素晴らしいエクステンションをありがとうございます! > @wonderful_panda さん

それでは、良いお年を。

コメント

hgweb にユーザー認証させる - Mercurial Advent Calendar 2012

2012 年 12 月 18 日 はてなブックマークへ追加 はてなブックマーク - hgweb にユーザー認証させる - Mercurial Advent Calendar 2012 Bookmark this on Delicious

Mercurial Advent Calendar 2012 の 18 日目は、 hgweb とユーザー認証の話をします。

とその前に、 LDAP の bind で認証するコードが https://gist.github.com/4104596 にあります。こんな記事を見るよりコードを読んだほうが早いですよ。

認証レイヤー

HTTP で Mercurial リポジトリを公開する場合、ユーザー認証を挟む場所が 2 つあります。

  1. Web サーバー — Apache の mod_auth_basic や nginx の auth_basic を使う。
  2. WSGI — application(environ, start_response) 関数で処理する。

簡単なのは 1. です。 ですから、もちろん 2. を使います。

テストしやすくする

コードを書く前に、まず hgweb_wsgi.py をテストしやすくしましょう。

すでに Flask はインストールされていることと思いますので、 Flask と一緒にインストールされた Werkzeug を使ってみます。

#!/usr/bin/env python
from mercurial import hgweb
application = hgweb.hgwebdir('hgweb.config')

if __name__ == '__main__':
    from werkzeug import serving
    serving.run_simple('localhost', 8000, application,
                       use_debugger=True, use_reloader=True)

これだけです。 hgweb_wsgi.py を直接実行できて、例外でデバッガが起動するようになりました。

401 Unauthorized をフックする

クライアントへ認証を要求するには、 401 Unauthorized レスポンスに WWW-Authenticate をのせる必要があります。 hgweb は認証が必要な場面で 401 を返しますが、 WWW-Authenticate ヘッダがついていません。 hgweb が認証の手段を知らないためです。

A very basic description of authentication opportunities in WSGI を参考にレスポンスヘッダをのせます。

hgapp = hgweb.hgwebdir('hgweb.config')

def application(environ, start_response):
    def wrapped_start_response(status, headers, exc_info=None):
        if status.startswith('401'):
            realm = 'Mercurial Repository'
            headers.append(('WWW-Authenticate', 'Basic realm="%s"' % realm))
        return start_response(status, headers, exc_info)

    return hgapp(environ, wrapped_start_response)

応答をみる

Basic 認証要求に対して、クライアントは HTTP_AUTHORIZATION ヘッダで応答します。 ここでやるべきは、認証データを検証して REMOTE_USER を渡すことです。 hgweb が REMOTE_USER をもとに操作を「認可」します。

from werkzeug import http

def check_auth(username, password):
    return {'hoge': 'fuga'}.get(username) == password

def application(environ, start_response):
    auth = http.parse_authorization_header(environ.pop('HTTP_AUTHORIZATION', None))
    if auth and check_auth(auth.username, auth.password):
        environ['REMOTE_USER'] = auth.username
    ...

あとは、 check_auth() を真面目に実装するだけですね。

最後に

認証が必要かどうかを hgweb が判断してくれるので楽です。 Apache の mod_auth_basic を使うと、そうは行きませんね。

コメント

TortoiseHg を疑う - TortoiseHg Advent Calendar 2012

2012 年 12 月 15 日 はてなブックマークへ追加 はてなブックマーク - TortoiseHg を疑う - TortoiseHg Advent Calendar 2012 Bookmark this on Delicious

TortoiseHg Advent Calendar 2012 の 15 日目です。今日はエクステンションのお話。

普段コマンドラインの hg に慣れていると、 TortoiseHg が何をしているか不安になりませんか?

そんな方に朗報です。

paranoid エクステンション

ソース: https://bitbucket.org/yuja/hgext-workarounds/src/tip/hgext/paranoid.py

def _runcommand(orig, lui, repo, cmd, fullargs, ui, options, d, cmdpats,
                cmdoptions):
    r = ui.promptchoice(_('about to execute: %s\nare you sure? (Y/n)')
                        % ('hg ' + subprocess.list2cmdline(fullargs)),
                        (_('&Yes'), _('&No')))
    if r == 1:
        raise util.Abort(_('by user request'))
    return orig(lui, repo, cmd, fullargs, ui, options, d, cmdpats, cmdoptions)

def uisetup(ui):
    extensions.wrapfunction(dispatch, 'runcommand', _runcommand)

見てのとおりです。コマンド実行前に小うるさく確認を出してきよります。

% hg update
about to execute: hg update
are you sure? (Y/n) n
中断: by user request

CLI では無意味さ炸裂ですが、 GUI の場合はこんな風になります。

まとめ

これで安心して TortoiseHg を使えますね!

コメント

パッチを投げよう - TortoiseHg Advent Calendar 2012

2012 年 12 月 13 日 はてなブックマークへ追加 はてなブックマーク - パッチを投げよう - TortoiseHg Advent Calendar 2012 Bookmark this on Delicious

TortoiseHg Advent Calendar 2012 - cointoss の 14 日目は、 最も使用頻度が高いと思われる「メール送信」ダイアログについて書こうと思います。

メール送信ダイアログ

これです。パッチをメーリングリストへ投下します。

え? 使ったこと無いって? モグリですね。

使い方

MQ で管理しているパッチを投げるには、コマンドラインにこうタイプしてください。

% thg email qbase::

簡単ですね。リビジョンを指定せずに

% thg email

で起動すると、全てのリビジョンがリストアップされます。 送信したいリビジョンにチェックマークを入れて下さい。

コミットが 1 万件程度であればパフォーマンスの問題は無いでしょう。

設定

メール送信サーバーの設定は ~/.hgrc (または Mercurial.ini) に書きます。 (GUI のユーザー設定ダイアログでもかまいません)

[smtp]
host = smtp.gmail.com
port = 587
tls = True
username = <username>@gmail.com

[email]
bcc = <username>@gmail.com

GMail を使っている場合は自分が送ったメールが配信されないため、 bcc を入れておくと良いでしょう。

それから、宛先アドレスを毎回書きたくないですよね? 宛先はリポジトリの .hg/hgrc に書くのがオススメです。

[email]
to = thg-dev@googlegroups.com

最後に

普段、コマンドラインの hg email を使っている方も、試しに thg email を使ってみて下さい。 メールを出す前にプレビューできて便利ですよ!

コメント

古い記事