SVN-fs-dump-format-version: 2 UUID: 2b9a0b3d-7cd0-0310-85b4-80501935bfcd Revision-number: 0 Prop-content-length: 56 Content-length: 56 K 8 svn:date V 27 2004-01-09T14:02:28.825238Z PROPS-END Revision-number: 1 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 20 * Import demo files. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-09T14:09:25.408100Z PROPS-END Node-path: SubversionSlideBasic.kwiki.txt Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 7393 Text-content-md5: 51fc7a571f03c5dfec5c72760bb26c81 Content-length: 7403 PROPS-END [&SLIDESHOW_SELECTOR] ---- [&title Subversion 基礎篇] == 本簡報流程 == * 簡述版本控制 * 簡述 CVS * Subversion 的特色 * 介紹 Subversion 常用指令 * 合併與標記 ---- == 為什麼需要版本控制 == * 記住過去的更動 * 獨立開發的空間 * 發展獨立的空間 ---- == CVS 的缺點 == * 難學 * 命令列選項 * 送交並不是不可分割的 * 不支援更名 * 沒有目錄單位 ---- == Subversion? == * 版本控制系統 * 類似 CVS 的架構 * 為網路設計 * 用來取代 CVS * 更好的 CVS * 自由的開放源碼 ---- == Subversion 的特色 == * 一致的使用者界面 * 目錄版本控制 * 不可分割的送交 * 納入版本控制的描述資料 * 多種網路通訊選擇 * 更佳的二進制資料處理 * 高效率的分支與標記 * 有效的網路傳輸 * Hackability ---- == Subversion 沒有的功能 == * 檔案保留 (cvs edit, watch) * Merge point * 檔案個別的版本 * 分散式檔案庫 * I18N, L10N ---- == 取得與安裝 Subversion == * 自 http://subversion.tigris.org 取得源碼 * 關聯程式庫 ** APR 0.95 以上 ** Neon 0.24.4 ** Berkeley DB 4.0 以上 (建議 4.2.50) ** Apache Web Server 2.0.48 (optional) ** Python (optional) ** Perl (optional) * FreeBSD 系統的 ports/devel/subversion * 在 http://subversion.tigris.org 找其它平台上的可執行檔 ---- == TortoiseSVN == * Windows 平台上最多人推薦用戶端 * 與檔案總管整合在一起 * 可與任何整合開放環境一同使用 * 網站: http://tortoisesvn.tigris.org/ ---- == Subversion 元件 == * 用戶端 ** svn ** svnversion * 伺服器端 ** svnadmin ** svnlook ** svnserve ** mod_dav_svn (optional) ---- == 檔案庫與修訂版 == * 類似檔案系統 * 修訂版是檔案庫的快照 [&img /~plasma/img/ch02dia7.png] * 全域的修訂版 * 修訂版關鍵字 ** HEAD ** BASE ** COMMITTED ** PREV * 單一修訂版號 --revision 1234 -r 1234 * 修訂版號範圍 --revision 1234:5678 -r 1234:5678 ---- == svn 命令列程式 == svn: 使用者與檔案庫之間的橋樑 * 動作目標可為 URL 或 路徑 ** 路徑作用的對象是工作複本 ** URL 工作的對象是檔案庫 * 命令列選項不受其所在位置影響 * 說明自己: help * URL 可能的 schema: ** file:// ** http:// ** https:// ** svn:// ** svn+ssh:// ---- == svnadmin 命令列程式 == svnadmin: 直接操控 Subversion 的檔案庫 * create: 建立檔案庫 * dump: 將檔案庫傾印至文字檔 * load: 自文字檔載入至檔案庫 ---- == 基本工作流程 == * 匯入至檔案庫 * 取出工作複本 * 更新工作複本 * 編輯、更動 * 檢視更動 * 回復更動 * 送交更動 ---- == 匯入至檔案庫 == * 匯入目前的工作目錄至檔案庫 % svn import http://repo.host/repos/project/trunk * 匯入指定的目錄至檔案庫 % svn import proj http://repo.host/repos/project/trunk ---- == 取出工作複本 == * 取出工作複本 % svn checkout http://svn.collab.net/repos/svn/trunk * 取出工作複本至指定的目錄 % svn checkout http://svn.collab.net/repos/svn/trunk svn * [=.svn] 管理目錄 ** 納入版本控制的項目的資料 ** 納入版本控制的項目的完整未更動檔案 ---- == 更新工作複本 == * 更新工作複本 ** 將所有的目錄與檔案更新至最新的修訂版 % svn update ** 將所有的目錄與檔案更新至某個較舊的修訂版 % svn update -r 1345 ** 只要 svn-doc.el 某個更老的版本 % svn update -r 999 svn-doc.el * 更新產生的結果 ;;[=A] : 預定新增至檔案庫. ;;[=M] : 檔案的內容已被更動. ;;[=D] : 預定要自檔案庫刪除. ;;[=?] : 未納入版本控制. ;;[=!] : 本項已納入版本控制, 但是不見了. ;;[=~] : 不同類別的物件. ;;[=C] : 衝突. ---- == 更動檔案 == * 使用文字編輯器 * 使用圖形編輯器 * 使用隨便什麼編輯器 * 新增現有的目錄或檔案 % svn add newfile.txt * 刪除現有的目錄或檔案 % svn rm bye.txt * 複製目錄或檔案 % svn copy foo.txt bar.txt * 搬移目錄或檔案 % svn move baz.txt buz.txt ---- == 檢視更動 (I) == * [=svn status] $ svn status L ./abc.c # svn 在 .svn 目錄中, 有 abc.c 的鎖定 M ./bar.c # bar.c 的內容, 有本地端的變更 M ./baz.c # baz.c 已變更了性質, 但是沒有內容的更動 ? ./foo.o # svn 並未管理 foo.o ! ./some_dir # svn 管理它, 但是不是不見了, 就是不完整 ~ ./qux # 納入管理的是目錄, 但是這裡是檔案, 或是相反的情況 A + ./moved_dir # 新增項目, 並以來源的歷史紀錄為其歷史紀錄 M + ./moved_dir/README # 新增項目, 使用來源的歷史紀錄, 再加上本地更動 D ./stuff/fish.c # 本檔案已預定要被刪除 A ./stuff/loot/bloo.h # 本檔案已預定要被新增 C ./stuff/loot/lump.c # 這個檔案有因更新而產生的衝突 S ./stuff/squawk # 這個檔案或目錄已切換到分支 ---- == 檢視更動 (II) == ** [=svn status]: 加上 -v 顯示更多的資訊 $ svn status --verbose M 44 23 sally ./README 44 30 sally ./INSTALL M 44 20 harry ./bar.c 44 18 ira ./stuff 44 35 harry ./stuff/trout.c D 44 19 ira ./stuff/fish.c 44 21 sally ./stuff/things A 0 ? ? ./stuff/things/bloo.h 44 36 harry ./stuff/things/gloo.c *** 顯示修訂版編號 *** 顯示更動檔案的人 ---- == 檢視更動 (III) == * 檢視你的更動 ** svn diff: 顯示所作的更動 *** 連性質的更動也會顯示 *** 顯示所有本地工作複本的目錄與檔案差異 % svn diff *** 顯示檔案庫的 3 號修訂版的 foo.pl 與工作複本的 foo.pl 之間的差異 % svn diff -r 3 foo.pl *** 顯示檔案庫中的 foo.pl 的 2 號與 3 號修訂版之間的差異, 無需存取本地複本 % svn diff -r 2:3 foo.pl ---- == 回復更動 == * 回復某檔案的更動 ** 完全不需要網路 % svn revert foo.pl ---- == 送交更動 == * 送交我們所作的更動 % svn commit * 在命令列提供送交訊息 % svn commit -m "Commit log message" * 送交之後, 工作複本目錄不會自動更新 ---- == 關鍵字展開 == * 如何使用關鍵字展開 ** 設定檔案的性質 % svn propset svn:keywords Id foo.pl ** 可使用的關鍵字 *** URL, HeadURL *** Author, LastChangedBy *** Date, LastChangedDate *** Rev, LastChangedRevision *** Id ---- == 檔案庫目錄架構 == * 其一 /repos/project1/trunk /repos/project1/branches /repos/project1/tags /repos/project2/trunk /repos/project2/branches /repos/project2/tags * 其二 /repos/trunk/project1 /repos/trunk/project2 /repos/branches/project1 /repos/branches/project2 /repos/tags/project1 /repos/tags/project2 ---- == 標記與分支 == * 廉價複本 ** 速度很快 ** 只是連結而已 * 標記與分支就只是複製而已 % svn cp http://svn.host/repos/proj/trunk \ http://svn.host/repos/proj/branches/add-new-features % svn cp http://svn.host/repos/proj/trunk \ http://svn.host/repos/proj/tags/0.0.1 * 標記與分支的差別 ** 標記不再更動 ** 分支將成為另一支發展線 ---- == 使用分支 == * 直接使用 checkout 命令 ** 直接使用分支目錄 % svn co http://svn.host/repos/proj/branches/add-new-features ** 另行指定分支目錄 % svn co http://svn.host/repos/proj/branches/add-new-features proj * 已有主分支的工作複本 ** 使用 svn switch % svn switch http://svn.host/repos/proj/branches/add-new-features ---- == 合併分支 == * 分支工作已完成, 該合併回主發展線 * 使用 merge 命令 * 最常犯的錯誤 % svn merge \ http://svn.host/repos/proj/branches/add-new-features \ http://svn.host/repos/proj/trunk * 正確的作法 % svn merge -r REV1:REV2 \ http://svn.host/repos/proj/branches/add-new-features ---- == 衝突 == * 無法正確無誤合併 * 產生三個額外的檔案 ** 原先在工作複本中的 ** 在合併來源的 ** 在合併目標的 * 無法進行送交 * 必須先解決衝突 * 使用 resolved 指令 % svn resolved foo.pl ---- == 參考網站 == * Subversion 網站: http://subversion.tigris.org * TortoiseSVN 網站: http://tortoisesvn.tigris.org * Subversion Book: http://svnbook.red-bean.com/ * Subversion Book 中譯版: http://freebsd.sinica.edu.tw/~plasma/svnbook/ Node-path: SubversionSlideRepo.kwiki.txt Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2233 Text-content-md5: abaf1ff8e01ca7d5ac9ef2b6cee2c9b4 Content-length: 2243 PROPS-END [&SLIDESHOW_SELECTOR] ---- [&title Subversion 檔案庫管理] == 檔案庫管理 == * svnadmin 命令列程式 * 與檔案庫在同一台機器上 * 目錄皆為路徑, 沒有 URL ---- == 檔案庫檔案架構 == * 檔案庫的內容 README.txt # 文字檔 conf # 包含設定檔的目錄 dav # 供 Apache mod_dav 使用的目錄 db # 資料庫目錄 format # 包含檔案庫格式版號的文字檔 hooks # 包含掛勾程式的目錄 locks # 供資料庫的鎖定使用的目錄 ---- == 檔案庫權限 == * 寫入檔案庫需有寫入權限 * 讀取檔案庫需有寫入權限 * 建議作法 ** 建立名為 svn 的使用者與群組 ** 檔案庫目錄設為該使用者與群組可讀寫 * umask ** 存取檔案庫應以 002 為之 ---- == 常用指令 == * 建立檔案庫 % svnadmin create SVN_ROOT * 傾印檔案庫內容 % svnadmin dump SVN_ROOT > repos.dump * 載入傾印檔內容 % svnadmin load SVN_ROOT < repos.dump * 列出無用的資料檔紀錄檔 % svnadmin list-unused-dblogs SVN_ROOT * 修正檔案庫問題 % svn recover ---- == 掛勾程式 == * 因檔案庫的事件而觸發 * 於檔案庫的機器上執行 * 實作的掛勾 ** start-commit ** pre-commit ** post-commit ** pre-revprop-change ** post-revprop-change ---- == 備份 == * 完整備份 ** svnadmin dump * 即時備份 ** svnadmin hotcopy * 回存 ** svnadmin load ---- == 開放至網路 == * 使用 Apache ** 功能強大 ** 可以和 Apache 模組協同使用 * 使用 svnserve ** 專屬伺服器 ** 使用簡單 * 使用 svnserve + ssh ** 使用簡單 ** 安全 ** 有 ssh 帳號即可使用 ---- == 使用 Apache == * 使用 mod_dav_svn * 設定檔範例 (一) LoadModule dav_svn_module modules/mod_dav_svn.so DAV svn SVNPath /absolute/path/to/repository * 設定檔範例 (二) LoadModule dav_svn_module modules/mod_dav_svn.so DAV svn SVNParentPath /usr/local/svn * 設定檔範例 (三) LoadModule dav_svn_module modules/mod_dav_svn.so DAV svn SVNParentPath /usr/local/svn AuthType Basic AuthName "Subversion repository" AuthUserFile /path/to/users/file Require valid-user ---- == 使用 svnserve == * 使用 port 3690 * 直接執行 svnserve -d * 透過 inetd * 必須使用完整路徑 * 可透過 -r 限制路徑範圍 ---- == 透過 SSH == * 只要有 SSH 即可 * 但是必須使用完整路徑 Revision-number: 2 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 20 Add a new text file. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-09T14:25:59.606510Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 5 Text-content-md5: 2145971cf82058b108229a3a2e3bff35 Content-length: 15 PROPS-END foo Revision-number: 3 Prop-content-length: 113 Content-length: 113 K 7 svn:log V 12 * more line. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-10T03:30:34.074309Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: change Text-content-length: 12 Text-content-md5: d8acd5d90b730b50006b9cee2b8f879f Content-length: 12 foo bar Revision-number: 4 Prop-content-length: 130 Content-length: 130 K 7 svn:log V 29 * Subversion SIG commit demo. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-10T03:55:21.959253Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: change Text-content-length: 15 Text-content-md5: a2ead3516dd1be4a3c7f45716c0a0eb7 Content-length: 15 foo bar baz Node-path: svn.txt Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 10 Text-content-md5: 3dbec9c1b92200eb56349835275e00b9 Content-length: 20 PROPS-END foo bar Revision-number: 5 Prop-content-length: 119 Content-length: 119 K 7 svn:log V 18 * Set Id property. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-10T04:04:21.780028Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: change Prop-content-length: 35 Text-content-length: 23 Text-content-md5: 130237c4c01b4deea15c662b9ac9a65c Content-length: 58 K 12 svn:keywords V 2 Id PROPS-END # $Id$ foo bar baz Revision-number: 6 Prop-content-length: 124 Content-length: 124 K 7 svn:log V 23 * Ready for conflict!!! K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-10T05:31:02.693444Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: change Text-content-length: 35 Text-content-md5: 21efbf723aa38d52b5c46223699a94da Content-length: 35 # $Id$ foo bar baz subversion Revision-number: 7 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 20 * Conflict resolved. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-10T05:37:04.015674Z PROPS-END Node-path: lines.txt Node-kind: file Node-action: change Text-content-length: 42 Text-content-md5: ca09a5ce149a8d6b2e8023b37964f683 Content-length: 42 # $Id$ foo bar baz subversion SIG. Revision-number: 8 Prop-content-length: 125 Content-length: 125 K 7 svn:log V 24 * Make a copy of svn.txt K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-16T09:08:16.754407Z PROPS-END Node-path: svn.copy.txt Node-kind: file Node-action: add Node-copyfrom-rev: 7 Node-copyfrom-path: svn.txt Revision-number: 9 Prop-content-length: 119 Content-length: 119 K 7 svn:log V 18 * Add a new layer. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-16T16:04:26.218350Z PROPS-END Node-path: dir Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: dir/lines.txt Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 9 Text-content-md5: 72f9e5fd3a2e61fcf3542092edc7cab8 Content-length: 19 PROPS-END FOO BAR Revision-number: 10 Prop-content-length: 119 Content-length: 119 K 7 svn:log V 18 * make a dir copy. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-16T17:30:22.602262Z PROPS-END Node-path: new_dir Node-kind: dir Node-action: add Node-copyfrom-rev: 9 Node-copyfrom-path: dir Revision-number: 11 Prop-content-length: 126 Content-length: 126 K 7 svn:log V 25 * multiple levels of dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-16T18:00:04.871383Z PROPS-END Node-path: deep Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: deep/more_deep Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: deep/more_deep/dir Node-kind: dir Node-action: add Node-copyfrom-rev: 9 Node-copyfrom-path: dir Revision-number: 12 Prop-content-length: 140 Content-length: 140 K 7 svn:log V 39 * Rename svn.copy.txt to svn.clone.txt. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-17T05:34:59.211765Z PROPS-END Node-path: svn.clone.txt Node-kind: file Node-action: add Node-copyfrom-rev: 8 Node-copyfrom-path: svn.copy.txt Node-path: svn.copy.txt Node-action: delete Revision-number: 13 Prop-content-length: 132 Content-length: 132 K 7 svn:log V 31 * Made a change to copied file. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T15:48:29.564987Z PROPS-END Node-path: svn.clone.txt Node-kind: file Node-action: change Text-content-length: 17 Text-content-md5: 3711a1d13b1345f49965c494ff91624f Content-length: 17 foo bar baz Revision-number: 14 Prop-content-length: 146 Content-length: 146 K 7 svn:log V 45 * Made a change to a file in deep copied dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T15:57:11.896860Z PROPS-END Node-path: deep/more_deep/dir/lines.txt Node-kind: file Node-action: change Text-content-length: 13 Text-content-md5: c08ae19747de7e34ba9a6a9319522437 Content-length: 13 FOO BAR BAZ Revision-number: 15 Prop-content-length: 141 Content-length: 141 K 7 svn:log V 40 * Move a deep directory to another name. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T16:08:49.545001Z PROPS-END Node-path: deep/more_deep/new_dir Node-kind: dir Node-action: add Node-copyfrom-rev: 13 Node-copyfrom-path: deep/more_deep/dir Node-path: deep/more_deep/new_dir/lines.txt Node-kind: file Node-action: delete Node-path: deep/more_deep/new_dir/lines.txt Node-kind: file Node-action: add Node-copyfrom-rev: 14 Node-copyfrom-path: deep/more_deep/dir/lines.txt Node-path: deep/more_deep/dir Node-action: delete Revision-number: 16 Prop-content-length: 147 Content-length: 147 K 7 svn:log V 46 * Made a change to a file in a deep directory. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T16:09:54.116527Z PROPS-END Node-path: deep/more_deep/new_dir/lines.txt Node-kind: file Node-action: change Text-content-length: 17 Text-content-md5: 17deba5591ff45fdfdc5a2382f9a2cda Content-length: 17 FOO BAR BAZ BUZ Revision-number: 17 Prop-content-length: 151 Content-length: 151 K 7 svn:log V 50 * Move a directory, modify a file withint the dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T16:19:18.836664Z PROPS-END Node-path: deep/more_deep/another_new_dir Node-kind: dir Node-action: add Node-copyfrom-rev: 16 Node-copyfrom-path: deep/more_deep/new_dir Node-path: deep/more_deep/another_new_dir/lines.txt Node-kind: file Node-action: change Text-content-length: 21 Text-content-md5: 1ef9a433976ba9435db98a55dd956b21 Content-length: 21 FOO BAR BAZ BUZ BZZ Node-path: deep/more_deep/new_dir Node-action: delete Revision-number: 18 Prop-content-length: 117 Content-length: 117 K 7 svn:log V 16 * Made a change. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-18T16:21:18.608747Z PROPS-END Node-path: deep/more_deep/another_new_dir/lines.txt Node-kind: file Node-action: change Text-content-length: 27 Text-content-md5: 5f0fe922acbbb8ae99344d44f1c62757 Content-length: 27 FOO BAR BAZ BUZ BZZ ERROR Revision-number: 19 Prop-content-length: 121 Content-length: 121 K 7 svn:log V 20 * Simulate a branch. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-19T14:18:57.105904Z PROPS-END Node-path: another_deep Node-kind: dir Node-action: add Node-copyfrom-rev: 18 Node-copyfrom-path: deep Revision-number: 20 Prop-content-length: 184 Content-length: 184 K 7 svn:log V 83 * Situation for new dir, copied a dir within, then modify a file in the lowest dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-20T00:51:58.906233Z PROPS-END Node-path: another_dir Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: another_dir/dir Node-kind: dir Node-action: add Node-copyfrom-rev: 19 Node-copyfrom-path: dir Node-path: another_dir/dir/lines.txt Node-kind: file Node-action: change Text-content-length: 13 Text-content-md5: c08ae19747de7e34ba9a6a9319522437 Content-length: 13 FOO BAR BAZ Revision-number: 21 Prop-content-length: 148 Content-length: 148 K 7 svn:log V 47 * remove previous rev. the test case is wrong. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-20T00:54:03.722689Z PROPS-END Node-path: another_dir Node-action: delete Revision-number: 22 Prop-content-length: 187 Content-length: 187 K 7 svn:log V 86 * A test case. New dir, add a copied path within, then edit a file in 3 level of dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-20T01:02:27.855682Z PROPS-END Node-path: another_dir Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: another_dir/more_deep Node-kind: dir Node-action: add Node-copyfrom-rev: 19 Node-copyfrom-path: another_deep/more_deep Node-path: another_dir/more_deep/another_new_dir/lines.txt Node-kind: file Node-action: change Text-content-length: 32 Text-content-md5: 3211cbe8eb62b72a8401a139b67398ac Content-length: 32 FOO BAR BAZ BUZ BZZ ERROR MILK Revision-number: 23 Prop-content-length: 147 Content-length: 147 K 7 svn:log V 46 * import a directory large enough to do tests. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T05:11:01.783505Z PROPS-END Node-path: svnperl Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/INSTALL Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 7648 Text-content-md5: 6fd4b903d76a7db18385509f333bc072 Content-length: 7658 PROPS-END -*-text-*- BUILDING SWIG BINDINGS FOR SVN ON UNIX Step 1: Build & install the proper version of SWIG (which is currently swig 1.3.16). * Go to http://www.swig.org/, download the sourceball, unpack. * In the SWIG-X.X.X directory, run ./configure. If you plan to build the python bindings, and have a system with more than one version of python installed, you may need to pass --with-python=/path/to/correct/python/binary to the configure script. You certainly don't want to use any version of python older than 2.0. * run 'make && make install' * To verify you have the goodz installed, check that these things were created, assuming your $PREFIX was /usr/local/lib: - /usr/local/lib/swig1.3/*.i - /usr/local/lib/libswig*.so - /usr/local/bin/swig In particular, you want to make sure that libswig_py.so was built and installed, since the python bindings are the most-used ones at the moment. Step 2: Build and Install Subversion. See Subversion's own INSTALL file for details. Make sure that Subversion's ./configure script sees your installed SWIG! It tries to detect SWIG near the very end of its output. If Subversion's ./configure finds a SWIG that it's happy with, then it will build a special glue library to link svn to the swig-python bindings: libsvn_swig_py.so (as well as any other languages). Step 3: Install Specific Language Bindings * Python 1. Run 'make swig-py' from the top of the Subversion source tree. This will invoke SWIG on the *.i files, resulting in a collection of .c source files. It will then compile and link those .c files into Python libraries. 2. Run 'make install-swig-py' (as root, typically) from the top of the Subversion source tree. This will copy your new Python libraries into the appropriate system location. Note: If you don't have access to install to python's site-packages directory, you can have the python modules install to your home directory. You can do this by running 'make install-swig-py swig_pydir=~'. Note: If you want to install to an alternate prefix (usually only if you are building packages), you can supply the prefix here. An example of doing this for building rpms looks like 'make install-swig-py DESTDIR=$RPM_BUILD_ROOT/usr'. 3. Make sure that whatever directory the bindings got installed in is in your PYTHONPATH. That directory depends on how you installed; a typical location is /usr/local/lib/svn-python/, see http://subversion.tigris.org/issues/show_bug.cgi?id=1125 for some imminent improvements to the install process. * Perl The build process of the Perl bindings is not yet tightly integrated with subversion's build system. It is using the standard way for building and installing perl extentions. You will have to install subversion before building and using it. Perl 5.8.0 is required. 1. Run `make swig-pl-lib' from the top of the Subversion source tree. 2. Go to subversion/bindings/swig/perl and run `env APR_CONFIG=/path/to/apr-config perl Makefile.PL'. 3. run `make all test'. 4. to install, run `make install-swig-pl-lib' from the top of the Subversion source tree, and `make install' from the perl directory. * Java The Java bindings are still under development, and have not yet reached a functional state. You can attempt to build them by running 'make swig-java' from the top level of the Subversion source tree. BUILDING SWIG BINDINGS FOR SVN ON WINDOWS 1. Install SWIG. Download the SWIG Windows zipfile (it's the same as the source tarball except that it also includes a copy of swig.exe) from http://www.swig.org/ and extract it somewhere, like C:\Program Files. 2. Install whatever languages you want to build runtimes for. Windows versions of Python, Perl, and Java are available from: http://www.python.org/ http://www.activestate.com/ActivePerl/ http://java.sun.com/j2se/ 3. Configure Visual C++ with paths to swig.exe and language specific libraries. In Visual C++ 6, go to Tools -> Options -> Directories. In Visual C++ .NET, go to Tools -> Options -> Projects -> VC++ Directories. Add the following paths: Executable Directories: Path to swig.exe (for example, C:\Program Files\SWIG-1.3.19) Library Directories: For Python, path to python##.lib (for example, C:\Program Files\Python22\libs) For Perl, path to perl##.lib (for example, C:\Program Files\Perl\lib\CORE) For Java, path to jvm.lib library (for example C:\Program Files\j2sdk1.4.2\lib) Include Directories: For Python, path to Python.h (for example, C:\Program Files\Python22\include) For Perl, path to perl.h (for example, C:\Program Files\Perl\lib\CORE) For Java, path to JNI headers, (for example, C:\Program Files\j2sdk1.4.2\include) Also for Java, path to JNI Windows headers, (for example, C:\Program Files\j2sdk1.4.2\include\win32) 4. If you haven't already built Subversion, you should do so now. Instructions are in the main INSTALL file. At the very least, you need to run gen-make.py to generate Visual Studio project files. 5. Build the bindings. Open the Subversion workspace in Visual C++ (subversion_msvc.dsw or subversion_vcnet.sln) and build one or more of the following projects: __SWIG_PYTHON__ __SWIG_PERL__ __SWIG_JAVA__ 6. Install the bindings. The procedure varies depending on the language. For Python, create two folders: \Lib\site-packages\svn \Lib\site-packages\libsvn Copy subversion\bindings\swig\python\svn\*.py into the svn folder. Copy subversion\bindings\swig\python\*.py and Release\subversion\bindings\swig\python\*.dll into the libsvn folder. Optionally, you can run the following commands to compile the Python sources into bytecode: python \lib\compileall.py \Lib\site-packages\svn python \lib\compileall.py \Lib\site-packages\libsvn This can make the modules load faster for users without write access to the site-packages directory. For Perl, ??? For Java, ??? TESTING AND USING SWIG BINDINGS * Python 1. Verify that an 'svn' package has been installed correctly. You can do this by running Python via 'python -c "from svn import client"'. 2. Try some demo programs. From the top of your svn working copy, cd tools/examples/ and try running 'svnlook.py'. 3. Start writing your own scripts. Use the Subversion API definitions and descriptions in: subversion/include/svn_client.h subversion/include/svn_delta.h subversion/include/svn_fs.h subversion/include/svn_ra.h subversion/include/svn_repos.h subversion/include/svn_wc.h * Perl The perl bindings are using the standard module testing facilities to do regression tests. Simply run make test as described in the install section. * Java Node-path: svnperl/README Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2313 Text-content-md5: e0377d3a634bab69f63f654c44f62f33 Content-length: 2323 PROPS-END -*-text-*- ==> For instructions on how to get swig bindings working, read the INSTALL file in this directory. SVN HEADER -> SWIG MODULE ------------------------- Subversion has a bunch of includes files, some are interesting for wrapping with language bindings, and others which are simple type declarations and constants. Below is the table which maps each header to its disposition: INCLUDE SWIG MODULE NAME svn_base64.h (1) svn_client.h _client svn_config.h ? svn_delta.h _delta svn_error.h (2) svn_error_codes.h (2) svn_fs.h _fs svn_hash.h (1) svn_io.h (4) (only stream functions) svn_path.h (1) svn_pools.h (4) (only pool manipulation) svn_quoprint.h (1) svn_ra.h _ra svn_repos.h _repos svn_sorts.h (1) svn_string.h (3) svn_test.h (2) svn_time.h (1) svn_types.h (3) svn_version.h (4) (some symbols) svn_wc.h _wc svn_xml.h (1) apr*.h (3) n/a _util (1) it is assumed that the binding languages will provide this functionality separately. ### HELP: Java does not provide base-64 natively. Should we wrap ### SVN's with SWIG, or include a stand-alone ASF implementation ### (such as from Jakarta Commons Codec)? (2) no significant/interesting functionality to export (3) only the types are exported; a SWIG interface file is present (4) limited symbols/functionality exported via the _util module NOTE: the bindings code is being developed using SWIG 1.3.16. Earlier versions of SWIG will simply *not* work. SWIG MODULES ------------ We will produce a number of modules/classes, expecting the binding languages to organize these into a package, and present the Subversion libraries' API in a manner familiar to programmers of a given language. For instance, the Python bindings are handled as follows: svn.client svn.delta svn.error svn.fs svn.io svn.ra svn.wc THUNK EDITORS ------------- "Thunk" is Windows programming term describing a "go between." Our SWIG bindings generally implement editors in C which delegate to the language-specific extension API (e.g. its C API for Python, JNI for Java, etc.). This transitional object implements a Subversion editor interface, allowing it to be passed between its native library code and the runtime of the language which the bindings were written for. Node-path: svnperl/apr.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 6648 Text-content-md5: 17ca72cdc920b97091a6e9a58063fe35 Content-length: 6658 PROPS-END /* * apr.i : SWIG interface file for selected APR types * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ /* This is the interface for the APR headers. This is not built as a module because we aren't going to wrap the APR functions. Thus, we only define the various types in here, as necessary. Actually, core.i wraps a few, key functions. */ %include typemaps.i /* This is default in SWIG 1.3.17 and is a really good idea */ %typemap(javagetcptr) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [], SWIGTYPE (CLASS::*) %{ protected static long getCPtr($javaclassname obj) { return (obj == null) ? 0 : obj.swigCPtr; } %} /* ----------------------------------------------------------------------- */ /* define an OUTPUT typemap for 'apr_off_t *'. for now, we'll treat it as a 'long' even if that isn't entirely correct... */ %typemap(python,in,numinputs=0) apr_off_t * (apr_off_t temp) "$1 = &temp;"; %typemap(python,argout,fragment="t_output_helper") apr_off_t * "$result = t_output_helper($result,PyInt_FromLong((long) (*$1)));"; %typemap(perl5,argout) apr_off_t * { /* ### FIXME-perl apr_off_t out*/ } /* ----------------------------------------------------------------------- */ %include apr.h /* ### be nice to have all the error values and macros. there are some ### problems including this file, tho. SWIG isn't smart enough with some ### of the preprocessing and thinks there is a macro redefinition */ //%include apr_errno.h typedef int apr_status_t; /* ### seems that SWIG isn't picking up the definition of size_t */ typedef unsigned long size_t; /* Define the time type (rather than picking up all of apr_time.h) */ typedef apr_int64_t apr_time_t; typedef apr_int32_t time_t; /* ----------------------------------------------------------------------- handle the mappings for apr_time_t Note: we don't generalize this to 'long long' since SWIG is starting to handle that. */ %apply long long { apr_time_t }; /* 'apr_time_t *' will always be an OUTPUT parameter */ %typemap(in,numinputs=0) apr_time_t * (apr_time_t temp) "$1 = &temp;"; %typemap(python,argout,fragment="t_output_helper") apr_time_t * "$result = t_output_helper($result, PyLong_FromLongLong(*$1));"; %typemap(java,argout) apr_time_t * { /* FIXME: What goes here? */ } %typemap(perl5,argout) apr_time_t * { /* ### FIXME-perl apr_time_t out */ } /* ----------------------------------------------------------------------- create some INOUT typemaps for apr_size_t */ %apply unsigned long *INOUT { apr_size_t *INOUT }; %typemap(python,in) apr_size_t *INOUT (apr_size_t temp) { temp = (apr_size_t) PyInt_AsLong($input); $1 = &temp; } %typemap(java,in) apr_size_t *INOUT (apr_size_t temp) { temp = (apr_size_t) JCALL2(CallLongMethod, jenv, $input, svn_swig_java_mid_long_longvalue); $1 = &temp; } %typemap(perl5,in) apr_size_t *INOUT (apr_size_t temp) { temp = (apr_size_t) SvIV($input); $1 = &temp; } /* ----------------------------------------------------------------------- create an OUTPUT argument typemap for an apr_hash_t ** */ %typemap(python,in,numinputs=0) apr_hash_t **OUTPUT (apr_hash_t *temp) "$1 = &temp;"; %typemap(perl5,in,numinputs=0) apr_hash_t **OUTPUT (apr_hash_t *temp) "$1 = &temp;"; /* ----------------------------------------------------------------------- create an OUTPUT argument defn for an apr_hash_t ** which is storing property values */ %typemap(python,in,numinputs=0) apr_hash_t **PROPHASH = apr_hash_t **OUTPUT; %typemap(python,argout) apr_hash_t **PROPHASH { /* toss prior result, get new result from the hash */ Py_DECREF($result); $result = svn_swig_py_prophash_to_dict(*$1); } /* ----------------------------------------------------------------------- Handle an apr_hash_t ** in Java */ %typemap(jni) apr_hash_t ** "jobject" %typemap(jtype) apr_hash_t ** "java.util.Map" %typemap(jstype) apr_hash_t ** "java.util.Map" %typemap(javain) apr_hash_t ** "$javainput" %typemap(javaout) apr_hash_t ** { return $jnicall; } %typemap(java,in) apr_hash_t **(apr_hash_t *temp){ $1 = &temp; } %typemap(java,out) apr_hash_t ** { svn_swig_java_add_to_map(jenv, *$1, $input); } %typemap(java,argout) apr_hash_t ** { svn_swig_java_add_to_map(jenv, *$1, $input); } %typemap(java,argout) apr_hash_t **PROPHASH { svn_swig_java_add_to_map(jenv, *$1, $input); } /* ----------------------------------------------------------------------- Handle an apr_array_header_t * in Java */ %typemap(jni) apr_array_header_t * "jobject" %typemap(jtype) apr_array_header_t * "java.util.List" %typemap(jstype) apr_array_header_t * "java.util.List" %typemap(javain) apr_array_header_t * "$javainput" %typemap(javaout) apr_array_header_t * { return $jnicall; } %typemap(java, argout) apr_array_header_t * { svn_swig_java_add_to_list(jenv, $1, $input); } %typemap(perl5,in,numinputs=0) apr_hash_t **PROPHASH = apr_hash_t **OUTPUT; %typemap(perl5,argout) apr_hash_t **PROPHASH { $result = svn_swig_pl_prophash_to_hash(*$1); argvi++; } /* ----------------------------------------------------------------------- handle apr_file_t * */ %typemap(python, in) apr_file_t * { $1 = svn_swig_py_make_file($input, _global_pool); } %typemap(perl5, in) apr_file_t * { $1 = svn_swig_pl_make_file($input, _global_pool); } /* ----------------------------------------------------------------------- apr_file_t ** is always an OUT param */ %typemap(in, numinputs=0) apr_file_t ** (apr_file_t *temp) "$1 = &temp;"; %typemap(python,argout,fragment="t_output_helper") apr_file_t ** "$result = t_output_helper( $result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0));"; %typemap(perl5, argout) apr_file_t ** { ST(argvi) = sv_newmortal(); SWIG_MakePtr(ST(argvi++), (void *)*$1, $*1_descriptor,0); } /* ----------------------------------------------------------------------- */ Node-path: svnperl/core.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 10691 Text-content-md5: 003fc58b1e75978efa6921d3eeccac0b Content-length: 10701 PROPS-END /* * core.i : SWIG interface file for various core SVN and APR components * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module core %include typemaps.i %{ #include "svn_opt.h" %} /* ----------------------------------------------------------------------- include svn_types.h early. other .i files will import svn_types.i which then includes svn_types.h, making further includes get skipped. we want to actually generate wrappers, so manage svn_types.h right here. */ /* ### for now, let's ignore this thing. */ %ignore svn_prop_t; /* ----------------------------------------------------------------------- The following struct members have to be read-only because otherwise strings assigned to then would never be freed, resulting in memory leaks. This prevents the swig warning "Warning(451): Setting const char * member may leak memory." */ %immutable svn_log_changed_path_t::copyfrom_path; %immutable svn_dirent::last_author; %immutable svn_error::message; %immutable svn_error::file; %include svn_types.h /* ----------------------------------------------------------------------- moving along... */ %import apr.i %import svn_types.i %import svn_string.i /* ----------------------------------------------------------------------- completely ignore a number of functions. the presumption is that the scripting language already has facilities for these things (or they are relatively trivial). */ %ignore svn_io_check_path; %ignore svn_io_check_resolved_path; %ignore svn_io_copy_file; %ignore svn_io_copy_dir_recursively; %ignore svn_io_append_file; %ignore svn_io_read_length_line; %ignore svn_io_file_affected_time; %ignore svn_io_fd_from_file; %ignore svn_io_get_dirents; %ignore svn_io_run_cmd; %ignore svn_io_remove_file; %ignore svn_io_remove_dir; %ignore svn_io_make_dir_recursively; %ignore svn_io_set_file_read_only; %ignore svn_io_set_file_read_write; %ignore svn_io_set_file_executable; %ignore svn_io_filesizes_different_p; %ignore svn_io_file_printf; %ignore apr_check_dir_empty; /* bad pool convention */ %ignore svn_opt_print_generic_help; /* scripts can do the printf, then write to a stream. we can't really handle the variadic, so ignore it. */ %ignore svn_stream_printf; /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_auth_baton_t **, svn_diff_t ** } /* ----------------------------------------------------------------------- apr_size_t * is always an IN/OUT parameter in svn_io.h */ %apply apr_size_t *INOUT { apr_size_t * }; /* ----------------------------------------------------------------------- handle the MIME type return value of svn_io_detect_mimetype() */ %apply const char **OUTPUT { const char ** }; /* ----------------------------------------------------------------------- handle the providers array as an input type. */ %typemap(python, in) apr_array_header_t *providers { svn_auth_provider_object_t *provider; int targlen; if (!PySequence_Check($input)) { PyErr_SetString(PyExc_TypeError, "not a sequence"); return NULL; } targlen = PySequence_Length($input); $1 = apr_array_make(_global_pool, targlen, sizeof(provider)); ($1)->nelts = targlen; while (targlen--) { SWIG_ConvertPtr(PySequence_GetItem($input, targlen), (void **)&provider, $descriptor(svn_auth_provider_object_t *), SWIG_POINTER_EXCEPTION | 0); APR_ARRAY_IDX($1, targlen, svn_auth_provider_object_t *) = provider; } } /* ----------------------------------------------------------------------- fix up the svn_stream_read() ptr/len arguments */ %typemap(python, in) (char *buffer, apr_size_t *len) ($*2_type temp) { if (!PyInt_Check($input)) { PyErr_SetString(PyExc_TypeError, "expecting an integer for the buffer size"); return NULL; } temp = PyInt_AsLong($input); if (temp < 0) { PyErr_SetString(PyExc_ValueError, "buffer size must be a positive integer"); return NULL; } $1 = malloc(temp); $2 = ($2_ltype)&temp; } %typemap(perl5, in) (char *buffer, apr_size_t *len) ($*2_type temp) { temp = SvIV($input); $1 = malloc(temp); $2 = ($2_ltype)&temp; } /* ### need to use freearg or somesuch to ensure the string is freed. ### watch out for 'return' anywhere in the binding code. */ %typemap(python, argout, fragment="t_output_helper") (char *buffer, apr_size_t *len) { $result = t_output_helper($result, PyString_FromStringAndSize($1, *$2)); free($1); } %typemap(perl5, argout) (char *buffer, apr_size_t *len) { $result = sv_newmortal(); sv_setpvn ($result, $1, *$2); free($1); argvi++; } /* ----------------------------------------------------------------------- fix up the svn_stream_write() ptr/len arguments */ %typemap(python, in) (const char *data, apr_size_t *len) ($*2_type temp) { if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "expecting a string for the buffer"); return NULL; } $1 = PyString_AS_STRING($input); temp = PyString_GET_SIZE($input); $2 = ($2_ltype)&temp; } %typemap(perl5, in) (const char *data, apr_size_t *len) ($*2_type temp) { $1 = SvPV($input, temp); $2 = ($2_ltype)&temp; } %typemap(python, argout, fragment="t_output_helper") (const char *data, apr_size_t *len) { $result = t_output_helper($result, PyInt_FromLong(*$2)); } %typemap(perl5, argout, fragment="t_output_helper") (const char *data, apr_size_t *len) { $result = newSViv(*$2); } /* auth provider convertors */ %typemap(perl5, in) apr_array_header_t *providers { $1 = (apr_array_header_t *) svn_swig_pl_objs_to_array($input, SWIGTYPE_p_svn_auth_provider_object_t, _global_pool); } /* ----------------------------------------------------------------------- describe how to pass a FILE* as a parameter (svn_stream_from_stdio) */ %typemap(python, in) FILE * { $1 = PyFile_AsFile($input); if ($1 == NULL) { PyErr_SetString(PyExc_ValueError, "Must pass in a valid file object"); return NULL; } } %typemap(perl5, in) FILE * { dSP ; int count, fd ; ENTER ; SAVETMPS; PUSHMARK(SP) ; XPUSHs($input); PUTBACK ; count = call_pv("fileno", G_SCALAR); SPAGAIN ; if (count != 1) croak("Big trouble\n") ; if (fd = POPi < 0) croak("not an accessible filehandle"); $1 = fdopen (fd, "r+"); PUTBACK ; FREETMPS ; LEAVE ; } /* ----------------------------------------------------------------------- the second argument to svn_parse_date is unused: always pass NULL */ %typemap(python,in,numinputs=0) struct getdate_time *now { $1 = NULL; } /* ignore the related structure */ /* ### hmm... this structure isn't namespace protected?! */ %ignore getdate_time; /* ----------------------------------------------------------------------- wrap some specific APR functionality */ apr_status_t apr_initialize(void); void apr_terminate(void); apr_status_t apr_time_ansi_put(apr_time_t *result, time_t input); void apr_pool_destroy(apr_pool_t *p); void apr_pool_clear(apr_pool_t *p); apr_status_t *apr_file_open_stdout (apr_file_t **out, apr_pool_t *pool); apr_status_t *apr_file_open_stderr (apr_file_t **out, apr_pool_t *pool); /* ----------------------------------------------------------------------- pool functions renaming since swig doesn't take care of the #define's */ %rename (svn_pool_create) svn_pool_create_ex; %ignore svn_pool_create_ex_debug; %typemap(default) apr_allocator_t *allocator { $1 = NULL; } /* ----------------------------------------------------------------------- Default pool handling for perl. */ #ifdef SWIGPERL apr_pool_t *current_pool; #endif /* ----------------------------------------------------------------------- wrap config functions */ %typemap(perl5,in,numinputs=0) apr_hash_t **cfg_hash = apr_hash_t **OUTPUT; %typemap(perl5,argout) apr_hash_t **cfg_hash { ST(argvi++) = svn_swig_pl_convert_hash(*$1, SWIGTYPE_p_svn_config_t); } %typemap(python,in,numinputs=0) apr_hash_t **cfg_hash = apr_hash_t **OUTPUT; %typemap(python,argout,fragment="t_output_helper") apr_hash_t **cfg_hash { $result = t_output_helper( $result, SWIG_NewPointerObj(*$1, SWIGTYPE_p_apr_hash_t, 0)); } /* Allow None to be passed as config_dir argument */ %typemap(python,in,parse="z") const char *config_dir ""; #ifdef SWIGPYTHON PyObject *svn_swig_py_exception_type(void); #endif /* ----------------------------------------------------------------------- */ %include svn_types.h %include svn_pools.h %include svn_version.h %include svn_time.h %include svn_props.h %include svn_opt.h %include svn_auth.h %include svn_config.h %include svn_version.h %include svn_error_codes.h /* SWIG won't follow through to APR's defining this to be empty, so we need to do it manually, before SWIG sees this in svn_io.h. */ #define __attribute__(x) %include svn_io.h #ifdef SWIGPERL %include svn_diff.h #endif %{ #include #include #include "svn_io.h" #include "svn_pools.h" #include "svn_version.h" #include "svn_time.h" #include "svn_props.h" #include "svn_opt.h" #include "svn_auth.h" #include "svn_config.h" #include "svn_version.h" #include "svn_md5.h" #include "svn_diff.h" #include "svn_error_codes.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} #ifdef SWIGPYTHON %init %{ /* This is a hack. I dunno if we can count on SWIG calling the module "m" */ PyModule_AddObject(m, "SubversionException", svn_swig_py_register_exception()); %} %pythoncode %{ SubversionException = _core.SubversionException %} #endif Node-path: svnperl/java Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/README Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 68 Text-content-md5: 78bbe491b38ccd5f68a483ef5d269e46 Content-length: 78 PROPS-END Subversion's SWIG/Java bindings support JDK version 1.2 and higher. Node-path: svnperl/java/org Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/org/tigris Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/org/tigris/subversion Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/org/tigris/subversion/client Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/org/tigris/subversion/client/StandardClient.java Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 4048 Text-content-md5: feffc12182847e1bf2905e7698c0e937 Content-length: 4058 PROPS-END package org.tigris.subversion.client; /* * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ import java.io.File; import java.io.OutputStream; import java.util.List; import org.tigris.subversion.SubversionException; import org.tigris.subversion.auth.AuthProvider; import org.tigris.subversion.opt.OptRevision; import org.tigris.subversion.util.NativeResources; import org.tigris.subversion.wc.Notifier; import org.tigris.subversion.swig.client; import org.tigris.subversion.swig.svn_client_ctx_t; import org.tigris.subversion.swig.SWIGTYPE_p_apr_file_t; import org.tigris.subversion.swig.SWIGTYPE_p_apr_pool_t; import org.tigris.subversion.swig.SWIGTYPE_p_svn_opt_revision_t; /** * A SWIG-based implementation of the {@link Client} interface. * * @since Subversion 0.31 */ public class StandardClient implements Client { static { NativeResources.getInstance().initialize(); } /** * @see Client#getSimplePromptProvider */ public AuthProvider getSimplePromptProvider(ClientPrompt prompt, int retryLimit) { throw new RuntimeException("Not implemented"); } /** * @see Client#getUsernamePromptProvider */ public AuthProvider getUsernamePromptProvider(ClientPrompt prompt, int retryLimit) { throw new RuntimeException("Not implemented"); } /** * @see Client#getNotifier */ public Notifier getNotifier() { throw new RuntimeException("Not implemented"); } /** * @see Client#getCommitLogReceiver */ public LogMessageReceiver getCommitLogReceiver() { throw new RuntimeException("Not implemented"); } /** * @see Client#checkout */ public void checkout(String url, File path, Object revision, boolean recurse) throws SubversionException { throw new RuntimeException("Not implemented"); } /** * @see Client#diff */ public void diff(List diffOptions, String path1, OptRevision revision1, String path2, OptRevision revision2, boolean recurse, boolean ignoreAncestry, boolean noDiffDeleted, OutputStream output, OutputStream error) throws SubversionException { // FIXME: How do I instantiate one of these? svn_client_ctx_t clientCtx = null; // FIXME: Temporary placeholder for revision1 and revision2. SWIGTYPE_p_svn_opt_revision_t dummy = null; SubversionException e = client.svn_client_diff((String []) diffOptions.toArray (new String[diffOptions.size()]), path1, dummy /*revision1*/, path2, dummy /*revision2*/, recurse, ignoreAncestry, noDiffDeleted, // TODO: Need type conversion for // output and error. (SWIGTYPE_p_apr_file_t) null, (SWIGTYPE_p_apr_file_t) null, clientCtx, (SWIGTYPE_p_apr_pool_t) null); if (e != null) { throw e; } } } Node-path: svnperl/java/org/tigris/subversion/util Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/java/org/tigris/subversion/util/NativeResources.java Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 3833 Text-content-md5: eaf22bc9d4f42fc50ef24bf26cca1693 Content-length: 3843 PROPS-END package org.tigris.subversion.util; /* * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ import org.tigris.subversion.swig.core; import org.tigris.subversion.swig.SWIGTYPE_p_apr_pool_t; import org.tigris.subversion.swig.SWIGTYPE_p_apr_allocator_t; /** * Handles operations involving the native libraries composing * Subversion's implementation. * * @since Subversion 0.31 */ public class NativeResources { private static NativeResources instance; static { String className = System.getProperty(NativeResources.class.getName()); if (className != null && className.length() > 0) { try { Class c = Class.forName(className); instance = (NativeResources) c.newInstance(); } catch (Exception useDefault) { // Likely an UnsatisfiedLinkError. System.err.println("NativeResources '" + className + '\'' + " not available, falling back to '" + NativeResources.class.getName() + '\''); } } if (instance == null) { instance = new NativeResources(); } } /** * Whether the native libraries have been loaded and initialized. */ protected boolean isInitialized = false; /** * The APR pool used for native code memory management. */ private SWIGTYPE_p_apr_pool_t pool; /** * Returns the single instance of this class for this * ClassLoader tree. */ public static NativeResources getInstance() { return instance; } /** * Default constructor, scoped to prevent direct instantiation. * @see #getInstance() */ protected NativeResources() { } /** * Loads and initializes the native libraries used by this * instance. */ public synchronized void initialize() { if (this.isInitialized) { return; } // Load the SWIG-based JNI bindings. System.loadLibrary("swigjava"); // Initialize the Apache Portable Runtime used by Subversion's // C implementation. core.apr_initialize(); System.out.println("Allocating parent pool"); this.pool = core.svn_pool_create((SWIGTYPE_p_apr_pool_t) null, (SWIGTYPE_p_apr_allocator_t) null); this.isInitialized = true; } public Object getMemoryManager() { return pool; } /** * Unloads and un-initializes the native libraries used by this * instance. */ public synchronized void uninitialize() { System.out.println("Destroying parent pool"); core.apr_pool_destroy(this.pool); core.apr_terminate(); this.isInitialized = false; } /** * @see #uninitialize */ protected void finalize() throws Throwable { try { super.finalize(); } finally { uninitialize(); } } } Node-path: svnperl/perl Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/perl/Base.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 3205 Text-content-md5: 3f435f0f269a582ed14eceb38e0109a9 Content-length: 3240 K 12 svn:keywords V 2 Id PROPS-END package SVN::Base; =head1 NAME SVN::Base - Base class for importing symbols for svn modules =head1 SYNOPSIS # Load the svn_ra_* functions into the SVN::Ra namespace. pacakge SVN::Ra; use SVN::Base qw(Ra svn_ra_); # Load svn_config_t structure accessors in the magic namcespace # provided by swig, so we could use it returned by other functions package _p_svn_config_t; use SVN::Base qw(Core svn_config_); =head1 DESCRIPTION SVN::Base is a module importing the subversion perl bindings raw symbols created by swig, into proper namespace and make them easier to use. It will also find the accessors for members of a C struct, create an simpler accessor function like C<$data-Efield()> and C<$data-Efield($new_value)>. Once you understand the convention of subversion functions in perl bindings, you could look at the subversion api and write them in perl. The API is available in the source header files or online at http://svn.collab.net/svn-doxygen/. =head1 INTERNALS The perl bindings of swig wraps raw functions into different perl modules, for example, SVN::_Core, SVN::_Repos. Upon import, SVN::Base bootstrap the requested module if it's not yet loaded, and iterate over the symbols provided in that module, it them puts the function with prefix trimmed in the namespace of the caller for this import. The 3rd through the last parameter is a list of symbol endings that you wish for SVN::Base not to import into your namespace. This is useful for cases where you may want to import certaion symbols differently than normally. =head1 CAVEATS SVN::Base consider a function as structure member accessor if it is postfixed ``_get'' or ``_set''. Real functions with this postfixes will need extra handling. =cut sub import { my (undef, $pkg, $prefix, @ignore) = @_; no warnings 'uninitialized'; unless (${"SVN::_${pkg}::ISA"}[0] eq 'DynaLoader') { @{"SVN::_${pkg}::ISA"} = qw(DynaLoader); eval qq' package SVN::_$pkg; require DynaLoader; bootstrap SVN::_$pkg; 1; ' or die $@; }; my $caller = caller(0); SYMBOL: for (keys %{"SVN::_${pkg}::"}) { my $name = $_; next unless s/^$prefix//i; foreach my $ignored_symbol (@ignore) { next SYMBOL if ("$prefix$ignored_symbol" eq $name); } # insert the accessor if (m/(.*)_get$/) { my $member = $1; *{"${caller}::$1"} = sub { &{"SVN::_${pkg}::${prefix}${member}_". (@_ > 1 ? 'set' : 'get')} (@_) } } elsif (m/(.*)_set$/) { } else { *{"${caller}::$_"} = ${"SVN::_${pkg}::"}{$name}; } } } =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Client.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 15544 Text-content-md5: a70873df186fb9dda0c7b4f102f58e78 Content-length: 15579 K 12 svn:keywords V 2 Id PROPS-END use SVN::Core; package SVN::Client; use SVN::Base(qw(Client svn_client_ checkout update switch add mkdir delete commit status log blame diff merge cleanup relocate revert resolved copy move revprop_set propset proplist revvprop_list export ls cat import)); =head1 NAME SVN::Client - Subversion client functions =head1 SYNOPSIS use SVN::Client; my $ctx = new SVN::Client( auth => [SVN::Client::get_simple_provider(), SVN::Client::get_simple_prompt_provider(\&simple_prompt,2), SVN::Client::get_username_provider()] ); $ctx->cat (\*STDOUT, 'http://svn.collab.net/repos/svn/trunk/README', 'HEAD'); sub simple_prompt { my $cred = shift; my $realm = shift; my $default_username = shift; my $may_save = shift; my $pool = shift; print "Enter authentication info for realm: $realm\n"; print "Username: "; my $username = <>; chop($username); $cred->username($username); print "Password: "; my $password = <>; chomp($password); $cred->password($password); } =head1 DESCRIPTION SVN::Client wraps the highest level of functions provided by subversion to accomplish specific tasks in an object oriented API. Methods are similar to the functions provided by the C API and as such the documentation for it may be helpful in understanding this interface. There are a few notable differences from the C API. Most C function calls take a svn_client_ctx_t pointer as the next to last parameter. The perl method calls take a SVN::Client object as the first parameter. This allows method call invocation of the methods to be possible. Many of the C API calls also take a apr_pool_t pointer as their last argument. The Perl bindings generally deal with this for you and you do not need to pass a pool parameter. However, you may still pass a pool parameter as the last parameter to override the automatic handling of this for you. Users of this interface should not directly manipulate the underlying hash values but should use the respective attribute methods. Many of these attribute methods do other things, especially when setting an attribute, besides simply manipulating the value in the hash. =head1 METHODS The following methods are available: =over 4 =item $ctx = SVN::Client->new( %options ); This class method constructs a new C object and returns a reference to it. Key/value pair arguments may be provided to set up the initial state of the user agent. The following methods correspond to attribute methods described below: KEY DEFAULT ---------- ---------------------------------------- config Hash containing the config from the default subversion config file location. auth auth_baton intiated to provide the provider that read cached authentication options from the subversion config only. pool A new pool is created for the context. =cut sub new { my $class = shift; my $self = bless {}, $class; my %args = @_; $self->{'ctx'} = SVN::_Client::new_svn_client_ctx_t (); if (defined($args{'auth'})) { $self->auth($args{'auth'}); } else { $self->auth([SVN::Client::get_username_provider(), SVN::Client::get_simple_provider(), SVN::Client::get_ssl_server_trust_file_provider(), SVN::Client::get_ssl_client_cert_file_provider(), SVN::Client::get_ssl_client_cert_pw_file_provider(), ]); } { my $pool_type = ref($args{'pool'}); if ($pool_type eq 'SVN::Pool' || $pool_type eq '_p_apr_pool_t') { $self->{'pool'} = $args{'pool'}; } else { $self->{'pool'} = new SVN::Pool(); } } # If we're passed a config use it, otherwise get the default # config. if (defined($args{'config'})) { if (ref($args{'config'}) eq 'HASH') { $self->config($args{'config'}); } } else { $self->config(SVN::Core::config_get_config(undef)); } return $self; } =item $ctx->cat(\*FILEHANDLE, path_or_url, revision, pool); Outputs the content of the file identified by path_or_url and revision to the FILEHANDLE. FILEHANLDE is a reference to a filehandle. revision should be a number or 'HEAD'. pool is an optional parameter. =cut # import methods into our name space and wrap them in a closure # to support method calling style $ctx->log() foreach my $function (qw(checkout update switch add mkdir delete commit status log blame diff merge cleanup relocate revert resolved copy move revprop_set propset proplist revvprop_list export ls cat import)) { my $real_function = \&{"SVN::_Client::svn_client_$function"}; *{"SVN::Client::$function"} = sub { # Allows import to work while not breaking use SVN::Client. if ($function eq 'import') { if (ref($_[$[]) ne 'SVN::Client') { return; } } my $self = shift; my @args; if (ref($_[$#_]) eq '_p_apr_pool_t') { # if we got a pool pased to us we need to # leave it off until we add the ctx first # so we push only the first arg to the next # to last arg. push @args, @_[$[ .. ($#_ - 1)]; unless ($function eq 'propset') { # propset doesn't take a ctx argument push @args, $self->{'ctx'}; } push @args, $_[$#_]; } else { push @args, @_; unless ($function eq 'propset') { push @args,$self->{'ctx'}; } if (defined($self->{'pool'}) && ref($self->{'pool'}) eq '_p_apr_pool_t') { # allow the pool entry in the SVN::Client # object to override the default pool. push @args, $self->{'pool'}; } } return $real_function->(@args); } } =head1 ATTRIBUTE METHODS The following attribute methods are provided that allow you to set various configuration or retrieve it. They all take value(s) to set the attribute and return the new value of the attribute or no paremeters which reuturns the current value. =item $ctx->auth(SVN::Client::get_username_provider()); Provides access the auth_baton in the svn_client_ctx_t attached to the SVN::Client object. This method will accept an array or array ref of values returned from the authentication provider functions see L. Which it will convert to an auth_baton for you. This is the preferred method of setting the auth_baton. It will also accept a scalar that references a _p_svn_auth_baton_t such as those returned from SVN::Core::auth_open and SVN::Core::auth_open_helper. =cut sub auth { my $self = shift; my $args; if (scalar(@_) == 0) { return $self->{'ctx'}->auth_baton(); } elsif (scalar(@_) > 1) { $args = \@_; } else { $args = shift; if (ref($args) eq '_p_svn_auth_baton_t') { # 1 arg as an auth_baton so just set # the baton. $self->{'ctx'}->auth_baton($args); return $self->{'ctx'}->auth_baton(); } } my ($auth_baton,$callbacks) = SVN::Core::auth_open_helper($args); $self->{'auth_provider_callbacks'} = $callbacks; $self->{'ctx'}->auth_baton($auth_baton); return $self->{'ctx'}->auth_baton(); } =item $ctx->pool(new SVN::Pool); Method that sets or gets the pool that is passed to method calls requiring a pool but that you didn't pass one. See L for more information about how pools are managed in this interface. =cut sub pool { my $self = shift; if (scalar(@_) == 0) { $self->{'pool'}; } else { return $self->{'pool'} = shift; } } =item $ctx->config(SVN::Core::config_get_config(undef)); Method that allows access to the config member of the svn_client_ctx_t. Accepts a perl hash to set, which is what functions like SVN::Core:config_get_config() will return. It will return a _p_arp_hash_t scalar. THis is a temporary situation. The return value is not particular useful. In the future, this value will be tied to the actual hash used by the C API. =cut sub config { my $self = shift; if (scalar(@_) == 0) { return $self->{'ctx'}->config(); } else { $self->{'ctx'}->config(shift); return $self->{'ctx'}->config(); } } =head1 AUTHENTICATION PROVIDERS The following functions get authentication providers for you. They come in two forms. Standard or File versions, which look for authentication information in the subversion configuration directory that was previously cached, or Prompt versions which call a subroutine to allow you to prompt the user for the information. The functions that return the provider objects for prompt style providers take a reference to a perl subroutine to use for the callback. The first parameter each of these subroutines receive is a credential object. The subroutines return the response by setting members of that object. Members may be set like so: $cred->username("breser"); These functions and credential objects always have a may_save member which specifies if the authentication data will be cached. The providers are as follows: NAME WHAT IT HANDLES ---------------- ---------------------------------------- simple username and password pairs username username only ssl_server_trust server certificates and failures authenticating them ssl_client_cert client side certificate files ssl_client_cert_pw password for a client side certificate file. =over 4 =item SVN::Client::get_simple_provider Returns a simple provider that returns information from previously cached sessions. Takes no parameters or one pool parameter. =item SVN::Client::get_simple_prompt_provider Returns a simple provider that prompts the user via a callback. Takes two or three parameters, the first is the callback subroutine, the 2nd is the number of retries to allow, the 3rd is optionally a pool. The subroutine gets called with the following parameters. A svn_auth_cred_simple object, a realm string, a default username, may_save, and a pool. The svn_auth_cred_simple has the following members: username, password, and may_save. =item SVN::Client::get_username_provider Returns a username provider that returns information from a previously cached sessions. Takes no parameters or one pool parameter. =item SVN::Client::get_username_prompt_provider Returns a username provider that prompts the user via a callback. Takes two or three parameters, the first is the callback subroutine, the 2nd is the number of retries to allow, the 3rd is optionally a pool. The subroutine gets called with the following parameters. A svn_auth_cred_username object, a realm string, a default username, may_save, and a pool. The svn_auth_cred_username has the following members: username and may_save. =item SVN::Client::get_ssl_server_trust_file_provider Returns a server trust provider that returns infromation from previously cached sessions. Takes no parameters or optionally a pool parameter. =item SVN::Client::get_ssl_server_trust_prompt_provider Returns a server trust provider that prompts the user via a callback. Takes one or two parameters the callback subroutine and optionally a pool parameter. The subroutine gets called with the following parameters. A svn_auth_cred_ssl_server_trust object, a realm string, an integer specifiying how the certificate failed authentication, a cert info object, may_save, and a pool. The svn_auth_cred_ssl_server_trust object has the following members: may_save and accepted_failures. The svn_ssl_cert_info object has the following members (and behaves just like cred objects though you can't modify it): hostname, fingerprint, valid_from, valid_until, issuer_dname, ascii_cert. The masks used for determaning the failures are in SVN::_Core and are named: $SVN::_Core::SVN_AUTH_SSL_NOTYETVALID $SVN::_Core::SVN_AUTH_SSL_EXPIRED $SVN::_Core::SVN_AUTH_SSL_CNMISMATCH $SVN::_Core::SVN_AUTH_SSL_UNKNOWNCA $SVN::_Core::SVN_AUTH_SSL_OTHER You reply by setting the accepted_failures of the cred object with an integer of the values for what you want to accept bitwise anded together. =item SVN::Client::get_ssl_cert_file_provider Returns a client certificate provider that returns infromation from previously cached sessions. Takes no parameters or optionally a pool parameter. =item SVN::Client::get_ssl_cert_prompt_provider Returns a client certificate provider that prompts the user via a callback. Takes two or three parameters, the first is the callback subroutine, the 2nd is the number of retries to allow, the 3rd is optionally a pool parameter. The subroutine gets called with the following parameters. A svn_auth_cred_ssl_client_cert object, a realm string, may_save, and a pool. The svn_auth_cred_ssl_client_cert the following members: cert_file and may_save. =item SVN::Client::get_ssl_cert_pw_file_provider Returns a client certificate password provider that returns infromation from previously cached sessions. Takes no parameters or optionally a pool paramater. =item SVN::Client::get_ssl_cert_pw_prompt_provider Returns a client certificate passowrd provider that prompts the user via a callback. Takes two or three parameters, the first is the callback subroutine, the 2nd is the number of retries to allow, the 3rd is optionally a pool parameter. The subroutine gets called with the following parameters. A svn_auth_cred_ssl_client_cert_pw object, a realm string, may_save, and a pool. The svn_auth_cred_ssl_client_cert_pw has the following members: password and may_save. =cut package _p_svn_client_commit_info_t; use SVN::Base qw(Client svn_client_commit_info_t_); package _p_svn_client_commit_item_t; use SVN::Base qw(Client svn_client_commit_item_t_); package _p_svn_client_ctx_t; use SVN::Base qw(Client svn_client_ctx_t_); package _p_svn_client_proplist_item_t; use SVN::Base qw(Client svn_client_proplist_item_t_); =head1 TODO * Complete documentation * Support for the notify callback. * Support for the log_msg callback. * Better support for the config. * More unit tests. =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE Ben Reser Eben@reser.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Core.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 10213 Text-content-md5: 5f220f02b6616942c8fc26216d362a32 Content-length: 10248 K 12 svn:keywords V 2 Id PROPS-END package SVN::Core; use SVN::Base qw(Core svn_); $VERSION = "$VER_MAJOR.$VER_MINOR.$VER_MICRO"; use strict; =head1 NAME SVN::Core - Core module of the subversion perl bindings =head1 SYNOPSIS require SVN::Core; # does apr_initialize and cleanup for you # create a root pool and set it as default pool for later use my $pool = SVN::Pool->new_default; sub something { # create a subpool of the current default pool my $pool = SVN::Pool->new_default_sub; # some svn operations... # $pool gets destroyed and the previous default pool # is restored when $pool's lexical scope ends } # svn_stream_t as native perl io handle my $stream = $txn->root->apply_text('trunk/filea', undef); print $stream $text; close $stream; # native perl io handle as svn_stream_t SVN::Repos::dump_fs($repos, \*STDOUT, \*STDERR, 0, $repos->fs->youngest_rev, 0); =head1 DESCRIPTION SVN::Core implements higher level functions of fundamental subversion functions. =head1 FUNCTIONS =over 4 =cut BEGIN { SVN::_Core::apr_initialize; } END { SVN::_Core::apr_terminate; } =item SVN::Core::auth_open([auth provider array]); Takes a reference to an array of authentication providers and returns an auth_baton. If you use prompt providers you can not use this function, but need to use the auth_open_helper. =item SVN::Core::auth_open_helper([auth provider array); Prompt providers return two values instead of one. The 2nd paramaeter is a reference to whatever was passed into them as the callback. auth_open_helper splits up these arguments, passing the provider objects into auth_open which gives it an auth_baton and putting the other ones in an array. The first return value of this function is the auth_baton, the second is a reference to an array containing the references to the callbacks. These callback arrays should be stored in the object the auth_baton is attached to. =cut sub auth_open_helper { my $args = shift; my (@auth_providers,@auth_callbacks); foreach my $arg (@{$args}) { if (ref($arg) eq '_p_svn_auth_provider_object_t') { push @auth_providers, $arg; } else { push @auth_callbacks, $arg; } } my $auth_baton = SVN::Core::auth_open(\@auth_providers); return ($auth_baton,\@auth_callbacks); } package _p_svn_stream_t; use SVN::Base qw(Core svn_stream_); package SVN::Stream; use IO::Handle; our @ISA = qw(IO::Handle); =head1 OTHER OBJECTS =over 4 =head2 svn_stream_t - SVN::Stream You can use native perl io handles (including io globs) as svn_stream_t in subversion functions. Returned svn_stream_t are also translated into perl io handles, so you could access them with regular print, read, etc. Note that some functions takes a stream to read or write, while it does not close it but still hold the reference to the handle. In this case the handle won't be destroyed properly. You should always use correct default pool before calling such functions. =cut use Symbol (); sub new { my $class = shift; my $self = bless Symbol::gensym(), ref($class) || $class; tie *$self, $self; *$self->{svn_stream} = shift; $self; } sub svn_stream { my $self = shift; *$self->{svn_stream}; } sub TIEHANDLE { return $_[0] if ref($_[0]); my $class = shift; my $self = bless Symbol::gensym(), $class; *$self->{svn_stream} = shift; $self; } sub CLOSE { my $self = shift; *$self->{svn_stream}->close if *$self->{svn_stream}; undef *$self->{svn_stream}; } sub GETC { my $self = shift; my $buf; return $buf if $self->read($buf, 1); return undef; } sub print { my $self = shift; $self->WRITE ($_[0], length ($_[0])); } sub PRINT { my $self = shift; if (defined $\) { if (defined $,) { $self->print(join($,, @_).$\); } else { $self->print(join("",@_).$\); } } else { if (defined $,) { $self->print(join($,, @_)); } else { $self->print(join("",@_)); } } } sub PRINTF { my $self = shift; my $fmt = shift; $self->print(sprintf($fmt, @_)); } sub getline { my $self = shift; *$self->{pool} ||= SVN::Core::pool_create (undef); my ($buf, $eof) = *$self->{svn_stream}->readline ($/, *$self->{pool}); return undef if $eof && !$buf; return $eof ? $buf : $buf.$/; } sub getlines { die "getlines() called in scalar context\n" unless wantarray; my $self = shift; my($line, @lines); push @lines, $line while defined($line = $self->getline); return @lines; } sub READLINE { my $self = shift; unless (defined $/) { my $buf = ''; while (my $chunk = *$self->{svn_stream}->read ($SVN::Core::STREAM_CHUNK_SIZE)) { $buf .= $chunk; } return $buf; } elsif (ref $/) { return *$self->{svn_stream}->read (${$/}) || undef; } return wantarray ? $self->getlines : $self->getline; } sub READ { my $self = shift; my $len = $_[1]; if (@_ > 2) { # read offset substr($_[0],$_[2]) = *$self->{svn_stream}->read ($len); } else { $_[0] = *$self->{svn_stream}->read ($len); } return $len; } sub WRITE { my $self = shift; my $slen = length($_[0]); my $len = $slen; my $off = 0; if (@_ > 1) { $len = $_[1] if $_[1] < $len; if (@_ > 2) { $off = $_[2] || 0; die "Offset outside string" if $off > $slen; if ($off < 0) { $off += $slen; die "Offset outside string" if $off < 0; } my $rem = $slen - $off; $len = $rem if $rem < $len; } *$self->{svn_stream}->write (substr ($_[0], $off, $len)); } return $len; } *close = \&CLOSE; sub FILENO { return undef; # XXX perlfunc says this means the file is closed } sub DESTROY { my $self = shift; $self->close; } package _p_apr_pool_t; my %WRAPPED; sub default { my ($pool) = @_; my $pobj = SVN::Pool->_wrap ($$pool); $WRAPPED{$pool} = $pobj; $pobj->default; } sub DESTROY { my ($pool) = @_; delete $WRAPPED{$pool}; } package SVN::Pool; use SVN::Base qw/Core svn_pool_/; =back =over 4 =head2 svn_pool_t - SVN::Pool The perl bindings significantly simplify the usage of pools, without making them not manually adjustable. Functions requiring pool as the last argument (which are, almost all of the subversion functions), the pool is optionally. the default pool is used if it is omitted. If default pool is not set, a new root pool will be created and set as default automatically when the first function requiring a default pool is called. For callback functions providing pool to your subroutine, you could also use $pool->default to make it the default pool in the scope. =head3 Methods =over =item new ([$parent]) Create a new pool. The pool is a root pool if $parent is not supplied. =item new_default ([$parent]) Create a new pool. The pool is a root pool if $parent is not supplied. Set the new pool as default pool. =item new_default_sub Create a new subpool of the current default pool, and set the resulting pool as new default pool. =item clear Clear the pool. =item destroy Destroy the pool. if the pool is the default pool, restore the previous default pool as default. This is normally called automatically when the SVN::Pool object is no longer used and destroyed by the perl garbage collector. =back =cut no strict 'refs'; *{"apr_pool_$_"} = *{"SVN::_Core::apr_pool_$_"} for qw/clear destroy/; my @POOLSTACK; sub new { my ($class, $parent) = @_; $parent = $$parent if ref ($parent) eq 'SVN::Pool'; my $self = bless \create ($parent), $class; return $self; } sub new_default_sub { my $parent = ref ($_[0]) ? ${+shift} : $SVN::_Core::current_pool; my $self = SVN::Pool->new_default ($parent); return $self; } sub new_default { my $self = new(@_); $self->default; return $self; } sub default { my $self = shift; push @POOLSTACK, $SVN::_Core::current_pool unless $$SVN::_Core::current_pool == 0; $SVN::_Core::current_pool = $$self; } sub clear { my $self = shift; apr_pool_clear ($$self); } my $globaldestroy; END { $globaldestroy = 1; } my %WRAPPOOL; # Create a cloned _p_apr_pool_t pointing to the same apr_pool_t # but on different address. this allows pools that are from C # to have proper lifetime. sub _wrap { my ($class, $rawpool) = @_; my $pool = \$rawpool; bless $pool, '_p_apr_pool_t'; my $npool = \$pool; bless $npool, $class; $WRAPPOOL{$npool} = 1; $npool; } sub DESTROY { return if $globaldestroy; my $self = shift; if ($$self eq $SVN::_Core::current_pool) { $SVN::_Core::current_pool = pop @POOLSTACK; } if (exists $WRAPPOOL{$self}) { delete $WRAPPOOL{$self}; } else { apr_pool_destroy ($$self) } } package _p_svn_log_changed_path_t; use SVN::Base qw(Core svn_log_changed_path_t_); =head2 svn_log_changed_path_t =cut package SVN::Node; use SVN::Base qw(Core svn_node_); =head2 svn_node_kind_t - SVN::Node =cut package _p_svn_opt_revision_t; use SVN::Base qw(Core svn_opt_revision_t_); =head2 svn_opt_revision_t =cut package _p_svn_opt_revision_t_value; use SVN::Base qw(Core svn_opt_revision_t_value_); package _p_svn_config_t; use SVN::Base qw(Core svn_config_); package _p_svn_dirent_t; use SVN::Base qw(Core svn_dirent_t_); =head2 svn_config_t =cut =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Delta.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 4811 Text-content-md5: e2d7d421818608204778613ee11fa6da Content-length: 4846 K 12 svn:keywords V 2 Id PROPS-END package SVN::Delta; use strict; use SVN::Base qw(Delta svn_delta_); =head1 NAME SVN::Delta - Subversion delta functions =head1 SYNOPSIS require SVN::Core; require SVN::Repos; require SVN::Delta; # driving an editor my $editor = SVN::Delta::Editor-> new(SVN::Repos::get_commit_editor($repos, "file://$repospath", '/', 'root', 'FOO', \&committed)); my $rootbaton = $editor->open_root(0); my $fbaton = $editor->add_file ('filea', $rootbaton, undef, -1); my $ret = $editor->apply_textdelta ($fbaton, undef); SVN::TxDelta::send_string("FILEA CONTENT", @$ret); # implement an editor in perl SVN::Repos::dir_delta($root1, $path, undef, $root2, $path, SVN::Delta::Editor->new(_debug=>1), 1, 1, 0, 1 =head1 DESCRIPTION SVN::Delta wraps delta related function in subversion. The most important one is SVN::Delta::Editor, the interface for describing tree deltas. by default SVN::Delta::Editor relays method calls to its internal member C<_editor>, which could either be an editor in C (such as the one you get from get_commit_editor), or another SVN::Delta::Editor object. =head1 SVN::Delta::Editor =head2 Driving Editors If you want to drive a native editor (such as commit_editor obtained by SVN::Repos::get_commit_editor), create a SVN::Delta::Editor object with the native editor/baton pair. The object will then be ready to use and its method calls will be relayed to the native editor. =head2 Implementing Editors If you want to implement an editor, subclass SVN::Delta::Editor and implement the editors callbacks. see the METHODS section below. =head2 CONSTRUCTOR - new (...) =over =item new ($editor, $editor_baton) Link to the native editor =back You can also pass a hash array to new: =over =item _debug Turn on debug. =item _editor An arrayref of the editor/baton pair or another SVN::Delta::Editor object to link with. =back =head2 METHODS Please consult the svn_delta.h section in the Subversion API. Member functions of svn_delta_editor_t could be called as methods of SVN::Delta::Editor objects, with the edit_baton omitted. The pool is also optional. If you are subclassing, the methods take exactly the same arguments as the member functions (note tht void ** are returned data though as throughout the perl bindings), with the edit_baton omitted. =cut package SVN::TxDelta; use SVN::Base qw(Delta svn_txdelta_); *new = *SVN::_Delta::svn_txdelta; package _p_svn_txdelta_op_t; use SVN::Base qw(Delta svn_txdelta_op_t_); package _p_svn_txdelta_window_t; use SVN::Base qw(Delta svn_txdelta_window_t_); package SVN::Delta::Editor; use SVN::Base qw(Delta svn_delta_editor_); use Carp; *invoke_set_target_revision = *SVN::_Delta::svn_delta_editor_invoke_set_target_revision; sub convert_editor { my $self = shift; $self->{_editor} = $_[0], return 1 if UNIVERSAL::isa ($_[0], __PACKAGE__); if (ref($_[0]) && $_[0]->isa('_p_svn_delta_editor_t')) { @{$self}{qw/_editor _baton/} = @_; return 1; } return 0; } sub new { my $class = shift; my $self = bless {}, $class; unless ($self->convert_editor(@_)) { %$self = @_; $self->convert_editor (@{$self->{_editor}}) if $self->{_editor}; } warn "debug" if $self->{_debug}; return $self; } our $AUTOLOAD; sub AUTOLOAD { no warnings 'uninitialized'; warn "$AUTOLOAD: ".join(',',@_) if $_[0]->{_debug}; return unless $_[0]->{_editor}; my $class = ref($_[0]); my $func = $AUTOLOAD; $func =~ s/^${class}::(SUPER::)?//; return if $func =~ m/^[A-Z]/; my %ebaton = ( set_target_revision => 1, open_root => 1, close_edit => 1, abort_edit => 1, ); my $self = shift; no strict 'refs'; my @ret = UNIVERSAL::isa ($self->{_editor}, __PACKAGE__) ? $self->{_editor}->$func (@_) : eval { &{"invoke_$func"}($self->{_editor}, $ebaton{$func} ? $self->{_baton} : (), @_) }; confess $@ if $@; return $#ret == 0 ? $ret[0] : [@ret]; } =head1 BUGS Functions returning editor/baton pair should really be typemapped to a SVN::Delta::Editor object. =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Fs.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 1054 Text-content-md5: bb24b9f8e0a5fff691959391602d29e7 Content-length: 1089 K 12 svn:keywords V 2 Id PROPS-END package SVN::Fs; use SVN::Base qw(Fs svn_fs_); package _p_svn_fs_t; our @methods = qw/youngest_rev revision_root revision_prop revision_proplist change_rev_prop list_transactions open_txn begin_txn get_uuid set_uuid/; for (@methods) { *{$_} = *{"SVN::Fs::$_"}; } package _p_svn_fs_root_t; our @methods = qw/apply_textdelta apply_text change_node_prop check_path close_root copied_from copy dir_entries delete file_contents file_length file_md5_checksum is_dir is_file is_revision_root is_txn_root make_dir make_file node_created_rev node_history node_id node_prop node_proplist paths_changed revision_link revision_root_revision/; *fs = *{"SVN::Fs::root_fs"}; for (@methods) { *{$_} = *{"SVN::Fs::$_"}; } package _p_svn_fs_history_t; use SVN::Base qw/Fs svn_fs_history_/; package _p_svn_fs_txn_t; use SVN::Base qw/Fs svn_fs_txn_/; *commit = *SVN::Fs::commit_txn; *abort = *SVN::Fs::abort_txn; *change_prop = *SVN::Fs::change_txn_prop; package _p_svn_fs_dirent_t; use SVN::Base qw(Fs svn_fs_dirent_t_); 1; Node-path: svnperl/perl/Makefile.PL Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2865 Text-content-md5: b8e2bb8ac1968bb404080572d7beac97 Content-length: 2875 PROPS-END #!/usr/bin/perl use ExtUtils::MakeMaker; my @modules = qw/client delta fs ra repos wc/; my @ldpaths = ('../.libs', map {"../../../libsvn_$_/.libs"} (@modules, qw/diff subr/)); my @ldmodules = map {"-lsvn_$_-1"} (@modules, qw/diff subr/); my $apr_config = $ENV{APR_CONFIG} || '/usr/local/lib/apache2/apr-config'; $apr_config = 'apr-config' unless -e $apr_config; my $apr_shlib_path_var = `$apr_config --shlib-path-var`; my $apr_cflags = `$apr_config --includes`; my $apr_ldflags = `$apr_config --cflags --link-ld --libs` if $^O eq 'darwin'; chomp $apr_shlib_path_var; chomp $apr_cflags; chomp $apr_ldflags; my %config = ( ABSTRACT => 'Perl bindings for Subversion', CCFLAGS => join(' ', $apr_cflags, `perl -MExtUtils::Embed -e ccopts`, ' -I.. -I../../../include -g'), OBJECT => q/$(O_FILES)/, dynamic_lib => { OTHERLDFLAGS => join(' ', $apr_ldflags, (map {"-L$_"} @ldpaths), @ldmodules, '-lsvn_swig_perl-1', `swig -perl -ldflags`), }, ); sub perlish { local $_ = $_[0]; s/^(\w)/\U$1/; $_; } WriteMakefile(%config, NAME => 'SVN::_Core', C => ['core.c'], PM => {map { ("$_.pm" => "\$(INST_LIBDIR)/$_.pm") } map { perlish $_ } ('base', 'core', @modules)}, clean => { FILES => "*.hi *.c *.bs". join(' Makefile.','',@modules) } ); for (@modules) { WriteMakefile(%config, MAKEFILE=> "Makefile.$_", NAME => "SVN::_".perlish($_), C => ["svn_$_.c"], ); } # the dependencies need to be fixed sub MY::postamble { package MY ; return join('', "all :: modules\ntest :: modules\ninstall :: modules\n\n", "par :: all\n\t", q{perl -MPAR::Dist -e"blib_to_par(name=>'SVN',version=>'`perl -Mblib -MSVN::Core -e'print $$SVN::Core::VERSION'`')"},"\n\n", # h2i "ra_plugin.hi: ../../../include/svn_ra.h\n\tperl h2i.pl ../../../include/svn_ra.h svn_ra_plugin_t > \$@\n\n", "ra_reporter.hi: ../../../include/svn_ra.h\n\tperl h2i.pl ../../../include/svn_ra.h svn_ra_reporter_t > \$@\n\n", "delta_editor.hi: ../../../include/svn_delta.h\n\tperl h2i.pl ../../../include/svn_delta.h svn_delta_editor_t > \$@\n\n", "modules :: ",(map { " svn_$_.c"} @modules),"\n", (map {"\tmake -f Makefile.$_\n"} @modules), "\t\$(NOECHO) \$(TOUCH) \$\@", # swig "\ncore.c :: ../core.i\n", "\tswig -c -nopm -perl -I.. -I../../../include $apr_cflags -module SVN::_Core -o core.c ../core.i\n", (map {"\nsvn_$_.c : ../svn_$_.i ra_plugin.hi ra_reporter.hi delta_editor.hi\n". "\tswig -c -nopm -perl -I.. -I../../../include $apr_cflags -module SVN::_".main::perlish($_)." -o svn_$_.c ../svn_$_.i\n"} @modules), "\nFULLPERLRUN=$apr_shlib_path_var=",join(':',@ldpaths), " \$(FULLPERL)\n", ); } Node-path: svnperl/perl/Ra.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 5018 Text-content-md5: 595de361710e4ae2daa1a89400add203 Content-length: 5053 K 12 svn:keywords V 2 Id PROPS-END package SVN::Ra; use SVN::Base qw(Ra svn_ra_); =head1 NAME SVN::Ra - Subversion remote acess functions =head1 SYNOPSIS require SVN::Core; require SVN::Ra; my $ra = SVN::Ra->new ('file:///tmp/svmtest'); print $ra->get_latest_revnum (); =head1 DESCRIPTION SVN::Ra wraps the object-oriented svn_ra_plugin_t functions. =head1 SVN::Ra =head2 CONSTRUCTOR - new (...) The method creates an RA object and calls C for it. It takes a hash array as parameter. if there's only one argument supplied, it's used as the url. valid keys are: =over =item url =item auth An auth_baton could be given to the SVN::RA object. Deafult to a auth_provider with a username_provider. See L for how to create auth_baton. =item pool The pool for the ra session to use, and also the member functions will be called with this pool. Default to a newly created root pool. =item config The config hash that could be obtained by SVN::Core::config_get_config(undef). =item callback The ra_callback namespace to use. Default to SVN::Ra::Callback. =back =head2 METHODS Please consult the svn_ra.h section in the Subversion API. Member functions of svn_ra_plugin_t could be called as methods of SVN::Ra objects, with the session_baton and pool omitted. =cut use strict; require SVN::Client; my $ralib = init_ra_libs; our $AUTOLOAD; sub AUTOLOAD { my $class = ref($_[0]); $AUTOLOAD =~ s/^${class}::(SUPER::)?//; return if $AUTOLOAD =~ m/^[A-Z]/; my $self = shift; no strict 'refs'; die "no such method $AUTOLOAD" unless $self->can("plugin_invoke_$AUTOLOAD"); my @ret = &{"plugin_invoke_$AUTOLOAD"}(@{$self}{qw/ra session/}, @_, $self->{pool}); return $ret[0] unless $#ret; return ($AUTOLOAD eq 'get_commit_editor') ? @ret : bless [@ret], 'SVN::Ra::Reporter'; } sub new { my $class = shift; my $self = bless {}, $class; %$self = $#_ ? @_ : (url => $_[0]); if (defined($self->{auth})) { if (ref($self->{auth}) ne '_p_svn_auth_baton_t') { # If the auth is already set to a auth_baton ignore it # otherwise make an auth_baton and store the callbacks my ($auth_baton,$auth_callbacks) = SVN::Core::auth_open_helper($self->{auth}); $self->{auth} = $auth_baton; $self->{auth_provider_callbacks} = $auth_callbacks; } } else { # no callback to worry about with a username provider so just call # auth_open directly $self->{auth} = SVN::Core::auth_open( [SVN::Client::get_username_provider()]); } my $pool = $self->{pool} ||= SVN::Core::pool_create(undef); $self->{ra} = get_ra_library ($ralib, $self->{url}); my $callback = 'SVN::Ra::Callbacks'; # custom callback namespace if ($self->{callback} && !ref($self->{callback})) { $callback = $self->{callback}; undef $self->{callback}; } $self->{callback} ||= $callback->new(auth => $self->{auth}, pool => $pool), $self->{session} = plugin_invoke_open ($self->{ra}, $self->{url}, $self->{callback}, $self->{config} || {}, $pool); return $self; } sub DESTROY { } package SVN::Ra::Reporter; use SVN::Base qw(Ra svn_ra_reporter_); =head1 SVN::Ra::Reporter the SVN::Ra methods: do_diff, do_status, do_switch, do_update, returns a SVN::Ra::Reporter object as a wrapper of svn_ra_reporter_t. You can use the member functions of it as methods of SVN::Ra::Reporter, with the reporter_baton omitted. =cut our $AUTOLOAD; sub AUTOLOAD { my $class = ref($_[0]); $AUTOLOAD =~ s/^${class}::(SUPER::)?//; return if $AUTOLOAD =~ m/^[A-Z]/; my $self = shift; no strict 'refs'; die "no such method $AUTOLOAD" unless $self->can("invoke_$AUTOLOAD"); &{"invoke_$AUTOLOAD"}(@$self, @_); } package SVN::Ra::Callbacks; =head1 SVN::Ra::Callbacks This is the wrapper class for svn_ra_callback_t. To supply custom callback to SVN::Ra, subclass this class and override the member functions. =cut require SVN::Core; sub new { my $class = shift; my $self = bless {}, $class; %$self = @_; return $self; } sub open_tmp_file { my $self = shift; my ($fd, $name) = SVN::Core::io_open_unique_file ('/tmp/foobar', 'tmp', 1, $self->{pool}); return $fd; } sub get_wc_prop { return undef; } =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Repos.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 1837 Text-content-md5: ad396b19e157c02aba5b998d30ca746e Content-length: 1872 K 12 svn:keywords V 2 Id PROPS-END package SVN::Repos; use SVN::Base qw(Repos svn_repos_); use strict; =head1 NAME SVN::Repos - Subversion repository functions =head1 SYNOPSIS require SVN::Core; require SVN::Repos; require SVN::Fs; my $repos = SVN::Repos::open ('/path/to/repos'); print $repos->fs->youngest_rev; =head1 DESCRIPTION SVN::Repos wraps the functions in svn_repos.h. The actual namespace for repos object is _p_svn_repos_t. =head2 CONSTRUCTORS =over =item open ($path) =item create ($path, undef, undef, $config, $fs_config) =back =head2 METHODS Please consult the svn_repos.h section in the Subversion API. Functions taking svn_repos_t * as the first inbound argument could be used as methods of the object returned by open or create. =cut package _p_svn_repos_t; my @methods = qw/fs get_logs get_commit_editor path db_env lock_dir db_lockfile hook_dir start_commit_hook pre_commit_hook post_commit_hook pre_revprop_change_hook post_revprop_change_hook dated_revision fs_commit_txn fs_begin_txn_for_commit fs_begin_txn_for_update fs_change_rev_prop node_editor dump_fs load_fs get_fs_build_parser/; no strict 'refs'; for (@methods) { *{$_} = *{"SVN::Repos::$_"}; } =head1 AUTHORS Chia-liang Kao Eclkao@clkao.orgE =head1 COPYRIGHT Copyright (c) 2003 CollabNet. All rights reserved. This software is licensed as described in the file COPYING, which you should have received as part of this distribution. The terms are also available at http://subversion.tigris.org/license-1.html. If newer versions of this license are posted there, you may use a newer version instead, at your option. This software consists of voluntary contributions made by many individuals. For exact contribution history, see the revision history and logs, available at http://subversion.tigris.org/. =cut 1; Node-path: svnperl/perl/Wc.pm Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 225 Text-content-md5: 05c653fa220e1caaef95bd0ea02f72e8 Content-length: 260 K 12 svn:keywords V 2 Id PROPS-END package SVN::Wc; use SVN::Base qw(Wc svn_wc_); package _p_svn_wc_t; package _p_svn_wc_entry_t; # still need to check if the function prototype allows it to be called # as method. use SVN::Base qw(Wc svn_wc_entry_t_); 1; Node-path: svnperl/perl/h2i.pl Node-kind: file Node-action: add Prop-content-length: 35 Text-content-length: 1504 Text-content-md5: 50be9fb241252dce05606bf5d693045f Content-length: 1539 K 12 svn:keywords V 2 Id PROPS-END # $Revision: #7 $ $Change: 7549 $ $DateTime: 2003/08/15 10:56:21 $ # extract member function from c header as invoker functions # by Autrijus Tang use 5.008; my $file = shift or die "Usage: $^X $0 svn_ra.h svn_ra_reporter_t\n"; my $lines = ''; while (my $s = shift) { my $out = ''; my $n = uc($s); $n =~ s/_T$//; $n =~ s/.*_//; my $prefix = $s; chop $prefix; my ($rv, $func, $args); open FILE, $file or die $!; my $temp = join('', ); $temp =~ s/^(typedef struct)(\n\{[^}]+\}\s+(\w+);)/$1 $3$2/ms; close FILE; open FILE, '<', \$temp; while () { next if 1 .. /^typedef struct $s/; next if /^{$/; next if m{^\s*/\*} .. m{\*/\s*$}; last if /^\s*}\s+/; $lines .= $_; next unless /^\s*$/; (($lines = ''), next) unless $lines =~ /\s*(\w+)\s*\W+(\w+)\W+\(([^)]+)/; # only care about functions ($rv, $func, $args) = ($1, $2, $3); print "$rv *${prefix}invoke_$func (\n"; print " $s *\L$n\E,\n"; print join(",\n", map " $_", split(/\s*,\s*/, $args)); print "\n);\n\n"; $out .= "${n}_INVOKER($func, $args)\n"; $args = join( ', ', map { s/^.*?(\w+)$/$1/; $_ } split(/\s*,\s*/, $args) ); $out .= "${n}_INVOKER_FUNC($func, $args);\n\n"; $lines = ''; } print "%{\n"; print " #define ${n}_INVOKER(method, ...) \\ $rv *${prefix}invoke_ ## method \\ (const $s *\L$n\E, __VA_ARGS__) #define ${n}_INVOKER_FUNC(method, ...) \\ { return \L${n}\E->method (__VA_ARGS__); } "; print $out; print "%}\n\n"; } Node-path: svnperl/perl/t Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/perl/t/0use.t Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 235 Text-content-md5: 607637d571241eb55c2aa0cdb59c27f6 Content-length: 245 PROPS-END #!/usr/bin/perl -w use Test::More tests => 7; use strict; BEGIN { require_ok 'SVN::Core'; require_ok 'SVN::Repos'; require_ok 'SVN::Fs'; require_ok 'SVN::Delta'; require_ok 'SVN::Ra'; require_ok 'SVN::Wc'; require_ok 'SVN::Client'; } Node-path: svnperl/perl/t/1repos.t Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 1917 Text-content-md5: 5b32576446a28fe3c4d8ec7863701605 Content-length: 1927 PROPS-END #!/usr/bin/perl -w use Test::More qw(no_plan); use strict; require SVN::Core; require SVN::Repos; require SVN::Fs; require SVN::Delta; my $repospath = "/tmp/svn-$$"; my $repos; ok($repos = SVN::Repos::create("$repospath", undef, undef, undef, undef), "create repository at $repospath"); my $fs = $repos->fs; sub committed { diag "committed ".join(',',@_); } my $editor = SVN::Delta::Editor-> new(SVN::Repos::get_commit_editor($repos, "file://$repospath", '/', 'root', 'FOO', \&committed)); my $rootbaton = $editor->open_root(0); my $dirbaton = $editor->add_directory ('trunk', $rootbaton, undef, 0); my $fbaton = $editor->add_file ('trunk/filea', $dirbaton, undef, -1); my $ret = $editor->apply_textdelta ($fbaton, undef); SVN::TxDelta::send_string("FILEA CONTENT", @$ret); $editor->close_edit(); cmp_ok($fs->youngest_rev, '==', 1); { $editor = SVN::Delta::Editor-> new (SVN::Repos::get_commit_editor($repos, "file://$repospath", '/', 'root', 'FOO', \&committed)); my $rootbaton = $editor->open_root(1); my $dirbaton = $editor->add_directory ('tags', $rootbaton, undef, 1); my $subdirbaton = $editor->add_directory ('tags/foo', $dirbaton, "file://$repospath/trunk", 1); $editor->close_edit(); } cmp_ok($fs->youngest_rev, '==', 2); my @history; SVN::Repos::history ($fs, 'tags/foo/filea', sub {push @history, [@_[0,1]]}, 0, 2, 1); is_deeply (\@history, [['/tags/foo/filea',2],['/trunk/filea',1]], 'repos_history'); { $editor = SVN::Delta::Editor-> new (SVN::Repos::get_commit_editor($repos, "file://$repospath", '/', 'root', 'FOO', \&committed)); my $rootbaton = $editor->open_root(2); $editor->delete_entry('tags', 2, $rootbaton); $editor->close_edit(); } cmp_ok($fs->youngest_rev, '==', 3); END { diag "cleanup"; print `svn cat file://$repospath/trunk/filea`; print `svn log -v file://$repospath`; `rm -rf $repospath`; } Node-path: svnperl/perl/t/2fs.t Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 1314 Text-content-md5: 3f58293e2c63dff0313f28644caaef47 Content-length: 1324 PROPS-END #!/usr/bin/perl -w use Test::More qw(no_plan); use strict; require SVN::Core; require SVN::Repos; require SVN::Fs; my $repospath = "/tmp/svn-$$"; my $repos; ok($repos = SVN::Repos::create("$repospath", undef, undef, undef, undef), "create repository at $repospath"); my $fs = $repos->fs; cmp_ok($fs->youngest_rev, '==', 0, "new repository start with rev 0"); my $txn = $fs->begin_txn($fs->youngest_rev); my $txns = $fs->list_transactions; ok(eq_array($fs->list_transactions, [$txn->name]), 'list transaction'); $txn->root->make_dir('trunk'); my $path = 'trunk/filea'; my $text = "this is just a test\n"; $txn->root->make_file('trunk/filea'); { my $stream = $txn->root->apply_text('trunk/filea', undef); print $stream $text; close $stream; } $txn->commit; cmp_ok($fs->youngest_rev, '==', 1, 'revision increased'); my $root = $fs->revision_root ($fs->youngest_rev); cmp_ok($root->check_path($path), '==', $SVN::Node::file); ok (!$root->is_dir($path)); ok ($root->is_file($path)); { my $stream = $root->file_contents ($path); local $/; is(<$stream>, $text, 'content verified'); is($root->file_md5_checksum ($path), 'dd2314129f81675e95b940ff94ddc935', 'md5 verified'); } is ($fs->revision_prop(1, 'not:exists'), undef, 'nonexisting property'); END { diag "cleanup"; `rm -rf $repospath`; } Node-path: svnperl/perl/t/3client.t Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 717 Text-content-md5: ab0e387baeadbcd6ac3db4f898f9b33a Content-length: 727 PROPS-END #!/usr/bin/perl -w use Test::More qw(no_plan); use strict; require SVN::Core; require SVN::Repos; require SVN::Client; my $repospath = "/tmp/svn-$$"; my $reposurl = "file://$repospath"; my $wcpath = "/tmp/svn-wc-$$"; # This is ugly to create the test repo with SVN::Repos, but # it seems to be the most reliable way. ok(SVN::Repos::create("$repospath", undef, undef, undef, undef), "create repository at $repospath"); my $ctx = SVN::Client->new; isa_ok($ctx,'SVN::Client','Client Object'); my $ci_dir1 = $ctx->mkdir(["$reposurl/dir1"]); isa_ok($ci_dir1,'_p_svn_client_commit_info_t'); is($ci_dir1->revision,1,'commit info revision equals 1'); END { diag "cleanup"; `rm -rf $repospath`; #`rm -rf $wcpath`; } Node-path: svnperl/perl/t/4pool.t Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 1253 Text-content-md5: a35f31f926bb1a11f36e0a6fe3f6c557 Content-length: 1263 PROPS-END #!/usr/bin/perl use strict; use Test::More qw(no_plan); require SVN::Core; require SVN::Repos; require SVN::Fs; require SVN::Delta; package TestEditor; our @ISA = qw(SVN::Delta::Editor); sub add_directory { my ($self, $path, undef, undef, undef, $pool) = @_; $pool->default; main::is_pool_default ($pool, 'default pool from c calls'); } package main; sub is_pool_default { my ($pool, $text) = @_; is (ref ($pool) eq 'SVN::Pool' ? $$$pool : $$pool, $$SVN::_Core::current_pool, $text); } my $repospath = "/tmp/svn-$$"; my $repos; ok($repos = SVN::Repos::create("$repospath", undef, undef, undef, undef), "create repository at $repospath"); my $fs = $repos->fs; my $pool = SVN::Pool->new_default; is_pool_default ($pool, 'default pool'); { my $spool = SVN::Pool->new_default_sub; is_pool_default ($spool, 'lexical default pool default'); } is_pool_default ($pool, 'lexical default pool destroyed'); my $root = $fs->revision_root (0); my $txn = $fs->begin_txn(0); $txn->root->make_dir('trunk'); $txn->commit; SVN::Repos::dir_delta ($root, '', '', $fs->revision_root (1), '', TestEditor->new(), undef, 1, 1, 0, 1); is_pool_default ($pool, 'default pool from c calls destroyed'); Node-path: svnperl/python Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/python/__init__.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 700 Text-content-md5: 5906faec481c0abf272f9daf099d2020 Content-length: 710 PROPS-END # # __init__.py: defines this directory as the 'libsvn' package. # # Subversion is a tool for revision control. # See http://subversion.tigris.org for more information. # # ==================================================================== # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # Node-path: svnperl/python/svn Node-kind: dir Node-action: add Prop-content-length: 10 Content-length: 10 PROPS-END Node-path: svnperl/python/svn/__init__.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 697 Text-content-md5: f50eb664847daeae8f40632ea0c558de Content-length: 707 PROPS-END # # __init__.py: defines this directory as the 'svn' package. # # Subversion is a tool for revision control. # See http://subversion.tigris.org for more information. # # ==================================================================== # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # Node-path: svnperl/python/svn/client.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 628 Text-content-md5: a886a5310794de93a536700e3d7dbf09 Content-length: 638 PROPS-END # # client.py : various utilities for interacting with the _client module # ###################################################################### # # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # from libsvn.client import * Node-path: svnperl/python/svn/core.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2162 Text-content-md5: 5ee70d27545e80ff6ada6cecf2bf7e88 Content-length: 2172 PROPS-END # # svn.core: public Python interface for core compontents # # Subversion is a tool for revision control. # See http://subversion.tigris.org for more information. # # ==================================================================== # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # # bring all the symbols up into this module ### in the future, we may want to limit this, rename things, etc from libsvn.core import * def run_app(func, *args, **kw): '''Run a function as an "APR application". APR is initialized, and an application pool is created. Cleanup is performed as the function exits (normally or via an exception. ''' apr_initialize() try: pool = svn_pool_create(None) try: return apply(func, (pool,) + args, kw) finally: svn_pool_destroy(pool) finally: apr_terminate() # some minor patchups svn_pool_destroy = apr_pool_destroy svn_pool_clear = apr_pool_clear class Stream: def __init__(self, stream): self._stream = stream def read(self, amt=None): if amt is None: # read the rest of the stream chunks = [ ] while 1: data = svn_stream_read(self._stream, SVN_STREAM_CHUNK_SIZE) if not data: break chunks.append(data) return ''.join(chunks) # read the amount specified return svn_stream_read(self._stream, int(amt)) def write(self, buf): ### what to do with the amount written? (the result value) svn_stream_write(self._stream, buf) def secs_from_timestr(svn_datetime, pool): aprtime = svn_time_from_cstring(svn_datetime, pool) # ### convert to a time_t; this requires intimate knowledge of # ### the apr_time_t type # ### aprtime is microseconds; turn it into seconds return aprtime / 1000000 Node-path: svnperl/python/svn/delta.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 1732 Text-content-md5: 42229ac841a613e1758d90a99841e5d1 Content-length: 1742 PROPS-END # # delta.py : various utilities for interacting with the _delta module # ###################################################################### # # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # from libsvn.delta import * class Editor: def set_target_revision(self, target_revision): pass def open_root(self, base_revision, dir_pool): return None def delete_entry(self, path, revision, parent_baton, pool): pass def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool): return None def open_directory(self, path, parent_baton, base_revision, dir_pool): return None def change_dir_prop(self, dir_baton, name, value, pool): pass def close_directory(self, dir_baton): pass def add_file(self, path, parent_baton, copyfrom_path, copyfrom_revision, file_pool): return None def open_file(self, path, parent_baton, base_revision, file_pool): return None def apply_textdelta(self, file_baton, base_checksum): return None def change_file_prop(self, file_baton, name, value, pool): pass def close_file(self, text_checksum, file_baton): pass def close_edit(self): pass def abort_edit(self): pass def make_editor(editor, pool): return svn_swig_py_make_editor(editor, pool) Node-path: svnperl/python/svn/fs.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 5847 Text-content-md5: 3b01d8850c6b4a33543d88b677fa871a Content-length: 5857 PROPS-END # # svn.fs: public Python FS interface # # Subversion is a tool for revision control. # See http://subversion.tigris.org for more information. # # ==================================================================== # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # ### hide these names? import tempfile import os import sys import popen2 import string import re import libsvn.fs import core # copy the wrapper functions out of the extension module, dropping the # 'svn_fs_' prefix. # XXX this might change in the future once we have a consistent naming # scheme for name in dir(libsvn.fs): if name[:7] == 'svn_fs_': vars()[name[7:]] = getattr(libsvn.fs, name) # we don't want these symbols exported del name, libsvn def entries(root, path, pool): "Call dir_entries returning a dictionary mappings names to IDs." e = dir_entries(root, path, pool) for name, entry in e.items(): e[name] = dirent_t_id_get(entry) return e class FileDiff: def __init__(self, root1, path1, root2, path2, pool, diffoptions=[]): assert path1 or path2 self.tempfile1 = None self.tempfile2 = None self.root1 = root1 self.path1 = path1 self.root2 = root2 self.path2 = path2 self.diffoptions = diffoptions # the caller can't manage this pool very well given our indirect use # of it. so we'll create a subpool and clear it at "proper" times. self.pool = core.svn_pool_create(pool) def either_binary(self): "Return true if either of the files are binary." if self.path1 is not None: prop = node_prop(self.root1, self.path1, core.SVN_PROP_MIME_TYPE, self.pool) if prop and core.svn_mime_type_is_binary(prop): return 1 if self.path2 is not None: prop = node_prop(self.root2, self.path2, core.SVN_PROP_MIME_TYPE, self.pool) if prop and core.svn_mime_type_is_binary(prop): return 1 return 0 def _dump_contents(self, file, root, path, pool): fp = open(file, 'w+') if path is not None: stream = file_contents(root, path, pool) try: while 1: chunk = core.svn_stream_read(stream, core.SVN_STREAM_CHUNK_SIZE) if not chunk: break fp.write(chunk) finally: core.svn_stream_close(stream) fp.close() def get_files(self): if self.tempfile1: # no need to do more. we ran this already. return self.tempfile1, self.tempfile2 # Make tempfiles, and dump the file contents into those tempfiles. self.tempfile1 = tempfile.mktemp() self.tempfile2 = tempfile.mktemp() self._dump_contents(self.tempfile1, self.root1, self.path1, self.pool) core.svn_pool_clear(self.pool) self._dump_contents(self.tempfile2, self.root2, self.path2, self.pool) core.svn_pool_clear(self.pool) return self.tempfile1, self.tempfile2 def get_pipe(self): self.get_files() # use an array for the command to avoid the shell and potential # security exposures cmd = ["diff"] \ + self.diffoptions \ + [self.tempfile1, self.tempfile2] # the windows implementation of popen2 requires a string if sys.platform == "win32": cmd = _escape_msvcrt_shell_command(cmd) # open the pipe, forget the end for writing to the child (we won't), # and then return the file object for reading from the child. fromchild, tochild = popen2.popen2(cmd) tochild.close() return fromchild def __del__(self): # it seems that sometimes the files are deleted, so just ignore any # failures trying to remove them if self.tempfile1 is not None: try: os.remove(self.tempfile1) except OSError: pass if self.tempfile2 is not None: try: os.remove(self.tempfile2) except OSError: pass def _escape_msvcrt_shell_command(argv): """Flatten a list of command line arguments into a command string. The resulting command string is expected to be passed to the system shell (cmd.exe) which os functions like popen() and system() invoke internally. The command line will be broken up correctly by Windows programs linked with the Microsoft C runtime. (Programs using other runtimes like Cygwin parse their command lines differently). """ # According cmd's usage notes (cmd /?), it parses the command line by # "seeing if the first character is a quote character and if so, stripping # the leading character and removing the last quote character." # So to prevent the argument string from being changed we add an extra set # of quotes around it here. return '"' + string.join(map(_escape_msvcrt_shell_arg, argv), " ") + '"' def _escape_msvcrt_shell_arg(arg): """Escape a command line argument. This escapes a command line argument to be passed to an MSVCRT program via the shell (cmd.exe). It uses shell escapes as well as escapes for MSVCRT. """ # The (very strange) parsing rules used by the C runtime library are # described at: # http://msdn.microsoft.com/library/en-us/vclang/html/_pluslang_Parsing_C.2b2b_.Command.2d.Line_Arguments.asp # double up slashes, but only if they are followed by a quote character arg = re.sub(_re_slashquote, r'\1\1\2', arg) # surround by quotes and escape quotes inside arg = '"' + string.replace(arg, '"', '"^""') + '"' return arg _re_slashquote = re.compile(r'(\\+)(\"|$)') Node-path: svnperl/python/svn/ra.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 616 Text-content-md5: c7f4b4e1d0c720e1a9a401c22ccd7697 Content-length: 626 PROPS-END # # ra.py : various utilities for interacting with the _ra module # ###################################################################### # # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # from libsvn.ra import * Node-path: svnperl/python/svn/repos.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 7690 Text-content-md5: 5b73f75c0f3ba099ce5d64c9dbe1907a Content-length: 7700 PROPS-END # # repos.py : various utilities for interacting with the _repos module # ###################################################################### # # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # ### hide these names? import string import svn.fs import svn.core import svn.delta from libsvn.repos import * class ChangedPath: __slots__ = [ 'item_kind', 'prop_changes', 'text_changed', 'base_path', 'base_rev', 'path', 'added', ] def __init__(self, item_kind, prop_changes, text_changed, base_path, base_rev, path, added): self.item_kind = item_kind self.prop_changes = prop_changes self.text_changed = text_changed self.base_path = base_path self.base_rev = base_rev self.path = path ### it would be nice to avoid this flag. however, without it, it would ### be quite difficult to distinguish between a change to the previous ### revision (which has a base_path/base_rev) and a copy from some ### other path/rev. a change in path is obviously add-with-history, ### but the same path could be a change to the previous rev or a restore ### of an older version. when it is "change to previous", I'm not sure ### if the rev is always repos.rev - 1, or whether it represents the ### created or time-of-checkout rev. so... we use a flag (for now) self.added = added class RevisionChangeCollector(svn.delta.Editor): # BATON FORMAT: [path, base_path, base_rev] def __init__(self, fs_ptr, rev, pool): self.fs_ptr = fs_ptr self.rev = rev self.changes = { } # path -> ChangedPathEntry() self.roots = { } # revision -> svn_fs_root_t self.pool = pool def _make_base_path(self, parent_path, path): idx = string.rfind(path, '/') if idx == -1: return parent_path + '/' + path return parent_path + path[idx:] def _get_root(self, rev): try: return self.roots[rev] except KeyError: pass root = self.roots[rev] = svn.fs.revision_root(self.fs_ptr, rev, self.pool) return root def open_root(self, base_revision, dir_pool): return ('', '', self.rev - 1) # dir_baton def delete_entry(self, path, revision, parent_baton, pool): base_path = self._make_base_path(parent_baton[1], path) if svn.fs.is_dir(self._get_root(parent_baton[2]), base_path, pool): item_type = svn.core.svn_node_dir else: item_type = svn.core.svn_node_file self.changes[path] = ChangedPath(item_type, False, False, base_path, parent_baton[2], # base_rev None, # (new) path False, # added ) def add_directory(self, path, parent_baton, copyfrom_path, copyfrom_revision, dir_pool): self.changes[path] = ChangedPath(svn.core.svn_node_dir, False, False, copyfrom_path, # base_path copyfrom_revision, # base_rev path, # path True, # added ) if copyfrom_path and (copyfrom_revision != -1): base_path = copyfrom_path else: base_path = path base_rev = copyfrom_revision return (path, base_path, base_rev) # dir_baton def open_directory(self, path, parent_baton, base_revision, dir_pool): base_path = self._make_base_path(parent_baton[1], path) return (path, base_path, parent_baton[2]) # dir_baton def change_dir_prop(self, dir_baton, name, value, pool): dir_path = dir_baton[0] if self.changes.has_key(dir_path): self.changes[dir_path].prop_changes = True else: # can't be added or deleted, so this must be CHANGED self.changes[dir_path] = ChangedPath(svn.core.svn_node_dir, True, False, dir_baton[1], # base_path dir_baton[2], # base_rev dir_path, # path False, # added ) def add_file(self, path, parent_baton, copyfrom_path, copyfrom_revision, file_pool): self.changes[path] = ChangedPath(svn.core.svn_node_file, False, False, copyfrom_path, # base_path copyfrom_revision, # base_rev path, # path True, # added ) if copyfrom_path and (copyfrom_revision != -1): base_path = copyfrom_path else: base_path = path base_rev = copyfrom_revision return (path, base_path, base_rev) # file_baton def open_file(self, path, parent_baton, base_revision, file_pool): base_path = self._make_base_path(parent_baton[1], path) return (path, base_path, parent_baton[2]) # file_baton def apply_textdelta(self, file_baton, base_checksum): file_path = file_baton[0] if self.changes.has_key(file_path): self.changes[file_path].text_changed = True else: # an add would have inserted a change record already, and it can't # be a delete with a text delta, so this must be a normal change. self.changes[file_path] = ChangedPath(svn.core.svn_node_file, False, True, file_baton[1], # base_path file_baton[2], # base_rev file_path, # path False, # added ) # no handler return None def change_file_prop(self, file_baton, name, value, pool): file_path = file_baton[0] if self.changes.has_key(file_path): self.changes[file_path].prop_changes = True else: # an add would have inserted a change record already, and it can't # be a delete with a prop change, so this must be a normal change. self.changes[file_path] = ChangedPath(svn.core.svn_node_file, True, False, file_baton[1], # base_path file_baton[2], # base_rev file_path, # path False, # added ) # enable True/False in older vsns of Python try: _unused = True except NameError: True = 1 False = 0 Node-path: svnperl/python/svn/util.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 850 Text-content-md5: 381b2bd6ff73f43df51db60f0f11c9ff Content-length: 860 PROPS-END # # svn.util: public Python interface for miscellaneous bindings # # Subversion is a tool for revision control. # See http://subversion.tigris.org for more information. # # ==================================================================== # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # # XXX This package might go a way eventually or get different contents # For compatability reasons, we import everything from core from core import * Node-path: svnperl/python/svn/wc.py Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 616 Text-content-md5: 80f3d6791fa944237c050c5d8ee2d40c Content-length: 626 PROPS-END # # wc.py : various utilities for interacting with the _wc module # ###################################################################### # # Copyright (c) 2000-2004 CollabNet. All rights reserved. # # This software is licensed as described in the file COPYING, which # you should have received as part of this distribution. The terms # are also available at http://subversion.tigris.org/license-1.html. # If newer versions of this license are posted there, you may use a # newer version instead, at your option. # ###################################################################### # from libsvn.wc import * Node-path: svnperl/svn_client.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 11850 Text-content-md5: 01dcfc856b8488958c3608cd1914b469 Content-length: 11860 PROPS-END /* * svn_client.i : SWIG interface file for svn_client.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module client %include typemaps.i %import apr.i %import svn_types.i %import svn_string.i %import svn_delta.i /* ----------------------------------------------------------------------- don't wrap the following items */ %ignore svn_client_proplist_item_t; /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_client_commit_info_t **, svn_auth_provider_object_t ** }; /* ----------------------------------------------------------------------- all "targets" and "diff_options" arrays are constant inputs of svn_stringbuf_t * */ %apply const apr_array_header_t *STRINGLIST { const apr_array_header_t *targets, const apr_array_header_t *diff_options }; /* ----------------------------------------------------------------------- fix up the return hash for svn_client_propget() */ %apply apr_hash_t **PROPHASH { apr_hash_t **props }; /* ----------------------------------------------------------------------- handle the return value for svn_client_proplist() */ %typemap(python,in,numinputs=0) apr_array_header_t ** (apr_array_header_t *temp) { $1 = &temp; } %typemap(python,argout,fragment="t_output_helper") apr_array_header_t ** { svn_client_proplist_item_t **ppitem; int i; int nelts = (*$1)->nelts; PyObject *list = PyList_New(nelts); if (list == NULL) return NULL; ppitem = (svn_client_proplist_item_t **)(*$1)->elts; for (i = 0; i < nelts; ++i, ++ppitem) { PyObject *item = PyTuple_New(2); PyObject *name = PyString_FromStringAndSize((*ppitem)->node_name->data, (*ppitem)->node_name->len); PyObject *hash = svn_swig_py_prophash_to_dict((*ppitem)->prop_hash); if (item == NULL || name == NULL || hash == NULL) { Py_XDECREF(item); Py_XDECREF(name); Py_XDECREF(hash); Py_DECREF(list); return NULL; } PyTuple_SET_ITEM(item, 0, name); PyTuple_SET_ITEM(item, 1, hash); PyList_SET_ITEM(list, i, item); } $result = t_output_helper($result, list); } /* ----------------------------------------------------------------------- handle svn_wc_notify_func_t/baton pairs */ %typemap(python,in) (svn_wc_notify_func_t notify_func, void *notify_baton) { $1 = svn_swig_py_notify_func; $2 = $input; /* our function is the baton. */ } %typemap(perl5,argout) apr_hash_t **statushash { /* ### FIXME-perl */ } %typemap(java,in) (svn_wc_notify_func_t notify_func, void *notify_baton) { $1 = svn_swig_java_notify_func; $2 = (void*)$input; /* our function is the baton. */ } %typemap(jni) svn_wc_notify_func_t "jobject" %typemap(jtype) svn_wc_notify_func_t "org.tigris.subversion.wc.Notifier" %typemap(jstype) svn_wc_notify_func_t "org.tigris.subversion.wc.Notifier" %typemap(javain) svn_wc_notify_func_t "$javainput" %typemap(javaout) svn_wc_notify_func_t { return $jnicall; } %typemap(perl5,in) (svn_wc_notify_func_t notify_func, void *notify_baton) { /* ### FIXME-perl */ } /* ----------------------------------------------------------------------- handle svn_wc_notify_func_t/baton pairs */ %typemap(python,in) (svn_wc_status_func_t status_func, void *status_baton) { $1 = svn_swig_py_status_func; $2 = $input; /* our function is the baton. */ } /* ----------------------------------------------------------------------- handle svn_client_get_commit_log_t/baton pairs */ %typemap(python,in) (svn_client_get_commit_log_t log_msg_func, void *log_msg_baton) { $1 = svn_swig_py_get_commit_log_func; $2 = $input; /* our function is the baton. */ } %typemap(java,in) (svn_client_get_commit_log_t log_msg_func, void *log_msg_baton) { $1 = svn_swig_java_get_commit_log_func; $2 = (void*)$input; /* our function is the baton. */ } %typemap(jni) svn_client_get_commit_log_t "jobject" %typemap(jtype) svn_client_get_commit_log_t "org.tigris.subversion.client.ClientPrompt" %typemap(jstype) svn_client_get_commit_log_t "org.tigris.subversion.client.ClientPrompt" %typemap(javain) svn_client_get_commit_log_t "$javainput" %typemap(javaout) svn_client_get_commit_log_t { return $jnicall; } %typemap(perl5,in) (svn_client_get_commit_log_t log_msg_func, void *log_msg_baton) { /* ### FIXME-perl */ } /* ----------------------------------------------------------------------- handle svn_client_prompt_t/baton pairs */ %typemap(java,memberin) (svn_client_prompt_t prompt_func, void *prompt_baton) { //$1 = svn_swig_java_client_prompt_func; //$2 = svn_swig_java_make_callback_baton(jenv, $input, _global_pool); } %typemap(java,in) (svn_client_prompt_t prompt_func, void *prompt_baton) { $1 = svn_swig_java_client_prompt_func; $2 = svn_swig_java_make_callback_baton(jenv, $input, _global_pool); } %typemap(java, jni) svn_client_prompt_t "jobject" %typemap(java, jtype) svn_client_prompt_t "org.tigris.subversion.client.ClientPrompt" %typemap(java, jstype) svn_client_prompt_t "org.tigris.subversion.client.ClientPrompt" %typemap(java, javain) svn_client_prompt_t "$javainput" /* ----------------------------------------------------------------------- handle svn_log_message_receiver_t/baton pairs */ %typemap(java,in) (svn_log_message_receiver_t receiver, void *receiver_baton) { $1 = svn_swig_java_log_message_receiver; $2 = (void*)$input; /* our function is the baton. */ } %typemap(jni) svn_log_message_receiver_t "jobject" %typemap(jtype) svn_log_message_receiver_t "org.tigris.subversion.client.LogMessageReceiver" %typemap(jstype) svn_log_message_receiver_t "org.tigris.subversion.client.LogMessageReceiver" %typemap(javain) svn_log_message_receiver_t "$javainput" %typemap(javaout) svn_log_message_receiver_t { return $jnicall; } /* ----------------------------------------------------------------------- handle the "statushash" OUTPUT param for svn_client_status() */ %typemap(python,in,numinputs=0) apr_hash_t **statushash = apr_hash_t **OUTPUT; %typemap(python,argout,fragment="t_output_helper") apr_hash_t **statushash { $result = t_output_helper( $result, svn_swig_py_convert_hash(*$1, SWIGTYPE_p_svn_wc_status_t)); } %typemap(perl5,argout) apr_hash_t **statushash { /* ### FIXME-perl */ } /* ----------------------------------------------------------------------- handle the prompt_baton */ %typemap(jni) svn_log_message_receiver_t "jobject" %typemap(jtype) svn_log_message_receiver_t "org.tigris.subversion.client.LogMessageReceiver" %typemap(jstype) svn_log_message_receiver_t "org.tigris.subversion.client.LogMessageReceiver" %typemap(javain) svn_log_message_receiver_t "$javainput" %typemap(javaout) svn_log_message_receiver_t { return $jnicall; } /* ----------------------------------------------------------------------- We use 'svn_wc_status_t *' in some custom code, but it isn't in the API anywhere. Thus, SWIG doesn't generate a typemap entry for it. by adding a simple declaration here, SWIG will insert a name for it. */ %types(svn_wc_status_t *); /* We also need SWIG to wrap svn_dirent_t for us. It doesn't appear in any API, but svn_client_ls returns a hash of pointers to dirents. */ %types(svn_dirent_t *); /* ----------------------------------------------------------------------- thunk the various authentication prompt functions and store the inputed SV in _global_callback for use in the later argout typemap */ %typemap(perl5, in) (svn_auth_simple_prompt_func_t prompt_func, void *prompt_baton) { $1 = svn_swig_pl_thunk_simple_prompt; _global_callback = $input; $2 = (void *) _global_callback; } %typemap(perl5, in) (svn_auth_username_prompt_func_t prompt_func, void *prompt_baton) { $1 = svn_swig_pl_thunk_username_prompt; _global_callback = $input; $2 = (void *) _global_callback; } %typemap(perl5, in) (svn_auth_ssl_server_trust_prompt_func_t prompt_func, void *prompt_baton) { $1 = svn_swig_pl_thunk_ssl_server_trust_prompt; _global_callback = $input; $2 = (void *) _global_callback; } %typemap(perl5, in) (svn_auth_ssl_client_cert_prompt_func_t prompt_func, void *prompt_baton) { $1 = svn_swig_pl_thunk_ssl_client_cert_prompt; _global_callback = $input; $2 = (void *) _global_callback; } %typemap(perl5, in) (svn_auth_ssl_client_cert_pw_prompt_func_t prompt_func, void *prompt_baton) { $1 = svn_swig_pl_thunk_ssl_client_cert_pw_prompt; _global_callback = $input; $2 = (void *) _global_callback; } /* For all the prompt functions create a reference for the baton * (which in this case is an SV pointing to the prompt callback) * and make that a second return from the prompt function. The * auth_open_helper can then split these values up so they * can be stored and the callback can stay valid until the * auth_baton is freed. */ %typemap(perl5, argout) void *prompt_baton (SV * _global_callback) { $result = sv_2mortal (newRV_inc (_global_callback)); argvi++; } /* ----------------------------------------------------------------------- */ /* Convert perl hashes back into apr_hash_t * for setting the config * member of the svn_client_ctx_t. This is an ugly hack, it will * always allocate the new apr_hash_t out of the global current_pool * It would be better to make apr_hash_t's into magic variables in * perl that are tied to the apr_hash_t interface. This would * remove the need to convert to and from perl hashs all the time. */ %typemap(perl5, in) apr_hash_t *config { $1 = svn_swig_pl_objs_to_hash_by_name ($input, "svn_config_t *", svn_swig_pl_make_pool ((SV *)NULL)); } %typemap(perl5, out) apr_hash_t *config { $result = svn_swig_pl_convert_hash($1, SWIG_TypeQuery("svn_config_t *")); argvi++; } /* ----------------------------------------------------------------------- */ %typemap(java, in) svn_stream_t *out %{ $1 = svn_swig_java_outputstream_to_stream(jenv, $input, _global_pool); %} %typemap(java, jni) svn_stream_t * "jobject"; %typemap(java, jtype) svn_stream_t * "java.io.OutputStream"; %typemap(java, jstype) svn_stream_t * "java.io.OutputStream"; %typemap(java, javain) svn_stream_t * "$javainput"; /* ----------------------------------------------------------------------- */ /* Include the headers before we swig-include the svn_client.h header file. SWIG will split the nested svn_client_revision_t structure, and we need the types declared *before* the split structure is encountered. */ %{ #include "svn_client.h" #include "svn_time.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} %include svn_client.h Node-path: svnperl/svn_delta.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2568 Text-content-md5: d6364c510619d33662b5dd756c718711 Content-length: 2578 PROPS-END /* * svn_delta.i : SWIG interface file for svn_delta.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module delta %include "typemaps.i" %import apr.i %import svn_types.i %import svn_string.i /* ----------------------------------------------------------------------- For these types, "type **" is always an OUT param. */ %apply SWIGTYPE **OUTPARAM { svn_txdelta_stream_t **, void **, svn_txdelta_window_t **, const svn_delta_editor_t **, svn_txdelta_window_handler_t * }; /* ----------------------------------------------------------------------- mark window.new_data as readonly since we would need a pool to set it properly (e.g. to allocate an svn_string_t structure). */ %immutable svn_txdelta_window_t::new_data; /* ----------------------------------------------------------------------- thunk editors for the various language bindings. */ #ifdef SWIGPYTHON void svn_swig_py_make_editor(const svn_delta_editor_t **editor, void **edit_baton, PyObject *py_editor, apr_pool_t *pool); #endif %typemap(perl5, in) (const svn_delta_editor_t *editor, void *edit_baton) { svn_delta_make_editor(&$1, &$2, $input, _global_pool); } /* ----------------------------------------------------------------------- */ %include svn_delta.h %{ #include "svn_md5.h" #include "svn_delta.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} /* ----------------------------------------------------------------------- editor callback invokers */ /* Cancel the typemap as they aren't returned valued in member functions if editor. */ %typemap(perl5, in) (const svn_delta_editor_t *editor, void *edit_baton); #ifdef SWIGPERL %include delta_editor.hi #endif Node-path: svnperl/svn_fs.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 5717 Text-content-md5: 483cb324468352333fd7fd1bb2febb66 Content-length: 5727 PROPS-END /* * svn_fs.i : SWIG interface file for svn_fs.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module fs %include typemaps.i %import apr.i %import svn_types.i %import svn_string.i %import svn_delta.i /* ----------------------------------------------------------------------- do not generate any constructors or destructors (of structures) -- all structures are going to come /out/ of the FS (so we don't need to construct the things) and will live in a pool (so we don't need to destroy the things). */ %nodefault; /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_fs_root_t **, svn_fs_txn_t **, void **, svn_fs_history_t **, svn_fs_id_t ** }; /* and this is always an OUT param */ %apply const char **OUTPUT { const char ** }; /* ### need to deal with IN params which have "const" and OUT params which ### return non-const type. SWIG's type checking may see these as ### incompatible. */ /* ----------------------------------------------------------------------- These parameters may be NULL. */ %apply const char *MAY_BE_NULL { const char *base_checksum, const char *result_checksum }; /* ----------------------------------------------------------------------- for the FS, 'int *' will always be an OUTPUT parameter */ %apply int *OUTPUT { int * }; /* ----------------------------------------------------------------------- define the data/len pair of svn_fs_parse_id to be a single argument */ %apply (const char *PTR, apr_size_t LEN) { (const char *data, apr_size_t len) } /* ----------------------------------------------------------------------- list_transaction's "apr_array_header_t **" is returning a list of strings. */ %typemap(in,numinputs=0) apr_array_header_t ** (apr_array_header_t *temp) { $1 = &temp; } %typemap(python, argout, fragment="t_output_helper") apr_array_header_t **names_p { $result = t_output_helper($result, svn_swig_py_array_to_list(*$1)); } %typemap(perl5, argout) apr_array_header_t **names_p { $result = svn_swig_pl_array_to_list(*$1); ++argvi; } /* ----------------------------------------------------------------------- revisions_changed's "apr_array_header_t **" is returning a list of revs. also, its input array is a list of strings. */ %typemap(python, argout, fragment="t_output_helper") apr_array_header_t **revs { $result = t_output_helper($result, svn_swig_py_revarray_to_list(*$1)); } %typemap(perl5, argout) apr_array_header_t **revs { $result = svn_swig_pl_ints_to_list(*$1); ++argvi; } /* ----------------------------------------------------------------------- all uses of "apr_hash_t **" are returning property hashes */ %apply apr_hash_t **PROPHASH { apr_hash_t ** }; /* ----------------------------------------------------------------------- except for svn_fs_dir_entries, which returns svn_fs_dirent_t structures */ %typemap(python,in,numinputs=0) apr_hash_t **entries_p = apr_hash_t **OUTPUT; %typemap(python,argout,fragment="t_output_helper") apr_hash_t **entries_p { $result = t_output_helper( $result, svn_swig_py_convert_hash(*$1, SWIGTYPE_p_svn_fs_dirent_t)); } %typemap(perl5,in,numinputs=0) apr_hash_t **entries_p = apr_hash_t **OUTPUT; %typemap(perl5,argout) apr_hash_t **entries_p { ST(argvi++) = svn_swig_pl_convert_hash(*$1, SWIGTYPE_p_svn_fs_dirent_t); } /* ----------------------------------------------------------------------- and except for svn_fs_paths_changed, which returns svn_fs_path_change_t structures */ %typemap(python, in,numinputs=0) apr_hash_t **changed_paths_p = apr_hash_t **OUTPUT; %typemap(python, argout, fragment="t_output_helper") apr_hash_t **changed_paths_p { $result = t_output_helper( $result, svn_swig_py_convert_hash(*$1, SWIGTYPE_p_svn_fs_path_change_t)); } /* ----------------------------------------------------------------------- Fix the return value for svn_fs_commit_txn(). If the conflict result is NULL, then t_output_helper() is passed Py_None, but that goofs up because that is *also* the marker for "I haven't started assembling a multi-valued return yet" which means the second return value (new_rev) will not cause a 2-tuple to be manufactured. The answer is to explicitly create a 2-tuple return value. */ %typemap(python, argout) (const char **conflict_p, svn_revnum_t *new_rev) { /* this is always Py_None */ Py_DECREF($result); /* build the result tuple */ $result = Py_BuildValue("zi", *$1, (long)*$2); } %typemap(perl5, argout) apr_hash_t **changed_paths_p { /* ### FIXME-perl */ } /* ----------------------------------------------------------------------- */ %include svn_fs.h %{ #include "svn_md5.h" #include "svn_fs.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} Node-path: svnperl/svn_ra.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 2602 Text-content-md5: 1eff5dcfd5431ffa33c6b4cd12bd9a79 Content-length: 2612 PROPS-END /* * svn_ra.i : SWIG interface file for svn_ra.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module ra %include typemaps.i %import apr.i %import svn_types.i %import svn_string.i %import svn_delta.i /* bad pool convention, also these should not be public interface at all as commented by sussman. */ %ignore svn_ra_svn_init; %ignore svn_ra_local_init; %ignore svn_ra_dav_init; /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_ra_plugin_t **, session_baton **, const svn_ra_reporter_t **reporter, void **report_baton }; %apply apr_hash_t **PROPHASH { apr_hash_t **props }; /* ----------------------------------------------------------------------- thunk ra_callback */ %apply const char **OUTPUT { const char **url, const char **uuid }; %apply const apr_array_header_t *STRINGLIST { const apr_array_header_t *paths }; %typemap(perl5, in) (const svn_delta_editor_t *update_editor, void *update_baton) { svn_delta_make_editor(&$1, &$2, $input, _global_pool); } %typemap(perl5, in) (const svn_delta_editor_t *diff_editor, void *diff_baton) { svn_delta_make_editor(&$1, &$2, $input, _global_pool); } %typemap(perl5, in) (const svn_ra_callbacks_t *callbacks, void *callback_baton) { svn_ra_make_callbacks(&$1, &$2, $input, _global_pool); } %typemap(perl5, in) apr_hash_t *config { $1 = svn_swig_pl_objs_to_hash_by_name ($input, "svn_config_t *", _global_pool); } /* ----------------------------------------------------------------------- */ %include svn_ra.h %{ #include "svn_ra.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} #ifdef SWIGPERL %include ra_plugin.hi %include ra_reporter.hi #endif Node-path: svnperl/svn_repos.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 3629 Text-content-md5: abc80867e227a5642d8288bdde1112c5 Content-length: 3639 PROPS-END /* * svn_repos.i : SWIG interface file for svn_repos.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module repos %include typemaps.i %import apr.i %import svn_types.i %import svn_string.i %import svn_delta.i %import svn_fs.i /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_repos_t ** }; /* ----------------------------------------------------------------------- Some of the various parameters need to be NULL sometimes */ %apply const char *MAY_BE_NULL { const char *src_entry, const char *on_disk_template, const char *in_repos_template }; /* ----------------------------------------------------------------------- handle the 'paths' parameter appropriately */ %apply const apr_array_header_t *STRINGLIST { const apr_array_header_t *paths }; /* ----------------------------------------------------------------------- XXX: for some reasons svn_delta_editor doesn't get typemapped even if svn_delta.i is imported. so we redeclare here. */ %typemap(perl5, in) (const svn_delta_editor_t *editor, void *edit_baton) { svn_delta_make_editor(&$1, &$2, $input, _global_pool); } /* ----------------------------------------------------------------------- commit editor support */ %apply SWIGTYPE **OUTPARAM { const svn_delta_editor_t **editor, void **edit_baton }; /* ----------------------------------------------------------------------- handle svn_repos_history_func_t/baton pairs */ %typemap(python,in) (svn_repos_history_func_t history_func, void *history_baton) { $1 = svn_swig_py_repos_history_func; $2 = $input; /* our function is the baton. */ } %typemap(perl5,in) (svn_repos_history_func_t history_func, void *history_baton) { $1 = svn_swig_pl_thunk_history_func; $2 = $input; /* our function is the baton. */ } /* ----------------------------------------------------------------------- handle svn_repos_authz_read_func_t/baton pairs */ %typemap(perl5, in) (svn_repos_authz_func_t authz_read_func, void *authz_read_baton) { if (SvOK ($input)) { $1 = svn_swig_pl_thunk_authz_func; $2 = $input; /* our function is the baton */ } else { $1 = NULL; $2 = NULL; } } /* ----------------------------------------------------------------------- handle config and fs_config in svn_repos_create */ %typemap(perl5, in) apr_hash_t *config { $1 = svn_swig_pl_objs_to_hash_by_name ($input, "svn_config_t *", _global_pool); } %typemap(perl5, in) apr_hash_t *fs_config { $1 = svn_swig_pl_strings_to_hash ($input, _global_pool); } /* ----------------------------------------------------------------------- */ %include svn_repos.h %{ #include "svn_repos.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} Node-path: svnperl/svn_string.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 6532 Text-content-md5: 82660c555cd5ccb442c420237530aca5 Content-length: 6542 PROPS-END /* * svn_string.i : SWIG interface file for svn_string.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ /* This interface file does not include a %module line because it should only be imported by other modules. */ %import apr.i %import svn_types.i typedef struct svn_stringbuf_t svn_stringbuf_t; typedef struct svn_string_t svn_string_t; /* ----------------------------------------------------------------------- generic OUT param typemap for svn_string(buf)_t. we can share these because we only refer to the ->data and ->len values. */ %typemap(python,argout,fragment="t_output_helper") RET_STRING { PyObject *s; if (*$1 == NULL) { Py_INCREF(Py_None); s = Py_None; } else { s = PyString_FromStringAndSize((*$1)->data, (*$1)->len); if (s == NULL) return NULL; } $result = t_output_helper($result, s); } %typemap(java,out) RET_STRING { /* FIXME: This is just a stub -- implement JNI code for returning a string! */ $output = NULL; } %typemap(jni) char * "jstring" %typemap(perl5,argout) RET_STRING { if (*$1) { $result = sv_newmortal(); sv_setpvn ($result, (*$1)->data, (*$1)->len); } else $result = &PL_sv_undef; argvi++; } /* ----------------------------------------------------------------------- TYPE: svn_stringbuf_t */ %typemap(python,in) svn_stringbuf_t * { if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "not a string"); return NULL; } $1 = svn_stringbuf_ncreate(PyString_AS_STRING($input), PyString_GET_SIZE($input), /* ### gah... what pool to use? */ _global_pool); } %typemap(perl5,in) svn_stringbuf_t * { /* ### FIXME-perl */ } %typemap(python,out) svn_stringbuf_t * { $result = PyString_FromStringAndSize($1->data, $1->len); } %typemap(perl5,out) svn_stringbuf_t * { /* ### FIXME-perl */ } /* svn_stringbuf_t ** is always an output parameter */ %typemap(python,in,numinputs=0) svn_stringbuf_t ** (svn_stringbuf_t *temp) { $1 = &temp; } %typemap(perl5,in,numinputs=0) svn_stringbuf_t ** (svn_stringbuf_t *temp) { $1 = &temp; } %apply RET_STRING { svn_stringbuf_t ** }; /* ----------------------------------------------------------------------- TYPE: svn_string_t */ /* const svn_string_t * is always an input parameter */ %typemap(python,in) const svn_string_t * (svn_string_t value) { if ($input == Py_None) $1 = NULL; else { if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "not a string"); return NULL; } value.data = PyString_AS_STRING($input); value.len = PyString_GET_SIZE($input); $1 = &value; } } %typemap(perl5,in) const svn_string_t * (svn_string_t value) { if (SvOK($input)) { value.data = SvPV($input, value.len); $1 = &value; } else { $1 = NULL; } } /* when storing an svn_string_t* into a structure, we must allocate the svn_string_t structure on the heap. */ %typemap(python,memberin) const svn_string_t * { $1 = svn_string_dup($input, _global_pool); } %typemap(perl5,memberin) const svn_string_t * { $1 = svn_string_dup($input, _global_pool); } %typemap(python,out) svn_string_t * { $result = PyString_FromStringAndSize($1->data, $1->len); } %typemap(perl5,out) svn_string_t * { $result = sv_2mortal(newSVpv($1->data, $1->len)); ++argvi; } /* svn_string_t ** is always an output parameter */ %typemap(in,numinputs=0) svn_string_t ** (svn_string_t *temp) { $1 = &temp; } %apply RET_STRING { svn_string_t ** }; /* ----------------------------------------------------------------------- define a way to return a 'const char *' */ /* ### note that SWIG drops the const in the arg decl, so we must cast */ %typemap(in, numinputs=0) const char **OUTPUT (const char *temp = NULL) "$1 = (char **)&temp;" %typemap(python,argout,fragment="t_output_helper") const char **OUTPUT { PyObject *s; if (*$1 == NULL) { Py_INCREF(Py_None); s = Py_None; } else { s = PyString_FromString(*$1); if (s == NULL) return NULL; } $result = t_output_helper($result, s); } %typemap(perl5,argout) const char **OUTPUT { if (*$1 == NULL) $result = &PL_sv_undef; else $result = sv_2mortal(newSVpv(*$1, 0)); ++argvi; } /* ----------------------------------------------------------------------- define a general INPUT param of an array of svn_stringbuf_t* items. */ %typemap(python,in) const apr_array_header_t *STRINGLIST { $1 = (apr_array_header_t *) svn_swig_py_strings_to_array($input, _global_pool); if ($1 == NULL) return NULL; } %typemap(perl5,in) const apr_array_header_t *STRINGLIST { $1 = (apr_array_header_t *) svn_swig_pl_strings_to_array($input, _global_pool); } %typemap(jni) const apr_array_header_t *STRINGLIST "jobjectArray" %typemap(jtype) const apr_array_header_t *STRINGLIST "java.lang.String[]" %typemap(jstype) const apr_array_header_t *STRINGLIST "java.lang.String[]" %typemap(javain) const apr_array_header_t *STRINGLIST "$javainput" %typemap(java,in) const apr_array_header_t *STRINGLIST (apr_array_header_t *temp) { temp = (apr_array_header_t *)svn_swig_java_strings_to_array(jenv, $input, _global_pool); $1 = temp; } %typemap(java,freearg) const apr_array_header_t *STRINGLIST { /* FIXME: Perhaps free up "temp"? */ } /* path lists */ %apply const apr_array_header_t *STRINGLIST { const apr_array_header_t *paths }; /* ----------------------------------------------------------------------- */ Node-path: svnperl/svn_types.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 13306 Text-content-md5: 5e8a9b95aa95943e34874cae5e13d463 Content-length: 13316 PROPS-END /* * svn_types.i : SWIG interface file for svn_types.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ /* This interface file only defines types and their related information. There is no module associated with this interface file. */ %import apr.i /* ----------------------------------------------------------------------- Create a typemap to define "type **" as OUT parameters. Note: SWIGTYPE is just a placeholder for "some arbitrary type". This typemap will be applied onto a "real" type. */ %typemap(python, in, numinputs=0) SWIGTYPE **OUTPARAM ($*1_type temp) { $1 = ($1_ltype)&temp; } %typemap(java, in) SWIGTYPE **OUTPARAM ($*1_type temp) { $1 = ($1_ltype)&temp; } %typemap(perl5, in, numinputs=0) SWIGTYPE **OUTPARAM ($*1_type temp) { $1 = ($1_ltype)&temp; } %typemap(python, argout, fragment="t_output_helper") SWIGTYPE **OUTPARAM { $result = t_output_helper($result, SWIG_NewPointerObj(*$1, $*1_descriptor, 0)); } %typemap(perl5, argout) SWIGTYPE **OUTPARAM { ST(argvi) = sv_newmortal(); SWIG_MakePtr(ST(argvi++), (void *)*$1, $*1_descriptor,0); } /* ----------------------------------------------------------------------- Create a typemap to handle enums. */ %typemap(python, in, numinputs=0) enum SWIGTYPE *OUTENUM ($*1_type temp) { $1 = ($1_ltype)&temp; } %typemap(perl5, in, numinputs=0) enum SWIGTYPE *OUTENUM (long temp) { $1 = ($1_ltype)&temp; } %typemap(perl5, argout) enum SWIGTYPE *OUTENUM { if (argvi >= items) { EXTEND(sp,1); } $result = sv_newmortal(); sv_setiv($result,(IV) *($1)); argvi++; } %typemap(java, in) enum SWIGTYPE *OUTENUM ($*1_type temp) { $1 = ($1_ltype)&temp; } %typemap(python, argout, fragment="t_output_helper") enum SWIGTYPE *OUTENUM { $result = t_output_helper($result, PyInt_FromLong(*$1)); } /* ----------------------------------------------------------------------- Create a typemap for specifying string args that may be NULL. */ %typemap(python, in, parse="z") const char *MAY_BE_NULL ""; %typemap(java, in) const char *MAY_BE_NULL { /* ### WHEN IS THIS USED? */ $1 = 0; if ($input) { $1 = ($1_ltype)JCALL2(GetStringUTFChars, jenv, $input, 0); if (!$1) return $null; } } #ifdef SWIGPERL %apply const char * { const char *MAY_BE_NULL }; #endif %typemap(perl5,out) svn_error_t * { if ($1) { char buf[128], *p; SV *err = sv_newmortal(); p = svn_strerror($1->apr_err, buf, 128); sv_setpv (err, p); while ($1) { sv_catpvf (err, ": %s", $1->message); $1 = $1->child; } croak (SvPV_nolen(err)); } } /* ----------------------------------------------------------------------- Define a more refined 'varin' typemap for 'const char *' members. This is used in place of the 'char *' handler defined automatically. We need to do the free/malloc/strcpy special because of the const */ %typemap(memberin) const char * { apr_size_t len = strlen($input) + 1; char *copied; if ($1) free((char *)$1); copied = malloc(len); memcpy(copied, $input, len); $1 = copied; } /* ----------------------------------------------------------------------- Specify how svn_error_t returns are turned into exceptions. */ %typemap(python, out) svn_error_t * { if ($1 != NULL) { if ($1->apr_err != SVN_ERR_SWIG_PY_EXCEPTION_SET) svn_swig_py_svn_exception($1); else svn_error_clear($1); return NULL; } Py_INCREF(Py_None); $result = Py_None; } %typemap(java, out) svn_error_t * %{ $result = ($1 != NULL) ? svn_swig_java_convert_error(jenv, $1) : NULL; %} %typemap(jni) svn_error_t * "jthrowable" %typemap(jtype) svn_error_t * "org.tigris.subversion.SubversionException" %typemap(jstype) svn_error_t * "org.tigris.subversion.SubversionException" %typemap(javain) svn_error_t * "@javainput" %typemap(javaout) svn_error_t * { return $jnicall; } /* Make the proxy classes much more usable */ %typemap(javaptrconstructormodifiers) SWIGTYPE, SWIGTYPE *, SWIGTYPE &, SWIGTYPE [] "public" /* ----------------------------------------------------------------------- 'svn_revnum_t *' and 'svn_boolean_t *' will always be an OUTPUT parameter */ %apply long *OUTPUT { svn_revnum_t * }; %apply int *OUTPUT { svn_boolean_t * }; /* ----------------------------------------------------------------------- Define an OUTPUT typemap for 'svn_filesize_t *'. For now, we'll treat it as a 'long' even if that isn't entirely correct... */ %typemap(python,in,numinputs=0) svn_filesize_t * (svn_filesize_t temp) "$1 = &temp;"; %typemap(python,argout,fragment="t_output_helper") svn_filesize_t * "$result = t_output_helper($result,PyInt_FromLong((long) (*$1)));"; %apply long *OUTPUT { svn_filesize_t * }; /* ----------------------------------------------------------------------- Define a general ptr/len typemap. This takes a single script argument and expands it into a ptr/len pair for the native call. */ %typemap(python, in) (const char *PTR, apr_size_t LEN) { if (!PyString_Check($input)) { PyErr_SetString(PyExc_TypeError, "expecting a string"); return NULL; } $1 = PyString_AS_STRING($input); $2 = PyString_GET_SIZE($input); } %typemap(java, in) (const char *PTR, apr_size_t LEN) (char c) { if ($input != NULL) { /* Do not use GetPrimitiveArrayCritical and ReleasePrimitiveArrayCritical * since the Subversion client might block the thread */ $1 = JCALL2(GetByteArrayElements, jenv, $input, NULL); $2 = JCALL1(GetArrayLength, jenv, $input); } else { $1 = &c; $2 = 0; } } %typemap(java, freearg) (const char *PTR, apr_size_t LEN) { if ($input != NULL) { JCALL3(ReleaseByteArrayElements, jenv, $input, $1, JNI_ABORT); } /* Since this buffer is used as input JNI_ABORT is safe as "mode" above*/ } %typemap(jni) (const char *PTR, apr_size_t LEN) "jbyteArray" %typemap(jtype) (const char *PTR, apr_size_t LEN) "byte[]" %typemap(jstype) (const char *PTR, apr_size_t LEN) "byte[]" %typemap(javain) (const char *PTR, apr_size_t LEN) "$javainput" %typemap(javaout) (const char *PTR, apr_size_t LEN) { return $jnicall; } %typemap(perl5, in) (const char *PTR, apr_size_t LEN) { if (SvPOK($input)) { $1 = SvPV($input, $2); } else { /* set to 0 to avoid warning */ $1 = 0; $2 = 0; SWIG_croak("Expecting a string"); } } /* ----------------------------------------------------------------------- Define a generic arginit mapping for pools. */ %typemap(python, arginit) apr_pool_t *pool(apr_pool_t *_global_pool) { /* Assume that the pool here is the last argument in the list */ SWIG_ConvertPtr(PyTuple_GET_ITEM(args, PyTuple_GET_SIZE(args) - 1), (void **)&$1, $1_descriptor, SWIG_POINTER_EXCEPTION | 0); _global_pool = $1; } %typemap(perl5, in) apr_pool_t *pool ""; %typemap(perl5, default) apr_pool_t *pool(apr_pool_t *_global_pool) { _global_pool = $1 = svn_swig_pl_make_pool (ST(items-1)); } #ifdef SWIGPERL %apply apr_pool_t *pool { apr_pool_t *dir_pool, apr_pool_t *file_pool, apr_pool_t *node_pool }; #endif %typemap(java, arginit) apr_pool_t *pool(apr_pool_t *_global_pool) { /* ### HACK: Get the input variable based on naming convention */ _global_pool = *(apr_pool_t **)&j$1; $1 = 0; } /* ----------------------------------------------------------------------- result of check_path */ %apply enum SWIGTYPE *OUTENUM { svn_node_kind_t * }; /* ----------------------------------------------------------------------- get_logs takes a callback function, so we have to thunk it */ %typemap(python, in) (svn_log_message_receiver_t receiver, void *receiver_baton) { $1 = svn_swig_py_thunk_log_receiver; $2 = (void *)$input; } %typemap(perl5, in) (svn_log_message_receiver_t receiver, void *receiver_baton) { $1 = svn_swig_pl_thunk_log_receiver; $2 = (void *)$input; } /* stream_t * */ %apply SWIGTYPE **OUTPARAM { svn_stream_t ** }; /* ----------------------------------------------------------------------- thunk commit_callback */ %typemap(perl5, in) (svn_commit_callback_t callback, void *callback_baton) { $1 = svn_swig_pl_thunk_commit_callback; $2 = (void *)$input; SvREFCNT_inc($input); }; /* ----------------------------------------------------------------------- svn_stream interpolability with io handle */ %typemap(perl5, in) svn_stream_t * { svn_swig_pl_make_stream (&$1, $input); } %typemap(perl5, argout) svn_stream_t ** { $result = svn_swig_pl_from_stream (*$1); argvi++; } /* ----------------------------------------------------------------------- Wrap the digest output for functions populating digests. */ %typemap(perl5, in, numinputs=0) unsigned char digest[ANY] ($*1_type temp[33]) { $1 = ($1_ltype)temp; } %typemap(perl5, argout) unsigned char digest[ANY] { ST(argvi) = sv_newmortal(); sv_setpv((SV*)ST(argvi++), svn_md5_digest_to_cstring ($1,_global_pool)); } #ifdef SWIGPERL %apply unsigned char digest[ANY] { unsigned char *digest }; #endif /* ----------------------------------------------------------------------- useful convertors for svn_opt_revision_t */ %typemap(perl5, in) svn_opt_revision_t * (svn_opt_revision_t rev) { $1 = &rev; if ($input == NULL || $input == &PL_sv_undef || !SvOK($input)) { rev.kind = svn_opt_revision_unspecified; } else if (sv_isobject($input) && sv_derived_from($input, "_p_svn_opt_revision_t")) { SWIG_ConvertPtr($input, (void **)&$1, $1_descriptor, 0); } else if (SvIOK($input)) { rev.kind = svn_opt_revision_number; rev.value.number = SvIV($input); } else if (SvPOK($input)) { char *input = SvPV_nolen($input); if (strcasecmp(input, "BASE") == 0) rev.kind = svn_opt_revision_base; else if (strcasecmp(input, "HEAD") == 0) rev.kind = svn_opt_revision_head; else if (strcasecmp(input, "WORKING") == 0) rev.kind = svn_opt_revision_working; else if (strcasecmp(input, "COMMITTED") == 0) rev.kind = svn_opt_revision_committed; else if (strcasecmp(input, "PREV") == 0) rev.kind = svn_opt_revision_previous; else if (*input == '{') { time_t tm; char *end = strchr(input,'}'); if (!end) SWIG_croak("unknown opt_revision_t type"); *end = '\0'; tm = svn_parse_date (input + 1, NULL); if (tm == -1) SWIG_croak("unknown opt_revision_t type"); rev.kind = svn_opt_revision_date; apr_time_ansi_put(&(rev.value.date), tm); } else SWIG_croak("unknown opt_revison_t type"); } else SWIG_croak("unknown opt_revision_t type"); } /* ----------------------------------------------------------------------- dirents hash */ %typemap(python,in,numinputs=0) apr_hash_t **dirents = apr_hash_t **OUTPUT; %typemap(python,argout,fragment="t_output_helper") apr_hash_t **dirents { $result = t_output_helper ($result, svn_swig_py_convert_hash(*$1, SWIG_TypeQuery("svn_dirent_t *"))); } %typemap(perl5,in,numinputs=0) apr_hash_t **dirents = apr_hash_t **OUTPUT; %typemap(perl5,argout) apr_hash_t **dirents { ST(argvi++) = svn_swig_pl_convert_hash (*$1, SWIG_TypeQuery("svn_dirent_t *")); } /* ----------------------------------------------------------------------- Special boolean mapping for java. */ %typemap(java, jni) svn_boolean_t "jboolean"; %typemap(java, jtype) svn_boolean_t "boolean"; %typemap(java, jstype) svn_boolean_t "boolean"; %typemap(java, in) svn_boolean_t %{ $1 = $input ? TRUE : FALSE; %} %typemap(java, out) svn_boolean_t %{ $result = $1 ? JNI_TRUE : JNI_FALSE; %} /* ----------------------------------------------------------------------- Handle python thread locking. Swig doesn't allow us to specify a language in the %exception command, so we have to use #ifdefs for the python-specific parts. */ %exception { #ifdef SWIGPYTHON svn_swig_py_release_py_lock(); #endif $action #ifdef SWIGPYTHON svn_swig_py_acquire_py_lock(); #endif } /* ----------------------------------------------------------------------- */ %include svn_types.h %{ #include "svn_types.h" #include "svn_time.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} Node-path: svnperl/svn_wc.i Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 3500 Text-content-md5: b56f7f908ad6d04cfabd25660fb2ff7b Content-length: 3510 PROPS-END /* * svn_wc.i : SWIG interface file for svn_wc.h * * ==================================================================== * Copyright (c) 2000-2003 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ %module wc %include typemaps.i %import apr.i %import svn_types.i %import svn_string.i %import svn_delta.i /* ----------------------------------------------------------------------- ### these functions require a pool, which we don't have immediately ### handy. just eliminate these funcs for now. */ %ignore svn_wc_set_auth_file; /* ### ignore this structure because the accessors will need a pool */ %ignore svn_wc_keywords_t; /* ----------------------------------------------------------------------- these types (as 'type **') will always be an OUT param */ %apply SWIGTYPE **OUTPARAM { svn_wc_entry_t **, svn_wc_adm_access_t **, svn_wc_status_t ** }; /* we can't use the OUTPARAM cuz that is only for pointers. use the standard OUTPARAM definition for 'int' instead. */ %apply int *OUTPUT { int * }; /* handle the property hash returned by svn_wc_prop_list */ %apply apr_hash_t **PROPHASH { apr_hash_t **props }; /* ----------------------------------------------------------------------- handle svn_wc_notify_func_t/baton pairs */ %typemap(python,in) (svn_wc_notify_func_t notify_func, void *notify_baton) { $1 = svn_swig_py_notify_func; $2 = $input; /* our function is the baton. */ } %typemap(java,in) (svn_wc_notify_func_t notify_func, void *notify_baton) { $1 = svn_swig_java_notify_func; $2 = (void*)$input; /* our function is the baton. */ } %typemap(jni) svn_wc_notify_func_t "jobject" %typemap(jtype) svn_wc_notify_func_t "org.tigris.subversion.wc.Notifier" %typemap(jstype) svn_wc_notify_func_t "org.tigris.subversion.wc.Notifier" %typemap(javain) svn_wc_notify_func_t "$javainput" %typemap(javaout) svn_wc_notify_func_t { return $jnicall; } /* ----------------------------------------------------------------------- handle svn_cancel_func_t/baton pairs */ %typemap(python,in) (svn_cancel_func_t cancel_func, void *cancel_baton) { $1 = svn_swig_py_cancel_func; $2 = $input; /* our function is the baton. */ } %typemap(java,in) (svn_cancel_func_t cancel_func, void *cancel_baton) { $1 = svn_swig_java_cancel_func; $2 = (void*)$input; /* our function is the baton. */ } %typemap(jni) svn_cancel_func_t "jobject" %typemap(jtype) svn_cancel_func_t "org.tigris.subversion.Canceller" %typemap(jstype) svn_cancel_func_t "org.tigris.subversion.Canceller" %typemap(javain) svn_cancel_func_t "$javainput" %typemap(javaout) svn_cancel_func_t { return $jnicall; } /* ----------------------------------------------------------------------- */ %include svn_wc.h %{ #include "svn_wc.h" #ifdef SWIGPYTHON #include "swigutil_py.h" #endif #ifdef SWIGJAVA #include "swigutil_java.h" #endif #ifdef SWIGPERL #include "swigutil_pl.h" #endif %} Node-path: svnperl/swigutil_java.c Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 38607 Text-content-md5: 4efe389f4e95d2271a657c0d3d134443 Content-length: 38617 PROPS-END /* * swigutil_java.c: utility functions for the SWIG Java bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #include #include #include #include "svn_client.h" #include "svn_string.h" #include "svn_delta.h" #define SVN_SWIG_JAVA_DEFINE_CACHE #include "swigutil_java.h" /* FIXME: Need java.swg for the JCALL macros. The following was taken from javahead.swg (which is included by java.swg). */ #ifndef JCALL0 #ifdef __cplusplus # define JCALL0(func, jenv) jenv->func() # define JCALL1(func, jenv, ar1) jenv->func(ar1) # define JCALL2(func, jenv, ar1, ar2) jenv->func(ar1, ar2) # define JCALL3(func, jenv, ar1, ar2, ar3) jenv->func(ar1, ar2, ar3) # define JCALL4(func, jenv, ar1, ar2, ar3, ar4) jenv->func(ar1, ar2, ar3, ar4) # define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) jenv->func(ar1, ar2, ar3, ar4, ar5, ar6, ar7) #else # define JCALL0(func, jenv) (*jenv)->func(jenv) # define JCALL1(func, jenv, ar1) (*jenv)->func(jenv, ar1) # define JCALL2(func, jenv, ar1, ar2) (*jenv)->func(jenv, ar1, ar2) # define JCALL3(func, jenv, ar1, ar2, ar3) (*jenv)->func(jenv, ar1, ar2, ar3) # define JCALL4(func, jenv, ar1, ar2, ar3, ar4) (*jenv)->func(jenv, ar1, ar2, ar3, ar4) # define JCALL7(func, jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) (*jenv)->func(jenv, ar1, ar2, ar3, ar4, ar5, ar6, ar7) #endif #endif /* Convert an svn_error_t into a SubversionException */ static jthrowable convert_error(JNIEnv *jenv, svn_error_t *error) { jthrowable cause; jthrowable exc; jstring msg; jstring file; /* Is it wise to use recursion in an error handler? */ cause = (error->child) ? convert_error(jenv, error->child) : NULL; /* ### need more error checking */ msg = JCALL1(NewStringUTF, jenv, error->message); file = error->file ? JCALL1(NewStringUTF, jenv, error->file) : NULL; exc = JCALL7(NewObject, jenv, svn_swig_java_cls_subversionexception, svn_swig_java_mid_subversionexception_init, msg, cause, (jlong) error->apr_err, file, (jlong) error->line); return exc; } /* Convert an svn_error_t into a SubversionException After conversion, the error will be cleared */ jthrowable svn_swig_java_convert_error(JNIEnv *jenv, svn_error_t *error) { jthrowable exc; exc = convert_error(jenv, error); svn_error_clear(error); return exc; } /* this baton is used for the editor, directory, and file batons. */ typedef struct { jobject editor; /* the editor handling the callbacks */ jobject baton; /* the dir/file baton (or NULL for edit baton) */ apr_pool_t *pool; /* pool to use for errors */ JNIEnv *jenv; /* Java native interface structure */ } item_baton; typedef struct { jobject handler; /* the window handler (a callable) */ apr_pool_t *pool; /* a pool for constructing errors */ JNIEnv *jenv; /* Java native interface structure */ } handler_baton; static jobject make_pointer(JNIEnv* env, void *ptr) { /* Return a Long object contining the C pointer to the object (SWIG/Java knows nothing of SWIG_NewPointerObj) */ jclass cls = JCALL1(FindClass, env, "java/lang/Long"); return JCALL3(NewObject, env, cls, JCALL3(GetMethodID, env, cls, "", "(J)V"), (jlong) ptr); } static jobject convert_hash(JNIEnv* jenv, apr_hash_t *hash, jobject (*converter_func)(JNIEnv* env, void *value, void *ctx), void *ctx) { apr_hash_index_t *hi; jclass cls = JCALL1(FindClass, jenv, "java/util/HashMap"); jobject dict = JCALL3(NewObject, jenv, cls, JCALL3(GetMethodID, jenv, cls, "", "(I)V"), (jint) apr_hash_count(hash)); jmethodID put = JCALL3(GetMethodID, jenv, cls, "put", "(Ljava/lang/Object;Ljava/lang/Object;)" "Ljava/lang/Object;"); if (dict == NULL) return NULL; for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) { const void *key; void *val; jobject value; apr_hash_this(hi, &key, NULL, &val); value = (*converter_func)(jenv, val, ctx); JCALL4(CallObjectMethod, jenv, dict, put, JCALL1(NewStringUTF, jenv, key), value); JCALL1(DeleteLocalRef, jenv, value); } return dict; } void svn_swig_java_add_to_list(JNIEnv* jenv, apr_array_header_t *array, jobject list) { /* TODO: This impl will be much like svn_swig_java_add_to_map */ } void svn_swig_java_add_to_map(JNIEnv* jenv, apr_hash_t *hash, jobject map) { apr_hash_index_t *hi; jclass cls = JCALL1(FindClass, jenv, "java/util/Map"); jmethodID put = JCALL3(GetMethodID, jenv, cls, "put", "(Ljava/lang/Object;Ljava/lang/Object;)" "Ljava/lang/Object;"); for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) { const void *key; void *val; jobject keyname, value, oldvalue; apr_hash_this(hi, &key, NULL, &val); keyname = JCALL1(NewStringUTF, jenv, key); value = make_pointer(jenv, val); oldvalue = JCALL4(CallObjectMethod, jenv, map, put, keyname, value); JCALL1(DeleteLocalRef, jenv, value); JCALL1(DeleteLocalRef, jenv, oldvalue); JCALL1(DeleteLocalRef, jenv, keyname); if (JCALL0(ExceptionOccurred, jenv)) return; } } static jobject convert_to_swigtype(JNIEnv* jenv, void *value, void *ctx) { return make_pointer(jenv, value); } static jobject convert_svn_string_t(JNIEnv* jenv, void *value, void *ctx) { const svn_string_t *s = value; /* This will copy the data */ return JCALL1(NewStringUTF, jenv, s->data); } jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash) { return convert_hash(jenv, hash, convert_svn_string_t, jenv); } jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash) { return convert_hash(jenv, hash, convert_to_swigtype, NULL); } jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings) { jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList"); jobject list = JCALL2(NewObject, jenv, cls, JCALL3(GetMethodID, jenv, cls, "", "()V")); jmethodID add = JCALL3(GetMethodID, jenv, cls, "add", "(Ljava/lang/Object;)Z"); char *s; jobject obj; while ((s = *strings++) != NULL) { obj = JCALL1(NewStringUTF, jenv, s); if (obj == NULL) goto error; JCALL3(CallBooleanMethod, jenv, list, add, obj); JCALL1(DeleteLocalRef, jenv, obj); } return list; error: JCALL1(DeleteLocalRef, jenv, list); return NULL; } jobject svn_swig_java_array_to_list(JNIEnv *jenv, const apr_array_header_t *strings) { jclass cls = JCALL1(FindClass, jenv, "java/util/ArrayList"); jobject list = JCALL3(NewObject, jenv, cls, JCALL3(GetMethodID, jenv, cls, "", "(I)V"), strings->nelts); int i; jobject obj; jmethodID add; if (strings->nelts > 0) add = JCALL3(GetMethodID, jenv, cls, "add", "(i, Ljava/lang/Object;)Z"); for (i = 0; i < strings->nelts; ++i) { const char *s; s = APR_ARRAY_IDX(strings, i, const char *); obj = JCALL1(NewStringUTF, jenv, s); if (obj == NULL) goto error; /* ### HELP: The format specifier might be 'I' instead of 'i' */ JCALL4(CallObjectMethod, jenv, list, add, i, obj); JCALL1(DeleteLocalRef, jenv, obj); } return list; error: JCALL1(DeleteLocalRef, jenv, list); return NULL; } const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv, jobject source, apr_pool_t *pool) { int targlen; apr_array_header_t *temp; jclass cls = JCALL1(FindClass, jenv, "java/util/List"); jmethodID size = JCALL3(GetMethodID, jenv, cls, "size", "()I"); jmethodID get = JCALL3(GetMethodID, jenv, cls, "get", "(I)Ljava/lang/Object;"); jclass illegalArgCls = JCALL1(FindClass, jenv, "java/lang/IllegalArgumentException"); if (!JCALL2(IsInstanceOf, jenv, source, cls)) { if (JCALL2(ThrowNew, jenv, illegalArgCls, "Not a List") != JNI_OK) return NULL; } targlen = JCALL2(CallIntMethod, jenv, source, size); temp = apr_array_make(pool, targlen, sizeof(const char *)); while (targlen--) { jobject o = JCALL3(CallObjectMethod, jenv, source, get, targlen); const char * c_string; if (o == NULL) return NULL; else if (!JCALL2(IsInstanceOf, jenv, o, JCALL1(FindClass, jenv, "java/lang/String"))) { JCALL1(DeleteLocalRef, jenv, o); if (JCALL2(ThrowNew, jenv, illegalArgCls, "Not a String") != JNI_OK) { return NULL; } } c_string = (*jenv)->GetStringUTFChars(jenv, o, 0); APR_ARRAY_IDX(temp, targlen, const char *) = apr_pstrdup(pool, c_string); (*jenv)->ReleaseStringUTFChars(jenv, o, c_string); JCALL1(DeleteLocalRef, jenv, o); } return temp; } /* Convert a Java exception into a svn_error_t. This function may only be called if there is a pending exception. */ static svn_error_t * convert_exception(JNIEnv *jenv, apr_pool_t *pool) { svn_error_t *result; apr_status_t status; char *msg; jthrowable exc; /* Fetch the exception */ exc = JCALL0(ExceptionOccurred, jenv); #ifdef SVN_DEBUG /* Print the pending exception to stderr */ JCALL0(ExceptionDescribe, jenv); #endif /* Clear the exception */ JCALL0(ExceptionClear, jenv); /* Interpret the exception: java.lang.OutOfMemoryError -> APR_ENOMEM other -> APR_EGENERAL */ /* ### Add other exceptions; use a table? */ if (JCALL2(IsInstanceOf, jenv, exc, svn_swig_java_cls_outofmemoryerror)) { status = APR_ENOMEM; msg = "JVM raised OutOfMemoryError"; } else { status = APR_EGENERAL; msg = "The Java callback raised an exception"; } result = svn_error_create(status, NULL, msg); /* Free the local reference */ JCALL1(DeleteLocalRef, jenv, exc); return result; } static item_baton * make_baton(JNIEnv *jenv, apr_pool_t *pool, jobject editor, jobject baton) { item_baton *newb = apr_palloc(pool, sizeof(*newb)); /* one more reference to the editor. */ JCALL1(NewGlobalRef, jenv, editor); JCALL1(NewGlobalRef, jenv, baton); /* note: we take the caller's reference to 'baton' */ newb->editor = JCALL1(NewGlobalRef, jenv, editor); newb->baton = baton; newb->pool = pool; newb->jenv = jenv; return newb; } static svn_error_t * close_baton(void *baton, const char *method) { item_baton *ib = baton; jobject result; JNIEnv *jenv = ib->jenv; jclass cls = JCALL1(GetObjectClass, jenv, ib->editor); jmethodID methodID; /* If there is no baton object, then it is an edit_baton, and we should not bother to pass an object. Note that we still shove a NULL onto the stack, but the format specified just won't reference it. */ if (ib->baton) { methodID = JCALL3(GetMethodID, jenv, cls, method, "(Ljava/lang/Object;)Ljava/lang/Object;"); result = JCALL3(CallObjectMethod, jenv, ib->editor, methodID, ib->baton); } else { methodID = JCALL3(GetMethodID, jenv, cls, method, "()Ljava/lang/Object;"); result = JCALL2(CallObjectMethod, jenv, ib->editor, methodID); } if (result == NULL) return convert_exception(ib->jenv, ib->pool); /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); /* We're now done with the baton. Since there isn't really a free, all we need to do is note that its objects are no longer referenced by the baton. */ JCALL1(DeleteGlobalRef, ib->jenv, ib->editor); JCALL1(DeleteGlobalRef, ib->jenv, ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif return SVN_NO_ERROR; } static svn_error_t * close_baton_checksum(void *baton, const char *text_checksum, const char *method) { item_baton *ib = baton; jobject result; JNIEnv *jenv = ib->jenv; jclass cls = JCALL1(GetObjectClass, jenv, ib->editor); jmethodID methodID; methodID = JCALL3(GetMethodID, jenv, cls, method, "(Ljava/lang/Object;)Ljava/lang/Object;"); result = JCALL4(CallObjectMethod, jenv, ib->editor, methodID, ib->baton, text_checksum); if (result == NULL) return convert_exception(ib->jenv, ib->pool); /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); /* We're now done with the baton. Since there isn't really a free, all we need to do is note that its objects are no longer referenced by the baton. */ JCALL1(DeleteGlobalRef, ib->jenv, ib->editor); JCALL1(DeleteGlobalRef, ib->jenv, ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif return SVN_NO_ERROR; } static svn_error_t * thunk_set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool) { item_baton *ib = edit_baton; jobject result; jclass cls; /*= JCALL(FindClass, ib->jenv, "FIXME");*/ /* FIXME: Signature wants svn_revnum type instead of java.lang.Object */ jmethodID methodID = JCALL3(GetMethodID, ib->jenv, cls, "set_target_revision", "(Ljava/lang/Object;)"); /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"set_target_revision", (char *)"l", target_revision)) == NULL) { return convert_exception(ib->jenv, pool); } */ /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); return SVN_NO_ERROR; } static svn_error_t * thunk_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **root_baton) { item_baton *ib = edit_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root", (char *)"lO&", base_revision, make_ob_pool, dir_pool)) == NULL) { return convert_exception(ib->jenv, dir_pool); } */ /* make_baton takes our 'result' reference */ *root_baton = make_baton(ib->jenv, dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_delete_entry(const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *pool) { item_baton *ib = parent_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry", (char *)"slOO&", path, revision, ib->baton, make_ob_pool, pool)) == NULL) { return convert_exception(ib->jenv, pool); } */ /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); return SVN_NO_ERROR; } static svn_error_t * thunk_add_directory(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory", (char *)"sOslO&", path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, dir_pool)) == NULL) { return convert_exception(ib->jenv, dir_pool); } */ /* make_baton takes our 'result' reference */ *child_baton = make_baton(ib->jenv, dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory", (char *)"sOlO&", path, ib->baton, base_revision, make_ob_pool, dir_pool)) == NULL) { return convert_exception(ib->jenv, dir_pool); } */ /* make_baton takes our 'result' reference */ *child_baton = make_baton(ib->jenv, dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_change_dir_prop(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = dir_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop", (char *)"Oss#O&", ib->baton, name, value->data, value->len, make_ob_pool, pool)) == NULL) { return convert_exception(ib->jenv, pool); } */ /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); return SVN_NO_ERROR; } static svn_error_t * thunk_close_directory(void *dir_baton, apr_pool_t *pool) { return close_baton(dir_baton, "close_directory"); } static svn_error_t * thunk_add_file(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file", (char *)"sOslO&", path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, file_pool)) == NULL) { return convert_exception(ib->jenv, file_pool); } */ /* make_baton takes our 'result' reference */ *file_baton = make_baton(ib->jenv, file_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_open_file(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file", (char *)"sOlO&", path, ib->baton, base_revision, make_ob_pool, file_pool)) == NULL) { return convert_exception(ib->jenv, file_pool); } */ /* make_baton takes our 'result' reference */ *file_baton = make_baton(ib->jenv, file_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window, void *baton) { handler_baton *hb = baton; jobject result; if (window == NULL) { /* the last call; it closes the handler */ /* invoke the handler with None for the window */ /* ### python doesn't have 'const' on the format */ /* FIXME: To JNI result = PyObject_CallFunction(hb->handler, (char *)"O", Py_None); */ /* we no longer need to refer to the handler object */ JCALL1(DeleteGlobalRef, hb->jenv, hb->handler); } else { /* invoke the handler with the window */ /* FIXME: Translate to JNI result = PyObject_CallFunction(hb->handler, (char *)"O&", make_ob_window, window); */ } if (result == NULL) return convert_exception(hb->jenv, hb->pool); /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, hb->jenv, result); return SVN_NO_ERROR; } static svn_error_t * thunk_apply_textdelta( void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **h_baton) { item_baton *ib = file_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta", (char *)"O", ib->baton)) == NULL) { return convert_exception(ib->jenv, pool); } */ /* FIXME: To JNI if (result == Py_None) { JCALL1(DeleteGlobalRef, ib->jenv, result); *handler = NULL; *h_baton = NULL; } else */ { handler_baton *hb = apr_palloc(ib->pool, sizeof(*hb)); /* return the thunk for invoking the handler. the baton takes our 'result' reference. */ hb->handler = result; hb->pool = ib->pool; hb->jenv = ib->jenv; *handler = thunk_window_handler; *h_baton = hb; } return SVN_NO_ERROR; } static svn_error_t * thunk_change_file_prop(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = file_baton; jobject result; /* FIXME: Translate to JNI if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop", (char *)"Oss#O&", ib->baton, name, value->data, value->len, make_ob_pool, pool)) == NULL) { return convert_exception(ib->jenv, pool); } */ /* there is no return value, so just toss this object */ JCALL1(DeleteGlobalRef, ib->jenv, result); return SVN_NO_ERROR; } static svn_error_t * thunk_close_file(void *file_baton, const char *text_checksum, apr_pool_t *pool) { return close_baton_checksum(file_baton, text_checksum, "close_file"); } static svn_error_t * thunk_close_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "close_edit"); } static svn_error_t * thunk_abort_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "abort_edit"); } void svn_swig_java_make_editor(JNIEnv *jenv, const svn_delta_editor_t **editor, void **edit_baton, jobject java_editor, apr_pool_t *pool) { svn_delta_editor_t *thunk_editor = svn_delta_default_editor (pool); thunk_editor->set_target_revision = thunk_set_target_revision; thunk_editor->open_root = thunk_open_root; thunk_editor->delete_entry = thunk_delete_entry; thunk_editor->add_directory = thunk_add_directory; thunk_editor->open_directory = thunk_open_directory; thunk_editor->change_dir_prop = thunk_change_dir_prop; thunk_editor->close_directory = thunk_close_directory; thunk_editor->add_file = thunk_add_file; thunk_editor->open_file = thunk_open_file; thunk_editor->apply_textdelta = thunk_apply_textdelta; thunk_editor->change_file_prop = thunk_change_file_prop; thunk_editor->close_file = thunk_close_file; thunk_editor->close_edit = thunk_close_edit; thunk_editor->abort_edit = thunk_abort_edit; *editor = thunk_editor; *edit_baton = make_baton(jenv, pool, java_editor, NULL); } /* This baton type is used for client prompt operations */ typedef struct { jobject callback; /* Object to call back */ apr_pool_t *pool; /* pool to use for errors */ JNIEnv *jenv; /* Java native interface structure */ } callback_baton_t; /* Pool cleanup handler. Removes global reference */ static apr_status_t callback_baton_cleanup_handler(void *baton) { callback_baton_t *callback_baton = (callback_baton_t *) baton; JCALL1(DeleteGlobalRef, callback_baton->jenv, callback_baton->callback); return APR_SUCCESS; } /* Create a callback baton */ void *svn_swig_java_make_callback_baton(JNIEnv *jenv, jobject callback, apr_pool_t *pool) { jobject globalref; callback_baton_t *callback_baton; globalref = JCALL1(NewGlobalRef, jenv, callback); if (globalref == NULL) { /* Exception occurred */ return 0; } callback_baton = apr_palloc(pool, sizeof(*callback_baton)); callback_baton->callback = globalref; callback_baton->pool = pool; callback_baton->jenv = jenv; apr_pool_cleanup_register(pool, callback_baton, callback_baton_cleanup_handler, apr_pool_cleanup_null); return callback_baton; } /* a notify function that executes a Java method on an object which is passed in via the baton argument */ void svn_swig_java_notify_func(void *baton, const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision) { /* TODO: svn_swig_java_notify_func is not implemented yet */ } /* a cancel function that executes a Java method on an object which is passed in via the cancel_baton argument */ svn_error_t *svn_swig_java_cancel_func(void *cancel_baton) { /* TODO: svn_swig_java_cancel_func is not implemented yet */ return SVN_NO_ERROR; } /* thunked commit log fetcher */ svn_error_t *svn_swig_java_get_commit_log_func (const char **log_msg, const char **tmp_file, apr_array_header_t *commit_items, void *baton, apr_pool_t *pool) { return svn_error_create(APR_EGENERAL, NULL, "TODO: " "svn_swig_java_get_commit_log_func is not " "implemented yet"); } /* log messages are returned in this */ svn_error_t *svn_swig_java_log_message_receiver(void *baton, apr_hash_t *changed_paths, svn_revnum_t revision, const char *author, const char *date, /* use svn_time_from_string() if need apr_time_t */ const char *message, apr_pool_t *pool) { return svn_error_create(APR_EGENERAL, NULL, "TODO: svn_swig_java_get_commit_log_func is not implemented yet"); } /* Prompt for username */ svn_error_t *svn_swig_java_client_prompt_func(const char **info, const char *prompt, svn_boolean_t hide, void *baton, apr_pool_t *pool) { callback_baton_t *callback_baton; JNIEnv *jenv; jobject callback; jstring jprompt; jstring jresult; jboolean jhide; const char *c_str; svn_error_t *result; callback_baton = (callback_baton_t *) baton; jenv = callback_baton->jenv; callback = callback_baton->callback; /* Create a new local reference frame. Exit immediately if functions fails. */ if (JCALL1(PushLocalFrame, jenv, 2) < 0) { return convert_exception(jenv, callback_baton->pool); } jprompt = JCALL1(NewStringUTF, jenv, prompt); if (!jprompt) { goto error; } jhide = hide ? JNI_TRUE : JNI_FALSE; jresult = JCALL4(CallObjectMethod, jenv, callback, svn_swig_java_mid_clientprompt_prompt, jprompt, jhide); if (!jresult) { goto error; } c_str = JCALL2(GetStringUTFChars, jenv, jresult, NULL); if (!c_str) { goto error; } *info = apr_pstrdup(pool, c_str); JCALL2(ReleaseStringUTFChars, jenv, jresult, c_str); JCALL1(PopLocalFrame, jenv, NULL); return SVN_NO_ERROR; error: result = convert_exception(jenv, callback_baton->pool); JCALL1(PopLocalFrame, jenv, NULL); return result; } /* This baton type is used for stream operations */ typedef struct { jobject stream; /* Java stream object */ apr_pool_t *pool; /* pool to use for errors */ JNIEnv *jenv; /* Java native interface structure */ } stream_baton_t; /* Create a stream baton. */ static stream_baton_t *make_stream_baton(JNIEnv *jenv, jobject stream, apr_pool_t *pool) { jobject globalref; stream_baton_t *stream_baton; /* The global reference is not necessary in all cases e.g. for a call to svn_client_cat() But we need it for svn_text_delta_t */ globalref = JCALL1(NewGlobalRef, jenv, stream); if (globalref == NULL) { /* Exception occurred */ return 0; } stream_baton = apr_palloc(pool, sizeof(*stream_baton)); stream_baton->stream = globalref; stream_baton->pool = pool; stream_baton->jenv = jenv; return stream_baton; } /* Pool cleanup handler. Removes global reference */ static apr_status_t stream_baton_cleanup_handler(void *baton) { stream_baton_t *stream_baton = (stream_baton_t *) baton; JCALL1(DeleteGlobalRef, stream_baton->jenv, stream_baton->stream); return APR_SUCCESS; } /* read/write/close functions for an OutputStream */ /* Read function for the OutputStream :-) Since this is a write only stream we simply generate an error. */ static svn_error_t *read_outputstream(void *baton, char *buffer, apr_size_t *len) { svn_error_t *svn_error = svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, "Can't read from write only stream"); return svn_error; } /* Writes to the OutputStream */ static svn_error_t *write_outputstream(void *baton, const char *buffer, apr_size_t *len) { stream_baton_t *stream_baton; JNIEnv *jenv; jthrowable exc; jbyteArray bytearray; svn_error_t *result; stream_baton = (stream_baton_t *) baton; jenv = stream_baton->jenv; bytearray = JCALL1(NewByteArray, jenv, (jsize) *len); if (bytearray == NULL) { goto outofmemory_error; } JCALL4(SetByteArrayRegion, jenv, bytearray, (jsize) 0, (jsize) *len, (jbyte *) buffer); exc = JCALL0(ExceptionOccurred, jenv); if (exc) { goto error; } JCALL3(CallVoidMethod, jenv, stream_baton->stream, svn_swig_java_mid_outputstream_write, bytearray); exc = JCALL0(ExceptionOccurred, jenv); if (exc) { goto error; } JCALL1(DeleteLocalRef, jenv, bytearray); return SVN_NO_ERROR; outofmemory_error: /* We now for sure that there is an exception pending */ exc = JCALL0(ExceptionOccurred, jenv); error: /* ### Better exception handling At this point, we now that there is exception exc pending. These are: - OutOfMemoryError (NewByteArray) - ArrayIndexOutOfBounds (SetByteArrayRegion) - IOException (CallVoidMethod[write]) At least, the OutOfMemory error should get a special treatment... */ /* DEBUG JCALL0(ExceptionDescribe, jenv); */ JCALL0(ExceptionClear, jenv); result = svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, "Write error on stream"); JCALL1(DeleteLocalRef, jenv, exc); return result; } /* Closes the OutputStream Does nothing because we are not the owner of the stream. May flush the stream in future. */ static svn_error_t *close_outputstream(void *baton) { return SVN_NO_ERROR; } /* read/write/close functions for an InputStream */ /* Reads from the InputStream */ static svn_error_t *read_inputstream(void *baton, char *buffer, apr_size_t *len) { stream_baton_t *stream_baton; JNIEnv *jenv; jthrowable exc; jbyteArray bytearray; jsize read_len; svn_error_t *result; stream_baton = (stream_baton_t *) baton; jenv = stream_baton->jenv; bytearray = JCALL1(NewByteArray, jenv, (jsize) *len); if (bytearray == NULL) { goto outofmemory_error; } read_len = JCALL3(CallIntMethod, jenv, stream_baton->stream, svn_swig_java_mid_inputstream_read, bytearray); exc = JCALL0(ExceptionOccurred, jenv); if (exc) { goto error; } if (read_len > 0) { JCALL4(GetByteArrayRegion, jenv, bytearray, (jsize) 0, (jsize) read_len, (jbyte *) buffer); exc = JCALL0(ExceptionOccurred, jenv); if (exc) { goto error; } } else { read_len = 0; /* -1 is EOF, svn_stream_t wants 0 */ } JCALL1(DeleteLocalRef, jenv, bytearray); *len = read_len; return SVN_NO_ERROR; outofmemory_error: /* We now for sure that there is an exception pending */ exc = JCALL0(ExceptionOccurred, jenv); error: /* ### Better exception handling At this point, we now that there is exception exc pending. These are: - OutOfMemoryError (NewByteArray) - ArrayIndexOutOfBounds (SetByteArrayRegion) - IOException (CallIntMethod[read]) At least, the OutOfMemory error should get a special treatment... */ /* DEBUG JCALL0(ExceptionDescribe, jenv); */ JCALL0(ExceptionClear, jenv); result = svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, "Write error on stream"); JCALL1(DeleteLocalRef, jenv, exc); return result; } /* Write function for the InputStream :-) Since this is a read only stream we simply generate an error. */ static svn_error_t *write_inputstream(void *baton, const char *buffer, apr_size_t *len) { svn_error_t *svn_error = svn_error_create(SVN_ERR_STREAM_UNEXPECTED_EOF, NULL, "Can't write on read only stream"); return svn_error; } /* Closes the InputStream Does nothing because we are not the owner of the stream. */ static svn_error_t *close_inputstream(void *baton) { return SVN_NO_ERROR; } /* Create a svn_stream_t from a java.io.OutputStream object. Registers a pool cleanup handler for deallocating JVM resources. */ svn_stream_t *svn_swig_java_outputstream_to_stream(JNIEnv *jenv, jobject outputstream, apr_pool_t *pool) { stream_baton_t *baton; svn_stream_t *stream; baton = make_stream_baton(jenv, outputstream, pool); if (baton == NULL) { return NULL; } apr_pool_cleanup_register(pool, baton, stream_baton_cleanup_handler, apr_pool_cleanup_null); stream = svn_stream_create(baton, pool); if (stream == NULL) { return NULL; } svn_stream_set_read(stream, read_outputstream); svn_stream_set_write(stream, write_outputstream); svn_stream_set_close(stream, close_outputstream); return stream; } /* Create a svn_stream_t from a java.io.InputStream object. Registers a pool cleanup handler for deallocating JVM resources. */ svn_stream_t *svn_swig_java_inputstream_to_stream(JNIEnv *jenv, jobject inputstream, apr_pool_t *pool) { stream_baton_t *baton; svn_stream_t *stream; baton = make_stream_baton(jenv, inputstream, pool); if (baton == NULL) { return NULL; } apr_pool_cleanup_register(pool, baton, stream_baton_cleanup_handler, apr_pool_cleanup_null); stream = svn_stream_create(baton, pool); if (stream == NULL) { return NULL; } svn_stream_set_read(stream, read_inputstream); svn_stream_set_write(stream, write_inputstream); svn_stream_set_close(stream, close_inputstream); return stream; } JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *jvm, void *reserved) { JNIEnv *jenv; if ((*jvm)->GetEnv(jvm, (void **) &jenv, JNI_VERSION_1_2)) { return JNI_ERR; } #define SVN_SWIG_JAVA_INIT_CACHE #include "swigutil_java_cache.h" return JNI_VERSION_1_2; } JNIEXPORT void JNICALL JNI_OnUnload(JavaVM *jvm, void *reserved) { JNIEnv *jenv; if ((*jvm)->GetEnv(jvm, (void **) &jenv, JNI_VERSION_1_2)) { return; } #define SVN_SWIG_JAVA_TERM_CACHE #include "swigutil_java_cache.h" } Node-path: svnperl/swigutil_java.h Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 5813 Text-content-md5: e2a626417957c43e30d9b9332cedd4ff Content-length: 5823 PROPS-END /* * swigutil_java.h : utility functions and stuff for the SWIG Java bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #ifndef SVN_SWIG_SWIGUTIL_JAVA_H #define SVN_SWIG_SWIGUTIL_JAVA_H #include #include #include #include #include #include #include "svn_types.h" #include "svn_string.h" #include "svn_delta.h" #include "svn_wc.h" #include "swigutil_java_cache.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* convert an svn_error_t into a SubversionException and clear error */ jthrowable svn_swig_java_convert_error(JNIEnv *jenv, svn_error_t *error); /* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to a Java Map */ jobject svn_swig_java_prophash_to_dict(JNIEnv *jenv, apr_hash_t *hash); /* convert a hash of 'const char *' -> TYPE into a Java Map */ jobject svn_swig_java_convert_hash(JNIEnv *jenv, apr_hash_t *hash); /* add all the elements from an array to an existing java.util.List */ void svn_swig_java_add_to_list(JNIEnv* jenv, apr_array_header_t *array, jobject list); /* add all the elements from a hash to an existing java.util.Map */ void svn_swig_java_add_to_map(JNIEnv* jenv, apr_hash_t *hash, jobject map); /* helper function to convert a 'char **' into a Java List of String objects */ jobject svn_swig_java_c_strings_to_list(JNIEnv *jenv, char **strings); /* helper function to convert an array of 'const char *' to a Java List of String objects */ jobject svn_swig_java_array_to_list(JNIEnv *jenv, const apr_array_header_t *strings); /* helper function to convert a Java List of String objects into an 'apr_array_header_t *' of 'const char *' objects. Note that the objects must remain alive -- the values are not copied. This is appropriate for incoming arguments which are defined to last the duration of the function's execution. */ const apr_array_header_t *svn_swig_java_strings_to_array(JNIEnv *jenv, jobject source, apr_pool_t *pool); /* make an editor that "thunks" from C callbacks up to Java */ void svn_swig_java_make_editor(JNIEnv *jenv, const svn_delta_editor_t **editor, void **edit_baton, jobject java_editor, apr_pool_t *pool); /* a notify function that executes a Java method on an object which is passed in via the baton argument */ void svn_swig_java_notify_func(void *baton, const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision); /* a cancel function that executes a Java method on an object passed in via the cancel_baton argument. */ svn_error_t *svn_swig_java_cancel_func(void *cancel_baton); /* thunked commit log fetcher */ svn_error_t *svn_swig_java_get_commit_log_func(const char **log_msg, const char **tmp_file, apr_array_header_t *commit_items, void *baton, apr_pool_t *pool); /* log messages are returned in this */ svn_error_t *svn_swig_java_log_message_receiver(void *baton, apr_hash_t *changed_paths, svn_revnum_t revision, const char *author, const char *date, /* use svn_time_from_string() if need apr_time_t */ const char *message, apr_pool_t *pool); /* Create a callback baton */ void *svn_swig_java_make_callback_baton(JNIEnv *jenv, jobject callback, apr_pool_t *pool); /* Prompt for username */ svn_error_t *svn_swig_java_client_prompt_func(const char **info, const char *prompt, svn_boolean_t hide, void *baton, apr_pool_t *pool); /* Create write-only svn_stream_t from java.io.OutputStream */ svn_stream_t *svn_swig_java_outputstream_to_stream(JNIEnv *jenv, jobject outputstream, apr_pool_t *pool); /* Create read-only svn_stream_t from java.io.InputStream */ svn_stream_t *svn_swig_java_inputstream_to_stream(JNIEnv *jenv, jobject inputstream, apr_pool_t *pool); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* SVN_SWIG_SWIGUTIL_JAVA_H */ Node-path: svnperl/swigutil_java_cache.h Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 4700 Text-content-md5: 1bb11a0e7bcd9b3ef852ee5258890922 Content-length: 4710 PROPS-END /** * @copyright * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== * @endcopyright * * @file swigutil_java_cache.h * @brief Caching of Java class references and method IDs. */ #if defined(SVN_SWIG_JAVA_DEFINE_CACHE) || defined(SVN_SWIG_JAVA_INIT_CACHE) || defined(SVN_SWIG_JAVA_TERM_CACHE) || !defined(SVN_SWIG_JAVACACHE_INCLUDED) #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* Define methodID/class references */ #if defined(SVN_SWIG_JAVA_DEFINE_CACHE) #define SVN_SWIG_JAVA_CACHE_START #define SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,name,clazz,method,signature) \ jmethodID name; #define SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,name,clazzname) \ jclass name; #define SVN_SWIG_JAVA_CACHE_END /* Initialize methodID/class references */ #elif defined(SVN_SWIG_JAVA_INIT_CACHE) #define SVN_SWIG_JAVA_CACHE_START \ { jclass _clazz; #define SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,name,clazz,method,signature) \ name = JCALL3(GetMethodID, jenv, clazz, method, signature); \ if (name == NULL) { return JNI_ERR; } #define SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,name,clazzname) \ _clazz = JCALL1(FindClass, jenv, clazzname); \ if (_clazz == NULL) { return JNI_ERR; } \ name = JCALL1(NewGlobalRef, jenv, _clazz); \ if (name == NULL) { return JNI_ERR; } #define SVN_SWIG_JAVA_CACHE_END \ } /* Clear methodID/class references */ #elif defined(SVN_SWIG_JAVA_TERM_CACHE) #define SVN_SWIG_JAVA_CACHE_START #define SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,name,clazz,method,signature) #define SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,name,clazzname) \ JCALL1(DeleteGlobalRef, jenv, name); #define SVN_SWIG_JAVA_CACHE_END /* Simple declaration */ #elif !defined(SVN_SWIG_JAVACACHE_INCLUDED) #define SVN_SWIG_JAVACACHE_INCLUDED #define SVN_SWIG_JAVA_CACHE_START #define SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,name,clazz,method,signature) \ extern jmethodID name; #define SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,name,clazzname) \ extern jclass name; #define SVN_SWIG_JAVA_CACHE_END #endif SVN_SWIG_JAVA_CACHE_START SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_long,"java/lang/Long") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_string,"java/lang/String") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_outofmemoryerror,"java/lang/OutOfMemoryError") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_outputstream,"java/io/OutputStream") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_inputstream,"java/io/InputStream") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_list,"java/util/ArrayList") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_list,"java/util/List") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_list,"java/util/Map") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_subversionexception,"org/tigris/subversion/SubversionException") SVN_SWIG_JAVA_CACHE_CLASS_DEF(jenv,svn_swig_java_cls_clientprompt,"org/tigris/subversion/client/ClientPrompt") SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,svn_swig_java_mid_long_longvalue,svn_swig_java_cls_long,"longValue","()J") SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,svn_swig_java_mid_outputstream_write,svn_swig_java_cls_outputstream,"write","([B)V") SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,svn_swig_java_mid_inputstream_read,svn_swig_java_cls_inputstream,"read","([B)I") SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,svn_swig_java_mid_subversionexception_init,svn_swig_java_cls_subversionexception,"","(Ljava/lang/String;Ljava/lang/Throwable;JLjava/lang/String;J)V") SVN_SWIG_JAVA_CACHE_METHOD_DEF(jenv,svn_swig_java_mid_clientprompt_prompt,svn_swig_java_cls_clientprompt,"prompt","(Ljava/lang/String;Z)Ljava/lang/String;") SVN_SWIG_JAVA_CACHE_END #undef SVN_SWIG_JAVA_CACHE_START #undef SVN_SWIG_JAVA_CACHE_CLASS_DEF #undef SVN_SWIG_JAVA_CACHE_METHOD_DEF #undef SVN_SWIG_JAVA_CACHE_END #undef SVN_SWIG_JAVA_DEFINE_CACHE #undef SVN_SWIG_JAVA_INIT_CACHE #undef SVN_SWIG_JAVA_TERM_CACHE #ifdef __cplusplus } #endif /* __cplusplus */ #endif Node-path: svnperl/swigutil_pl.c Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 33243 Text-content-md5: 7f9788620af1b6fba78988b8963f2c79 Content-length: 33253 PROPS-END /* * swigutil_py.c: utility functions for the SWIG Perl bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #include #include #include #include #include #include #include #include "svn_pools.h" #include "svn_opt.h" #include "swigutil_pl.h" /* element convertors for perl -> c */ typedef void *(*pl_element_converter_t)(SV *value, void *ctx, apr_pool_t *pool); static void *convert_pl_string (SV *value, void *dummy, apr_pool_t *pool) { void **result = apr_palloc(pool, sizeof(void *)); *result = SvPV_nolen (value); return *result; } static void *convert_pl_obj (SV *value, swig_type_info *tinfo, apr_pool_t *pool) { void **result = apr_palloc(pool, sizeof(void *)); if (SWIG_ConvertPtr(value, result, tinfo, 0) < 0) { croak("unable to convert from swig object"); } return *result; } /* perl -> c hash convertors */ static apr_hash_t *svn_swig_pl_to_hash(SV *source, pl_element_converter_t cv, void *ctx, apr_pool_t *pool) { apr_hash_t *hash; HV *h; char *key; I32 cnt, retlen; if (!(source && SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVHV)) { return NULL; } hash = apr_hash_make (pool); h = (HV *)SvRV(source); cnt = hv_iterinit(h); while (cnt--) { SV* item = hv_iternextsv(h, &key, &retlen); void *val = cv (item, ctx, pool); apr_hash_set (hash, key, APR_HASH_KEY_STRING, val); } return hash; } apr_hash_t *svn_swig_pl_objs_to_hash(SV *source, swig_type_info *tinfo, apr_pool_t *pool) { return svn_swig_pl_to_hash(source, (pl_element_converter_t)convert_pl_obj, tinfo, pool); } apr_hash_t *svn_swig_pl_strings_to_hash(SV *source, apr_pool_t *pool) { return svn_swig_pl_to_hash(source, convert_pl_string, NULL, pool); } apr_hash_t *svn_swig_pl_objs_to_hash_by_name(SV *source, const char *typename, apr_pool_t *pool) { swig_type_info *tinfo = SWIG_TypeQuery(typename); return svn_swig_pl_objs_to_hash (source, tinfo, pool); } /* perl -> c array convertors */ static const apr_array_header_t *svn_swig_pl_to_array (SV *source, pl_element_converter_t cv, void *ctx, apr_pool_t *pool) { int targlen; apr_array_header_t *temp; AV* array; if (!(source && SvROK(source) && SvTYPE(SvRV(source)) == SVt_PVAV)) { /* raise exception here */ return NULL; } array = (AV *)SvRV (source); targlen = av_len (array) + 1; temp = apr_array_make (pool, targlen, sizeof(const char *)); temp->nelts = targlen; while (targlen--) { /* more error handling here */ SV **item = av_fetch (array, targlen, 0); APR_ARRAY_IDX(temp, targlen, const char *) = cv (*item, ctx, pool); } return temp; } const apr_array_header_t *svn_swig_pl_strings_to_array(SV *source, apr_pool_t *pool) { return svn_swig_pl_to_array (source, convert_pl_string, NULL, pool); } const apr_array_header_t *svn_swig_pl_objs_to_array(SV *source, swig_type_info *tinfo, apr_pool_t *pool) { return svn_swig_pl_to_array (source, (pl_element_converter_t)convert_pl_obj, tinfo, pool); } /* element convertors for c -> perl */ typedef SV *(*element_converter_t)(void *value, void *ctx); static SV *convert_string (const char *value, void *dummy) { SV *obj = sv_2mortal(newSVpv(value, 0)); return obj; } static SV *convert_svn_string_t (svn_string_t *value, void *dummy) { SV *obj = sv_2mortal(newSVpv(value->data, value->len)); return obj; } static SV *convert_to_swig_type (void *ptr, swig_type_info *tinfo) { SV *obj = sv_newmortal(); SWIG_MakePtr(obj, ptr, tinfo, 0); return obj; } static SV *convert_int(int value, void *dummy) { return newSViv (value); } /* c -> perl hash convertors */ static SV *convert_hash (apr_hash_t *hash, element_converter_t converter_func, void *ctx) { apr_hash_index_t *hi; HV *hv; hv = newHV(); for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) { const char *key; void *val; int klen; SV *obj; apr_hash_this(hi, (void *)&key, NULL, &val); klen = strlen(key); obj = converter_func (val, ctx); hv_store(hv, (const char *)key, klen, obj, 0); SvREFCNT_inc(obj); } return newRV_inc((SV*)hv); } SV *svn_swig_pl_prophash_to_hash (apr_hash_t *hash) { return convert_hash (hash, (element_converter_t)convert_svn_string_t, NULL); } SV *svn_swig_pl_convert_hash (apr_hash_t *hash, swig_type_info *tinfo) { return convert_hash (hash, (element_converter_t)convert_to_swig_type, tinfo); } /* c -> perl array convertors */ static SV *convert_array(const apr_array_header_t *array, element_converter_t converter_func, void *ctx) { AV *list = newAV(); int i; for (i = 0; i < array->nelts; ++i) { void *element = APR_ARRAY_IDX(array, i, void *); SV *item = converter_func (element, ctx); av_push (list, item); SvREFCNT_inc (item); } return newRV_inc((SV*)list); } SV *svn_swig_pl_array_to_list(const apr_array_header_t *array) { return convert_array (array, (element_converter_t)convert_string, NULL); } SV *svn_swig_pl_ints_to_list(const apr_array_header_t *array) { return convert_array (array, (element_converter_t)convert_int, NULL); } typedef enum perl_func_invoker { CALL_METHOD, CALL_SV } perl_func_invoker_t; /* put the va_arg in stack and invoke caller_func with func. fmt: * O: perl object * i: integer * s: string * S: swigtype put returned value in result if result is not NULL */ static svn_error_t *perl_callback_thunk (perl_func_invoker_t caller_func, void *func, SV **result, const char *fmt, ...) { const char *fp = fmt; va_list ap; int count; dSP ; ENTER ; SAVETMPS ; PUSHMARK(SP) ; va_start(ap, fmt); while (*fp) { char *c; void *o; SV *obj; swig_type_info *t; switch (*fp++) { case 'O': XPUSHs (va_arg (ap, SV *)); break; case 'S': /* swig object */ o = va_arg (ap, void *); t = va_arg (ap, swig_type_info *); obj = sv_newmortal (); SWIG_MakePtr (obj, o, t, 0); XPUSHs(obj); break; case 's': /* string */ c = va_arg (ap, char *); XPUSHs(c ? sv_2mortal(newSVpv(c, 0)) : &PL_sv_undef); break; case 'i': /* integer */ XPUSHs(sv_2mortal(newSViv(va_arg(ap, int)))); break; } } va_end (ap); PUTBACK; switch (caller_func) { case CALL_SV: count = call_sv (func, G_SCALAR); break; case CALL_METHOD: count = call_method (func, G_SCALAR); break; default: croak ("unkonwn calling type"); break; } SPAGAIN ; if (count != 1) croak("Big trouble\n") ; if (result) { *result = POPs; SvREFCNT_inc(*result); } FREETMPS ; LEAVE ; return SVN_NO_ERROR; } /*** Editor Wrapping ***/ /* this could be more perlish */ typedef struct { SV *editor; /* the editor handling the callbacks */ SV *baton; /* the dir/file baton (or NULL for edit baton) */ } item_baton; static item_baton * make_baton(apr_pool_t *pool, SV *editor, SV *baton) { item_baton *newb = apr_palloc(pool, sizeof(*newb)); SvREFCNT_inc(editor); newb->editor = editor; newb->baton = baton; return newb; } static svn_error_t * close_baton(void *baton, const char *method) { item_baton *ib = baton; dSP ; ENTER ; SAVETMPS ; PUSHMARK(SP) ; XPUSHs(ib->editor); if (ib->baton) XPUSHs(ib->baton); PUTBACK; call_method(method, G_DISCARD); /* check result? */ SvREFCNT_dec(ib->editor); if (ib->baton) SvREFCNT_dec(ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif FREETMPS ; LEAVE ; return SVN_NO_ERROR; } static svn_error_t * thunk_set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool) { item_baton *ib = edit_baton; SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"set_target_revision", NULL, "Oi", ib->editor, target_revision)); return SVN_NO_ERROR; } static svn_error_t * thunk_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **root_baton) { item_baton *ib = edit_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SV *result; SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"open_root", &result, "OiS", ib->editor, base_revision, dir_pool, poolinfo)); *root_baton = make_baton(dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_delete_entry(const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *pool) { item_baton *ib = parent_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"delete_entry", NULL, "OsiOS", ib->editor, path, revision, ib->baton, pool, poolinfo)); return SVN_NO_ERROR; } static svn_error_t * thunk_add_directory(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SV *result; SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"add_directory", &result, "OsOsiS", ib->editor, path, ib->baton, copyfrom_path, copyfrom_revision, dir_pool, poolinfo)); *child_baton = make_baton(dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; SV *result; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"open_directory", &result, "OsOiS", ib->editor, path, ib->baton, base_revision, dir_pool, poolinfo)); *child_baton = make_baton(dir_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_change_dir_prop(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = dir_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"change_dir_prop", NULL, "OOssS", ib->editor, ib->baton, name, value ? value->data : NULL, pool, poolinfo)); return SVN_NO_ERROR; } static svn_error_t * thunk_close_directory(void *dir_baton, apr_pool_t *pool) { return close_baton(dir_baton, "close_directory"); } static svn_error_t * thunk_absent_directory(const char *path, void *parent_baton, apr_pool_t *pool) { item_baton *ib = parent_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"absent_directory", NULL, "OsOS", ib->editor, path, ib->baton, pool, poolinfo)); return SVN_NO_ERROR; } static svn_error_t * thunk_add_file(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; SV *result; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"add_file", &result, "OsOsiS", ib->editor, path, ib->baton, copyfrom_path, copyfrom_revision, file_pool, poolinfo)); *file_baton = make_baton(file_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_open_file(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SV *result; SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"open_file", &result, "OsOiS", ib->editor, path, ib->baton, base_revision, file_pool, poolinfo)); *file_baton = make_baton(file_pool, ib->editor, result); return SVN_NO_ERROR; } static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window, void *baton) { SV *handler = baton; if (window == NULL) { SVN_ERR (perl_callback_thunk (CALL_SV, handler, NULL, "O", &PL_sv_undef)); } else { swig_type_info *tinfo = SWIG_TypeQuery("svn_txdelta_window_t *"); SVN_ERR (perl_callback_thunk (CALL_SV, handler, NULL, "S", window, tinfo)); } return SVN_NO_ERROR; } static svn_error_t * thunk_apply_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **h_baton) { item_baton *ib = file_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SV *result; SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"apply_textdelta", &result, "OOsS", ib->editor, ib->baton, base_checksum, pool, poolinfo)); if (SvOK(result)) { if (SvROK(result) && SvTYPE(SvRV(result)) == SVt_PVAV) { swig_type_info *handler_info = SWIG_TypeQuery("svn_txdelta_window_handler_t"), *void_info = SWIG_TypeQuery("void *"); AV *array = (AV *)SvRV(result); if (SWIG_ConvertPtr(*av_fetch (array, 0, 0), (void **)handler, handler_info,0) < 0) { croak("FOO!"); } if (SWIG_ConvertPtr(*av_fetch (array, 1, 0), h_baton, void_info,0) < 0) { croak("FOO!"); } } else { *handler = thunk_window_handler; *h_baton = result; } } else { *handler = svn_delta_noop_window_handler; *h_baton = NULL; } return SVN_NO_ERROR; } static svn_error_t * thunk_change_file_prop(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = file_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"change_file_prop", NULL, "OOssS", ib->editor, ib->baton, name, value ? value->data : NULL, pool, poolinfo)); return SVN_NO_ERROR; } static svn_error_t * thunk_close_file(void *file_baton, const char *text_checksum, apr_pool_t *pool) { item_baton *ib = file_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"close_file", NULL, "OOsS", ib->editor, ib->baton, text_checksum, pool, poolinfo)); SvREFCNT_dec(ib->editor); SvREFCNT_dec(ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif return SVN_NO_ERROR; } static svn_error_t * thunk_absent_file(const char *path, void *parent_baton, apr_pool_t *pool) { item_baton *ib = parent_baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); SVN_ERR (perl_callback_thunk (CALL_METHOD, (void *)"absent_file", NULL, "OsOS", ib->editor, path, ib->baton, pool, poolinfo)); return SVN_NO_ERROR; } static svn_error_t * thunk_close_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "close_edit"); } static svn_error_t * thunk_abort_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "abort_edit"); } void svn_delta_make_editor(svn_delta_editor_t **editor, void **edit_baton, SV *perl_editor, apr_pool_t *pool) { svn_delta_editor_t *thunk_editor = svn_delta_default_editor (pool); thunk_editor->set_target_revision = thunk_set_target_revision; thunk_editor->open_root = thunk_open_root; thunk_editor->delete_entry = thunk_delete_entry; thunk_editor->add_directory = thunk_add_directory; thunk_editor->open_directory = thunk_open_directory; thunk_editor->change_dir_prop = thunk_change_dir_prop; thunk_editor->close_directory = thunk_close_directory; thunk_editor->absent_directory = thunk_absent_directory; thunk_editor->add_file = thunk_add_file; thunk_editor->open_file = thunk_open_file; thunk_editor->apply_textdelta = thunk_apply_textdelta; thunk_editor->change_file_prop = thunk_change_file_prop; thunk_editor->close_file = thunk_close_file; thunk_editor->absent_file = thunk_absent_file; thunk_editor->close_edit = thunk_close_edit; thunk_editor->abort_edit = thunk_abort_edit; *editor = thunk_editor; *edit_baton = make_baton(pool, perl_editor, NULL); } svn_error_t *svn_swig_pl_thunk_log_receiver(void *baton, apr_hash_t *changed_paths, svn_revnum_t rev, const char *author, const char *date, const char *msg, apr_pool_t *pool) { SV *receiver = baton, *result; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); swig_type_info *tinfo = SWIG_TypeQuery("svn_log_changed_path_t *"); if (!SvOK(receiver)) return SVN_NO_ERROR; perl_callback_thunk (CALL_SV, receiver, &result, "OisssS", (changed_paths) ? svn_swig_pl_convert_hash(changed_paths, tinfo) : &PL_sv_undef, rev, author, date, msg, pool, poolinfo); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_history_func(void *baton, const char *path, svn_revnum_t revision, apr_pool_t *pool) { SV *func = baton; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); if (!SvOK(func)) return SVN_NO_ERROR; perl_callback_thunk (CALL_SV, func, NULL, "siS", path, revision, pool, poolinfo); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_authz_func (svn_boolean_t *allowed, svn_fs_root_t *root, const char *path, void *baton, apr_pool_t *pool) { SV *func = baton, *result; swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); swig_type_info *rootinfo = SWIG_TypeQuery("svn_fs_root_t *"); if (!SvOK(func)) return SVN_NO_ERROR; perl_callback_thunk (CALL_SV, func, &result, "SsS", root, rootinfo, path, pool, poolinfo); *allowed = SvIV (result); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision, const char *date, const char *author, void *baton) { if (!SvOK((SV *)baton)) return SVN_NO_ERROR; perl_callback_thunk (CALL_SV, baton, NULL, "iss", new_revision, date, author); return SVN_NO_ERROR; } /* Wrap RA */ static svn_error_t * thunk_open_tmp_file(apr_file_t **fp, void *callback_baton, apr_pool_t *pool) { SV *result; swig_type_info *tinfo = SWIG_TypeQuery("apr_file_t *"); perl_callback_thunk (CALL_METHOD, (void *)"open_tmp_file", &result, "O", callback_baton); if (SWIG_ConvertPtr(result, (void *)fp, tinfo,0) < 0) { croak("ouch"); } return SVN_NO_ERROR; } svn_error_t *thunk_get_wc_prop (void *baton, const char *relpath, const char *name, const svn_string_t **value, apr_pool_t *pool) { SV *result; swig_type_info *tinfo = SWIG_TypeQuery("apr_pool_t *"); perl_callback_thunk (CALL_METHOD, (void *)"get_wc_prop", &result, "OssS", baton, relpath, name, pool, tinfo); /* this is svn_string_t * typemap in */ if (!SvOK (result) || result == &PL_sv_undef) { *value = NULL; } else if (SvPOK(result)) { *value = svn_string_create (SvPV_nolen (result), pool); } else { croak("not a string"); } return SVN_NO_ERROR; } svn_error_t *svn_ra_make_callbacks(svn_ra_callbacks_t **cb, void **c_baton, SV *perl_callbacks, apr_pool_t *pool) { swig_type_info *tinfo = SWIG_TypeQuery("svn_auth_baton_t *"); SV *auth_baton; *cb = apr_pcalloc (pool, sizeof(**cb)); (*cb)->open_tmp_file = thunk_open_tmp_file; (*cb)->get_wc_prop = thunk_get_wc_prop; (*cb)->set_wc_prop = NULL; (*cb)->push_wc_prop = NULL; (*cb)->invalidate_wc_props = NULL; auth_baton = *hv_fetch((HV *)SvRV(perl_callbacks), "auth", 4, 0); if (SWIG_ConvertPtr(auth_baton, (void **)&(*cb)->auth_baton, tinfo,0) < 0) { croak("ouch"); } *c_baton = perl_callbacks; SvREFCNT_inc(perl_callbacks); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_simple_prompt(svn_auth_cred_simple_t **cred, void *baton, const char *realm, const char *username, svn_boolean_t may_save, apr_pool_t *pool) { SV *result; swig_type_info *poolinfo = SWIG_TypeQuery ("apr_pool_t *"); swig_type_info *credinfo = SWIG_TypeQuery ("svn_auth_cred_simple_t *"); /* Be nice and allocate the memory for the cred structure before passing it * off to the perl space */ *cred = apr_pcalloc (pool, sizeof (**cred)); if (!*cred) { croak ("Could not allocate memory for cred structure"); } perl_callback_thunk (CALL_SV, baton, &result, "SssiS", *cred, credinfo, realm, username, may_save, pool, poolinfo); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_username_prompt(svn_auth_cred_username_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool) { SV *result; swig_type_info *poolinfo = SWIG_TypeQuery ("apr_pool_t *"); swig_type_info *credinfo = SWIG_TypeQuery ("svn_auth_cred_username_t *"); /* Be nice and allocate the memory for the cred structure before passing it * off to the perl space */ *cred = apr_pcalloc (pool, sizeof (**cred)); if (!*cred) { croak ("Could not allocate memory for cred structure"); } perl_callback_thunk (CALL_SV, baton, &result, "SsiS", *cred, credinfo, realm, may_save, pool, poolinfo); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_ssl_server_trust_prompt( svn_auth_cred_ssl_server_trust_t **cred, void *baton, const char *realm, apr_uint32_t failures, const svn_auth_ssl_server_cert_info_t *cert_info, svn_boolean_t may_save, apr_pool_t *pool) { SV *result; swig_type_info *poolinfo = SWIG_TypeQuery ("apr_pool_t *"); swig_type_info *credinfo = SWIG_TypeQuery ( "svn_auth_cred_ssl_server_trust_t *"); swig_type_info *cert_info_info = SWIG_TypeQuery ( "svn_auth_ssl_server_cert_info_t *"); /* Be nice and allocate the memory for the cred structure before passing it * off to the perl space */ *cred = apr_pcalloc (pool, sizeof (**cred)); if (!*cred) { croak ("Could not allocate memory for cred structure"); } perl_callback_thunk (CALL_SV, baton, &result, "SsiSiS", *cred, credinfo, realm, failures, cert_info, cert_info_info, may_save, pool, poolinfo); /* Allow the perl callback to indicate failure by setting all vars to 0 * or by simply doing nothing. While still allowing them to indicate * failure by setting the cred strucutre's pointer to 0 via $$cred = 0 */ if (*cred) { if ((*cred)->may_save == 0 && (*cred)->accepted_failures == 0) { *cred = NULL; } } return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_ssl_client_cert_prompt( svn_auth_cred_ssl_client_cert_t **cred, void *baton, const char * realm, svn_boolean_t may_save, apr_pool_t *pool) { SV *result; swig_type_info *poolinfo = SWIG_TypeQuery ("apr_pool_t *"); swig_type_info *credinfo = SWIG_TypeQuery ( "svn_auth_cred_ssl_client_cert_t *"); /* Be nice and allocate the memory for the cred structure before passing it * off to the perl space */ *cred = apr_pcalloc (pool, sizeof (**cred)); if (!*cred) { croak ("Could not allocate memory for cred structure"); } perl_callback_thunk (CALL_SV, baton, &result, "SsiS", *cred, credinfo, realm, may_save, pool, poolinfo); return SVN_NO_ERROR; } svn_error_t *svn_swig_pl_thunk_ssl_client_cert_pw_prompt( svn_auth_cred_ssl_client_cert_pw_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool) { SV *result; swig_type_info *poolinfo = SWIG_TypeQuery ("apr_pool_t *"); swig_type_info *credinfo = SWIG_TypeQuery ( "svn_auth_cred_ssl_client_cert_pw_t *"); /* Be nice and allocate the memory for the cred structure before passing it * off to the perl space */ *cred = apr_pcalloc (pool, sizeof (**cred)); if (!*cred) { croak ("Could not allocate memory for cred structure"); } perl_callback_thunk (CALL_SV, baton, &result, "SsiS", *cred, credinfo, realm, may_save, pool, poolinfo); return SVN_NO_ERROR; } /* default pool support */ apr_pool_t *current_pool; apr_pool_t *svn_swig_pl_make_pool (SV *obj) { apr_pool_t *pool; if (obj && sv_isobject (obj)) { swig_type_info *poolinfo = SWIG_TypeQuery("apr_pool_t *"); if (sv_derived_from (obj, "SVN::Pool")) { obj = SvRV(obj); } if (sv_derived_from(obj, "_p_apr_pool_t")) { SWIG_ConvertPtr(obj, (void **)&pool, poolinfo, 0); return pool; } } if (!current_pool) perl_callback_thunk (CALL_METHOD, (void *)"new_default", &obj, "s", "SVN::Pool"); pool = current_pool; return pool; } /* stream interpolability with io::handle */ typedef struct { SV *obj; IO *io; } io_baton_t; static svn_error_t *io_handle_read (void *baton, char *buffer, apr_size_t *len) { io_baton_t *io = baton; MAGIC *mg; if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { SV *ret; SV *buf = sv_newmortal(); perl_callback_thunk (CALL_METHOD, (void *)"READ", &ret, "OOi", SvTIED_obj((SV*)io->io, mg), buf, *len); *len = SvIV (ret); memmove (buffer, SvPV_nolen(buf), *len); } else *len = PerlIO_read (IoIFP (io->io), buffer, *len); return SVN_NO_ERROR; } static svn_error_t *io_handle_write (void *baton, const char *data, apr_size_t *len) { io_baton_t *io = baton; MAGIC *mg; if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { SV *ret, *pv; pv = sv_2mortal (newSVpvn (data, *len)); perl_callback_thunk (CALL_METHOD, (void *)"WRITE", &ret, "OOi", SvTIED_obj((SV*)io->io, mg), pv, *len); *len = SvIV (ret); } else *len = PerlIO_write (IoIFP (io->io), data, *len); return SVN_NO_ERROR; } static svn_error_t *io_handle_close (void *baton) { io_baton_t *io = baton; MAGIC *mg; if ((mg = SvTIED_mg((SV*)io->io, PERL_MAGIC_tiedscalar))) { perl_callback_thunk (CALL_METHOD, (void *)"CLOSE", NULL, "O", SvTIED_obj((SV*)io->io, mg)); } else { PerlIO_close (IoIFP (io->io)); } return SVN_NO_ERROR; } static apr_status_t io_handle_cleanup (void *baton) { io_baton_t *io = baton; SvREFCNT_dec (io->obj); return APR_SUCCESS; } svn_error_t *svn_swig_pl_make_stream (svn_stream_t **stream, SV *obj) { swig_type_info *tinfo = SWIG_TypeQuery("svn_stream_t *"); IO *io; int simple_type = 1; if (!SvOK (obj)) { *stream = NULL; return SVN_NO_ERROR; } if (obj && sv_isobject(obj)) { if (sv_derived_from (obj, "SVN::Stream")) perl_callback_thunk (CALL_METHOD, (void *)"svn_stream", &obj, "O", obj); else if (!sv_derived_from(obj, "_p_svn_stream_t")) simple_type = 0; if (simple_type) { SWIG_ConvertPtr(obj, (void **)stream, tinfo, 0); return SVN_NO_ERROR; } } if (obj && SvROK(obj) && SvTYPE(SvRV(obj)) == SVt_PVGV && (io = GvIO(SvRV(obj)))) { apr_pool_t *pool = current_pool; io_baton_t *iob = apr_palloc (pool, sizeof(io_baton_t)); SvREFCNT_inc (obj); iob->obj = obj; iob->io = io; *stream = svn_stream_create (iob, pool); svn_stream_set_read (*stream, io_handle_read); svn_stream_set_write (*stream, io_handle_write); svn_stream_set_close (*stream, io_handle_close); apr_pool_cleanup_register (pool, iob, io_handle_cleanup, io_handle_cleanup); } else croak ("unknown type for svn_stream_t"); return SVN_NO_ERROR; } SV *svn_swig_pl_from_stream (svn_stream_t *stream) { swig_type_info *tinfo = SWIG_TypeQuery("svn_stream_t *"); SV *ret; perl_callback_thunk (CALL_METHOD, (void *)"new", &ret, "sS", "SVN::Stream", stream, tinfo); return sv_2mortal (ret); } apr_file_t *svn_swig_pl_make_file (SV *file, apr_pool_t *pool) { apr_file_t *apr_file = NULL; if (!SvOK(file) || file == &PL_sv_undef) return NULL; if (SvPOKp(file)) { apr_file_open(&apr_file, SvPV_nolen(file), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); } else if (SvROK(file) && SvTYPE(SvRV(file)) == SVt_PVGV) { apr_status_t status; apr_os_file_t osfile = PerlIO_fileno(IoIFP(sv_2io(file))); status = apr_os_file_put (&apr_file, &osfile, O_CREAT | O_WRONLY, pool); if (status) return NULL; } return apr_file; } Node-path: svnperl/swigutil_pl.h Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 7631 Text-content-md5: 0c8d33bcb42fb6359587ee385a96e520 Content-length: 7641 PROPS-END /* * swigutil_pl.h : utility functions and stuff for the SWIG Perl bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #ifndef SVN_SWIG_SWIGUTIL_PL_H #define SVN_SWIG_SWIGUTIL_PL_H #include #include #include #include #include #include #include #include #include "svn_types.h" #include "svn_string.h" #include "svn_delta.h" #include "svn_client.h" #include "svn_repos.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* If this file is being included outside of a wrapper file, then need to create stubs for some of the SWIG types. */ /* if SWIGEXPORT is defined, then we're in a wrapper. otherwise, we need the prototypes and type definitions. */ #ifndef SWIGEXPORT #define SVN_NEED_SWIG_TYPES #endif #ifdef SVN_NEED_SWIG_TYPES /* XXX: this has to be set by configure and also swig -swiglib needs to be added to include paths. */ #if SWIG_VERSION >= 0x010320 #include "perl5/precommon.swg" #endif typedef struct _unnamed swig_type_info; swig_type_info *SWIG_TypeQuery(const char *name); int SWIG_ConvertPtr(SV *, void **, swig_type_info *, int flags); void SWIG_MakePtr(SV *, void *, swig_type_info *, int flags); #endif /* SVN_NEED_SWIG_TYPES */ extern apr_pool_t *current_pool; apr_pool_t *svn_swig_pl_make_pool (SV *obj); SV *svn_swig_pl_prophash_to_hash (apr_hash_t *hash); SV *svn_swig_pl_convert_hash (apr_hash_t *hash, swig_type_info *tinfo); const apr_array_header_t *svn_swig_pl_strings_to_array(SV *source, apr_pool_t *pool); apr_hash_t *svn_swig_pl_strings_to_hash(SV *source, apr_pool_t *pool); apr_hash_t *svn_swig_pl_objs_to_hash(SV *source, swig_type_info *tinfo, apr_pool_t *pool); apr_hash_t *svn_swig_pl_objs_to_hash_by_name(SV *source, const char *typename, apr_pool_t *pool); const apr_array_header_t *svn_swig_pl_objs_to_array(SV *source, swig_type_info *tinfo, apr_pool_t *pool); SV *svn_swig_pl_array_to_list(const apr_array_header_t *array); SV *svn_swig_pl_ints_to_list(const apr_array_header_t *array); /* thunked log receiver function. */ svn_error_t * svn_swig_pl_thunk_log_receiver(void *py_receiver, apr_hash_t *changed_paths, svn_revnum_t rev, const char *author, const char *date, const char *msg, apr_pool_t *pool); /* thunked commit editor callback. */ svn_error_t *svn_swig_pl_thunk_commit_callback(svn_revnum_t new_revision, const char *date, const char *author, void *baton); /* thunked repos_history callback. */ svn_error_t *svn_swig_pl_thunk_history_func(void *baton, const char *path, svn_revnum_t revision, apr_pool_t *pool); /* thunked dir_delta authz read function. */ svn_error_t *svn_swig_pl_thunk_authz_func (svn_boolean_t *allowed, svn_fs_root_t *root, const char *path, void *baton, apr_pool_t *pool); /* ra callbacks. */ svn_error_t *svn_ra_make_callbacks(svn_ra_callbacks_t **cb, void **c_baton, SV *perl_callbacks, apr_pool_t *pool); /* thunked simple_prompt callback function */ svn_error_t *svn_swig_pl_thunk_simple_prompt (svn_auth_cred_simple_t **cred, void *baton, const char *realm, const char *username, svn_boolean_t may_save, apr_pool_t *pool); /* thunked username_prompt callback function */ svn_error_t *svn_swig_pl_thunk_username_prompt (svn_auth_cred_username_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool); /* thunked ssl_server_trust_prompt callback function */ svn_error_t *svn_swig_pl_thunk_ssl_server_trust_prompt( svn_auth_cred_ssl_server_trust_t **cred, void *baton, const char *realm, apr_uint32_t failures, const svn_auth_ssl_server_cert_info_t *cert_info, svn_boolean_t may_save, apr_pool_t *pool); /* thunked ssl_client_cert callback function */ svn_error_t *svn_swig_pl_thunk_ssl_client_cert_prompt ( svn_auth_cred_ssl_client_cert_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool); /* thunked ssl_client_cert_pw callback function */ svn_error_t *svn_swig_pl_thunk_ssl_client_cert_pw_prompt ( svn_auth_cred_ssl_client_cert_pw_t **cred, void *baton, const char *realm, svn_boolean_t may_save, apr_pool_t *pool); /* thunked callback for svn_ra_get_wc_prop_func_t */ svn_error_t *thunk_get_wc_prop (void *baton, const char *relpath, const char *name, const svn_string_t **value, apr_pool_t *pool); /* helper for making the editor */ void svn_delta_make_editor(svn_delta_editor_t **editor, void **edit_baton, SV *perl_editor, apr_pool_t *pool); /* svn_stream_t helpers */ svn_error_t *svn_swig_pl_make_stream (svn_stream_t **stream, SV *obj); SV *svn_swig_pl_from_stream (svn_stream_t *stream); /* apr_file_t * */ apr_file_t *svn_swig_pl_make_file (SV *file, apr_pool_t *pool); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* SVN_SWIG_SWIGUTIL_PL_H */ Node-path: svnperl/swigutil_py.c Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 34414 Text-content-md5: 4de4897430543d70e6dfc050bf151488 Content-length: 34424 PROPS-END /* * swigutil_py.c: utility functions for the SWIG Python bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #include #include #include #include #include #include #include #include #include "svn_string.h" #include "svn_opt.h" #include "svn_delta.h" #include "swigutil_py.h" /*** Manage the Global Interpreter Lock ***/ /* If both Python and APR have threads available, we can optimize ourselves * by releasing the global interpreter lock when we drop into our SVN calls. * * In svn_types.i, svn_swig_py_release_py_lock is called before every * function, then svn_swig_py_acquire_py_lock is called after every * function. So, if these functions become no-ops, then Python will * start to block... * * The Subversion libraries can be assumed to be thread-safe *only* when * APR_HAS_THREAD is 1. The APR pool allocations aren't thread-safe unless * APR_HAS_THREAD is 1. */ #if defined(WITH_THREAD) && APR_HAS_THREADS #define ACQUIRE_PYTHON_LOCK #endif #ifdef ACQUIRE_PYTHON_LOCK static apr_threadkey_t *_saved_thread_key = NULL; static apr_pool_t *_saved_thread_pool = NULL; #endif void svn_swig_py_release_py_lock(void) { #ifdef ACQUIRE_PYTHON_LOCK PyThreadState *thread_state; if (_saved_thread_key == NULL) { /* This is ugly. We call svn_swig_py_release_py_lock before executing any subversion function. Thus it gets called before any call to apr_initialize in our script. This means we have to call apr_initialize ourselves, or otherwise we won't be able to create our pool. */ apr_initialize(); /* Obviously, creating a top-level pool for this is pretty stupid. */ apr_pool_create(&_saved_thread_pool, NULL); apr_threadkey_private_create(&_saved_thread_key, NULL, _saved_thread_pool); } thread_state = PyEval_SaveThread(); apr_threadkey_private_set(thread_state, _saved_thread_key); #endif } void svn_swig_py_acquire_py_lock(void) { #ifdef ACQUIRE_PYTHON_LOCK void *val; PyThreadState *thread_state; apr_threadkey_private_get(&val, _saved_thread_key); thread_state = val; PyEval_RestoreThread(thread_state); #endif } /*** Custom SubversionException stuffs. ***/ /* Global SubversionException class object. */ static PyObject *SubversionException = NULL; PyObject *svn_swig_py_exception_type(void) { Py_INCREF(SubversionException); return SubversionException; } PyObject *svn_swig_py_register_exception(void) { /* If we haven't created our exception class, do so. */ if (SubversionException == NULL) { SubversionException = PyErr_NewException ((char *)"libsvn._core.SubversionException", NULL, NULL); } /* Regardless, return the exception class. */ return svn_swig_py_exception_type(); } void svn_swig_py_svn_exception(svn_error_t *err) { PyObject *exc_ob, *apr_err_ob; if (err == NULL) return; /* Make an integer for the error code. */ apr_err_ob = PyInt_FromLong(err->apr_err); if (apr_err_ob == NULL) return; /* Instantiate a SubversionException object. */ exc_ob = PyObject_CallFunction(SubversionException, (char *)"sO", err->message, apr_err_ob); if (exc_ob == NULL) { Py_DECREF(apr_err_ob); return; } /* Set the "apr_err" attribute of the exception to our error code. */ if (PyObject_SetAttrString(exc_ob, (char *)"apr_err", apr_err_ob) == -1) { Py_DECREF(apr_err_ob); Py_DECREF(exc_ob); return; } /* Finished with the apr_err object. */ Py_DECREF(apr_err_ob); /* Set the error state to our exception object. */ PyErr_SetObject(SubversionException, exc_ob); /* Finished with the exc_ob object. */ Py_DECREF(exc_ob); } /*** Helper/Conversion Routines ***/ static PyObject *make_pointer(const char *typename, void *ptr) { /* ### cache the swig_type_info at some point? */ return SWIG_NewPointerObj(ptr, SWIG_TypeQuery(typename), 0); } /* for use by the "O&" format specifier */ static PyObject *make_ob_pool(void *ptr) { return make_pointer("apr_pool_t *", ptr); } /* for use by the "O&" format specifier */ static PyObject *make_ob_window(void *ptr) { return make_pointer("svn_txdelta_window_t *", ptr); } /* for use by the "O&" format specifier */ static PyObject *make_ob_status(void *ptr) { return make_pointer("svn_wc_status_t *", ptr); } static PyObject *convert_hash(apr_hash_t *hash, PyObject * (*converter_func)(void *value, void *ctx), void *ctx) { apr_hash_index_t *hi; PyObject *dict = PyDict_New(); if (dict == NULL) return NULL; for (hi = apr_hash_first(NULL, hash); hi; hi = apr_hash_next(hi)) { const void *key; void *val; PyObject *value; apr_hash_this(hi, &key, NULL, &val); value = (*converter_func)(val, ctx); if (value == NULL) { Py_DECREF(dict); return NULL; } /* ### gotta cast this thing cuz Python doesn't use "const" */ if (PyDict_SetItemString(dict, (char *)key, value) == -1) { Py_DECREF(value); Py_DECREF(dict); return NULL; } Py_DECREF(value); } return dict; } static PyObject *convert_to_swigtype(void *value, void *ctx) { /* ctx is a 'swig_type_info *' */ return SWIG_NewPointerObj(value, ctx, 0); } static PyObject *convert_svn_string_t(void *value, void *ctx) { /* ctx is unused */ const svn_string_t *s = value; /* ### borrowing from value in the pool. or should we copy? note ### that copying is "safest" */ /* ### gotta cast this thing cuz Python doesn't use "const" */ return PyBuffer_FromMemory((void *)s->data, s->len); } static PyObject *convert_svn_client_commit_item_t(void *value, void *ctx) { PyObject *list; PyObject *path, *kind, *url, *rev, *cf_url, *state; svn_client_commit_item_t *item = value; /* ctx is unused */ list = PyList_New(6); if (item->path) path = PyString_FromString(item->path); else { path = Py_None; Py_INCREF(Py_None); } if (item->url) url = PyString_FromString(item->url); else { url = Py_None; Py_INCREF(Py_None); } if (item->copyfrom_url) cf_url = PyString_FromString(item->copyfrom_url); else { cf_url = Py_None; Py_INCREF(Py_None); } kind = PyInt_FromLong(item->kind); rev = PyInt_FromLong(item->revision); state = PyInt_FromLong(item->state_flags); if (! (list && path && kind && url && rev && cf_url && state)) { Py_XDECREF(list); Py_XDECREF(path); Py_XDECREF(kind); Py_XDECREF(url); Py_XDECREF(rev); Py_XDECREF(cf_url); Py_XDECREF(state); return NULL; } PyList_SET_ITEM(list, 0, path); PyList_SET_ITEM(list, 1, kind); PyList_SET_ITEM(list, 2, url); PyList_SET_ITEM(list, 3, rev); PyList_SET_ITEM(list, 4, cf_url); PyList_SET_ITEM(list, 5, state); return list; } PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash) { return convert_hash(hash, convert_svn_string_t, NULL); } PyObject *svn_swig_py_convert_hash(apr_hash_t *hash, swig_type_info *type) { return convert_hash(hash, convert_to_swigtype, type); } PyObject *svn_swig_py_c_strings_to_list(char **strings) { PyObject *list = PyList_New(0); char *s; while ((s = *strings++) != NULL) { PyObject *ob = PyString_FromString(s); if (ob == NULL) goto error; if (PyList_Append(list, ob) == -1) goto error; } return list; error: Py_DECREF(list); return NULL; } const apr_array_header_t *svn_swig_py_strings_to_array(PyObject *source, apr_pool_t *pool) { int targlen; apr_array_header_t *temp; if (!PySequence_Check(source)) { PyErr_SetString(PyExc_TypeError, "not a sequence"); return NULL; } targlen = PySequence_Length(source); temp = apr_array_make(pool, targlen, sizeof(const char *)); /* APR_ARRAY_IDX doesn't actually increment the array item count (like, say, apr_array_push would). */ temp->nelts = targlen; while (targlen--) { PyObject *o = PySequence_GetItem(source, targlen); if (o == NULL) return NULL; if (!PyString_Check(o)) { Py_DECREF(o); PyErr_SetString(PyExc_TypeError, "not a string"); return NULL; } APR_ARRAY_IDX(temp, targlen, const char *) = PyString_AS_STRING(o); Py_DECREF(o); } return temp; } /*** apr_array_header_t conversions. To create a new type of converter, simply copy-n-paste one of these function and tweak the creation of the PyObject *ob. ***/ PyObject *svn_swig_py_array_to_list(const apr_array_header_t *array) { PyObject *list = PyList_New(array->nelts); int i; for (i = 0; i < array->nelts; ++i) { PyObject *ob = PyString_FromString(APR_ARRAY_IDX(array, i, const char *)); if (ob == NULL) goto error; PyList_SET_ITEM(list, i, ob); } return list; error: Py_DECREF(list); return NULL; } PyObject *svn_swig_py_revarray_to_list(const apr_array_header_t *array) { PyObject *list = PyList_New(array->nelts); int i; for (i = 0; i < array->nelts; ++i) { PyObject *ob = PyInt_FromLong(APR_ARRAY_IDX(array, i, svn_revnum_t)); if (ob == NULL) goto error; PyList_SET_ITEM(list, i, ob); } return list; error: Py_DECREF(list); return NULL; } static PyObject * commit_item_array_to_list(const apr_array_header_t *array) { PyObject *list = PyList_New(array->nelts); int i; for (i = 0; i < array->nelts; ++i) { PyObject *ob = convert_svn_client_commit_item_t (APR_ARRAY_IDX(array, i, svn_client_commit_item_t *), NULL); if (ob == NULL) goto error; PyList_SET_ITEM(list, i, ob); } return list; error: Py_DECREF(list); return NULL; } static svn_error_t * convert_python_error(void) { return svn_error_create(SVN_ERR_SWIG_PY_EXCEPTION_SET, NULL, "The Python callback raised an exception"); } /*** Editor Wrapping ***/ /* this baton is used for the editor, directory, and file batons. */ typedef struct { PyObject *editor; /* the editor handling the callbacks */ PyObject *baton; /* the dir/file baton (or NULL for edit baton) */ } item_baton; static item_baton * make_baton(apr_pool_t *pool, PyObject *editor, PyObject *baton) { item_baton *newb = apr_palloc(pool, sizeof(*newb)); /* one more reference to the editor. */ Py_INCREF(editor); /* note: we take the caller's reference to 'baton' */ newb->editor = editor; newb->baton = baton; return newb; } static svn_error_t * close_baton(void *baton, const char *method) { item_baton *ib = baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* If there is no baton object, then it is an edit_baton, and we should not bother to pass an object. Note that we still shove a NULL onto the stack, but the format specified just won't reference it. */ /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)method, ib->baton ? (char *)"(O)" : NULL, ib->baton)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); /* We're now done with the baton. Since there isn't really a free, all we need to do is note that its objects are no longer referenced by the baton. */ Py_DECREF(ib->editor); Py_XDECREF(ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_set_target_revision(void *edit_baton, svn_revnum_t target_revision, apr_pool_t *pool) { item_baton *ib = edit_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"set_target_revision", (char *)"l", target_revision)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_open_root(void *edit_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **root_baton) { item_baton *ib = edit_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_root", (char *)"lO&", base_revision, make_ob_pool, dir_pool)) == NULL) { err = convert_python_error(); goto finished; } /* make_baton takes our 'result' reference */ *root_baton = make_baton(dir_pool, ib->editor, result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_delete_entry(const char *path, svn_revnum_t revision, void *parent_baton, apr_pool_t *pool) { item_baton *ib = parent_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"delete_entry", (char *)"slOO&", path, revision, ib->baton, make_ob_pool, pool)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_add_directory(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_directory", (char *)"sOslO&", path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, dir_pool)) == NULL) { err = convert_python_error(); goto finished; } /* make_baton takes our 'result' reference */ *child_baton = make_baton(dir_pool, ib->editor, result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_open_directory(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *dir_pool, void **child_baton) { item_baton *ib = parent_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_directory", (char *)"sOlO&", path, ib->baton, base_revision, make_ob_pool, dir_pool)) == NULL) { err = convert_python_error(); goto finished; } /* make_baton takes our 'result' reference */ *child_baton = make_baton(dir_pool, ib->editor, result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_change_dir_prop(void *dir_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = dir_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_dir_prop", (char *)"Oss#O&", ib->baton, name, value ? value->data : NULL, value ? value->len : 0, make_ob_pool, pool)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_close_directory(void *dir_baton, apr_pool_t *pool) { return close_baton(dir_baton, "close_directory"); } static svn_error_t * thunk_add_file(const char *path, void *parent_baton, const char *copyfrom_path, svn_revnum_t copyfrom_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"add_file", (char *)"sOslO&", path, ib->baton, copyfrom_path, copyfrom_revision, make_ob_pool, file_pool)) == NULL) { err = convert_python_error(); goto finished; } /* make_baton takes our 'result' reference */ *file_baton = make_baton(file_pool, ib->editor, result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_open_file(const char *path, void *parent_baton, svn_revnum_t base_revision, apr_pool_t *file_pool, void **file_baton) { item_baton *ib = parent_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"open_file", (char *)"sOlO&", path, ib->baton, base_revision, make_ob_pool, file_pool)) == NULL) { err = convert_python_error(); goto finished; } /* make_baton takes our 'result' reference */ *file_baton = make_baton(file_pool, ib->editor, result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_window_handler(svn_txdelta_window_t *window, void *baton) { PyObject *handler = baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); if (window == NULL) { /* the last call; it closes the handler */ /* invoke the handler with None for the window */ /* ### python doesn't have 'const' on the format */ result = PyObject_CallFunction(handler, (char *)"O", Py_None); /* we no longer need to refer to the handler object */ Py_DECREF(handler); } else { /* invoke the handler with the window */ /* ### python doesn't have 'const' on the format */ result = PyObject_CallFunction(handler, (char *)"O&", make_ob_window, window); } if (result == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_apply_textdelta(void *file_baton, const char *base_checksum, apr_pool_t *pool, svn_txdelta_window_handler_t *handler, void **h_baton) { item_baton *ib = file_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"apply_textdelta", (char *)"(Os)", ib->baton, base_checksum)) == NULL) { err = convert_python_error(); goto finished; } /* Interpret None to mean svn_delta_noop_window_handler. This is much easier/faster than making code always have to write a NOOP handler in Python. */ if (result == Py_None) { Py_DECREF(result); *handler = svn_delta_noop_window_handler; *h_baton = NULL; } else { /* return the thunk for invoking the handler. the baton takes our 'result' reference, which is the handler. */ *handler = thunk_window_handler; *h_baton = result; } err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_change_file_prop(void *file_baton, const char *name, const svn_string_t *value, apr_pool_t *pool) { item_baton *ib = file_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"change_file_prop", (char *)"Oss#O&", ib->baton, name, value ? value->data : NULL, value ? value->len : 0, make_ob_pool, pool)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_close_file(void *file_baton, const char *text_checksum, apr_pool_t *pool) { item_baton *ib = file_baton; PyObject *result; svn_error_t *err; svn_swig_py_acquire_py_lock(); /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallMethod(ib->editor, (char *)"close_file", (char *)"(Os)", ib->baton, text_checksum)) == NULL) { err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); /* We're now done with the baton. Since there isn't really a free, all we need to do is note that its objects are no longer referenced by the baton. */ Py_DECREF(ib->editor); Py_XDECREF(ib->baton); #ifdef SVN_DEBUG ib->editor = ib->baton = NULL; #endif err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } static svn_error_t * thunk_close_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "close_edit"); } static svn_error_t * thunk_abort_edit(void *edit_baton, apr_pool_t *pool) { return close_baton(edit_baton, "abort_edit"); } void svn_swig_py_make_editor(const svn_delta_editor_t **editor, void **edit_baton, PyObject *py_editor, apr_pool_t *pool) { svn_delta_editor_t *thunk_editor = svn_delta_default_editor (pool); thunk_editor->set_target_revision = thunk_set_target_revision; thunk_editor->open_root = thunk_open_root; thunk_editor->delete_entry = thunk_delete_entry; thunk_editor->add_directory = thunk_add_directory; thunk_editor->open_directory = thunk_open_directory; thunk_editor->change_dir_prop = thunk_change_dir_prop; thunk_editor->close_directory = thunk_close_directory; thunk_editor->add_file = thunk_add_file; thunk_editor->open_file = thunk_open_file; thunk_editor->apply_textdelta = thunk_apply_textdelta; thunk_editor->change_file_prop = thunk_change_file_prop; thunk_editor->close_file = thunk_close_file; thunk_editor->close_edit = thunk_close_edit; thunk_editor->abort_edit = thunk_abort_edit; *editor = thunk_editor; *edit_baton = make_baton(pool, py_editor, NULL); } /*** Other Wrappers for SVN Functions ***/ /* This is very hacky and gross. */ apr_file_t *svn_swig_py_make_file (PyObject *py_file, apr_pool_t *pool) { apr_file_t *apr_file = NULL; if (py_file == NULL || py_file == Py_None) return NULL; if (PyString_Check(py_file)) { /* input is a path -- just open an apr_file_t */ apr_file_open(&apr_file, PyString_AS_STRING(py_file), APR_CREATE | APR_READ | APR_WRITE, APR_OS_DEFAULT, pool); } else if (PyFile_Check (py_file)) { apr_status_t status; FILE *file; apr_os_file_t osfile; /* input is a file object -- convert to apr_file_t */ file = PyFile_AsFile(py_file); #ifdef WIN32 osfile = (apr_os_file_t)_get_osfhandle(_fileno(file)); #else osfile = (apr_os_file_t)fileno(file); #endif status = apr_os_file_put (&apr_file, &osfile, O_CREAT | O_WRONLY, pool); if (status) return NULL; } return apr_file; } /* Thunked version of svn_wc_notify_func_t callback type. */ void svn_swig_py_notify_func(void *baton, const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision) { PyObject *function = baton; PyObject *result; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, (char *)"(siisiii)", path, action, kind, mime_type, content_state, prop_state, revision)) != NULL) { Py_XDECREF(result); } svn_swig_py_release_py_lock(); } /* Thunked version of svn_wc_status_func_t callback type. */ void svn_swig_py_status_func(void *baton, const char *path, svn_wc_status_t *status) { PyObject *function = baton; PyObject *result; if (function == NULL || function == Py_None) return; svn_swig_py_acquire_py_lock(); /* ### shouldn't we set an exception if this fails? */ if ((result = PyObject_CallFunction(function, (char *)"sO&", path, make_ob_status, status)) != NULL) { Py_DECREF(result); } svn_swig_py_release_py_lock(); } /* Thunked version of svn_wc_cancel_func_t callback type. */ svn_error_t *svn_swig_py_cancel_func(void *cancel_baton) { PyObject *function = cancel_baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; if (function == NULL || function == Py_None) return SVN_NO_ERROR; svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, NULL)) != NULL) { err = convert_python_error(); goto finished; } Py_DECREF(result); finished: svn_swig_py_release_py_lock(); return err; } /* Thunked version of svn_client_get_commit_log_t callback type. */ svn_error_t *svn_swig_py_get_commit_log_func(const char **log_msg, const char **tmp_file, apr_array_header_t *commit_items, void *baton, apr_pool_t *pool) { PyObject *function = baton; PyObject *result; PyObject *cmt_items; svn_error_t *err; *log_msg = NULL; *tmp_file = NULL; /* ### todo: for now, just ignore the whole tmp_file thing. */ if ((function == NULL) || (function == Py_None)) return SVN_NO_ERROR; svn_swig_py_acquire_py_lock(); if (commit_items) { cmt_items = commit_item_array_to_list(commit_items); } else { cmt_items = Py_None; Py_INCREF(Py_None); } /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallFunction(function, (char *)"OO&", cmt_items, make_ob_pool, pool)) == NULL) { Py_DECREF(cmt_items); err = convert_python_error(); goto finished; } Py_DECREF(cmt_items); if (result == Py_None) { Py_DECREF(result); *log_msg = NULL; err = SVN_NO_ERROR; goto finished; } else if (PyString_Check(result)) { *log_msg = apr_pstrdup(pool, PyString_AS_STRING(result)); Py_DECREF(result); err = SVN_NO_ERROR; goto finished; } Py_DECREF(result); PyErr_SetString(PyExc_TypeError, "not a string"); err = convert_python_error(); finished: svn_swig_py_release_py_lock(); return err; } /* Thunked version of svn_repos_history_func_t callback type. */ svn_error_t *svn_swig_py_repos_history_func(void *baton, const char *path, svn_revnum_t revision, apr_pool_t *pool) { PyObject *function = baton; PyObject *result; svn_error_t *err = SVN_NO_ERROR; if (function == NULL || function == Py_None) return SVN_NO_ERROR; svn_swig_py_acquire_py_lock(); if ((result = PyObject_CallFunction(function, (char *)"slO&", path, revision, make_ob_pool, pool)) != NULL) { if (result != Py_None) err = convert_python_error(); Py_DECREF(result); goto finished; } finished: svn_swig_py_release_py_lock(); return err; } /* Thunked version of svn_log_message_receiver_t callback type. */ svn_error_t * svn_swig_py_thunk_log_receiver(void *baton, apr_hash_t *changed_paths, svn_revnum_t rev, const char *author, const char *date, const char *msg, apr_pool_t *pool) { PyObject *receiver = baton; PyObject *result; swig_type_info *tinfo = SWIG_TypeQuery("svn_log_changed_path_t *"); PyObject *chpaths; svn_error_t *err; if ((receiver == NULL) || (receiver == Py_None)) return SVN_NO_ERROR; svn_swig_py_acquire_py_lock(); if (changed_paths) { chpaths = svn_swig_py_convert_hash (changed_paths, tinfo); } else { chpaths = Py_None; Py_INCREF(Py_None); } /* ### python doesn't have 'const' on the method name and format */ if ((result = PyObject_CallFunction(receiver, (char *)"OlsssO&", chpaths, rev, author, date, msg, make_ob_pool, pool)) == NULL) { Py_DECREF(chpaths); err = convert_python_error(); goto finished; } /* there is no return value, so just toss this object (probably Py_None) */ Py_DECREF(result); Py_DECREF(chpaths); err = SVN_NO_ERROR; finished: svn_swig_py_release_py_lock(); return err; } Node-path: svnperl/swigutil_py.h Node-kind: file Node-action: add Prop-content-length: 10 Text-content-length: 6039 Text-content-md5: 0d5f2aa933a5359d7fb29eacbb735b4b Content-length: 6049 PROPS-END /* * swigutil_py.h : utility functions and stuff for the SWIG Python bindings * * ==================================================================== * Copyright (c) 2000-2004 CollabNet. All rights reserved. * * This software is licensed as described in the file COPYING, which * you should have received as part of this distribution. The terms * are also available at http://subversion.tigris.org/license-1.html. * If newer versions of this license are posted there, you may use a * newer version instead, at your option. * * This software consists of voluntary contributions made by many * individuals. For exact contribution history, see the revision * history and logs, available at http://subversion.tigris.org/. * ==================================================================== */ #ifndef SVN_SWIG_SWIGUTIL_PY_H #define SVN_SWIG_SWIGUTIL_PY_H #include #include #include #include #include #include #include "svn_types.h" #include "svn_string.h" #include "svn_delta.h" #include "svn_client.h" #include "svn_repos.h" #ifdef __cplusplus extern "C" { #endif /* __cplusplus */ /* If this file is being included outside of a wrapper file, then need to create stubs for some of the SWIG types. */ /* if SWIGEXPORT is defined, then we're in a wrapper. otherwise, we need the prototypes and type definitions. */ #ifndef SWIGEXPORT #define SVN_NEED_SWIG_TYPES #endif #ifdef SVN_NEED_SWIG_TYPES typedef struct _unnamed swig_type_info; PyObject *SWIG_NewPointerObj(void *, swig_type_info *, int own); swig_type_info *SWIG_TypeQuery(const char *name); #endif /* SVN_NEED_SWIG_TYPES */ /* Functions to manage python's global interpreter lock */ void svn_swig_py_release_py_lock(void); void svn_swig_py_acquire_py_lock(void); /*** Functions to expose a custom SubversionException ***/ /* register a new subversion exception class */ PyObject *svn_swig_py_register_exception(void); /* get the object which represents the subversion exception class */ PyObject *svn_swig_py_exception_type(void); /* raise a subversion exception, created from a normal subversion error */ void svn_swig_py_svn_exception(svn_error_t *err); /* helper function to convert an apr_hash_t* (char* -> svnstring_t*) to a Python dict */ PyObject *svn_swig_py_prophash_to_dict(apr_hash_t *hash); /* convert a hash of 'const char *' -> TYPE into a Python dict */ PyObject *svn_swig_py_convert_hash(apr_hash_t *hash, swig_type_info *type); /* helper function to convert a 'char **' into a Python list of string objects */ PyObject *svn_swig_py_c_strings_to_list(char **strings); /* helper function to convert an array of 'const char *' to a Python list of string objects */ PyObject *svn_swig_py_array_to_list(const apr_array_header_t *strings); /* helper function to convert an array of 'svn_revnum_t' to a Python list of int objects */ PyObject *svn_swig_py_revarray_to_list(const apr_array_header_t *revs); /* helper function to convert a Python sequence of strings into an 'apr_array_header_t *' of 'const char *' objects. Note that the objects must remain alive -- the values are not copied. This is appropriate for incoming arguments which are defined to last the duration of the function's execution. */ const apr_array_header_t *svn_swig_py_strings_to_array(PyObject *source, apr_pool_t *pool); /* make an editor that "thunks" from C callbacks up to Python */ void svn_swig_py_make_editor(const svn_delta_editor_t **editor, void **edit_baton, PyObject *py_editor, apr_pool_t *pool); apr_file_t *svn_swig_py_make_file(PyObject *py_file, apr_pool_t *pool); /* a notify function that executes a Python function that is passed in via the baton argument */ void svn_swig_py_notify_func(void *baton, const char *path, svn_wc_notify_action_t action, svn_node_kind_t kind, const char *mime_type, svn_wc_notify_state_t content_state, svn_wc_notify_state_t prop_state, svn_revnum_t revision); /* a status function that executes a Python function that is passed in via the baton argument */ void svn_swig_py_status_func(void *baton, const char *path, svn_wc_status_t *status); /* a cancel function that executes a Python function passed in via the cancel_baton argument. */ svn_error_t *svn_swig_py_cancel_func(void *cancel_baton); /* thunked commit log fetcher */ svn_error_t *svn_swig_py_get_commit_log_func(const char **log_msg, const char **tmp_file, apr_array_header_t *commit_items, void *baton, apr_pool_t *pool); /* thunker history callback function */ svn_error_t *svn_swig_py_repos_history_func(void *baton, const char *path, svn_revnum_t revision, apr_pool_t *pool); /* thunked log receiver function. */ svn_error_t * svn_swig_py_thunk_log_receiver(void *py_receiver, apr_hash_t *changed_paths, svn_revnum_t rev, const char *author, const char *date, const char *msg, apr_pool_t *pool); #ifdef __cplusplus } #endif /* __cplusplus */ #endif /* SVN_SWIG_SWIGUTIL_PY_H */ Revision-number: 24 Prop-content-length: 200 Content-length: 200 K 7 svn:log V 99 * Mimic r6941 in svn.collab. Made a branch and remove some files and directories just in that dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T05:13:20.320762Z PROPS-END Node-path: svnperl_branch Node-kind: dir Node-action: add Node-copyfrom-rev: 23 Node-copyfrom-path: svnperl Node-path: svnperl_branch/swigutil_java.c Node-action: delete Node-path: svnperl_branch/swigutil_java.h Node-action: delete Node-path: svnperl_branch/swigutil_py.c Node-action: delete Node-path: svnperl_branch/java Node-action: delete Node-path: svnperl_branch/python Node-action: delete Node-path: svnperl_branch/swigutil_java_cache.h Node-action: delete Node-path: svnperl_branch/swigutil_py.h Node-action: delete Revision-number: 25 Prop-content-length: 122 Content-length: 122 K 7 svn:log V 21 * Remove branch test. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T08:38:14.380867Z PROPS-END Node-path: svnperl_branch Node-action: delete Revision-number: 26 Prop-content-length: 199 Content-length: 199 K 7 svn:log V 98 * Mimic r6941 in svn.collab. Made a branch and remove some files and directories within that dir. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T08:39:31.136538Z PROPS-END Node-path: svnperl_branch Node-kind: dir Node-action: add Node-copyfrom-rev: 24 Node-copyfrom-path: svnperl Node-path: svnperl_branch/perl/t/1repos.t Node-action: delete Node-path: svnperl_branch/perl/t/2fs.t Node-action: delete Node-path: svnperl_branch/perl/t/0use.t Node-action: delete Node-path: svnperl_branch/perl/t/4pool.t Node-action: delete Node-path: svnperl_branch/perl/t/3client.t Node-action: delete Node-path: svnperl_branch/swigutil_java.c Node-action: delete Node-path: svnperl_branch/swigutil_java.h Node-action: delete Node-path: svnperl_branch/swigutil_py.c Node-action: delete Node-path: svnperl_branch/java Node-action: delete Node-path: svnperl_branch/python Node-action: delete Node-path: svnperl_branch/swigutil_java_cache.h Node-action: delete Node-path: svnperl_branch/swigutil_py.h Node-action: delete Revision-number: 27 Prop-content-length: 140 Content-length: 140 K 7 svn:log V 39 * Simulate a simple branch for svnperl. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T13:50:48.043288Z PROPS-END Node-path: svnperl_001 Node-kind: dir Node-action: add Node-copyfrom-rev: 26 Node-copyfrom-path: svnperl Revision-number: 28 Prop-content-length: 130 Content-length: 130 K 7 svn:log V 29 * Simulate a branch from r23. K 10 svn:author V 6 plasma K 8 svn:date V 27 2004-01-23T14:00:30.450298Z PROPS-END Node-path: svnperl_002 Node-kind: dir Node-action: add Node-copyfrom-rev: 23 Node-copyfrom-path: svnperl