The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
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 °ò¦½g]
== ¥»Â²³ø¬yµ{ ==

* ²­zª©¥»±±¨î
* ²­z CVS
* Subversion ªº¯S¦â
* ¤¶²Ð Subversion ±`¥Î«ü¥O
* ¦X¨Ö»P¼Ð°O
----
== ¬°¤°»ò»Ý­nª©¥»±±¨î ==

* °O¦í¹L¥hªº§ó°Ê
* ¿W¥ß¶}µoªºªÅ¶¡
* µo®i¿W¥ßªºªÅ¶¡
----
== CVS ªº¯ÊÂI ==

* Ãø¾Ç
* ©R¥O¦C¿ï¶µ
* °e¥æ¨Ã¤£¬O¤£¥i¤À³Îªº
* ¤£¤ä´©§ó¦W
* ¨S¦³¥Ø¿ý³æ¦ì
----
== Subversion? ==

* ª©¥»±±¨î¨t²Î
* Ãþ¦ü CVS ªº¬[ºc
* ¬°ºô¸ô³]­p
* ¥Î¨Ó¨ú¥N CVS
* §ó¦nªº CVS
* ¦Û¥Ñªº¶}©ñ·½½X
----
== Subversion ªº¯S¦â ==

* ¤@­Pªº¨Ï¥ÎªÌ¬É­±
* ¥Ø¿ýª©¥»±±¨î
* ¤£¥i¤À³Îªº°e¥æ
* ¯Ç¤Jª©¥»±±¨îªº´y­z¸ê®Æ
* ¦hºØºô¸ô³q°T¿ï¾Ü
* §ó¨Îªº¤G¶i¨î¸ê®Æ³B²z
* °ª®Ä²vªº¤À¤ä»P¼Ð°O
* ¦³®Äªººô¸ô¶Ç¿é
* Hackability
----
== Subversion ¨S¦³ªº¥\¯à ==

* Àɮ׫O¯d (cvs edit, watch)
* Merge point
* ÀÉ®×­Ó§Oªºª©¥»
* ¤À´²¦¡ÀÉ®×®w
* I18N, L10N
----
== ¨ú±o»P¦w¸Ë Subversion ==

* ¦Û http://subversion.tigris.org ¨ú±o·½½X
* ÃöÁpµ{¦¡®w
** APR 0.95 ¥H¤W
** Neon 0.24.4
** Berkeley DB 4.0 ¥H¤W («Øij 4.2.50)
** Apache Web Server 2.0.48 (optional)
** Python (optional)
** Perl (optional)
* FreeBSD ¨t²Îªº ports/devel/subversion
* ¦b http://subversion.tigris.org §ä¨ä¥¦¥­¥x¤Wªº¥i°õ¦æÀÉ
----
== TortoiseSVN ==

* Windows ¥­¥x¤W³Ì¦h¤H±ÀÂ˥ΤáºÝ
* »PÀÉ®×Á`ºÞ¾ã¦X¦b¤@°_
* ¥i»P¥ô¦ó¾ã¦X¶}©ñÀô¹Ò¤@¦P¨Ï¥Î
* ºô¯¸: http://tortoisesvn.tigris.org/
----
== Subversion ¤¸¥ó ==
* ¥Î¤áºÝ
** svn
** svnversion
* ¦øªA¾¹ºÝ
** svnadmin
** svnlook
** svnserve
** mod_dav_svn (optional)
----
== ÀÉ®×®w»P­×­qª© ==

* Ãþ¦üÀɮרt²Î
* ­×­qª©¬OÀÉ®×®wªº§Ö·Ó
[&img /~plasma/img/ch02dia7.png]
* ¥þ°ìªº­×­qª©
* ­×­qª©ÃöÁä¦r
** HEAD
** BASE
** COMMITTED
** PREV
* ³æ¤@­×­qª©¸¹
  --revision 1234
  -r 1234
* ­×­qª©¸¹½d³ò
  --revision 1234:5678
  -r 1234:5678
