« 2009年4月 | トップページ | 2009年6月 »

2009年5月

2009年5月30日 (土)

SVNリポジトリを複数のTracから共有し,post-commitでのコメントをそれぞれに振り分ける

チケットタイプによってカスタムフィールドが大きく違っていたりして,TicketExtプラグインを使用してもおなじTracで扱うのに無理があるような場合に,複数のTracプロジェクトに分けたいと思うときがあります.しかし,別のTracプロジェクトから同じリポジトリを使うことはできますが,コミットのコメントをどのTracに割り振るかを決めることができなくいので,リポジトリを使うのは一つのTracプロジェクトにまとめる必要がありました.(私が知らないだけかもしれませんが…)それで,InterTracリンクからヒントを得て,trac-post-commit-hookでTracプロジェクトに割り振る仕組みを作ってみました.

とにかくちゃんとやるのは面倒なので,とりあえず次のようなコメントが登録されるところまでを作ってみることとします.

svn commit -m "refs test2:#4 refs test3:#2"

1. create-projectでtest1,test2,test3を作り,適当に必要な番号までチケットを追加してください

2. 各プロジェクトのconf/trac.iniを編集し,InterTracを有効にします(ショートカットも設定しているが,できれば使ってほしくない)

[intertrac]
t1 = test1
t2 = test2
t3 = test3
test1.title = Trac Test Project 1
test1.url = http://192.168.1.8/trac/test1
test2.title = Trac Test Project 2
test2.url = http://192.168.1.8/trac/test2
test3.title = Trac Test Project 3
test3.url = http://192.168.1.8/trac/test3

3. 副プロジェクト(このばあいはtest2,test3)のconf/trac.iniのたぶん最後のあたりを編集し,リポジトリを主になるプロジェクト(test1)のものに変更する

[trac]
authz_module_name = test1
repository_dir = C:\TracLight\projects/svn/test1

4. リポジトリに再同期する

trac-admin.bat resync c:\TracLight\projects\trac\test2

5. 「trac-post-commit-hook」をダウンロード し,python-lib\trac\contribにおく

元のファイルはバックアップしてください.

6. リポジトリをチェックアウトし,何かを適当にコミットします.

cd 適切なフォルダ
svn co http://localhost/svn/test1
フォルダを作ったり,移動したりする.
svn commit -m "refs test2:#4 refs test3:#2"

7. 確認します

まずはチェンジセット

Test1cs3

ログメッセージからtest2:#4をクリックし表示されることを確認

Test24

同様にコメントからtest3:#2をクリックし表示されることを確認

Test32

コメントがついてちゃんとリンクできることが確認できました. 今回は私が必要としている形のコメントに対応するところまでしかやっていません.あと,InterTracの設定を使っていないので,同じサーバの兄弟プロジェクトのみでしか動きません.

Python全然わからないので修正する力はありませんが,間違っていたら指摘してください.

http://zakizaki.cocolog-nifty.com/software/2009/06/post-d614.html で リポジトリを共有しない場合の修正方法を追加しました(2009/06/15)

| | コメント (0) | トラックバック (0)

2009年5月29日 (金)

TracXMLRPC.clsを使って進捗報告のレポートを作成する例

Tracをプロジェクタ等で見ながらの進捗の報告がゆるされない職場ってまだまだありますよね.そういう場合は,何らかのレポートを作成することになりますが,せっかくXMLRPCでアクセスするクラスモジュールを作ったので,それを使って作ってみました.出力画面は次のようになります.

Tracreport

XMLRPCで接続して各種日付の情報から次の順番でレポートを作成していきます.

  1. 期間内にクローズ済みのチケット
  2. 作業中のチケット
  3. 開始予定のチケット

ちゃんとしたTracのプロジェクトではないので上の例ではわかりにくいと思いますが,その中にはsummary, id, due_assign, due_close, complete, descriptionを二行で追加しています.そのサンプルを次に貼り付けます.

Dim trac As TracXMLRPC
Dim s As Worksheet
Dim owner As String

