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"AUTHENTICATION PROVIDERS">. 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