----
== svn ©R¥O¦Cµ{¦¡ ==
svn: ¨Ï¥ÎªÌ»PÀÉ®×®w¤§¶¡ªº¾ô¼Ù
* °Ê§@¥Ø¼Ð¥i¬° URL ©Î ¸ô®|
** ¸ô®|§@¥Îªº¹ï¶H¬O¤u§@½Æ¥»
** URL ¤u§@ªº¹ï¶H¬OÀÉ®×®w
* ©R¥O¦C¿ï¶µ¤£¨ü¨ä©Ò¦b¦ì¸m¼vÅT
* »¡©ú¦Û¤v: help
* URL ¥i¯àªº schema:
** file://
** http://
** https://
** svn://
** svn+ssh://
----
== svnadmin ©R¥O¦Cµ{¦¡ ==
svnadmin: ª½±µ¾Þ±± Subversion ªºÀÉ®×®w
* create: «Ø¥ßÀÉ®×®w
* dump: ±NÀÉ®×®w¶É¦L¦Ü¤å¦rÀÉ
* load: ¦Û¤å¦rÀɸü¤J¦ÜÀÉ®×®w
----
== °ò¥»¤u§@¬yµ{ ==
* ¶×¤J¦ÜÀÉ®×®w
* ¨ú¥X¤u§@½Æ¥»
* §ó·s¤u§@½Æ¥»
* ½s¿è¡B§ó°Ê
* À˵ø§ó°Ê
* ¦^´_§ó°Ê
* °e¥æ§ó°Ê
----
== ¶×¤J¦ÜÀÉ®×®w ==
* ¶×¤J¥Ø«eªº¤u§@¥Ø¿ý¦ÜÀÉ®×®w
  % svn import http://repo.host/repos/project/trunk
* ¶×¤J«ü©wªº¥Ø¿ý¦ÜÀÉ®×®w
  % svn import proj http://repo.host/repos/project/trunk
----
== ¨ú¥X¤u§@½Æ¥» ==
* ¨ú¥X¤u§@½Æ¥»
  % svn checkout http://svn.collab.net/repos/svn/trunk
* ¨ú¥X¤u§@½Æ¥»¦Ü«ü©wªº¥Ø¿ý
  % svn checkout http://svn.collab.net/repos/svn/trunk svn
* [=.svn] ºÞ²z¥Ø¿ý
** ¯Ç¤Jª©¥»±±¨îªº¶µ¥Øªº¸ê®Æ
** ¯Ç¤Jª©¥»±±¨îªº¶µ¥Øªº§¹¾ã¥¼§ó°ÊÀÉ®×
----
== §ó·s¤u§@½Æ¥» ==
* §ó·s¤u§@½Æ¥»
** ±N©Ò¦³ªº¥Ø¿ý»PÀɮקó·s¦Ü³Ì·sªº­×­qª©
    % svn update
** ±N©Ò¦³ªº¥Ø¿ý»PÀɮקó·s¦Ü¬Y­Ó¸ûªº­×­qª©
    % svn update -r 1345
** ¥u­n svn-doc.el ¬Y­Ó§ó¦Ñªºª©¥»
    % svn update -r 999 svn-doc.el
* §ó·s²£¥Íªºµ²ªG
;;[=A] : ¹w©w·s¼W¦ÜÀÉ®×®w.
;;[=M] : Àɮתº¤º®e¤w³Q§ó°Ê.
;;[=D] : ¹w©w­n¦ÛÀÉ®×®w§R°£.
;;[=?] : ¥¼¯Ç¤Jª©¥»±±¨î.
;;[=!] : ¥»¶µ¤w¯Ç¤Jª©¥»±±¨î, ¦ý¬O¤£¨£¤F.
;;[=~] : ¤£¦PÃþ§Oªºª«¥ó.
;;[=C] : ½Ä¬ð.
----
== §ó°ÊÀÉ®× ==
* ¨Ï¥Î¤å¦r½s¿è¾¹
* ¨Ï¥Î¹Ï§Î½s¿è¾¹
* ¨Ï¥ÎÀH«K¤°»ò½s¿è¾¹
* ·s¼W²{¦³ªº¥Ø¿ý©ÎÀÉ®×
  % svn add newfile.txt
* §R°£²{¦³ªº¥Ø¿ý©ÎÀÉ®×
  % svn rm bye.txt
* ½Æ»s¥Ø¿ý©ÎÀÉ®×
  % svn copy foo.txt bar.txt
* ·h²¾¥Ø¿ý©ÎÀÉ®×
  % svn move baz.txt buz.txt
----
== À˵ø§ó°Ê (I) ==
* [=svn status]

  $ svn status
    L    ./abc.c               # svn ¦b .svn ¥Ø¿ý¤¤, ¦³ abc.c ªºÂê©w
  M      ./bar.c               # bar.c ªº¤º®e, ¦³¥»¦aºÝªºÅܧó
   M     ./baz.c               # baz.c ¤wÅܧó¤F©Ê½è, ¦ý¬O¨S¦³¤º®eªº§ó°Ê
  ?      ./foo.o               # svn ¨Ã¥¼ºÞ²z foo.o
  !      ./some_dir            # svn ºÞ²z¥¦, ¦ý¬O¤£¬O¤£¨£¤F, ´N¬O¤£§¹¾ã
  ~      ./qux                 # ¯Ç¤JºÞ²zªº¬O¥Ø¿ý, ¦ý¬O³o¸Ì¬OÀÉ®×, ©Î¬O¬Û¤Ïªº±¡ªp
  A  +   ./moved_dir           # ·s¼W¶µ¥Ø, ¨Ã¥H¨Ó·½ªº¾ú¥v¬ö¿ý¬°¨ä¾ú¥v¬ö¿ý
  M  +   ./moved_dir/README    # ·s¼W¶µ¥Ø, ¨Ï¥Î¨Ó·½ªº¾ú¥v¬ö¿ý, ¦A¥[¤W¥»¦a§ó°Ê
  D      ./stuff/fish.c        # ¥»Àɮפw¹w©w­n³Q§R°£
  A      ./stuff/loot/bloo.h   # ¥»Àɮפw¹w©w­n³Q·s¼W
  C      ./stuff/loot/lump.c   # ³o­ÓÀɮצ³¦]§ó·s¦Ó²£¥Íªº½Ä¬ð
      S  ./stuff/squawk        # ³o­ÓÀɮשΥؿý¤w¤Á´«¨ì¤À¤ä

----
== À˵ø§ó°Ê (II) ==
** [=svn status]: ¥[¤W -v Åã¥Ü§ó¦hªº¸ê°T

  $ 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

*** Åã¥Ü­×­qª©½s¸¹
*** Åã¥Ü§ó°ÊÀɮתº¤H
----
== À˵ø§ó°Ê (III) ==
* À˵ø§Aªº§ó°Ê
** svn diff: Åã¥Ü©Ò§@ªº§ó°Ê
*** ³s©Ê½èªº§ó°Ê¤]·|Åã¥Ü
*** Åã¥Ü©Ò¦³¥»¦a¤u§@½Æ¥»ªº¥Ø¿ý»PÀÉ®×®t²§
      % svn diff
*** Åã¥ÜÀÉ®×®wªº 3 ¸¹­×­qª©ªº foo.pl »P¤u§@½Æ¥»ªº foo.pl ¤§¶¡ªº®t²§
      % svn diff -r 3 foo.pl
*** Åã¥ÜÀÉ®×®w¤¤ªº foo.pl ªº 2 ¸¹»P 3 ¸¹­×­qª©¤§¶¡ªº®t²§, µL»Ý¦s¨ú¥»¦a½Æ¥»
      % svn diff -r 2:3 foo.pl
----
== ¦^´_§ó°Ê ==
* ¦^´_¬YÀɮתº§ó°Ê
** §¹¥þ¤£»Ý­nºô¸ô
    % svn revert foo.pl
----
== °e¥æ§ó°Ê ==
* °e¥æ§Ú­Ì©Ò§@ªº§ó°Ê
    % svn commit
* ¦b©R¥O¦C´£¨Ñ°e¥æ°T®§
    % svn commit -m "Commit log message"
* °e¥æ¤§«á, ¤u§@½Æ¥»¥Ø¿ý¤£·|¦Û°Ê§ó·s
----
== ÃöÁä¦r®i¶} ==
* ¦p¦ó¨Ï¥ÎÃöÁä¦r®i¶}
** ³]©wÀɮתº©Ê½è
  % svn propset svn:keywords Id foo.pl
** ¥i¨Ï¥ÎªºÃöÁä¦r
*** URL, HeadURL
*** Author, LastChangedBy
*** Date, LastChangedDate
*** Rev, LastChangedRevision
*** Id
----
== ÀÉ®×®w¥Ø¿ý¬[ºc ==

* ¨ä¤@
  /repos/project1/trunk
  /repos/project1/branches
  /repos/project1/tags
  /repos/project2/trunk
  /repos/project2/branches
  /repos/project2/tags
* ¨ä¤G
  /repos/trunk/project1
  /repos/trunk/project2
  /repos/branches/project1
  /repos/branches/project2
  /repos/tags/project1
  /repos/tags/project2
----
== ¼Ð°O»P¤À¤ä ==

* ·G»ù½Æ¥»
** ³t«×«Ü§Ö
** ¥u¬O³sµ²¦Ó¤w
* ¼Ð°O»P¤À¤ä´N¥u¬O½Æ»s¦Ó¤w
  % 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
* ¼Ð°O»P¤À¤äªº®t§O
** ¼Ð°O¤£¦A§ó°Ê
** ¤À¤ä±N¦¨¬°¥t¤@¤äµo®i½u
----
== ¨Ï¥Î¤À¤ä ==

* ª½±µ¨Ï¥Î checkout ©R¥O
** ª½±µ¨Ï¥Î¤À¤ä¥Ø¿ý
  % svn co http://svn.host/repos/proj/branches/add-new-features
** ¥t¦æ«ü©w¤À¤ä¥Ø¿ý
  % svn co http://svn.host/repos/proj/branches/add-new-features proj
* ¤w¦³¥D¤À¤äªº¤u§@½Æ¥»
** ¨Ï¥Î svn switch
  % svn switch http://svn.host/repos/proj/branches/add-new-features
----
== ¦X¨Ö¤À¤ä ==

* ¤À¤ä¤u§@¤w§¹¦¨, ¸Ó¦X¨Ö¦^¥Dµo®i½u
* ¨Ï¥Î merge ©R¥O
* ³Ì±`¥Çªº¿ù»~
  % svn merge \
    http://svn.host/repos/proj/branches/add-new-features \
    http://svn.host/repos/proj/trunk
* ¥¿½Tªº§@ªk
  % svn merge -r REV1:REV2 \
    http://svn.host/repos/proj/branches/add-new-features
----
== ½Ä¬ð ==

* µLªk¥¿½TµL»~¦X¨Ö
* ²£¥Í¤T­ÓÃB¥~ªºÀÉ®×
** ­ì¥ý¦b¤u§@½Æ¥»¤¤ªº
** ¦b¦X¨Ö¨Ó·½ªº
** ¦b¦X¨Ö¥Ø¼Ðªº
* µLªk¶i¦æ°e¥æ
* ¥²¶·¥ý¸Ñ¨M½Ä¬ð
* ¨Ï¥Î resolved «ü¥O
  % 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 ÀÉ®×®wºÞ²z]
== ÀÉ®×®wºÞ²z ==

* svnadmin ©R¥O¦Cµ{¦¡
* »PÀÉ®×®w¦b¦P¤@¥x¾÷¾¹¤W
* ¥Ø¿ý¬Ò¬°¸ô®|, ¨S¦³ URL
----
== ÀÉ®×®wÀɮ׬[ºc ==

* ÀÉ®×®wªº¤º®e
  README.txt  # ¤å¦rÀÉ
  conf        # ¥]§t³]©wÀɪº¥Ø¿ý
  dav         # ¨Ñ Apache mod_dav ¨Ï¥Îªº¥Ø¿ý
  db          # ¸ê®Æ®w¥Ø¿ý
  format      # ¥]§tÀÉ®×®w®æ¦¡ª©¸¹ªº¤å¦rÀÉ
  hooks       # ¥]§t±¾¤Äµ{¦¡ªº¥Ø¿ý
  locks       # ¨Ñ¸ê®Æ®wªºÂê©w¨Ï¥Îªº¥Ø¿ý
----
== ÀÉ®×®wÅv­­ ==

* ¼g¤JÀÉ®×®w»Ý¦³¼g¤JÅv­­
* Ū¨úÀÉ®×®w»Ý¦³¼g¤JÅv­­
* «Øij§@ªk
** «Ø¥ß¦W¬° svn ªº¨Ï¥ÎªÌ»P¸s²Õ
** ÀÉ®×®w¥Ø¿ý³]¬°¸Ó¨Ï¥ÎªÌ»P¸s²Õ¥iŪ¼g
* umask
** ¦s¨úÀÉ®×®wÀ³¥H 002 ¬°¤§

----
== ±`¥Î«ü¥O ==

* «Ø¥ßÀÉ®×®w
  % svnadmin create SVN_ROOT
* ¶É¦LÀÉ®×®w¤º®e
  % svnadmin dump SVN_ROOT > repos.dump
* ¸ü¤J¶É¦LÀɤº®e
  % svnadmin load SVN_ROOT < repos.dump
* ¦C¥XµL¥Îªº¸ê®ÆÀɬö¿ýÀÉ
  % svnadmin list-unused-dblogs SVN_ROOT
* ­×¥¿ÀÉ®×®w°ÝÃD
  % svn recover
----
== ±¾¤Äµ{¦¡ ==

* ¦]ÀÉ®×®wªº¨Æ¥ó¦ÓIJµo
* ©óÀÉ®×®wªº¾÷¾¹¤W°õ¦æ
* ¹ê§@ªº±¾¤Ä
** start-commit
** pre-commit
** post-commit
** pre-revprop-change
** post-revprop-change
----
== ³Æ¥÷ ==

* §¹¾ã³Æ¥÷
** svnadmin dump
* §Y®É³Æ¥÷
** svnadmin hotcopy
* ¦^¦s
** svnadmin load
----
== ¶}©ñ¦Üºô¸ô ==

* ¨Ï¥Î Apache
** ¥\¯à±j¤j
** ¥i¥H©M Apache ¼Ò²Õ¨ó¦P¨Ï¥Î
* ¨Ï¥Î svnserve
** ±MÄݦøªA¾¹
** ¨Ï¥Î²³æ
* ¨Ï¥Î svnserve + ssh
** ¨Ï¥Î²³æ
** ¦w¥þ
** ¦³ ssh ±b¸¹§Y¥i¨Ï¥Î
----
== ¨Ï¥Î Apache ==

* ¨Ï¥Î mod_dav_svn
* ³]©wÀɽd¨Ò (¤@)

  LoadModule dav_svn_module modules/mod_dav_svn.so
  <Location /repos&gt>
    DAV svn
    SVNPath /absolute/path/to/repository
  </Location>

* ³]©wÀɽd¨Ò (¤G)

  LoadModule dav_svn_module modules/mod_dav_svn.so
  <Location /repos&gt>
    DAV svn
    SVNParentPath /usr/local/svn
  </Location>