Function initSheet(dBefore As String, dReport As String, dNext As String) As Integer
    s.Cells(1, 3).value = "作業進捗報告"
    s.Cells(1, 3).HorizontalAlignment = xlCenter
    s.Cells(2, 4).value = "報告日:" & dReport
    s.Cells(2, 4).HorizontalAlignment = xlRight
    s.Cells(3, 4).value = "期間:" & dBefore & " - " & dNext
    s.Cells(3, 4).HorizontalAlignment = xlRight
    s.Cells(4, 4).value = "報告者:"
    s.Cells(4, 4).HorizontalAlignment = xlRight
    initSheet = 5
    s.Range(s.Rows(initSheet), s.Rows(65536)).Delete xlUp
End Function

Public Function importClosedTickets(row As Integer, pre As String, dStart As String) As Integer
    Dim t1 As Collection
    Dim query As String
    query = "<string>status=closed&amp;owner=" & owner & "</string>"
    Set t1 = trac.queryTicket(query)
    Dim no As Integer
    no = 1
   
    On Error Resume Next
    For Each t In t1
        due_assign = due_close = complete = ""
        due_assign = t.Item("due_assign")
        due_close = t.Item("due_close")
        complete = t.Item("complete")
        If due_close >= dStart Then '前回報告日以後にクローズされているなら
            s.Cells(row, 2).value = pre & no & ". " & t.Item("summary") & "(" & t.Item("id") & ")"
            work = due_assign & "-" & due_close
            If complete <> "" Then work = work & "(" & complete & "%)"
            s.Cells(row, 4).value = work
            s.Cells(row, 4).HorizontalAlignment = xlRight
            row = row + 1
            work = ""
            work = t.Item("description")
            work = Replace(work, "[[BR]]", vbCrLf)
            s.Cells(row, 3).value = work
            row = row + 1
            no = no + 1
        End If
    Next
    On Error GoTo 0
    importClosedTickets = row
End Function

Public Function importWorkingTickets(row As Integer, pre As String, dReport As String, dEnd As String) As Integer
    Dim t1 As Collection
    Dim query As String
    query = "<string>status!=closed&amp;owner=" & owner & "</string>"
    Set t1 = trac.queryTicket(query)
    Dim no As Integer
    no = 1
   
    On Error Resume Next
    For Each t In t1
        due_assign = due_close = complete = ""
        due_assign = t.Item("due_assign")
        due_close = t.Item("due_close")
        complete = t.Item("complete")
        If due_assign <= dReport Then '報告日以前に開始しているなら
            s.Cells(row, 2).value = pre & no & ". " & t.Item("summary") & "(" & t.Item("id") & ")"
            work = due_assign & "-" & due_close
            If complete <> "" Then work = work & "(" & complete & "%)"
            s.Cells(row, 4).value = work
            s.Cells(row, 4).HorizontalAlignment = xlRight
            row = row + 1
            work = ""
            work = t.Item("description")
            work = Replace(work, "[[BR]]", vbCrLf)
            s.Cells(row, 3).value = work
            row = row + 1
            no = no + 1
        End If
    Next
    On Error GoTo 0
    importWorkingTickets = row
End Function

Public Function importDueAssignTickets(row As Integer, pre As String, dReport As String, dEnd As String) As Integer
    Dim t1 As Collection
    Dim query As String
    query = "<string>status!=closed&amp;owner=" & owner & "</string>"
    Set t1 = trac.queryTicket(query)
    Dim no As Integer
    no = 1
   
    On Error Resume Next
    For Each t In t1
        due_assign = due_close = complete = ""
        due_assign = t.Item("due_assign")
        due_close = t.Item("due_close")
        complete = t.Item("complete")
        If due_assign > dReport And due_assign <= dEnd Then '報告日以後で次回報告以前に開始する予定なら
            s.Cells(row, 2).value = pre & no & ". " & t.Item("summary") & "(" & t.Item("id") & ")"
            work = due_assign & "-" & due_close
            If complete <> "" Then work = work & "(" & complete & "%)"
            s.Cells(row, 4).value = work
            s.Cells(row, 4).HorizontalAlignment = xlRight
            row = row + 1
            work = ""
            work = t.Item("description")
            work = Replace(work, "[[BR]]", vbCrLf)
            s.Cells(row, 3).value = work
            row = row + 1
            no = no + 1
        End If
    Next
    On Error GoTo 0
    importDueAssignTickets = row
