Subversion 的 svnadmin obliterate 功能一直沒有實作出來,這實在是有點麻煩,尤其是當負責管理一個 repository 時,常常就會有人把 *.exe, *.obj, *.lib, *.a 統統給 commit 進去了….
然後你就會發現整個 repository 長大的速度越來越快,就算事後用 svn delete 把它砍掉還是無濟於事,因為那已經成為無法抹滅的歷史了
雖然可以事先設定 svn:ignore 來解決,不過偶而還是會有漏網之魚,官方提供的解決方法是使用 svndumpfiler 來把不要的檔案徹底從歷史記憶中濾除
# svnadmin create REPOS2
# svnadmin dump REPOS1 | svndumpfilter exclude XX.exe | svnadmin load REPOS2
這方法當然沒有 svnadmin obliterate 好,不過也是目前狀況下不得不的作法
但是這個方法最大的問題在於 svndumpfilter 無法接受 wildcards (萬用字元),也就是你無法指定 svndumpfilter exclude ‘*.exe’
所以,萬一不小心遇上了機車的狀況,你可能要一個一個把檔名找出來濾掉 XD
所以不久前就想辦法修改了 svndumpfilter 的程式,把它加上直接濾除特定副檔名檔案的功能…
[patch to subversion/svndumpfilter/main.c]
(the filename with leading dot will be matched against filename extension)
--- subversion/svndumpfilter/main.c.orig +++ subversion/svndumpfilter/main.c @@ -111,7 +111,12 @@ pfx_len = strlen(pfx); if (path_len < pfx_len) continue; - if (strncmp(path, pfx, pfx_len) == 0) + if( pfx[0] == '.' ) + { + if( strncmp( path+path_len-pfx_len, pfx, pfx_len ) == 0 ) + return TRUE; + } + else if (strncmp (path, pfx, pfx_len) == 0) return TRUE; } @@ -1257,7 +1262,8 @@ style, and absolute. */ SVN_INT_ERR(svn_utf_cstring_to_utf8(&prefix, os->argv[i], pool)); prefix = svn_path_internal_style(prefix, pool); - prefix = svn_path_join("/", prefix, pool); + if( prefix[0] != '.' ) + prefix = svn_path_join("/", prefix, pool); APR_ARRAY_PUSH(opt_state.prefixes, const char *) = prefix; } } |
這個 patch 有點投機取巧,因為我懶得真的去實作 wildcards,我需要的功能只要能濾除指定的副檔名就可以了…
所以這個 patch 把原來 svndumpfilter include/exclude 後面接的檔名參數作特殊判斷,只要第一字元是小數點,就當作要去 match 的副檔名,因此,要濾除 *.exe 只要這樣作就可以了:
# svnadmin create REPOS2
# svnadmin dump REPOS1 | svndumpfilter exclude .exe | svnadmin load REPOS2
剛好看到前幾天也有人寫了個 PATCH 讓 svndumpfilter 完全支援 wildcards… 不過我沒試過,相信不久的將來應該會被整合進正式版本中
當然最希望還是 svmadmin obliterate 能早日被支援,就不用這麼辛苦了
自動引用通知: Dada's Blog » Subversion: revert a commit [時光倒轉]