Trac 0.12.x + Subversion 1.6.x でリポジトリのパスの先頭スラッシュを2つにして登録して sync させるとこける

管理画面での設定変更時のエラー - だめだま、という記事があったので試してみる。

jun66j5@gotanda:47$ trac-admin ~/var/trac/0.12-stable
Welcome to trac-admin 0.12.3dev
Interactive Trac administration console.
Copyright (C) 2003-2011 Edgewall Software

Type:  '?' or 'help' for help on commands.

Trac [/home/jun66j5/var/trac/0.12-stable]> repository add '' //var/lib/svn/practice
Trac [/home/jun66j5/var/trac/0.12-stable]> repository list

Name       Type  Alias  Directory
----------------------------------------------
(default)               //var/lib/svn/practice

Trac [/home/jun66j5/var/trac/0.12-stable]> repository sync ''
python: subversion/libsvn_subr/path.c:114: svn_path_join: Assertion `svn_path_is_canonical(base, pool)' failed.
Aborted

こけた…。とりあえず subversion リポジトリに直にアクセスされなきゃこけないので trac-admin コマンドから削除してやり直せば解消できる。

jun66j5@gotanda:62$ trac-admin ~/var/trac/0.12-stable
Welcome to trac-admin 0.12.3dev
Interactive Trac administration console.
Copyright (C) 2003-2011 Edgewall Software

Type:  '?' or 'help' for help on commands.

Trac [/home/jun66j5/var/trac/0.12-stable]> repository list

Name       Type  Alias  Directory
----------------------------------------------
(default)               //var/lib/svn/practice

Trac [/home/jun66j5/var/trac/0.12-stable]> repository remove ''
Trac [/home/jun66j5/var/trac/0.12-stable]> repository list

Name  Type  Alias  Directory
----------------------------

似たようなチケットは #8179 (Assertion `svn_path_is_canonical(base, pool)' failed: while using "Annotate") – The Trac Project かなぁ。

Subversion 1.6.x は何も assertion で殺さなくてもいいのに。

TracDragDropPlugin が Chrome 6 以降で動作しない...のを修正

TracDragDropPlugin が Google Chrome 7 beta で動作しない、という報告をもらいました。ありがとうございます。
TracDragDropPluginをChrome7.0betaに対応 - Hirohiroの日記
「なぜにー」とか思ってたらしっかりバグってるだけでした。しかもかなり下らないバグ... orz
Changeset 9288 - Trac Hacks で修正しました。Firefox 4 beta で drop 後にそのファイルをブラウザで開いてしまうバグも修正しています。

TracWiki で手軽に br マクロを入力する

「TracWiki で [[br]] を入力するのがめんどくさい」というのを聞いて、「そういえばあまり Wiki (TracWiki に限らず) であまり物理改行は使わないなぁ…」と思いつつも

Shift+Enter で [[br]] を挿入するような javascript でも仕込んでおけばいいんじゃなかろうか…とか思った。_

ので、実際に javascript を書いてみました。
いろいろ面倒なので trac/htdocs/js/wikitoolbar.js を直接パッチします。

diff --git a/trac/htdocs/js/wikitoolbar.js b/trac/htdocs/js/wikitoolbar.js
index 107e4d2..ceb534e 100644
--- a/trac/htdocs/js/wikitoolbar.js
+++ b/trac/htdocs/js/wikitoolbar.js
@@ -82,6 +82,50 @@
     });

     $(textarea).before(toolbar);
+    $(textarea).keypress(insertBreakOnShiftEnter);
+  }
+
+  function insertBreakOnShiftEnter(event) {
+    if (event.shiftKey === true && event.keyCode === 0x0d /* ENTER */) {
+      var text = "[[br]]";
+      var d = this.ownerDocument;
+      var w = d.defaultView || d.parentWindow;
+      if (w.getSelection) {
+        if (!w.opera) {
+          try {   // Google Chrome, Safari
+            d.execCommand("insertHTML", false, text);
+            return false;
+          }
+          catch (e) { }
+          try {     // Firefox
+            for (var i = 0; i < text.length; i++) {
+              var evt = d.createEvent("KeyboardEvent");
+              evt.initKeyEvent("keypress", true, true, null,
+                false, false, false, false, 0, text.charCodeAt(i));
+              this.dispatchEvent(evt);
+            }
+            return false;
+          }
+          catch (e) { }
+        }
+        else {  // Opera
+          var selection = w.getSelection();
+          var start = this.selectionStart;
+          var end = this.selectionEnd;
+          var value = this.value;
+          this.value = value.substring(0, start) + text + value.substring(end);
+          this.setSelectionRange(start + text.length, start + text.length);
+          return false;
+        }
+      }
+      else if (d.selection) {        // IE
+        var range = d.selection.createRange();
+        range.execCommand("paste", false, text);
+        range.collapse(false);
+        range.select();
+        return false;
+      }
+    }
   }

 })(jQuery);