End Function

Sub createReport()
    '進捗報告という名前のシートを変数に設定する.
    Set s = Application.ActiveWorkbook.Sheets.Item("進捗報告")
    Dim dBefore As String
    Dim dReport As String
    Dim dNext As String
    Dim row As Integer
   
    dBefore = "2009/05/22" '前回報告日
    dReport = "2009/05/29" '報告日
    dNext = "2009/06/05" '次回報告日
    owner = "u-z" '担当者
    Set trac = New TracXMLRPC
    trac.init "http://localhost/trac", "test3", "admin", "admin"
    row = initSheet(dBefore, dReport, dNext) '
    s.Cells(row, 1).value = "1. 期間内にクローズ済みのチケット"
    row = importClosedTickets(row + 1, "1.", dBefore)
    s.Cells(row, 1).value = "2. 作業中のチケット"
    row = importWorkingTickets(row + 1, "2.", dReport, dNext)
    s.Cells(row, 1).value = "3. 開始予定のチケット"
    row = importDueAssignTickets(row + 1, "3.", dReport, dNext)
    s.Cells(row + 1, 1).value = "以上"
End Sub

確認手順

  1. あたらしいExcelファイルを作成
  2. VBEditorでTracXMLRPC.clsをインポート
  3. 上のサンプルをどこか(TishWorkBookとか)に貼り付け
  4. どれかのシート名を”進捗報告”に変更するか追加する
  5. 日付やowner等を適切に変更
  6. createReportを実行

でどうでしょう.

| | コメント (0) | トラックバック (0)

2009年5月27日 (水)

TracXMLRPC.clsの使い方2

TracXMLRPC.clsをインポートして,どこでもいいので次のコードを追加する.testを実行すると,Tracに接続し,マイルストーンの一覧を表示,チケットを追加し,内容を表示し,カスタムフィールドの進捗率を変更するサンプルです.TracXMLRPCにはデバッグのprintが残っているのでわかりにくいですが,イミディエイトに結果が表示されます.

Sub test()
    Dim trac As TracXMLRPC
    Set trac = New TracXMLRPC
    Dim attr As Collection
    Dim ticket As Collection
    Set attr = New Collection
    Dim id As Long
    '初期化
    trac.init "http://localhost/trac", "SampleProject", "admin", "admin"
    'マイルストーンなどのデータはすでにとられている.
    Debug.Print vbCrLf & "マイルストーンを表示する"
    For Each ms In trac.milestone
        Debug.Print "    " & ms.Item("name")
    Next
    '進捗率だけ設定してチケットを追加
    attr.Add "50", "complete"
    id = trac.createTicket("VBAから追加", "詳細は...[[BR]]改行", attr, False)
    Debug.Print "チケット id=" & id & " で追加しました"
   
    '登録したチケットの情報を取得する
    Set ticket = trac.getTicket(CStr(id))
    For Each field In ticket
        Debug.Print field
    Next
    'これだけではわからないのでcompleteをとってみる
    Debug.Print "summary=" & ticket.Item("summary")
    Debug.Print "complete=" & ticket.Item("complete")
    Debug.Print "description=" & ticket.Item("description")
    '進捗率を変更してみる.
    Set attr = New Collection
    attr.Add "100", "complete"
    Set ticket = trac.updateTicket(id, "コメントもつけられる", attr, False)
    Debug.Print "変更された進捗率は " & ticket.Item("complete")
End Sub

| | コメント (0) | トラックバック (0)

一つ前の記事のクラスモジュールを使ってTicketImportPluginに代わるExcelマクロを作る