* ³]©wÀɽd¨Ò (¤T)


  LoadModule dav_svn_module modules/mod_dav_svn.so
  <Location /svn>
    DAV svn
    SVNParentPath /usr/local/svn
    AuthType Basic
    AuthName "Subversion repository"
    AuthUserFile /path/to/users/file
    <LimitExcept GET PROPFIND OPTIONS REPORT>
      Require valid-user
    </LimitExcept>
  </Location>
----
== ¨Ï¥Î svnserve ==

* ¨Ï¥Î port 3690
* ª½±µ°õ¦æ
  svnserve -d
* ³z¹L inetd
* ¥²¶·¨Ï¥Î§¹¾ã¸ô®|
* ¥i³z¹L -r ­­¨î¸ô®|½d³ò
----
== ³z¹L SSH ==

* ¥u­n¦³ SSH §Y¥i
* ¦ý¬O¥²¶·¨Ï¥Î§¹¾ã¸ô®|


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:

          <PYTHON>\Lib\site-packages\svn
          <PYTHON>\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 <PYTHON>\lib\compileall.py <PYTHON>\Lib\site-packages\svn
          python <PYTHON>\lib\compileall.py <PYTHON>\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 <apr.h>
#include <apr_general.h>

#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
     * <code>ClassLoader</code> 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-E<gt>field()> and