このパッチを当てて Shift+Enter すれば [[br]] が挿入されるようになります。
また、まともに undo できるようにするために textarea.value を直接変更するのは止めて以下のような処理を行っています。

  • Google Chrome, Safari では document.execCommand("inserthtml") を利用して挿入
  • Firefox では KeyboardEvent イベントを利用して挿入
  • Internet Explorer では TextRange.execCommand("paste") を利用して挿入し、選択領域を調整
  • Opera では undo 可能にする方法が見つからなかったので textarea.value を直接変更した後 textarea.setSelectionRange() で選択領域を調整

これで少しは楽になるのではないでしょうか。

TracDragDropPlugin を Google Chrome 4 に対応させてみました

Gmail が Firefox, Chrome でドラッグ&ドロップによるファイル添付を可能になったそうなので TracDragDropPluginGoogle Chrome 4 に対応させてみました。Google Chrome 4 は FileReader (File API) に対応していないので、ファイル読み込みとアップロード部分は Google Gears の機能でやってます。
あと XMLHttpRequest の終了ハンドリングがダメダメなのを直しました。

Drag-and-Drop でファイル添付できるようにする Trac Plugin

#9127 (Drag and drop attachments) – The Trac Projectチケット #21236: 画像のドラッグアンドドロップ登録機能 - Trac Lightning - SourceForge.JP のチケットに触発されて Drag-and-Drop でファイルを添付できるようにする Trac Plugin を書きました。
» TracDragDropPlugin - Trac Hacks - Plugins Macros etc.
現状動作するのは Firefox 3.6 以降のみです。HTML5 drag and drop, File API, XMLHttpRequest Level 2 (XMLHttpRequest.sendAsBinary) を使っているので、これが実装されていないと機能しません。
ドロップできるページでは ↓ のように右上に表示が出るので、この表示が出るページではそのままファイルをドロップするだけで添付を作成出来ます。


いまのところ、ドロップ可能なページは Wiki 参照ページ、Wiki 編集ページ、チケット変更ページ、マイルストーン参照ページ、マイルストーン編集ページです。
ドロップしようとすると右上の表示の色が変わるようになってます。

かなり荒削りな作りでまだまだですが、よかったら使ってみてください。

sudo が Error dropping capabilities, aborting というエラーになるのは capability カーネルモジュールがないから。

非常に困って時間をかなり使ったのでメモとして残しておきます。結論はタイトルどおりなんですが、とある構築中の環境(CentOS 5.3)で sudo -u apache id が失敗することに気づきました。

# sudo -u apache id
sudo: Error dropping capabilities, aborting
: Operation not permitted

うーん。さっぱり意味が解りません。検索すると見つかるページは 0003512: Sudo Bug On CentOS 5.3 - CentOS Bug Tracker というのがあるが、解決していません。
次に strace をしてみることに。

# strace -f -o sudo-trace.log sudo -u apache id

これで sudo-trace.log を確認すると capset(2) が EPERM になっているのが見えます。

....
20635 munmap(0xb778f000, 15976)         = 0
20635 setgid32(48)                      = 0
20635 setgroups32(1, [48])              = 0
20635 setresuid32(48, 48, 48)           = 0
20635 prctl(0x8, 0, 0, 0, 0)            = 0
20635 capset(0x19980330, 0, {CAP_AUDIT_WRITE, CAP_AUDIT_WRITE, 0}) = -1 EPERM (Operation not permitted)
20635 write(2, "sudo: ", 6)             = 6
20635 write(2, "Error dropping capabilities, abo"..., 38) = 38
20635 write(2, ": ", 2)                 = 2
20635 open("/usr/share/locale/locale.alias", O_RDONLY) = 4
20635 fstat64(4, {st_mode=S_IFREG|0644, st_size=2528, ...}) = 0
20635 mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7efa000
20635 read(4, "# Locale name alias data base.\n#"..., 4096) = 2528
20635 read(4, "", 4096)                 = 0
20635 close(4)                          = 0
20635 munmap(0xb7efa000, 4096)          = 0
20635 open("/usr/share/locale/en_US.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en_US.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en_US/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en.UTF-8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en.utf8/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 open("/usr/share/locale/en/LC_MESSAGES/libc.mo", O_RDONLY) = -1 ENOENT (No such file or directory)
20635 write(2, "Operation not permitted\n", 24) = 24
20635 exit_group(1)                     = ?

ここまで調べてまだ解らずに1週間ぐらい放置していたんですが、lsmod すると capability というのがないことに気づきました。

# lsmod
Module                  Size  Used by
loop                   13032  0
binfmt_misc             9256  1
dm_mirror              19764  0
dm_multipath           17192  0
dm_mod                 50708  2 dm_mirror,dm_multipath

sudo -u apache id が成功する別の環境では lsmod が以下のようになり capability があります。

# lsmod
Module                  Size  Used by
loop                   13032  0
capability              4552  0
commoncap               6912  1 capability
binfmt_misc             9256  1
dm_mirror              19764  0
dm_multipath           17192  0
dm_mod                 50708  2 dm_mirror,dm_multipath

ここで modprobe で capability をロードさせてからやってみると無事に sudo が成功するようになりました。

# modprobe capability
# sudo -u apache id
uid=48(apache) gid=48(apache) groups=48(apache)

/etc/sysconfig/udev-stw ファイルに capability を追加して、起動時に modprobe capability されるようにしておきました。

MODULES="capability nvram floppy parport lp snd-powermac"