MS-Project<->Trac連携を作っていると,テストのためのデータを登録するのもすごく大変で,TicketImportPluginを使おうとしたが,チケットタイプが文字化けする等の問題があるので,VBAで作ってみた.といっても,TicketImportPluginに文句言っている人もいないので,VBAの部分をTracXMLRPCの使用例として公開する.かなぁーり汚いコードですが,使い方のサンプルということでお許しを…下の二つのファイルを取り込んで,sheet1のVBAに下のソースを貼り付けると使える.

「TicketEdit.cls」をダウンロード

「MiscModule.bas」をダウンロード

sheet1のVBA

Sub export()
    Dim user As String, pw As String, URL As String, projectName As String
   
    Dim settingSheet As Worksheet
    Set settingSheet = Sheet1
   
    URL = settingSheet.Cells(2, 3).value 'アドレス
    user = settingSheet.Cells(6, 3).value 'アカウント
    pw = settingSheet.Cells(7, 3).value 'パスワード
    projectName = settingSheet.Cells(3, 3).value '開発プロジェクト名

    Dim te As TicketEdit
    Set te = New TicketEdit
   
    te.init URL, projectName, user, pw, "Sheet2"
    te.export
End Sub

Sub check()
    Dim user As String, pw As String, URL As String, projectName As String
   
    Dim settingSheet As Worksheet
    Set settingSheet = Sheet1
   
    URL = settingSheet.Cells(2, 3).value 'アドレス
    user = settingSheet.Cells(6, 3).value 'アカウント
    pw = settingSheet.Cells(7, 3).value 'パスワード
    projectName = settingSheet.Cells(3, 3).value '開発プロジェクト名

    Dim te As TicketEdit
    Set te = New TicketEdit
   
    te.init URL, projectName, user, pw, "Sheet2"
    te.check
End Sub

Sub update()
    Dim user As String, pw As String, URL As String, projectName As String
   
    Dim settingSheet As Worksheet
    Set settingSheet = Sheet1
   
    URL = settingSheet.Cells(2, 3).value 'アドレス
    user = settingSheet.Cells(6, 3).value 'アカウント
    pw = settingSheet.Cells(7, 3).value 'パスワード
    projectName = settingSheet.Cells(3, 3).value '開発プロジェクト名

    Dim te As TicketEdit
    Set te = New TicketEdit
   
    te.init URL, projectName, user, pw, "Sheet2"
    te.update
End Sub

exportして変更箇所をチェックした画面

Ticketedit

URL, user, pw, projectNameはsheet1から持ってきていますが面倒なら次のように直接マクロを変更して設定してください.

    URL = http://localhost/trac"
    user = "admin"
    pw = "admin"
    projectName = "SampleProject"

(ちょっと不親切なので追加しました)

| | コメント (0) | トラックバック (0)

TracにXMLRPCで接続するVBAクラスモジュール

いま,MS-ProjectとTracの連携をやっているのですが,Tracに接続する部分をExcel(たぶんWordでも大丈夫)からでも使えるように,アプリの依存部と別にしてクラスモジュールにしました.これを使えば,Tracから進捗報告ぐらいは簡単に作れるはずです.自分が必要なmethodしか使ってないし,まだ,コメントが残っていたり問題がありますが,ご意見,ご要望等あれば連絡願います.

使ってくれる人が多ければ,どこかに登録したいですが…

| | コメント (2) | トラックバック (0)

2009年5月25日 (月)

VBAのモジュールをSVNで管理するためにマクロでエクスポートする

ExcelとProjectでVBAのクラスモジュールを簡単に共有したりとか,VBAのプロジェクトも何とかSVNで差分が見えるように,テキストファイルで管理したい.テキストにするには,エクスポートすればいいが何かと面倒なので,マクロでできないか調べてみた.まず,マクロの記録で何とか仕様としたが,VBEditorでは何も記録されない.Webで検索すると,エクスポート方法が見つかった.後は,フォルダとファイルの存在確認なので,いつもお世話になっているOffice TANAKAのFileSystemObjectの解説を参照する.できあがったソースは

Const svnCommonFolder = "C:\TracTools\TracTools\trunk\VBA\Common\"
Const moduleName = "TracXMLRPC"

