最近被迫在短時間內學會 strace、gdb 這些之前一直用不到的重兵器, 都還不熟練就是了。剛好使用 hgsubversion 時有些困擾, 雖說它和 svn 整合得很好, 無縫接好 pull / push, 但它不會顯示 mercurial 對應到的 svn 版本, 平時看其它和 svn 整合的工具 (如 issue tracking) 會很困擾, 用得都是 svn 版號。
剛剛想到可以學 Strace -- The Sysadmin's Microscope 的做法, 用 strace 找出關聯的程式, 再來看怎麼修正它。
我推測 hg 一定有記錄 svn 相關版本的方式, 不然無法和 svn server 同步資料。於是挑個會讀到 svn 資料的指令來試:
strace -o trace.log -s 512 -e read,open hg svn info
用顯示的 svn 版號 123 來翻 trace.log, 發現這兩行:
open("/path/to/project/.hg/svn/lastpulled", O_RDONLY) = 3 read(3, "123\n", 4096) = 5
於是找到 meta data 存在 .hg/svn/ 下。 到該目錄下找到 .hg/svn/rev_map 這個檔案, 裡面存 hg 和 svn 的版號對應表。至少這樣就有足夠的材料寫個 script 來轉換 hg、svn 的版號。
不過若能直接加到 hg 裡, 應該會更方便也較可攜。要做這點相對容易, 可以到 hgsubversion 原始碼目錄下用 ack 找相關程式。
先用 ack rev_map 找到存 meta data 的物件 revmap, 再用 ack revmap 找到 wrappers.py 是換掉 hg 指令的程式。
再來用 pdb 觀察 revmap 如何被使用。先在 wrappers.py 裡設中斷點, 然後執行 pdb /usr/local/bin/hg parents --svn 找出 meta data 如何被讀出來。於是明白可在函式 parents 的部份塞入幾行顯示 svn 版本:
--- a/hgsubversion/wrappers.py 2011-12-25 00:34:39.170606104 +0800 +++ b/hgsubversion/wrappers.py 2011-12-25 00:33:04.161800527 +0800 @@ -57,6 +57,9 @@ raise hgutil.Abort('No parent svn revision!') displayer = cmdutil.show_changeset(ui, repo, opts, buffered=False) displayer.show(ha) + # patch svn revision + print '\033[1;32msvn revision: %d\033[0m' % hashes[ha.node()][0] + print return 0
這樣打 hg parents --svn 就會多輸出一行 svn 的版號。雖說顯示在 hg log 會更方便, 不過 wrappers.py 裡沒有 log, 之後有再找時間看看怎麼加。
附帶一提, 剛用 pdb 時還不太習慣, 忘了 python 是執行期載入程式, 不能像 gdb 那樣在執行前就指定檔名指定行數設中斷點。而是要在 script 裡直接塞
import pdb; pdb.set_trace()
2011-12-25 更新
如留言裡的討論, 上述的修正沒有實質幫助, 就當作練 debugger 吧。最後覺得另外寫個 shell script 最省事效果也最好, 寫好的東西放在這裡。
Hey學長,我最近也打算架設一個紀錄學習心得的blog,能否請教你我該怎麼把code/command貼上來(syntax highlighter?)
回覆刪除@Heron 你是打算用blogger, wordpress or 自己架設?
回覆刪除不然google search code highlight or syntax highlight.
ex:
http://heisencoder.net/2009/01/adding-syntax-highlighting-to-blogger.html
工具用的好。strace 最好用的功能之一就是『程式到底在讀哪個檔案』,而只 trace syscall 剛好能看到此重點。你這樣短時間內改別人程式的能力應感覺到有提昇?
回覆刪除你的 use case 我有點疑惑:
打 "hg svn info" 看 SVN revision 跟打 "hg parents --svn" 不是差不多? 若是看 "hg log" 時需要 SVN rev 我還能理解.
gdb 下也可像 "pdb.set_trace()" 一樣在 source 中插入中斷: https://github.com/scottt/debugbreak
gdb 除錯的對象有用 shared library 時,往往也是『執行期載入程式』。pdb 不能用檔名、行數預設 breakpoint 可算是缺功能。我自己最常用的其實是將 ipython 類似 "pdb.set_trace()"來用:
import IPython; IPython.embed()
(ipython 0.10 後的 API)
另外也鼓勵你對 hgsubversion 從 bitbucket.org 回報 bug 、 merge request。
我有寫過一個小程式,像是一個特殊功能的 debugger 是當 debug 的 target 發出 syscall (用 PTRACE_SYSCALL) 時就印出 stack trace (用 libunwind)。我整理一下,下次見面時跟你分享。
@Heron: 在這頁 view-source,然後找 Google Code Prettify.類似的程式不少
回覆刪除恩,我弄好了,本來想使用新版Blogger的動態檢視,卻發現他限制更改html。接下我也要來好好學習寫好的Blog了。
回覆刪除http://heron-note.blogspot.com/
@Heron 順便廣告一下不直接相關的事, 我都是用自己寫的工具發文 http://fcamel-fc.blogspot.com/2011/06/ego-post-wsyiwyg-wiki.html
回覆刪除這東西可以直接改成 Chrome Web App, 這樣別人要用按個安裝就結束了。不過目前自己用得好好的, 暫時也沒時間移過去, 所以就一直拖著 ...
@Scott 這個 use case 的確有問題, 應該要直接改 log 才對。我原本是看到 parents 有 --svn 的功能, 至少可克難的用 hg parents -r REV --svn 查對應, 不過目前的程式這部份並沒有用, 所以就是.....還沒達到目的, 接下來有空會再看怎麼改到 log 裡, 然後問看看該社群有沒有興趣接收。
回覆刪除目前想到兩個用法:
1. 加個新指令 hg svn lookup 查 svn -> hg 的對應, 改起來簡單, 用法也不會令人困惑
2. 加上 hg log --svn, 首先得先定義這個 --svn 的行為為何, 還有顯示的方式。定規格部份就滿麻煩的, 也得另外定顯示方式
所以應該會先試 1 吧
目前覺得進步滿多的, 不過離能應付實戰還有段距離。待能順手應付實戰後, 應該會成長不少吧 XD
回覆刪除下個目標是加強使用 gdb 的能力, 再來則是補充 linux system programming 的常識
svn2hg line 40 指定 hg_revision 中,grep 前面多了反斜線? 類似 svn2hg 這種 script,需要 option parsing 時我後來都用 Python 寫。
回覆刪除也是, 我想說只有一個參數就將就一下, 再多一點用 python 比較方便。
回覆刪除那個反斜線表示不要用 alias 展開的結果, 就叫 shell 執行 "grep"。我平時有設 alias grep='grep --color=auto'
@fcamel: Re: svn2hg alias
回覆刪除I see. 但讓 grep alias 展開應該無妨?
以前踩過雷, 有時寫 shell script 就會順手加。經你這樣一提, 才想起來了, 是 ls 有影響, grep 到是沒差。
回覆刪除我的 ls 是 alias ls='ls -F --color', 配合 for loop 取檔名時會變成拿到錯誤的檔名
ls --color=auto 就會在只有 isatty(stdout) 時才輸出控制碼
回覆刪除但是 pipe 後也會消失, 有時會 ls | less, 希望保有顏色, 還有我習慣加 -F。所以就變成 alias ls 設成那樣, 寫 shell script 時記得寫 \ls 了
回覆刪除Re: ls --color:
回覆刪除這樣有一天別人的 shell script 只有在你的系統上有問題的時候你要記得檢查 ls 部份啊 ... ;)