C<$data-E<gt>field($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 E<lt>clkao@clkao.orgE<gt>

=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<SVN::Client> 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<SVN::Core> 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 E<lt>clkao@clkao.orgE<gt>
Ben Reser E<lt>ben@reser.orgE<gt>

=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 E<lt>clkao@clkao.orgE<gt>

=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 E<lt>clkao@clkao.orgE<gt>

=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<open> 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<SVN::Client> 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 E<lt>clkao@clkao.orgE<gt>

=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 E<lt>clkao@clkao.orgE<gt>

=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('', <FILE>);
    $temp =~ s/^(typedef struct)(\n\{[^}]+\}\s+(\w+);)/$1 $3$2/ms;
    close FILE;
    open FILE, '<', \$temp;
    while (<FILE>) {
	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 <jni.h>

#include <apr_pools.h>
#include <apr_hash.h>


#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, "<init>", "(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, "<init>", "(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, "<init>", "()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, "<init>", "(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 <jni.h>

#include <apr.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include <apr_hash.h>
#include <apr_tables.h>

#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,"<init>","(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 <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#include <stdarg.h>

#include <apr.h>
#include <apr_general.h>
#include <apr_portable.h>

#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 <EXTERN.h>
#include <perl.h>
#include <XSUB.h>

#include <apr.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include <apr_hash.h>
#include <apr_tables.h>

#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 <Python.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>

#include <apr_pools.h>
#include <apr_hash.h>
#include <apr_portable.h>
#include <apr_thread_proc.h>

#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 <Python.h>

#include <apr.h>
#include <apr_pools.h>
#include <apr_strings.h>
#include <apr_hash.h>
#include <apr_tables.h>

#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