Private Sub Workbook_BeforeSave(ByVal SaveAsUI As Boolean, Cancel As Boolean)
    Dim FSO
    Set FSO = CreateObject("Scripting.FileSystemObject")
    'フォルダがあるかどうか確認する
    If FSO.FolderExists(svnCommonFolder) = False Then
        MsgBox svnCommonFolder & "フォルダは存在しません.モジュールの保存は行いません."
        Exit Sub
    End If
    ActiveWorkbook.VBProject.VBComponents.Item(moduleName).Export svnCommonFolder & "TracXMLRPC.cls"
End Sub

Private Sub Workbook_Open()
    Dim FSO
    Set FSO = CreateObject("Scripting.FileSystemObject")
    'ファイルがあるかどうか確認する
    If FSO.FileExists(svnCommonFolder & moduleName) = False Then
        MsgBox svnCommonFolder & moduleName & "ファイルは存在しません.モジュールの取り込みは中止しました"
        Exit Sub
    End If
   
    'オープンの時に呼ばれれば,当然saveされているが,デバッグの時はsaveされていないこともある
    If ActiveWorkbook.VBProject.VBComponents.Item(moduleName).Saved = False Then
        MsgBox "ファイルが保存されていないので,TracXMLRPCのオープンを中止します"
        Exit Sub
    End If
    'まず削除する
    ActiveWorkbook.VBProject.VBComponents.Remove ActiveWorkbook.VBProject.VBComponents.Item(moduleName)
    '読み込む
    ActiveWorkbook.VBProject.VBComponents.Import svnCommonFolder & moduleName & ".cls"
End Sub

後はフォルダをワークブックの相対にするとか,SVNコマンドを自動で発行するとかすればいいか.

| | コメント (0) | トラックバック (0)

2009年5月20日 (水)

XMLRPCでticket.aueryの応答にarrayの件数が100件に制限されている(?)ことについて調査する

追記(2011/04/17):ひまわりさんにご指摘いただきました。m(_ _)m

この記事でいろいろなことやっていますが、XMLRPCでやる場合は”status!=close&amp;max=1000”(’&’は’^amp;’にエンコード)のようにクエリーにmaxを指定することでOkになることを実際に確認しました。

XMLRPCの仕様をよく見ていなかったので
http://www.futomi.com/lecture/japanese/xml_rpc.html
で確認するが,返す情報の上限とかって話は載っていない.

まずはそれっぽいところをTracHacksのソースから探す.

XMLRPCのtracrpc/ticket.py(45)
    def query(self, req, qstr='status!=closed'):
        """ Perform a ticket query, returning a list of ticket ID's. """
        q = query.Query.from_string(self.env, qstr)
        out = []
        for t in q.execute(req):
            out.append(t['id'])
        return out

この件とは関係ないが,ticket.queryで何も指定しない場合は,全チケットが出てくるのだと思っていたが,
openの物が出てくることがこの前わかった.そういうものかと思っていたが,ここに'status!=closed'とかいてあったんだ.

TLのソースから検索しtrac/ticket/query.py(121)

    def from_string(cls, env, string, **kw):
        filters = string.split('&')
        kw_strs = ['order', 'group', 'page', 'max']
'max'って,なんかあたりっぽい

maxに何が入るか探す.

trac/ticket/query.py(82)
        if max is None: # meaning unspecified
            max = self.items_per_page

結局は次の場所で値を入れていた.100件って件数もticket.queryの件数と合う.

trac/ticket/query.py(708)
    items_per_page = IntOption('query', 'items_per_page', 100,
        """カスタムクエリの検索結果で 1 ページあたり表示するチケット数の
        デフォルト値 (''0.11 以降'')""")

どうやって設定するのかを検索してみると

trac.ini.sampleに
[query]
default_anonymous_query = status!=closed&cc~=$USER
default_query = status!=closed&owner=$USER
items_per_page = 100

こう書いてあった.XMLRPCからQueryの最大を設定するのは無理なようなので,
trac.iniで設定するってことしか無いようです.

| | コメント (3) | トラックバック (0)

プロジェクト間のリンク

ヘルプを読んでいると,/wiki/InterTracにプロジェクト間のリンクについて書いてあった.プロジェクト名がtest1から3の場合で,すべてのtrac.iniに次のように追加

[intertrac]
t1 = test1
t2 = test2
t3 = test3
test1.title = Trac Test Project 1
test1.url = http://192.168.1.1/trac/test1
test2.title = Trac Test Project 2
test2.url = http://192.168.1.1/trac/test2
test3.title = Trac Test Project 3
test3.url = http://192.168.1.1/trac/test3

あとはwikiとか,チケットのdescriptionに"test1:#1"とするとリンクを追加できる.これは,使えそう.

やりたかったのは,カスタムフィールドの親チケットの場所に書いて,上のうす黄色のところでリンクにしたかったのだが,リンクにはならなかった.MasterTicketsはここがリンクになっているので,どうやっているかを見て,自前のプラグイン作成で何とかなるはずなので後でやる.

| | コメント (0) | トラックバック (0)

2009年5月18日 (月)

ファイルのプロパティに情報を保存するVBA(Project2003)

ExcelのVBAだとシートに情報を保存していたけど,ProjectのVBAだとできないので,なにか方法はないか調べてみました.次のようにやることでファイルのプロパティに情報が保存できました.

Private Sub test1() '登録
    addCustomDocumentProperty PROP_NAME_URL, msoPropertyTypeString, "http://localhost/trac"
    addCustomDocumentProperty PROP_NAME_PROJ, msoPropertyTypeString, "SampleProject"
End Sub

Private Sub test2() ' 表示
    Set properties = Application.ActiveProject.CustomDocumentProperties
    Dim i As Integer
    For i = 1 To properties.Count
        Set prop = properties(i)
        Debug.Print properties(i).name
    Next i
End Sub

Private Sub addCustomDocumentProperty(name As String, propertyType As Integer, value As Variant)
    Set properties = Application.ActiveProject.CustomDocumentProperties
    On Error GoTo catcherr
    properties.Add _
        name:=name, _
        LinkToContent:=False, _
        Type:=propertyType, _
        value:=value, _
        LinkSource:=False
    Exit Sub
catcherr: '存在した場合は追加できない
    On Error GoTo 0
    properties(name).Delete 'まず削除して追加する
    properties.Add _
        name:=name, _
        LinkToContent:=False, _
        Type:=propertyType, _
        value:=value, _
        LinkSource:=False
End Sub

参考:Custom Document Properties

| | コメント (0) | トラックバック (0)

2009年5月13日 (水)

VBAでツールバーのアイコンのIDを調べる

追加するツールバーのアイコンを調べるには,まず手動でツールバーとアイコンを追加し,ツールバーの設定が開いている状態でボタンを右クリックし,アイコンを変更する.次のマクロを追加し,実行するとイミディエイトに表示される.

Private Sub check()
    Dim objBar As CommandBar
    Dim objBtn As CommandBarButton
    Set objBar = CommandBars.Item("Trac-Project連携")
    Set objBtn = objBar.Controls.Item("取り込み")
    Debug.Print objBtn.FaceId
End Sub

ここでの表示が2109だったとして追加するには

Private Sub projectopen()
    Project_Open Application.ActiveProject
End Sub

Private Sub Project_Open(ByVal pj As Project)
    Dim objBar As CommandBar
    Dim objBtn As CommandBarButton
    On Error GoTo err1
    Set objBar = CommandBars.Add(name:="Trac-Project連携")
    objBar.Visible = True
   
    Set objBtn = objBar.Controls.Add
    objBtn.FaceId = 2109
    objBtn.Style = msoButtonIconAndCaption
    objBtn.Caption = "取り込み"
    objBtn.TooltipText = "Tracに接続してチケットを取り込みます"
    objBtn.OnAction = "Macro ""Trac.mpp!init"""
    objBtn.Visible = True
   
    Exit Sub
err1:
    Exit Sub
End Sub

使用したアプリ:MS-Project 2003

参照ページ:新しいツールバーを作る

| | コメント (0) | トラックバック (0)

« 2009年4月 | トップページ | 2009年6月 »