Vendor import svn-1.14.0.
This commit is contained in:
parent
ad2fc96c38
commit
68dcf7776f
@ -7,3 +7,13 @@ indent_style = space
|
||||
indent_size = 2
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = false
|
||||
|
||||
[**/Makefile*]
|
||||
indent_style = tab
|
||||
|
||||
[build-outputs.mk]
|
||||
indent_style = tab
|
||||
|
||||
[build/generator/templates/build-outputs.mk.ezt]
|
||||
indent_style = tab
|
||||
|
||||
|
0
.swig_pl_checked
Normal file
0
.swig_pl_checked
Normal file
0
.swig_py_checked
Normal file
0
.swig_py_checked
Normal file
0
.swig_rb_checked
Normal file
0
.swig_rb_checked
Normal file
409
CHANGES
409
CHANGES
@ -1,3 +1,323 @@
|
||||
# To view a revision listed as (rXXXXXXX), visit:
|
||||
# https://svn.apache.org/rXXXXXXX
|
||||
#
|
||||
# To view an issue listed as (issue #XXXX), visit:
|
||||
# https://subversion.apache.org/issue-XXXX
|
||||
|
||||
Version 1.14.0
|
||||
(6 May 2020, from /branches/1.14.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.14.0
|
||||
|
||||
User-visible changes:
|
||||
- Minor new features and improvements:
|
||||
* Experimental shelving feature is now disabled by default (r1875039)
|
||||
* Reinstate support for experimental shelving v2 from SVN 1.11 (r1875037)
|
||||
* Introduce 'svnadmin build-repcache' command (r1875921 et al)
|
||||
|
||||
- Client-side improvements and bugfixes:
|
||||
* Add 'changelist' option to 'svn info --show-item' (r1869481)
|
||||
* Allow simultaneous use of 'svn log' --quiet and --diff options (r1871916)
|
||||
* Fix 'svn info' for file that was inside replaced directory (issue #4837)
|
||||
* Don't abort if the server redirects to a non-canonical URL (r1873375)
|
||||
* Fix merge assertion failure in svn_sort__array_insert (issue #4840)
|
||||
* Escape filenames when invoking $SVN_EDITOR (r1874057 et al)
|
||||
* Small performance optimization for FSFS rep-cache.db (r1875918)
|
||||
* Fix a crash seen when using git-svn with kwallet (r1875680)
|
||||
|
||||
- Server-side improvements and bugfixes:
|
||||
* Fix 'svnadmin load --normalize-props' for versioned properties (r1868203)
|
||||
* mailer.py: prevent SMTP errors from impeding later emails (issue #1804)
|
||||
* mailer.py: Add option to specify the SMTP port to connect to (r1872398)
|
||||
* Make svn-backup-dump.py work on Python 3
|
||||
* validate-files.py: Fix handling for non-ASCII characters (r1874393)
|
||||
* Fix an undefined behavior problem in FSFS caching code (r1876054)
|
||||
|
||||
Developer-visible changes:
|
||||
* Require at least version 1.5 of APR (r1874094)
|
||||
* Support Python3 in the py-swig bindings; requires py3c (r1869354 et al)
|
||||
* Support building with SWIG 4 on Python 3.x (r1869853)
|
||||
* Fix svnserveautocheck for Python 3 (r1868151)
|
||||
* contribulyze.py: Support Python 3 in addition to Python 2 (r1871211)
|
||||
* Fix Proc.new warnings in Ruby bindings with Ruby >= 2.7 (r1876020)
|
||||
|
||||
Version 1.13.0
|
||||
(30 Oct 2019, from /branches/1.13.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.13.0
|
||||
|
||||
User-visible changes:
|
||||
- Minor new features and improvements:
|
||||
* New 'svnadmin rev-size' command to report revision size (r1857624)
|
||||
* In 'svn help', hide experimental commands and global options (issue #4828)
|
||||
* Add a hint about mod_dav_svn misconfiguration (r1866738)
|
||||
* Performance improvement for 'svn st' etc., in WC SQLite DB (r1865523)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Windows: avoid delays in SSL certificate validation override (r1863018)
|
||||
* Fix 'svn patch' setting mode 0600 on patched files with props (r1864440)
|
||||
* Fix "svn diff --changelist ARG" broken in subdirectories (issue #4822)
|
||||
* Fix misleading 'redirect cycle' error on a non-repository URL (r1866899)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* svnserve: Report some errors that we previously ignored (r1866062)
|
||||
* Make server code more resilient to malformed paths and URLs (r1866318 et al)
|
||||
* Make dump stream parser more resilient to malformed dump stream (r1866951)
|
||||
* mod_dav_svn: Fix missing Last-Modified header on 'external' GET requests (r1866425)
|
||||
|
||||
- Client-side and server-side bugfixes:
|
||||
* Fix excessive memory usage in some cases reading binary data (r1866950)
|
||||
* Win32: fix svn_io_file_rename2() spinning in a retry loop (r1865518)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* svn_load_dirs.pl: do not show password; fix cleanup (r1863262, r1863392)
|
||||
|
||||
Developer-visible changes:
|
||||
* New svn_fs_ioctl() API for FSFS stats, dump/load index, rev-size (r1857435)
|
||||
|
||||
|
||||
Version 1.12.2
|
||||
(24 Jul 2019, from /branches/1.12.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.12.2
|
||||
|
||||
User-visible changes:
|
||||
* Fix conflict resolver bug: local and incoming edits swapped. (r1863285)
|
||||
* Fix memory lifetime problem in a libsvn_wc error code path. (r1863287)
|
||||
* Faster Windows file existence checks, improving 'svn st' etc. (r1863289)
|
||||
|
||||
Developer-visible changes:
|
||||
* Allow generating Visual Studio 2019 projects (r1863286)
|
||||
* Fix build with APR 1.7.0. (r1860377)
|
||||
* Fix building Subversion with Visual Studio 2005 and 2008. (r1863288)
|
||||
* Allow svnserve's 'get-deleted-rev' API to return 'not deleted'. (r1863290)
|
||||
|
||||
|
||||
Version 1.12.1
|
||||
(Not released; see changes for 1.12.2.)
|
||||
|
||||
|
||||
Version 1.12.0
|
||||
(12 Apr 2019, from /branches/1.12.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.12.0
|
||||
|
||||
User-visible changes:
|
||||
- Major new features:
|
||||
|
||||
- Minor new features and improvements:
|
||||
* 'move vs. move' merge conflicts can now be resolved (r1846851, r1851913)
|
||||
* 'svn --version --verbose' shows loaded libraries on Linux (r1843774)
|
||||
* 'svnrdump' can read/write a file instead of stdin/stdout (r1844906)
|
||||
* 'svn list' tries to not truncate the author's name (r1847384 et al.)
|
||||
* 'svn list' can show sizes in base-2 unit suffixes (r1847384 et al.)
|
||||
* 'svn info' shows the size of files in the repository (r1847441 et al.)
|
||||
* 'svn cleanup' can remove read-only directories (#4806, r1854072 et al.)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Repos-to-WC copy with --parents works with absent target (r1843888)
|
||||
* Repos-to-WC copy from foreign repo with peg/operative revs (#4785)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* Ignore empty group definitions in authz files (#4802, r1851687)
|
||||
|
||||
- Client-side and server-side bugfixes:
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* svnauthz: warn about empty groups in authz files (#4803, r1851823)
|
||||
* Storing passwords in plain text on disk is disabled by default (r1845377)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* Updated the required libtool version to 2.x (r1845716)
|
||||
* get-deps.sh: Remove references to Googlemock and Googletest (r1849200)
|
||||
* All C++ code is compiled in C++11 mode by default (r1849202)
|
||||
|
||||
- Bindings:
|
||||
* JavaHL: Fixed potential core dump in ISVNClient.diff (r1845408)
|
||||
* JavaHL: Let clients decode file contents from ISVNClient.blame (r1851333)
|
||||
|
||||
|
||||
Version 1.11.1
|
||||
(11 Jan 2019, from /branches/1.11.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.11.1
|
||||
|
||||
User-visible changes:
|
||||
- Minor new features and improvements:
|
||||
* Conflict resolver support for added vs unversioned file (r1845577)
|
||||
* Conflict resolver support for unversioned directories (r1846299)
|
||||
* Improve help for 'svn add' and the '-N' option (r1842814 et al.)
|
||||
* Improve display of Mac OS name in 'svn --version --verbose' (r1842334)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Fix: repos-to-WC copy with --parents doesn't create dirs (#4768)
|
||||
* Fix: foreign repo copy with peg/operative revisions (#4785)
|
||||
* Fix: foreign repo copy of file adding mergeinfo (#4792)
|
||||
* Fix: assertion failure using -rPREV on a working copy at r0 (#4532)
|
||||
* Fix: tree conflict message ends a sentence with a colon (#4717)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* Fix CVE-2018-11803: malicious SVN clients can crash mod_dav_svn
|
||||
* Fix: unexpected SVN_ERR_FS_NOT_DIRECTORY errors (#4791)
|
||||
* Fix: mod_dav_svn's SVNUseUTF8 had no effect in some setups (r1844882)
|
||||
* Fix crash in mod_http2 (#4782)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* svndumpfilter: Clarify error messages by including node path (r1845261)
|
||||
|
||||
- Bindings bugfixes:
|
||||
* JavaHL: Fix crash in client code when using external diff (r1845408)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* Fix build on systems without python in $PATH (r1845555)
|
||||
* Fix compiler warnings about indentation (r1845556 et al.)
|
||||
|
||||
- API changes:
|
||||
(none)
|
||||
|
||||
|
||||
Version 1.11.0
|
||||
(30 Oct 2018, from /branches/1.11.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.11.0
|
||||
|
||||
User-visible changes:
|
||||
- Major new features:
|
||||
* Shelving is no longer based on patch files (experimental) (issue #3625)
|
||||
* Checkpointing (experimental) (issue #3626)
|
||||
* Viewspec output command (experimental) (issue #4753)
|
||||
|
||||
- Minor new features and improvements:
|
||||
* Improvements to tree conflict resolution (issue #4694 #4766 ...)
|
||||
* 'patch' can now read non-pretty-printed svn:mergeinfo diffs (r1822151)
|
||||
* Better error when http:// URL is not a Subversion repository (r1825302)
|
||||
* Add 'schedule' and 'depth' items to 'svn info --show-item' (r1827032)
|
||||
* Allow the client cert password to be saved (r1836762)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Fix a crash in a repo:WC summary diff of a local copy (r1835218)
|
||||
* Fix double diff headers (r1836746)
|
||||
* Tree conflict resolver: avoid endless scan in some cases (r1839662)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* svnadmin dump shouldn't canonicalize svn:date (issue #4767)
|
||||
* 'svnadmin verify --keep-going --quiet' shows an error summary (r1837790)
|
||||
* Let 'svnadmin recover' prune the rep-cache even if disabled (r1838813)
|
||||
|
||||
- Client-side and server-side bugfixes:
|
||||
* Fix pattern-matching of top level path in listing with search (r1830599)
|
||||
* Allow commands like 'svn ci --file X' to work when X is a FIFO (r1836306)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* tools/client-side/bash_completion: Add '--password-from-stdin' (r1820045)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* new tool: tools/dist/edit-N-log-messages (r1819207)
|
||||
* tools/dev/unix-build/Makefile.svn: various fixes
|
||||
* Expose the diff option 'pretty_print_mergeinfo' in APIs (r1822014)
|
||||
* In 'revert' APIs, choose whether to delete schedule-add nodes (r1822534)
|
||||
|
||||
- Bindings:
|
||||
* Fix Python binding fs.FileDiff behaviour with python-future (r1823802)
|
||||
* Fix Python unit test, fs.SubversionFSTestCase, on Windows (r1824410)
|
||||
* Bump minimum JDK version required for JavaHL to 1.8 (r1831895)
|
||||
* Enable building against Java 10 (r1841180 et al)
|
||||
* Fix a potential crash in JavaHL (issue #4764)
|
||||
|
||||
|
||||
Version 1.10.6
|
||||
(24 Jul 2019, from /branches/1.10.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.10.6
|
||||
|
||||
User-visible changes:
|
||||
* Allow the use of empty groups in authz rules. (r1854883)
|
||||
* Fix conflict resolver case with move vs move conflicts. (r1863297)
|
||||
* Fix #4760: Missing children in svnadmin dump --include/exclude. (r1863298)
|
||||
* Fix #4793: authz rights from inverted access selectors. (r1854882)
|
||||
* Fix conflict resolver bug: local and incoming edits swapped. (r1863300)
|
||||
* Fix #4806: Remove on-disk trees with read-only dirs. (r1863299)
|
||||
* Fix memory lifetime problem in a libsvn_wc error code path. (r1863302)
|
||||
* No tree conflict when 'svn up' deletes unmodified dir with unversioned items. (r1863296)
|
||||
* Remove a useless common ancestor search from conflict resolver. (r1863294)
|
||||
|
||||
Developer-visible changes:
|
||||
* Allow generating Visual Studio 2019 projects (r1863304)
|
||||
* Fix a use-after-free in mod_dav_svn's logging of FS warnings. (r1863292)
|
||||
* Fix "unused static function" warning in release-mode builds. (r1854884)
|
||||
* Fix build with APR 1.7.0. (r1863303)
|
||||
* Fix issue #4804: spurious SQLite-related test failures. (r1863295)
|
||||
* Allow svnserve's 'get-deleted-rev' API to return 'not deleted'. (r1863305)
|
||||
* Silence a deprecation warning from amalgamated SQLite on macOS. (r1863291)
|
||||
|
||||
|
||||
Version 1.10.5
|
||||
(Not released; see changes for 1.10.6.)
|
||||
|
||||
|
||||
Version 1.10.4
|
||||
(11 Jan 2019, from /branches/1.10.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.10.4
|
||||
|
||||
User-visible changes:
|
||||
- Minor new features and improvements:
|
||||
* Conflict resolver support for added vs unversioned file (r1845577)
|
||||
* Conflict resolver support for unversioned directories (r1846299)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Fix: repos-to-WC copy with --parents doesn't create dirs (#4768)
|
||||
* Fix: foreign repo copy with peg/operative revisions (#4785)
|
||||
* Fix: foreign repo copy of file adding mergeinfo (#4792)
|
||||
* Fix: assertion failure using -rPREV on a working copy at r0 (#4532)
|
||||
* Fix: tree conflict message ends a sentence with a colon (#4717)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* Fix CVE-2018-11803: malicious SVN clients can crash mod_dav_svn
|
||||
* Fix: unexpected SVN_ERR_FS_NOT_DIRECTORY errors (#4791)
|
||||
* Fix: mod_dav_svn's SVNUseUTF8 had no effect in some setups (r1844882)
|
||||
* Fix crash in mod_http2 (#4782)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* svndumpfilter: Clarify error messages by including node path (r1845261)
|
||||
|
||||
- Bindings bugfixes:
|
||||
* JavaHL: Fix crash in client code when using external diff (r1845408)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* Fix build on systems without python in $PATH (r1845555)
|
||||
|
||||
- API changes:
|
||||
(none)
|
||||
|
||||
|
||||
Version 1.10.3
|
||||
(10 Oct 2018, from /branches/1.10.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.10.3
|
||||
|
||||
User-visible changes:
|
||||
- Minor new features and improvements:
|
||||
* Store the HTTPS client cert password (r1842578)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* Fix shelving when custom diff command is configured (issue #4758)
|
||||
* Fix conflict resolver crashes (issue #4744, r1842581, r1842582, r1842583)
|
||||
* Fix conflict resolver endless scan in some cases (r1842586)
|
||||
* Fix "Accept incoming deletion" on locally deleted file (issue #4739)
|
||||
* Fix "resolver adds unrelated moves to move target list" (issue #4766)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* Reject bad PUT before CHECKOUT in v1 HTTP protocol (r1841281)
|
||||
* Let 'svnadmin recover' prune the rep-cache even if disabled (r1842585)
|
||||
|
||||
- Client-side and server-side bugfixes:
|
||||
* Allow commands like 'svn ci --file X' to work when X is a FIFO (r1841282)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* 'svnadmin verify --keep-going --quiet' shows an error summary (r1842584)
|
||||
* Fix error in german translation for 'svn help merge' (r1837038)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* Python tests use the current python executable (r1842626)
|
||||
|
||||
|
||||
Version 1.10.2
|
||||
(20 Jul 2018, from /branches/1.10.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.10.2
|
||||
@ -38,7 +358,7 @@ the 1.9 release: https://subversion.apache.org/docs/release-notes/1.10.html
|
||||
User-visible changes:
|
||||
- Major new features:
|
||||
* Better interactive conflict resolution for tree conflicts (r1687489 et al)
|
||||
* Wilcards and improved performance in path-based authorization (r1776832)
|
||||
* Wildcards and improved performance in path-based authorization (r1776832)
|
||||
* New experimental 'svn shelve' command (issue #3625)
|
||||
- Minor new features and improvements:
|
||||
* svnbench: Show time taken & bytes transferred (r1703383, r1710586)
|
||||
@ -59,7 +379,7 @@ the 1.9 release: https://subversion.apache.org/docs/release-notes/1.10.html
|
||||
* ra_serf: Adjustments for serf versions with HTTP/2 support (r1716400)
|
||||
* ra_serf: Send svndiff1 deltas during commit (r1704317, r1704613, r1791290)
|
||||
* ra_serf: Stream svndiff deltas w/o creating temporary files (r1803143 et al)
|
||||
* ra_serf: Don't necessarily request full MERGE reponses (r1806017 et al)
|
||||
* ra_serf: Don't necessarily request full MERGE responses (r1806017 et al)
|
||||
* 'svn patch': Parse binary diffs in git-style patches (r1703925)
|
||||
* 'svnadmin info' now reports latest revision in the repository (r1697953)
|
||||
* ra_svn: Various performance-related tweaks (r1694490)
|
||||
@ -316,6 +636,67 @@ the 1.9 release: https://subversion.apache.org/docs/release-notes/1.10.html
|
||||
* Ruby: Detect versions up to 2.4 (r1806570)
|
||||
|
||||
|
||||
Version 1.9.12
|
||||
(24 Jul 2019, from /branches/1.9.x)
|
||||
https://svn.apache.org/repos/asf/subversion/tags/1.9.12
|
||||
|
||||
User-visible changes:
|
||||
* No tree conflict when 'svn up' deletes unmodified dir with unversioned items. (r1863309)
|
||||
|
||||
Developer-visible changes:
|
||||
* Allow generating Visual Studio 2019 projects (r1863311)
|
||||
* Fix a use-after-free in mod_dav_svn's logging of FS warnings. (r1863307)
|
||||
* Fix "unused static function" warning in release-mode builds. (r1854881)
|
||||
* Fix build with APR 1.7.0. (r1863310)
|
||||
* Fix issue #4804: spurious SQLite-related test failures. (r1863308)
|
||||
* Allow svnserve's 'get-deleted-rev' API to return 'not deleted'. (r1863312)
|
||||
* Silence a deprecation warning from amalgamated SQLite on macOS. (r1863306)
|
||||
|
||||
|
||||
Version 1.9.11
|
||||
(Not released; see changes for 1.9.12.)
|
||||
|
||||
|
||||
Version 1.9.10
|
||||
(11 Jan 2019, from /branches/1.9.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.9.10
|
||||
|
||||
User-visible changes:
|
||||
- Client-side bugfixes:
|
||||
* Fix: repos-to-WC copy with --parents doesn't create dirs (#4768)
|
||||
* Fix: foreign repo copy with peg/operative revisions (#4785)
|
||||
* Fix: assertion failure using -rPREV on a working copy at r0 (#4532)
|
||||
* Fix: german translation for 'svn help merge' (r1837037)
|
||||
* Fix: prune externals after 'update --set-depth=exclude' (r1830883 et al.)
|
||||
* Fix: detection of GPG-agent (r1794166 et al.)
|
||||
* Fix: null updates don't update last-changed-revision (#4700)
|
||||
* Fix: merge "Unable to parse reversed revision range" (#4686)
|
||||
|
||||
- Server-side bugfixes:
|
||||
* Fix: unexpected SVN_ERR_FS_NOT_DIRECTORY errors (#4791)
|
||||
* Fix: mod_dav_svn's SVNUseUTF8 had no effect in some setups (r1844882)
|
||||
* Fix: crash in mod_http2 (#4782)
|
||||
* Fix: 'svnadmin upgrade' of BDB: Error out on too-new formats (r1804013)
|
||||
* Fix: Enforce v1 HTTP protocol: error if PUT before CHECKOUT (r1833465)
|
||||
* Fix: Let 'svnadmin recover' prune rep-cache even if disabled (r1838813)
|
||||
* Add test and FSFS checksum verification for issue #4722 (r1826720 et al.)
|
||||
|
||||
- Other tool improvements and bugfixes:
|
||||
* Install 'fsfs-stats' wrapper for 1.8 compat (r1802032 et al.)
|
||||
* Note that 'tools/client-side/detach.py' doesn't work on 1.8+ (r1696722)
|
||||
|
||||
- Bindings bugfixes:
|
||||
* JavaHL: Fix crash in client code when using external diff (r1845408)
|
||||
* JavaHL: SSL server trust prompt: allow accepting temporarily (r1820718)
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
(none)
|
||||
|
||||
- API changes:
|
||||
(none)
|
||||
|
||||
|
||||
Version 1.9.9
|
||||
(20 Jul 2018, from /branches/1.9.x)
|
||||
http://svn.apache.org/repos/asf/subversion/tags/1.9.9
|
||||
@ -948,7 +1329,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.9.0
|
||||
* cache: fix premature eviction due to 64-bit underflows (r1567996 et al)
|
||||
* svnserve: fix potential integer overflow in Cyrus SASL support (r1570434)
|
||||
* bdb: fix potential integer overflow and underflow (r1570701)
|
||||
* bdb: prevent silent propogation of some corruption (r1570778)
|
||||
* bdb: prevent silent propagation of some corruption (r1570778)
|
||||
* svnadmin hotcopy: do not corrupt db/current contents when copying old
|
||||
FSFS repos (r1603485)
|
||||
* svnadmin hotcopy: don't produce broken copies when a concurrent pack
|
||||
@ -1208,7 +1589,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.9.0
|
||||
ranges (r1569731)
|
||||
* svn_rangelist_inheritable2() and svn_mergeinfo_inheritable2(): fix a
|
||||
pool lifetime issue (r1569764)
|
||||
* new APIs to support cancelation during unified diff output and
|
||||
* new APIs to support cancellation during unified diff output and
|
||||
allow the context size to be specified (r1570149 et al)
|
||||
* APIs related to retrieving logs are now documented to be unlimited when
|
||||
a negative value is passed for the limit (r1570330, 1570335)
|
||||
@ -1326,7 +1707,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.9.0
|
||||
* swig-py: Add close to the core.Stream class (r1619077)
|
||||
* javahl: add example clients that use the authn API (r1640533)
|
||||
* swig-py: implement dump stream parser (r1642813)
|
||||
* swig-pl: remove some unneded cleanup code that triggered a cleanup
|
||||
* swig-pl: remove some unneeded cleanup code that triggered a cleanup
|
||||
failure on windows (r1643072)
|
||||
* swig-pl: make cancel_func, cancel_baton parameter pairs work (r1648852)
|
||||
* javahl: expose whitespace diff parameters to blame method (issue #4475)
|
||||
@ -1657,7 +2038,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.9
|
||||
- Client-side bugfixes:
|
||||
* log: use proper peg revision over DAV (r1568872)
|
||||
* upgrade: allow upgrading from 1.7 with exclusive locks (r1572102 et al)
|
||||
* proplist: resolve inconsitent inherited property results (r1575270 et al)
|
||||
* proplist: resolve inconsistent inherited property results (r1575270 et al)
|
||||
* increase minimal timestamp sleep from 1ms to 10ms (r1581305 et al)
|
||||
* merge: automatic merge confused by subtree merge (issue #4481)
|
||||
* propget: report proper error on invalid revision for url (r1586255)
|
||||
@ -1699,7 +2080,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.9
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* improve consistency checks of DAV inherited property requests (r1498000)
|
||||
* fix ocassional failure in autoprop_tests.py (r1567752)
|
||||
* fix occasional failure in autoprop_tests.py (r1567752)
|
||||
* avoid duplicate sqlite analyze information rows (r1571214)
|
||||
* add Mavericks to our sysinfo output (r1573088)
|
||||
* bump copyright years to 2014 (r1555403)
|
||||
@ -1752,7 +2133,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.8
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* fix ocassional failure of check_tests.py 12 (r1496127 et al)
|
||||
* fix occasional failure of check_tests.py 12 (r1496127 et al)
|
||||
* fix failure with SQLite 3.8.1-3.8.3 when built with
|
||||
SQLITE_ENABLE_STAT3/4 due to bug in SQLite (r1567286, r1567392)
|
||||
* specify SQLite defaults that can be changed when SQLite is built
|
||||
@ -1858,7 +2239,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.8.3
|
||||
- Client- and server-side bugfixes:
|
||||
* translation updates for Swedish
|
||||
* enforce strict version equality between tools and libraries (r1502267)
|
||||
* consistently output revisions as "r%ld" in error messags (r1499044 et al)
|
||||
* consistently output revisions as "r%ld" in error messages (r1499044 et al)
|
||||
|
||||
- Client-side bugfixes:
|
||||
* status: always use absolute paths in XML output (issue #4398)
|
||||
@ -2437,7 +2818,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.7.18
|
||||
|
||||
Developer-visible changes:
|
||||
- General:
|
||||
* fix ocassional failure in checkout_tests.py test 12. (r1496127)
|
||||
* fix occasional failure in checkout_tests.py test 12. (r1496127)
|
||||
* disable building ZLib's assembly optimizations on Windows.
|
||||
|
||||
|
||||
@ -3052,7 +3433,7 @@ the 1.6 release: http://subversion.apache.org/docs/release-notes/1.7.html
|
||||
* fixed: wc-to-wc copy of a switch source (issue #1802)
|
||||
* fixed: 'svn st' reports symlinks as obstructed items (issue #2284)
|
||||
* fixed: 'cd e:\; svn up e:\' fails (issue #2556)
|
||||
* fixed: svn aborts on commiting from root dir on windows (issue #3346)
|
||||
* fixed: svn aborts on committing from root dir on windows (issue #3346)
|
||||
* fixed: removing a dir scheduled for deletion corrupts wc (issue #2741)
|
||||
* fixed: 'svn cleanup' fails on obstructed paths (issue #2867)
|
||||
* fixed: case-only renames resulting from merges don't work (issue #3115)
|
||||
@ -3089,7 +3470,7 @@ the 1.6 release: http://subversion.apache.org/docs/release-notes/1.7.html
|
||||
* fixed: 'svn info' returns parent info on missing dirs (issue #3178)
|
||||
* fixed: spurious prop conflict with 'merge --reintegrate' (issue #3919)
|
||||
* fixed: 'svn --version' fails with non-existent $HOME (issue #3947)
|
||||
* fixed: unforced export silently overwites existing file (issue #3799)
|
||||
* fixed: unforced export silently overwrites existing file (issue #3799)
|
||||
* fixed: reverse merge which adds subtree mergeinfo fails (issue #3978)
|
||||
* fixed: 'svn up -r{R>HEAD}' hangs client over ra_svn (issue #3963)
|
||||
* fixed: 'svn up' updates file externals in target siblings (issue #3819)
|
||||
@ -3433,7 +3814,7 @@ http://svn.apache.org/repos/asf/subversion/tags/1.6.11
|
||||
Developer-visible changes:
|
||||
* disable checks for wc-ng working copies when running the test suite
|
||||
* on Windows, don't ignore move operation error codes (r896915)
|
||||
* more precise reporting of errors occuring with sqlite init (r927323, -8)
|
||||
* more precise reporting of errors occurring with sqlite init (r927323, -8)
|
||||
* ensure rangelist APIs are commutative (r923389, -91)
|
||||
|
||||
|
||||
@ -6796,7 +7177,7 @@ Version 0.9 (released 15 Feb 2002, revision 1302)
|
||||
- no more 'path styles' in path library
|
||||
- rewrite bootstrapping code for python test framework
|
||||
- rewrite commandline app's help-system and alias-system
|
||||
- feedback table replaced with notfication callback
|
||||
- feedback table replaced with notification callback
|
||||
- rewrite sorting of hashes
|
||||
- svnadmin internal rewrite
|
||||
- faster post-update processing
|
||||
|
@ -61,6 +61,9 @@ Blanket commit access:
|
||||
astieger Andreas Stieger <andreas.stieger@gmx.de>
|
||||
jamessan James McCoy <jamessan@jamessan.com>
|
||||
luke1410 Stefan Hett <luke1410@posteo.de>
|
||||
troycurtisjr Troy Curtis, Jr <troycurtisjr@gmail.com>
|
||||
hartmannathan Nathan Hartman <hartman.nathan@gmail.com>
|
||||
futatuki Yasuhito Futatsuki <futatuki@yf.bsdclub.org>
|
||||
|
||||
[[END ACTIVE FULL COMMITTERS. LEAVE THIS LINE HERE; SCRIPTS LOOK FOR IT.]]
|
||||
|
||||
@ -104,7 +107,6 @@ Commit access for specific areas:
|
||||
rschupp Roderich Schupp <roderich.schupp@gmail.com> (Swig bindings)
|
||||
stilor Alexey Neyman <stilor@att.net> (Python bindings,
|
||||
svn-vendor.py)
|
||||
troycurtisjr Troy Curtis, Jr <troycurtisjr@gmail.com> (Swig bindings)
|
||||
|
||||
Packages:
|
||||
|
||||
|
263
INSTALL
263
INSTALL
@ -3,7 +3,7 @@
|
||||
A Quick Guide
|
||||
======================================
|
||||
|
||||
$LastChangedDate: 2017-12-25 04:00:08 +0000 (Mon, 25 Dec 2017) $
|
||||
$LastChangedDate: 2020-02-17 03:49:42 +0000 (Mon, 17 Feb 2020) $
|
||||
|
||||
|
||||
Contents:
|
||||
@ -23,8 +23,8 @@ Contents:
|
||||
|
||||
III. BUILDING A SUBVERSION SERVER
|
||||
A. Setting Up Apache Httpd
|
||||
B. Making and Installing the Subversion Server
|
||||
C. Configuring Apache for Subversion
|
||||
B. Making and Installing the Subversion Apache Server Module
|
||||
C. Configuring Apache Httpd for Subversion
|
||||
D. Running and Testing
|
||||
E. Alternative: 'svnserve' and ra_svn
|
||||
|
||||
@ -96,6 +96,11 @@ I. INTRODUCTION
|
||||
These diff streams are used everywhere -- over the network,
|
||||
in the repository, and in the client's working copy.
|
||||
|
||||
* utf8proc (REQUIRED for client and server)
|
||||
|
||||
Subversion uses utf8proc for UTF-8 support, including Unicode
|
||||
normalization.
|
||||
|
||||
* Apache Serf (OPTIONAL for client)
|
||||
|
||||
The Apache Serf library allows the Subversion client to send HTTP
|
||||
@ -116,21 +121,21 @@ I. INTRODUCTION
|
||||
|
||||
* Netwide Assembler (OPTIONAL for client and server)
|
||||
|
||||
The Netwide Assembler (NASM) is used to build the (optionally)
|
||||
The Netwide Assembler (NASM) is used to build the (optional)
|
||||
assembler modules of OpenSSL. As of OpenSSL 1.1.0 NASM is the
|
||||
only supported assembler.
|
||||
|
||||
* Berkeley DB (OPTIONAL for client and server)
|
||||
* Berkeley DB (DEPRECATED and OPTIONAL for client and server)
|
||||
|
||||
There are two different repository 'back-end'
|
||||
implementations. One implementation stores data in a flat
|
||||
filesystem (known as FSFS); the other implementation stores
|
||||
data in a Berkeley DB database (known as BDB). When you
|
||||
create a repository, you have the option of specifying a
|
||||
storage back-end. The Berkeley DB back-end will only be
|
||||
available if the BDB libraries are discovered at compile
|
||||
time. The Berkeley DB back-end has been deprecated and
|
||||
is not recommend.
|
||||
When you create a repository, you have the option of
|
||||
specifying a storage 'back-end' implementation. Currently,
|
||||
there are two options. The newer and recommended one, known
|
||||
as FSFS, does not require Berkeley DB. FSFS stores data in a
|
||||
flat filesystem. The older implementation, known as BDB, has
|
||||
been deprecated and is not recommended for new repositories,
|
||||
but is still available. BDB stores data in a Berkeley DB
|
||||
database. This back-end will only be available if the BDB
|
||||
libraries are discovered at compile time.
|
||||
|
||||
* libsasl (OPTIONAL for client and server)
|
||||
|
||||
@ -147,10 +152,16 @@ I. INTRODUCTION
|
||||
for other languages, you need to have those languages
|
||||
available at build time.
|
||||
|
||||
* KDELibs, GNOME Keyring (OPTIONAL for client)
|
||||
* py3c (OPTIONAL, but REQUIRED for Python bindings)
|
||||
|
||||
The Python 3 Compatibility Layer for C Extensions is required
|
||||
to build the Python language bindings.
|
||||
|
||||
* KDE Framework 5, libsecret, GNOME Keyring (OPTIONAL for client)
|
||||
|
||||
Subversion contains optional support for storing passwords in
|
||||
KWallet (KDE 4) or GNOME Keyring.
|
||||
KWallet via KDE Framework 5 libraries (preferred) or kdelibs4,
|
||||
and GNOME Keyring via libsecret (preferred) or GNOME APIs.
|
||||
|
||||
* libmagic (OPTIONAL)
|
||||
|
||||
@ -160,10 +171,6 @@ I. INTRODUCTION
|
||||
configured via auto-props or the mime-types-file option
|
||||
take precedence.
|
||||
|
||||
* Googlemock aka Gmock (OPTIONAL)
|
||||
|
||||
This optional package is used by the tests for Subversions'
|
||||
C++ bindings.
|
||||
|
||||
|
||||
C. Dependencies in Detail
|
||||
@ -199,7 +206,7 @@ I. INTRODUCTION
|
||||
commands described in section II.B before installing the following.
|
||||
|
||||
|
||||
1. Apache Portable Runtime 1.3 or newer (REQUIRED)
|
||||
1. Apache Portable Runtime 1.5 or newer (REQUIRED)
|
||||
|
||||
Whenever you want to build any part of Subversion, you need the
|
||||
Apache Portable Runtime (APR) and the APR Utility (APR-util)
|
||||
@ -253,22 +260,55 @@ I. INTRODUCTION
|
||||
configure script.
|
||||
|
||||
|
||||
2. Zlib (REQUIRED)
|
||||
2. SQLite (REQUIRED)
|
||||
|
||||
Subversion requires SQLite version 3.8.2 or above. You can meet this
|
||||
dependency several ways:
|
||||
* Use an SQLite amalgamation file.
|
||||
* Specify an SQLite installation to use.
|
||||
* Let Subversion find an installed SQLite.
|
||||
|
||||
To use an SQLite-provided amalgamation, just drop sqlite3.c into
|
||||
Subversion's sqlite-amalgamation/ directory, or point to it with the
|
||||
--with-sqlite configure option. This file also ships with the Subversion
|
||||
dependencies distribution, or you can download it from SQLite:
|
||||
|
||||
https://www.sqlite.org/download.html
|
||||
|
||||
|
||||
3. Zlib (REQUIRED)
|
||||
|
||||
Subversion's binary-differencing engine depends on zlib for
|
||||
compression. Most Unix systems have libz pre-installed, but
|
||||
if you need it, you can get it from
|
||||
compression. Most Unix systems have libz pre-installed, but if
|
||||
you need it, you can get it from
|
||||
|
||||
http://www.zlib.net/
|
||||
|
||||
|
||||
3. autoconf 2.59 or newer (Unix only)
|
||||
4. utf8proc (REQUIRED)
|
||||
|
||||
Subversion uses utf8proc for UTF-8 support. Configure will
|
||||
attempt to locate utf8proc by default using pkg-config and known
|
||||
paths.
|
||||
|
||||
If it is installed in a non-standard location, then use:
|
||||
|
||||
--with-utf8proc=/path/to/libutf8proc
|
||||
|
||||
Alternatively, a copy of utf8proc comes bundled with the
|
||||
Subversion sources. If configure should use the bundled copy,
|
||||
use:
|
||||
|
||||
--with-utf8proc=internal
|
||||
|
||||
|
||||
5. autoconf 2.59 or newer (Unix only)
|
||||
|
||||
This is required only if you plan to build from the latest source
|
||||
(see section II.B). Generally only developers would be doing this.
|
||||
|
||||
|
||||
4. libtool 1.4 or newer (Unix only)
|
||||
6. libtool 1.4 or newer (Unix only)
|
||||
|
||||
This is required only if you plan to build from the latest source
|
||||
(see section II.B).
|
||||
@ -277,7 +317,7 @@ I. INTRODUCTION
|
||||
newer. The autogen.sh script knows about that.
|
||||
|
||||
|
||||
5. Apache Serf library 1.3.4 or newer (OPTIONAL)
|
||||
7. Apache Serf library 1.3.4 or newer (OPTIONAL)
|
||||
|
||||
If you want your client to be able to speak to an Apache
|
||||
server (via a http:// or https:// URL), you must link against
|
||||
@ -292,12 +332,13 @@ I. INTRODUCTION
|
||||
instead.
|
||||
|
||||
Apache Serf can be obtained via your system's package distribution
|
||||
system or directly from http://code.google.com/p/serf/.
|
||||
system or directly from https://serf.apache.org/.
|
||||
|
||||
For more information on Apache Serf and Subversion's ra_serf, see the
|
||||
file subversion/libsvn_ra_serf/README.
|
||||
|
||||
6. OpenSSL (OPTIONAL)
|
||||
|
||||
8. OpenSSL (OPTIONAL)
|
||||
|
||||
### needs some updates. I think Apache Serf automagically handles
|
||||
### finding OpenSSL, but we may need more docco here. and w.r.t
|
||||
@ -343,17 +384,25 @@ I. INTRODUCTION
|
||||
https://www.openssl.org/
|
||||
|
||||
|
||||
7. Berkeley DB 4.X (OPTIONAL)
|
||||
9. Berkeley DB 4.X (DEPRECATED and OPTIONAL)
|
||||
|
||||
Berkeley DB is needed to build a Subversion server that supports
|
||||
the BDB repository filesystem, or to access a BDB repository on
|
||||
local disk. If you will only use the FSFS repository filesystem,
|
||||
or if you are building a Subversion client that will only speak
|
||||
to remote (networked) repositories, you don't need it.
|
||||
You need the Berkeley DB libraries only if you are building a
|
||||
Subversion server that supports the older BDB repository storage
|
||||
back-end, or a Subversion client that can access local BDB
|
||||
repositories via the file:// URI scheme.
|
||||
|
||||
The current recommended version is 4.4.20 or newer, which brings
|
||||
auto-recovery functionality to the Berkeley DB database
|
||||
environment.
|
||||
The BDB back-end has been deprecated and is not recommended for
|
||||
new repositories. BDB may be removed in Subversion 2.0. We
|
||||
recommend the newer FSFS back-end for all new repositories.
|
||||
FSFS does not require the Berkeley DB libraries.
|
||||
|
||||
If in doubt, the 'svnadmin info' command, added in Subversion
|
||||
1.9, can identify whether an existing repository uses BDB or
|
||||
FSFS.
|
||||
|
||||
The current recommended version of Berkeley DB is 4.4.20 or
|
||||
newer, which brings auto-recovery functionality to the Berkeley
|
||||
DB database environment.
|
||||
|
||||
If you must use an older version of Berkeley DB, we *strongly*
|
||||
recommend using 4.3 or 4.2 over the 4.1 or 4.0 versions. Not
|
||||
@ -386,7 +435,7 @@ I. INTRODUCTION
|
||||
Look in the "Releases > Windows > Windows BDB" section.
|
||||
|
||||
|
||||
8. Cyrus SASL library (OPTIONAL)
|
||||
10. Cyrus SASL library (OPTIONAL)
|
||||
|
||||
If the Simple Authentication and Security Layer (SASL) library
|
||||
is detected on your system, then the Subversion client and
|
||||
@ -397,7 +446,7 @@ I. INTRODUCTION
|
||||
http://freshmeat.net/projects/cyrussasl/
|
||||
|
||||
|
||||
9. Apache Web Server 2.2.X or newer (OPTIONAL)
|
||||
11. Apache Web Server 2.2.X or newer (OPTIONAL)
|
||||
|
||||
(https://httpd.apache.org/download.cgi)
|
||||
|
||||
@ -410,78 +459,103 @@ I. INTRODUCTION
|
||||
is done: See section III for details.
|
||||
|
||||
|
||||
10. Python 2.7 or newer (https://www.python.org/) (OPTIONAL)
|
||||
12. Python 3.x or newer (https://www.python.org/) (OPTIONAL)
|
||||
|
||||
If you want to run "make check" or build from the latest source
|
||||
under Unix/Windows as described in section II.B, II.E and III.D,
|
||||
install Python 2.7 or higher on your system. The majority of the
|
||||
test suite is written in Python, as is part of Subversion's build
|
||||
system.
|
||||
Subversion does not require Python for its basic operation.
|
||||
However, Python is required for building and testing Subversion
|
||||
and for using Subversion's SWIG Python bindings or hook scripts
|
||||
coded in Python.
|
||||
|
||||
Note that Python 3.x is not supported and most likely won't work.
|
||||
The majority of Subversion's test suite is written in Python, as
|
||||
is part of Subversion's build system.
|
||||
|
||||
In more detail, Python is required to do any of the following:
|
||||
|
||||
* Use the SWIG Python bindings.
|
||||
* Use the ctypes Python bindings.
|
||||
* Use hook scripts coded in Python.
|
||||
* Build Subversion from a tarball on Unix-like systems and run
|
||||
Subversion's test suite as described in section II.B.
|
||||
* Build Subversion on Windows as described in section II.E.
|
||||
* Build Subversion from a working copy checked out from
|
||||
Subversion's own repository (whether or not running the test
|
||||
suite).
|
||||
* Build the SWIG Python bindings.
|
||||
* Build the ctypes Python bindings.
|
||||
* Testing as described in section III.D.
|
||||
|
||||
The Python bindings are used by:
|
||||
|
||||
* Third-party programs (e.g., ViewVC)
|
||||
* Scripts distributed with Subversion itself in the tools/
|
||||
subdirectory.
|
||||
* Any in-house scripts you may have.
|
||||
|
||||
Python is NOT required to do any of the following:
|
||||
|
||||
* Use the core command-line binaries (svn, svnadmin, svnsync,
|
||||
etc.)
|
||||
* Use Subversion's C libraries.
|
||||
* Use any of Subversion's other language bindings.
|
||||
* Build Subversion from a tarball on Unix-like systems without
|
||||
running Subversion's test suite
|
||||
|
||||
Although this section calls for Python 3.x, Subversion still
|
||||
technically works with Python 2.7. However, Support for Python
|
||||
2.7 is being phased out. As of 1 January 2020, Python 2.7 has
|
||||
reached end of life. All users are strongly encouraged to move
|
||||
to Python 3.
|
||||
|
||||
|
||||
11. Perl 5.8 or newer (Windows only) (OPTIONAL)
|
||||
13. Perl 5.8 or newer (Windows only) (OPTIONAL)
|
||||
|
||||
To build Subversion under any of the MS Windows platforms, you
|
||||
will also need Perl 5.8 or newer to run apr-util's w32locatedb.pl
|
||||
script.
|
||||
|
||||
|
||||
12. SQLite (REQUIRED)
|
||||
|
||||
Subversion requires SQLite version 3.8.2 or above. You can meet this
|
||||
dependency several ways:
|
||||
* Use an SQLite amalgamation file.
|
||||
* Specify an SQLite installation to use.
|
||||
* Let Subversion find an installed SQLite.
|
||||
|
||||
To use an SQLite-provided amalgamation, just drop sqlite3.c into
|
||||
Subversion's sqlite-amalgamation/ directory, or point to it with the
|
||||
--with-sqlite configure option. This file also ships with the Subversion
|
||||
dependencies distribution, or you can download it from SQLite:
|
||||
|
||||
https://www.sqlite.org/download.html
|
||||
|
||||
|
||||
13. pkg-config (Unix only, OPTIONAL)
|
||||
14. pkg-config (Unix only, OPTIONAL)
|
||||
|
||||
Subversion uses pkg-config to find appropriate options used
|
||||
at build time.
|
||||
|
||||
|
||||
14. D-Bus (Unix only, OPTIONAL)
|
||||
15. D-Bus (Unix only, OPTIONAL)
|
||||
|
||||
D-Bus is a message bus system. D-Bus is required for support for KWallet
|
||||
and GNOME Keyring. pkg-config is needed to find D-Bus headers and library.
|
||||
|
||||
|
||||
15. Qt 4 (Unix only, OPTIONAL)
|
||||
16. Qt 5 or Qt 4 (Unix only, OPTIONAL)
|
||||
|
||||
Qt is a cross-platform application framework. QtCore, QtDBus and QtGui
|
||||
modules are required for support for KWallet. pkg-config is needed
|
||||
to find Qt headers and libraries.
|
||||
|
||||
|
||||
16. KDELibs 4 (Unix only, OPTIONAL)
|
||||
17. KDE 5 Framework libraries or KDELibs 4 (Unix only, OPTIONAL)
|
||||
|
||||
Subversion contains optional support for storing passwords in KWallet.
|
||||
Subversion will look for KF5Wallet, KF5CoreAddons, KF5I18n APIs by default,
|
||||
and needs kf5-config to find them. The KDELibs 4 api is also supported.
|
||||
KDELibs contains core KDE libraries. Subversion uses libkdecore and libkdeui
|
||||
libraries when support for KWallet is enabled. kde4-config is used to get
|
||||
some necessary options. pkg-config, D-Bus and Qt 4 are also required.
|
||||
|
||||
If you want to build support for KWallet, then pass the '--with-kwallet'
|
||||
option to `configure`. If KDE is installed in a non-standard prefix, then
|
||||
use:
|
||||
|
||||
--with-kwallet=/path/to/KDE/prefix
|
||||
|
||||
17. GLib 2 (Unix only, OPTIONAL)
|
||||
|
||||
18. GLib 2 (Unix only, OPTIONAL)
|
||||
|
||||
GLib is a general-purpose utility library. GLib is required for support
|
||||
for GNOME Keyring. pkg-config is needed to find GLib headers and library.
|
||||
|
||||
|
||||
18. GNOME Keyring (Unix only, OPTIONAL)
|
||||
19. GNOME Keyring (Unix only, OPTIONAL)
|
||||
|
||||
Subversion contains optional support for storing passwords in GNOME Keyring.
|
||||
pkg-config is needed to find GNOME Keyring headers and library. D-Bus and
|
||||
@ -489,7 +563,7 @@ I. INTRODUCTION
|
||||
then pass the '--with-gnome-keyring' option to `configure`.
|
||||
|
||||
|
||||
19. Ctypesgen (OPTIONAL)
|
||||
20. Ctypesgen (OPTIONAL)
|
||||
|
||||
Ctypesgen is Python wrapper generator for ctypes. It is used to generate
|
||||
a part of Subversion Ctypes Python bindings (CSVN). If you want to build
|
||||
@ -500,7 +574,8 @@ I. INTRODUCTION
|
||||
|
||||
For more information on CSVN, see subversion/bindings/ctypes-python/README.
|
||||
|
||||
20. libmagic (OPTIONAL)
|
||||
|
||||
21. libmagic (OPTIONAL)
|
||||
|
||||
Subversion's configure script attempts to find libmagic automatically.
|
||||
If it is installed in a non-standard location, then use:
|
||||
@ -521,11 +596,6 @@ I. INTRODUCTION
|
||||
|
||||
--with-libmagic
|
||||
|
||||
21. Googlemock (OPTIONAL)
|
||||
|
||||
Googlemock can be installed and built in-tree by invoking
|
||||
|
||||
$ ./get-dep.sh gmock
|
||||
|
||||
22. LZ4 (OPTIONAL)
|
||||
|
||||
@ -540,6 +610,32 @@ I. INTRODUCTION
|
||||
If configure should use the version bundled with the sources, use:
|
||||
--with-lz4=internal
|
||||
|
||||
|
||||
23. py3c (OPTIONAL)
|
||||
|
||||
Subversion uses the Python 3 Compatibility Layer for C
|
||||
Extensions (py3c) library when building the Python language
|
||||
bindings.
|
||||
|
||||
As py3c is a header-only library, it is needed only to build the
|
||||
bindings, not to use them.
|
||||
|
||||
Configure will attempt to locate py3c by default using
|
||||
pkg-config and known paths.
|
||||
|
||||
If it is installed in a non-standard location, then use:
|
||||
|
||||
--with-py3c=/path/to/py3c/prefix
|
||||
|
||||
The library can be downloaded from GitHub:
|
||||
|
||||
https://github.com/encukou/py3c
|
||||
|
||||
On Unix systems, you can also use the provided get-deps.sh
|
||||
script to download py3c and several other dependencies; see the
|
||||
top of section I.C for more about get-deps.sh.
|
||||
|
||||
|
||||
D. Documentation
|
||||
|
||||
The primary documentation for Subversion is the free book
|
||||
@ -731,13 +827,12 @@ II. INSTALLATION
|
||||
Edition). Make sure you enable C++ support during setup.
|
||||
* Python 2.7 or higher, downloaded from https://www.python.org/ which is
|
||||
used to generate the project files.
|
||||
Note that Python 3.x is not supported (yet).
|
||||
* Perl 5.8 or higher from https://www.perl.org/get.html
|
||||
* Awk (from https://www.cs.princeton.edu/~bwk/btl.mirror/awk95.exe) is
|
||||
needed to compile Apache. Note that this is the actual awk program,
|
||||
not an installer - just rename it to awk.exe and it is ready to use.
|
||||
* Apache apr, apr-util, and optionally apr-iconv libraries, version
|
||||
1.3 or later (1.2 for apr-iconv). If you are building from a Subversion
|
||||
1.5 or later (1.2 for apr-iconv). If you are building from a Subversion
|
||||
checkout and have not downloaded Apache 2, then get these 3 libraries
|
||||
from https://www.apache.org/dist/apr/.
|
||||
* SQLite 3.8.2 or higher from https://www.sqlite.org/download.html
|
||||
@ -856,11 +951,7 @@ II. INSTALLATION
|
||||
|
||||
E.4 Building the Binaries
|
||||
|
||||
To build the binaries either follow the instructions here or use
|
||||
build\win32\vc6-build.bat.in after editing its default paths to match
|
||||
yours and saving it as vc6-build.bat. The vc6-build.bat does a full build
|
||||
using all options so it requires Apache 2 source and the other optional
|
||||
components.
|
||||
To build the binaries either follow these instructions.
|
||||
|
||||
Start in the SVN directory you created.
|
||||
|
||||
@ -922,7 +1013,7 @@ II. INSTALLATION
|
||||
C:>nmake -f Makefile.win
|
||||
C:>nmake -f Makefile.win install
|
||||
|
||||
Please refere to the build instructions provided by the library source
|
||||
Please refer to the build instructions provided by the library source
|
||||
for actual build instructions.
|
||||
|
||||
ZLib
|
||||
@ -931,7 +1022,7 @@ II. INSTALLATION
|
||||
Building ZLib using Visual Studio should be quite simple. Just open the
|
||||
appropriate solution and build the project zlibstat using the IDE.
|
||||
|
||||
Please refere to the build instructions provided by the library source
|
||||
Please refer to the build instructions provided by the library source
|
||||
for actual build instructions.
|
||||
|
||||
Note that you'd make sure to define ZLIB_WINAPI in the ZLib config
|
||||
|
21
LICENSE
21
LICENSE
@ -423,3 +423,24 @@ For the (modified) LZ4 library files in subversion/libsvn_subr/lz4
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
|
||||
THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
For the Autoconf Archive macros for Boost:
|
||||
|
||||
* in build/ac-macros/ax_boost_base.m4:
|
||||
|
||||
Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
|
||||
Copyright (c) 2009 Peter Adolphs
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty provided the copyright notice
|
||||
and this notice are preserved. This file is offered as-is, without any
|
||||
warranty.
|
||||
|
||||
* in build/ac-macros/ax_boost_unit_test_framework.m4:
|
||||
|
||||
Copyright (c) 2008 Thomas Porschberg <thomas@randspringer.de>
|
||||
|
||||
Copying and distribution of this file, with or without modification, are
|
||||
permitted in any medium without royalty provided the copyright notice
|
||||
and this notice are preserved. This file is offered as-is, without any
|
||||
warranty.
|
||||
|
55
Makefile.in
55
Makefile.in
@ -56,6 +56,8 @@ SVN_XML_LIBS = @SVN_XML_LIBS@
|
||||
SVN_ZLIB_LIBS = @SVN_ZLIB_LIBS@
|
||||
SVN_LZ4_LIBS = @SVN_LZ4_LIBS@
|
||||
SVN_UTF8PROC_LIBS = @SVN_UTF8PROC_LIBS@
|
||||
SVN_MACOS_PLIST_LIBS = @SVN_MACOS_PLIST_LIBS@
|
||||
SVN_MACOS_KEYCHAIN_LIBS = @SVN_MACOS_KEYCHAIN_LIBS@
|
||||
|
||||
LIBS = @LIBS@
|
||||
|
||||
@ -78,6 +80,9 @@ datadir = @datadir@
|
||||
datarootdir = @datarootdir@
|
||||
localedir = @localedir@
|
||||
|
||||
# where to install SVN++
|
||||
svnxx_libdir = @libdir@
|
||||
|
||||
# where to install libsvn_swig_*
|
||||
swig_py_libdir = @libdir@
|
||||
swig_pl_libdir = @libdir@
|
||||
@ -139,16 +144,17 @@ APACHE_INCLUDES = @APACHE_INCLUDES@
|
||||
APACHE_LIBEXECDIR = $(DESTDIR)@APACHE_LIBEXECDIR@
|
||||
APACHE_LDFLAGS = @APACHE_LDFLAGS@
|
||||
|
||||
SVN_USE_GOOGLEMOCK = @SVN_USE_GOOGLEMOCK@
|
||||
GOOGLEMOCK_INCLUDES = -I@GOOGLEMOCK_SRCDIR@/googlemock/include -I@GOOGLEMOCK_SRCDIR@/googletest/include
|
||||
GOOGLEMOCK_LIB_INCLUDES = -I@GOOGLEMOCK_SRCDIR@/googlemock -I@GOOGLEMOCK_SRCDIR@/googletest $(GOOGLEMOCK_INCLUDES)
|
||||
BOOST_TEST_CPPFLAGS = @BOOST_CPPFLAGS@ -DBOOST_TEST_DYN_LINK -DBOOST_TEST_NO_MAIN
|
||||
BOOST_TEST_LDFLAGS = @BOOST_LDFLAGS@ @BOOST_UNIT_TEST_FRAMEWORK_LIB@
|
||||
|
||||
SWIG = @SWIG@
|
||||
SWIG_PY_INCLUDES = @SWIG_PY_INCLUDES@ -I$(SWIG_SRC_DIR)/python/libsvn_swig_py
|
||||
SWIG_PY_INCLUDES = @SWIG_PY_INCLUDES@ @SVN_PY3C_INCLUDES@ -I$(SWIG_SRC_DIR)/python/libsvn_swig_py
|
||||
SWIG_PY_COMPILE = @SWIG_PY_COMPILE@
|
||||
SWIG_PY_LINK = @SWIG_PY_LINK@
|
||||
SWIG_PY_LIBS = @SWIG_PY_LIBS@
|
||||
SWIG_PY_ERRMSG = @SWIG_PY_ERRMSG@
|
||||
SWIG_PL_INCLUDES = @SWIG_PL_INCLUDES@
|
||||
SWIG_PL_ERRMSG = @SWIG_PL_ERRMSG@
|
||||
SWIG_RB_INCLUDES = @SWIG_RB_INCLUDES@ -I$(SWIG_SRC_DIR)/ruby/libsvn_swig_ruby
|
||||
SWIG_RB_COMPILE = @SWIG_RB_COMPILE@
|
||||
SWIG_RB_LINK = @SWIG_RB_LINK@
|
||||
@ -157,6 +163,7 @@ SWIG_RB_SITE_LIB_DIR = @SWIG_RB_SITE_LIB_DIR@
|
||||
SWIG_RB_SITE_ARCH_DIR = @SWIG_RB_SITE_ARCH_DIR@
|
||||
SWIG_RB_TEST_VERBOSE = @SWIG_RB_TEST_VERBOSE@
|
||||
SWIG_RB_RI_DATADIR = $(DESTDIR)$(datadir)/ri/$(RUBY_MAJOR).$(RUBY_MINOR)/site
|
||||
SWIG_RB_ERRMSG = @SWIG_RB_ERRMSG@
|
||||
|
||||
CTYPESGEN = @CTYPESGEN@
|
||||
CTYPES_PYTHON_SRC_DIR = $(abs_srcdir)/subversion/bindings/ctypes-python
|
||||
@ -164,7 +171,9 @@ CTYPES_PYTHON_SRC_DIR = $(abs_srcdir)/subversion/bindings/ctypes-python
|
||||
JAVAHL_JAR=subversion/bindings/javahl/svn-javahl.jar
|
||||
JAVAHL_INCLUDES= @JNI_INCLUDES@ -I$(abs_builddir)/subversion/bindings/javahl/include
|
||||
|
||||
CXXHL_INCLUDES = -I$(abs_srcdir)/subversion/bindings/cxxhl/include
|
||||
SVN_BUILD_SVNXX = @SVN_BUILD_SVNXX@
|
||||
SVN_BUILD_SVNXX_TESTS = @SVN_BUILD_SVNXX_TESTS@
|
||||
SVNXX_INCLUDES = -I$(abs_srcdir)/subversion/bindings/cxx/include
|
||||
|
||||
SVN_APR_CONFIG = @SVN_APR_CONFIG@
|
||||
SVN_APR_INCLUDES = @SVN_APR_INCLUDES@
|
||||
@ -194,6 +203,7 @@ SWIG_FEATURES = @SWIG_FEATURES@
|
||||
SWIG_PY_FEATURES = @SWIG_PY_FEATURES@
|
||||
SWIG_PL_FEATURES = @SWIG_PL_FEATURES@
|
||||
SWIG_RB_FEATURES = @SWIG_RB_FEATURES@
|
||||
SWIG_PY_OPTS = @SWIG_PY_OPTS@
|
||||
|
||||
COMPILE = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CMAINTAINERFLAGS) $(CFLAGS) $(INCLUDES)
|
||||
COMPILE_NOWARN = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CNOWARNFLAGS) $(CFLAGS) $(INCLUDES)
|
||||
@ -218,7 +228,6 @@ COMPILE_SWIG_RB = $(LIBTOOL) $(LTFLAGS) --mode=compile $(SWIG_RB_COMPILE) $(CPPF
|
||||
# special compilation for files destined for javahl (i.e. C++)
|
||||
COMPILE_JAVAHL_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=compile $(COMPILE_CXX) $(LT_CFLAGS) $(JAVAHL_INCLUDES) -o $@ -c
|
||||
COMPILE_JAVAHL_JAVAC = $(JAVAC) $(JAVAC_FLAGS)
|
||||
COMPILE_JAVAHL_JAVAH = $(JAVAH)
|
||||
COMPILE_JAVAHL_COMPAT_JAVAC = $(JAVAC) $(JAVAC_COMPAT_FLAGS)
|
||||
|
||||
# On Mac OS X, export an env variable so that the tests can run without
|
||||
@ -259,15 +268,15 @@ TEST_SHLIB_VAR_SWIG_RB=\
|
||||
export @SVN_APR_SHLIB_PATH_VAR@; \
|
||||
fi;
|
||||
|
||||
# special compilation for files destined for cxxhl
|
||||
COMPILE_CXXHL_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) -o $@ -c
|
||||
COMPILE_GOOGLEMOCK_CXX = $(LT_COMPILE_CXX_NOWARN) $(GOOGLEMOCK_LIB_INCLUDES) -o $@ -c
|
||||
COMPILE_CXXHL_GOOGLEMOCK_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) $(GOOGLEMOCK_INCLUDES) -o $@ -c
|
||||
# special compilation for files destined for SVN++
|
||||
COMPILE_SVNXX = $(LT_COMPILE_CXX) $(SVNXX_INCLUDES) -o $@ -c
|
||||
COMPILE_SVNXX_TEST = $(LT_COMPILE_CXX) $(SVNXX_INCLUDES) $(BOOST_TEST_CPPFLAGS) -o $@ -c
|
||||
|
||||
LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir)
|
||||
LINK_LIB = $(LINK) $(LT_SO_VERSION)
|
||||
LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS) $(LDFLAGS) -rpath $(libdir)
|
||||
LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION)
|
||||
LINK_SVNXX_TEST = $(LINK_CXX) $(BOOST_TEST_LDFLAGS)
|
||||
|
||||
# special link rule for mod_dav_svn
|
||||
LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS) -shared
|
||||
@ -321,6 +330,8 @@ INSTALL_DATA = $(INSTALL) -m 644
|
||||
INSTALL_LOCALE = $(INSTALL_DATA)
|
||||
INSTALL_APACHE_MODS = @INSTALL_APACHE_MODS@
|
||||
|
||||
INSTALL_SVNXX_LIB = $(INSTALL_LIB)
|
||||
|
||||
### this isn't correct yet
|
||||
INSTALL_SWIG_PY = $(INSTALL_LIB)
|
||||
INSTALL_SWIG_PY_LIB = $(INSTALL_LIB)
|
||||
@ -393,7 +404,6 @@ JAVAC = @JAVAC@
|
||||
JAVADOC = @JAVADOC@
|
||||
JAVAC_FLAGS = @JAVAC_FLAGS@
|
||||
JAVAC_COMPAT_FLAGS = @JAVAC_COMPAT_FLAGS@
|
||||
JAVAH = @JAVAH@
|
||||
JAR = @JAR@
|
||||
|
||||
JAVA_CLASSPATH=$(abs_srcdir)/subversion/bindings/javahl/src:@JAVA_CLASSPATH@
|
||||
@ -494,8 +504,8 @@ revision-install:
|
||||
install-static: @INSTALL_STATIC_RULES@
|
||||
|
||||
# JavaHL target aliases
|
||||
javahl: mkdir-init javahl-java javahl-javah javahl-callback-javah javahl-remote-javah javahl-types-javah javahl-util-javah javahl-lib @JAVAHL_TESTS_TARGET@ javahl-compat
|
||||
install-javahl: javahl install-javahl-java install-javahl-javah install-javahl-lib
|
||||
javahl: mkdir-init javahl-java javahl-callback-java javahl-remote-java javahl-types-java javahl-util-java javahl-lib @JAVAHL_TESTS_TARGET@ javahl-compat
|
||||
install-javahl: javahl install-javahl-java install-javahl-lib
|
||||
javahl-compat: javahl-compat-java @JAVAHL_COMPAT_TESTS_TARGET@
|
||||
|
||||
clean-javahl:
|
||||
@ -526,6 +536,9 @@ check-javahl: check-apache-javahl
|
||||
|
||||
check-all-javahl: check-apache-javahl check-tigris-javahl check-deprecated-authn-javahl
|
||||
|
||||
check-svnxx: svnxx-tests
|
||||
$(abs_builddir)/$(svnxx_tests_PATH)/svnxx-tests$(EXEEXT)
|
||||
|
||||
# "make check CLEANUP=true" will clean up directories for successful tests.
|
||||
# "make check TESTS=subversion/tests/cmdline/basic_tests.py"
|
||||
# will perform only basic tests (likewise for other tests).
|
||||
@ -601,6 +614,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@
|
||||
if test "$(FSFS_DIR_DELTIFICATION)" != ""; then \
|
||||
flags="--fsfs-dir-deltification $(FSFS_DIR_DELTIFICATION) $$flags";\
|
||||
fi; \
|
||||
if test "$(ALLOW_REMOTE_HTTP_CONNECTION)" != ""; then \
|
||||
flags="--allow-remote-http-connection $$flags"; \
|
||||
fi; \
|
||||
if test "$(SVN_BIN_DIR)" != ""; then \
|
||||
flags="--bin $(SVN_BIN_DIR) $$flags"; \
|
||||
fi; \
|
||||
@ -674,7 +690,7 @@ gcov-reset:
|
||||
gcov-clean:
|
||||
rm -f gcov-lcov.dat gcov-lcov.log gcov-genhtml.log
|
||||
rm -rf gcov-report
|
||||
find . -name "*.gcda" -o -name "*.gcno" -exec rm -f -- {} \;
|
||||
find . \( -name "*.gcda" -o -name "*.gcno" \) -exec rm -f -- {} \;
|
||||
|
||||
check-clean: gcov-clean
|
||||
if [ -d subversion/tests/cmdline/svn-test-work ]; then \
|
||||
@ -694,7 +710,8 @@ check-clean: gcov-clean
|
||||
subversion/tests/libsvn_diff/T1 \
|
||||
subversion/tests/libsvn_diff/T2 \
|
||||
subversion/tests/libsvn_diff/T3 \
|
||||
subversion/tests/svnserveautocheck.pid \
|
||||
subversion/tests/cmdline/httpd-* \
|
||||
subversion/tests/cmdline/svnserve-* \
|
||||
tests.log fails.log
|
||||
|
||||
mkdir-init:
|
||||
@ -895,6 +912,7 @@ EXTRACLEAN_SWIG_PL=rm -f $(SWIG_PL_SRC_DIR)/native/svn_*.c \
|
||||
# Makefile does not exist, DO NOT try to make it. But, if it doesn't exist,
|
||||
# then the directory is probably clean anyway.
|
||||
clean-swig-pl:
|
||||
rm -f .swig_pl_checked
|
||||
if test -z "$(RELEASE_MODE)"; then \
|
||||
$(EXTRACLEAN_SWIG_PL); \
|
||||
fi
|
||||
@ -917,6 +935,7 @@ copy-swig-py: autogen-swig-py $(SWIG_PY_DIR)/libsvn
|
||||
@for f in $(SWIG_PY_SRC_DIR)/*.py $(SWIG_PY_DIR)/*.py; do \
|
||||
! [ -f "$$f" ] || cp -pf $$f $(SWIG_PY_DIR)/libsvn; \
|
||||
done
|
||||
@cd $(SWIG_PY_DIR)/libsvn;ln -sf ../.libs/*.so .
|
||||
@touch $(SWIG_PY_DIR)/libsvn/__init__.py
|
||||
|
||||
swig-py: autogen-swig-py copy-swig-py
|
||||
@ -926,9 +945,10 @@ check-swig-py: swig-py
|
||||
cd $(SWIG_PY_DIR); \
|
||||
$(PYTHON) $(SWIG_PY_SRC_DIR)/tests/run_all.py
|
||||
|
||||
EXTRACLEAN_SWIG_PY=rm -rf $(SWIG_PY_SRC_DIR)/svn_*.c $(SWIG_PY_SRC_DIR)/core.c \
|
||||
$(SWIG_PY_SRC_DIR)/[a-z]*.py
|
||||
EXTRACLEAN_SWIG_PY=rm -rf $(SWIG_PY_DIR)/svn_*.c $(SWIG_PY_DIR)/core.c \
|
||||
$(SWIG_PY_DIR)/[a-z]*.py
|
||||
clean-swig-py:
|
||||
rm -f .swig_py_checked
|
||||
rm -rf $(SWIG_PY_DIR)/libsvn
|
||||
if test -z "$(RELEASE_MODE)"; then \
|
||||
$(EXTRACLEAN_SWIG_PY); \
|
||||
@ -961,6 +981,7 @@ check-swig-rb: swig-rb svnserve
|
||||
EXTRACLEAN_SWIG_RB=rm -f $(SWIG_RB_SRC_DIR)/svn_*.c $(SWIG_RB_SRC_DIR)/core.c
|
||||
|
||||
clean-swig-rb:
|
||||
rm -f .swig_rb_checked
|
||||
rm -rf $(SWIG_RB_DIR)/test/repos $(SWIG_RB_DIR)/test/wc
|
||||
if test -z "$(RELEASE_MODE)"; then \
|
||||
$(EXTRACLEAN_SWIG_RB); \
|
||||
|
5
NOTICE
5
NOTICE
@ -1,5 +1,5 @@
|
||||
Apache Subversion
|
||||
Copyright 2018 The Apache Software Foundation
|
||||
Copyright 2020 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by many people, and distributed
|
||||
under Contributor License Agreements to The Apache Software Foundation
|
||||
@ -29,3 +29,6 @@ license, see LICENSE.
|
||||
|
||||
This product includes code derived from the software developed by Yann Collet
|
||||
under a BSD 2-Clause license, see LICENSE.
|
||||
|
||||
This product includes code derived from the software developed by Thomas
|
||||
Porschberg and Peter Adolphs under a permissive license, see LICENSE.
|
||||
|
3
aclocal.m4
vendored
3
aclocal.m4
vendored
@ -35,6 +35,8 @@ sinclude(build/ac-macros/apache.m4)
|
||||
sinclude(build/ac-macros/apr.m4)
|
||||
sinclude(build/ac-macros/aprutil.m4)
|
||||
sinclude(build/ac-macros/apr_memcache.m4)
|
||||
sinclude(build/ac-macros/ax_boost_base.m4)
|
||||
sinclude(build/ac-macros/ax_boost_unit_test_framework.m4)
|
||||
sinclude(build/ac-macros/berkeley-db.m4)
|
||||
sinclude(build/ac-macros/compiler.m4)
|
||||
sinclude(build/ac-macros/ctypesgen.m4)
|
||||
@ -42,6 +44,7 @@ sinclude(build/ac-macros/java.m4)
|
||||
sinclude(build/ac-macros/sasl.m4)
|
||||
sinclude(build/ac-macros/serf.m4)
|
||||
sinclude(build/ac-macros/sqlite.m4)
|
||||
sinclude(build/ac-macros/py3c.m4)
|
||||
sinclude(build/ac-macros/swig.m4)
|
||||
sinclude(build/ac-macros/zlib.m4)
|
||||
sinclude(build/ac-macros/lz4.m4)
|
||||
|
@ -176,7 +176,7 @@ if test -n "$RELEASE_MODE"; then
|
||||
"$PYTHON" ./gen-make.py build.conf || gen_failed=1
|
||||
|
||||
# Build the SWIG-related files
|
||||
make -f autogen-standalone.mk autogen-swig
|
||||
make -f autogen-standalone.mk autogen-swig || gen_failed=1
|
||||
|
||||
# Remove the .swig_checked file
|
||||
rm -f .swig_checked
|
||||
|
1893
build-outputs.mk
1893
build-outputs.mk
File diff suppressed because one or more lines are too long
179
build.conf
179
build.conf
@ -38,11 +38,14 @@ private-includes =
|
||||
subversion/include/private/*.h
|
||||
subversion/bindings/swig/include/*.swg
|
||||
subversion/libsvn_delta/compose_delta.c
|
||||
subversion/bindings/cxxhl/include/*.hpp
|
||||
subversion/bindings/cxxhl/include/svncxxhl/*.hpp
|
||||
subversion/bindings/cxxhl/src/*.hpp
|
||||
subversion/bindings/cxxhl/src/aprwrap/*.hpp
|
||||
subversion/bindings/cxxhl/src/private/*.hpp
|
||||
subversion/bindings/cxx/include/*.hpp
|
||||
subversion/bindings/cxx/include/svnxx/*.hpp
|
||||
subversion/bindings/cxx/include/svnxx/client/*.hpp
|
||||
subversion/bindings/cxx/include/svnxx/detail/*.hpp
|
||||
subversion/bindings/cxx/src/*.hpp
|
||||
subversion/bindings/cxx/src/aprwrap/*.hpp
|
||||
subversion/bindings/cxx/src/private/*.hpp
|
||||
subversion/bindings/cxx/tests/*.hpp
|
||||
subversion/bindings/javahl/native/*.hpp
|
||||
subversion/bindings/javahl/native/jniwrapper/jni_*.hpp
|
||||
tools/dev/svnmover/linenoise/linenoise.h
|
||||
@ -98,7 +101,7 @@ test-scripts =
|
||||
|
||||
bdb-test-scripts =
|
||||
|
||||
swig-python-opts = $(SWIG_FEATURES) -python $(SWIG_PY_FEATURES) -classic
|
||||
swig-python-opts = $(SWIG_FEATURES) $(SWIG_PY_OPTS) $(SWIG_PY_FEATURES)
|
||||
swig-perl-opts = $(SWIG_FEATURES) -perl $(SWIG_PL_FEATURES) -nopm -noproxy
|
||||
swig-ruby-opts = $(SWIG_FEATURES) -ruby $(SWIG_RB_FEATURES)
|
||||
swig-languages = python perl ruby
|
||||
@ -245,7 +248,7 @@ type = lib
|
||||
path = subversion/libsvn_client
|
||||
libs = libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr apriconv apr
|
||||
install = lib
|
||||
msvc-export = svn_client.h private/svn_client_mtcc.h private/svn_client_private.h
|
||||
msvc-export = svn_client.h private/svn_client_mtcc.h private/svn_client_private.h private/svn_client_shelf.h private/svn_client_shelf2.h
|
||||
|
||||
# Routines for binary diffing and tree-deltas
|
||||
[libsvn_delta]
|
||||
@ -371,7 +374,8 @@ type = lib
|
||||
install = fsmod-lib
|
||||
path = subversion/libsvn_subr
|
||||
sources = *.c lz4/*.c
|
||||
libs = aprutil apriconv apr xml zlib apr_memcache sqlite magic intl lz4 utf8proc
|
||||
libs = aprutil apriconv apr xml zlib apr_memcache
|
||||
sqlite magic intl lz4 utf8proc macos-plist macos-keychain
|
||||
msvc-libs = kernel32.lib advapi32.lib shfolder.lib ole32.lib
|
||||
crypt32.lib version.lib
|
||||
msvc-export =
|
||||
@ -392,7 +396,7 @@ msvc-export =
|
||||
private\svn_string_private.h private\svn_magic.h
|
||||
private\svn_subr_private.h private\svn_mutex.h
|
||||
private\svn_packed_data.h private\svn_object_pool.h private\svn_cert.h
|
||||
private\svn_config_private.h
|
||||
private\svn_config_private.h private\svn_dirent_uri_private.h
|
||||
|
||||
# Working copy management lib
|
||||
[libsvn_wc]
|
||||
@ -438,7 +442,7 @@ description = Subversion FSFS Repository Manipulation Tool
|
||||
type = exe
|
||||
path = subversion/svnfsfs
|
||||
install = bin
|
||||
libs = libsvn_repos libsvn_fs libsvn_fs_fs libsvn_delta libsvn_subr apriconv apr
|
||||
libs = libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
#
|
||||
@ -608,16 +612,14 @@ msvc-export = ../bindings/swig/ruby/libsvn_swig_ruby/swigutil_rb.h
|
||||
[javahl-java]
|
||||
type = java
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl
|
||||
subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
|
||||
subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
|
||||
subversion/bindings/javahl/src/org/apache/subversion/javahl/types
|
||||
subversion/bindings/javahl/src/org/apache/subversion/javahl/util
|
||||
src-root = subversion/bindings/javahl/src
|
||||
sources = *.java
|
||||
native = CommitItemStateFlags.java NativeResources.java SVNClient.java
|
||||
SVNRepos.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
classes = subversion/bindings/javahl/classes
|
||||
package-roots = org
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl
|
||||
|
||||
[javahl-compat-java]
|
||||
type = java
|
||||
@ -626,10 +628,12 @@ sources = *.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_COMPAT_JAVAC)
|
||||
classes = subversion/bindings/javahl/classes
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
add-deps = $(javahl_callback_java_DEPS) $(javahl_remote_java_DEPS)
|
||||
$(javahl_types_java_DEPS) $(javahl_util_java_DEPS)
|
||||
$(javahl_java_DEPS)
|
||||
### Replace JAR call in INSTALL_EXTRA_JAVAHL_JAVA macro Makefile.in.
|
||||
#jar = svn-javahl.jar
|
||||
package-roots = org
|
||||
package = org.tigris.subversion.javahl
|
||||
|
||||
[javahl-tests]
|
||||
type = java
|
||||
@ -638,10 +642,12 @@ sources = *.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
classes = subversion/bindings/javahl/classes
|
||||
package-roots = org
|
||||
package = org.apache.subversion.javahl
|
||||
### Java targets don't do up-to-date checks yet.
|
||||
#add-deps = javahl-java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
add-deps = $(javahl_callback_java_DEPS) $(javahl_remote_java_DEPS)
|
||||
$(javahl_types_java_DEPS) $(javahl_util_java_DEPS)
|
||||
$(javahl_java_DEPS)
|
||||
|
||||
[javahl-compat-tests]
|
||||
type = java
|
||||
@ -650,65 +656,59 @@ sources = *.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_COMPAT_JAVAC)
|
||||
classes = subversion/bindings/javahl/classes
|
||||
package-roots = org
|
||||
package = org.tigris.subversion.javahl
|
||||
### Java targets don't do up-to-date checks yet.
|
||||
#add-deps = javahl-compat-java
|
||||
add-deps = $(javahl_compat_java_DEPS)
|
||||
|
||||
[javahl-callback-javah]
|
||||
type = javah
|
||||
[javahl-callback-java]
|
||||
type = java
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl/callback
|
||||
classes = subversion/bindings/javahl/classes
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl.callback
|
||||
sources = *.java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
install = javahl-javah
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
|
||||
native = UserPasswordCallback.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
|
||||
[javahl-remote-javah]
|
||||
type = javah
|
||||
[javahl-remote-java]
|
||||
type = java
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl/remote
|
||||
classes = subversion/bindings/javahl/classes
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl.remote
|
||||
sources = *.java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
install = javahl-javah
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
|
||||
native = CommitEditor.java RemoteFactory.java RemoteSession.java
|
||||
StateReporter.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
|
||||
[javahl-types-javah]
|
||||
type = javah
|
||||
[javahl-types-java]
|
||||
type = java
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl/types
|
||||
classes = subversion/bindings/javahl/classes
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl.types
|
||||
sources = *.java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
install = javahl-javah
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
|
||||
native = NativeInputStream.java NativeOutputStream.java Revision.java
|
||||
RevisionRangeList.java RuntimeVersion.java VersionExtended.java
|
||||
Version.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
|
||||
[javahl-util-javah]
|
||||
type = javah
|
||||
[javahl-util-java]
|
||||
type = java
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl/util
|
||||
classes = subversion/bindings/javahl/classes
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl.util
|
||||
sources = *.java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
install = javahl-javah
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
|
||||
|
||||
[javahl-javah]
|
||||
type = javah
|
||||
path = subversion/bindings/javahl/src/org/apache/subversion/javahl
|
||||
classes = subversion/bindings/javahl/classes
|
||||
headers = subversion/bindings/javahl/include
|
||||
package = org.apache.subversion.javahl
|
||||
sources = *.java
|
||||
add-deps = $(javahl_java_DEPS)
|
||||
install = javahl-javah
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAH) -force
|
||||
native = ConfigImpl.java ConfigLib.java DiffLib.java PropLib.java
|
||||
RequestChannel.java ResponseChannel.java SubstLib.java
|
||||
TunnelChannel.java
|
||||
install = javahl-java
|
||||
link-cmd = $(COMPILE_JAVAHL_JAVAC)
|
||||
|
||||
[libsvnjavahl]
|
||||
description = Subversion Java HighLevel binding
|
||||
@ -717,9 +717,9 @@ path = subversion/bindings/javahl/native
|
||||
libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff
|
||||
libsvn_subr libsvn_fs aprutil apriconv apr java-sdk
|
||||
sources = *.cpp jniwrapper/*.cpp
|
||||
add-deps = $(javahl_java_DEPS) $(javahl_callback_javah_DEPS)
|
||||
$(javahl_remote_javah_DEPS) $(javahl_types_javah_DEPS)
|
||||
$(javahl_util_javah_DEPS) $(javahl_javah_DEPS)
|
||||
add-deps = $(javahl_java_DEPS) $(javahl_callback_java_DEPS)
|
||||
$(javahl_remote_java_DEPS) $(javahl_types_java_DEPS)
|
||||
$(javahl_util_java_DEPS) $(javahl_java_DEPS)
|
||||
install = javahl-lib
|
||||
# need special build rule to include -I$(JDK)/include/jni.h
|
||||
compile-cmd = $(COMPILE_JAVAHL_CXX)
|
||||
@ -727,48 +727,34 @@ link-cmd = $(LINK_JAVAHL_CXX)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
#
|
||||
# C++HL targets
|
||||
# SVN++ targets
|
||||
#
|
||||
|
||||
[libsvncxxhl]
|
||||
description = Subversion C++ HighLevel bindings
|
||||
[libsvnxx]
|
||||
description = Subversion C++ bindings
|
||||
when = SVN_BUILD_SVNXX
|
||||
type = lib
|
||||
path = subversion/bindings/cxxhl
|
||||
path = subversion/bindings/cxx
|
||||
libs = libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff
|
||||
libsvn_subr libsvn_fs aprutil apriconv apr
|
||||
sources = src/*.cpp src/aprwrap/*.cpp
|
||||
install = cxxhl-lib
|
||||
install = svnxx-lib
|
||||
msvc-static = yes
|
||||
compile-cmd = $(COMPILE_CXXHL_CXX)
|
||||
compile-cmd = $(COMPILE_SVNXX)
|
||||
link-cmd = $(LINK_CXX_LIB)
|
||||
|
||||
[cxxhl-tests]
|
||||
description = Unit tests for Subversion C++ HighLevel bindings
|
||||
when = SVN_USE_GOOGLEMOCK
|
||||
[svnxx-tests]
|
||||
description = Unit tests for Subversion C++ bindings
|
||||
when = SVN_BUILD_SVNXX_TESTS
|
||||
type = exe
|
||||
path = subversion/bindings/cxxhl
|
||||
libs = libsvncxxhl libgooglemock libsvn_subr apr
|
||||
path = subversion/bindings/cxx
|
||||
libs = libsvnxx
|
||||
libsvn_repos libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff
|
||||
libsvn_subr libsvn_fs aprutil apriconv apr
|
||||
sources = tests/*.cpp
|
||||
install = cxxhl-tests
|
||||
compile-cmd = $(COMPILE_CXXHL_GOOGLEMOCK_CXX)
|
||||
link-cmd = $(LINK_CXX)
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
#
|
||||
# Googlemock targets
|
||||
#
|
||||
|
||||
[libgooglemock]
|
||||
description = Googlemock Library
|
||||
when = SVN_USE_GOOGLEMOCK
|
||||
type = lib
|
||||
path = googlemock
|
||||
sources = googletest/src/gtest-all.cc googlemock/src/gmock-all.cc
|
||||
install = cxxhl-tests
|
||||
msvc-static = yes
|
||||
compile-cmd = $(COMPILE_GOOGLEMOCK_CXX)
|
||||
link-cmd = $(LINK_CXX_LIB)
|
||||
install = svnxx-tests
|
||||
compile-cmd = $(COMPILE_SVNXX_TEST)
|
||||
link-cmd = $(LINK_SVNXX_TEST)
|
||||
|
||||
# ----------------------------------------------------------------------------
|
||||
#
|
||||
@ -1474,6 +1460,14 @@ external-lib = $(SVN_KWALLET_LIBS)
|
||||
type = lib
|
||||
external-lib = $(SVN_MAGIC_LIBS)
|
||||
|
||||
[macos-plist]
|
||||
type = lib
|
||||
external-lib = $(SVN_MACOS_PLIST_LIBS)
|
||||
|
||||
[macos-keychain]
|
||||
type = lib
|
||||
external-lib = $(SVN_MACOS_KEYCHAIN_LIBS)
|
||||
|
||||
[sasl]
|
||||
type = lib
|
||||
external-lib = $(SVN_SASL_LIBS)
|
||||
@ -1588,7 +1582,7 @@ libs = __ALL__
|
||||
conflict-data-test db-test pristine-store-test entries-compat-test
|
||||
op-depth-test dirent_uri-test wc-queries-test wc-test
|
||||
auth-test
|
||||
parse-diff-test x509-test xml-test afl-x509 compress-test
|
||||
parse-diff-test x509-test xml-test afl-x509 afl-svndiff compress-test
|
||||
svndiff-stream-test
|
||||
|
||||
[__MORE__]
|
||||
@ -1630,7 +1624,7 @@ lang = ruby
|
||||
[__JAVAHL__]
|
||||
type = project
|
||||
path = build/win32
|
||||
libs = javahl-java javahl-javah libsvnjavahl
|
||||
libs = javahl-java libsvnjavahl
|
||||
|
||||
[__JAVAHL_TESTS__]
|
||||
type = project
|
||||
@ -1749,3 +1743,12 @@ sources = afl-x509.c
|
||||
install = test
|
||||
libs = libsvn_subr apr
|
||||
testing = skip
|
||||
|
||||
[afl-svndiff]
|
||||
description = AFL fuzzer for svndiff to txdelta parser
|
||||
type = exe
|
||||
path = subversion/tests/afl
|
||||
sources = afl-svndiff.c
|
||||
install = test
|
||||
libs = libsvn_delta libsvn_subr apr
|
||||
testing = skip
|
||||
|
122
configure.ac
122
configure.ac
@ -23,7 +23,7 @@ AC_PREREQ(2.59)
|
||||
dnl Get the version of Subversion, using m4's esyscmd() command to do this
|
||||
dnl at m4-time, since AC_INIT() requires it then.
|
||||
AC_INIT([subversion],
|
||||
[esyscmd(python build/getversion.py SVN subversion/include/svn_version.h)],
|
||||
[esyscmd($PYTHON build/getversion.py SVN subversion/include/svn_version.h)],
|
||||
[http://subversion.apache.org/])
|
||||
|
||||
AC_CONFIG_SRCDIR(subversion/include/svn_types.h)
|
||||
@ -91,7 +91,7 @@ AC_SUBST([MKDIR])
|
||||
dnl verify apr version and set apr flags
|
||||
dnl These regular expressions should not contain "\(" and "\)".
|
||||
|
||||
APR_VER_REGEXES=["1\.[3-9]\. 2\."]
|
||||
APR_VER_REGEXES=["1\.[5-9]\. 2\."]
|
||||
|
||||
SVN_LIB_APR($APR_VER_REGEXES)
|
||||
|
||||
@ -593,7 +593,7 @@ if test "$with_old_gnome_keyring" != "no"; then
|
||||
[Is GNOME Keyring support enabled?])
|
||||
CPPFLAGS="$old_CPPFLAGS"
|
||||
SVN_GNOME_KEYRING_LIBS="`$PKG_CONFIG --libs glib-2.0 gnome-keyring-1`"
|
||||
SVN_GNOME_KEYRING_PCLIBS="glib-2.0 gnome-keyring-1"
|
||||
SVN_GNOME_KEYRING_PCLIBS="glib-2.0, gnome-keyring-1"
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
if test "$with_old_gnome_keyring" = "yes"; then
|
||||
@ -640,29 +640,6 @@ AC_SUBST(SVN_GNOME_KEYRING_LIBS)
|
||||
dnl LibSecret -------------------
|
||||
SVN_LIB_SECRET
|
||||
|
||||
dnl Googlemock -----------------
|
||||
AC_ARG_ENABLE([googlemock],
|
||||
AS_HELP_STRING([--disable-googlemock],
|
||||
[Do not use the Googlemock testing framework]),
|
||||
[],
|
||||
[enable_googlemock=yes])
|
||||
|
||||
AC_SUBST([GOOGLEMOCK_SRCDIR], [$abs_srcdir/googlemock])
|
||||
AC_MSG_CHECKING([whether use Googlemock])
|
||||
if test "$enable_googlemock" != "no"; then
|
||||
if test -d "$GOOGLEMOCK_SRCDIR"; then
|
||||
AC_MSG_RESULT([yes])
|
||||
SVN_USE_GOOGLEMOCK=true
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
SVN_USE_GOOGLEMOCK=false
|
||||
fi
|
||||
else
|
||||
AC_MSG_RESULT([no])
|
||||
SVN_USE_GOOGLEMOCK=false
|
||||
fi
|
||||
AC_SUBST([SVN_USE_GOOGLEMOCK])
|
||||
|
||||
dnl Ev2 experimental features ----------------------
|
||||
dnl Note: The Ev2 implementations will be built unconditionally, but by
|
||||
dnl providing this flag, users can choose to use the currently-shimmed Ev2
|
||||
@ -867,18 +844,21 @@ fi
|
||||
|
||||
dnl plaintext passwords -------------------
|
||||
AC_ARG_ENABLE(plaintext-password-storage,
|
||||
AS_HELP_STRING([--disable-plaintext-password-storage],
|
||||
[Disable on-disk caching of plaintext passwords and passphrases.
|
||||
(Leaving this functionality enabled will not force Subversion
|
||||
AS_HELP_STRING([--enable-plaintext-password-storage],
|
||||
[Enable on-disk caching of plaintext passwords and passphrases.
|
||||
(Enabling this functionality will not force Subversion
|
||||
to store passwords in plaintext, but does permit users to
|
||||
explicitly allow that behavior via runtime configuration.)]),
|
||||
[
|
||||
if test "$enableval" = "no"; then
|
||||
[plaintext_passwordd_storage="$enableval"],
|
||||
[plaintext_passwordd_storage="no"])
|
||||
|
||||
if test "$plaintext_passwordd_storage" = "yes"; then
|
||||
AC_MSG_WARN([Enabling plaintext password/passphrase storage])
|
||||
else
|
||||
AC_MSG_NOTICE([Disabling plaintext password/passphrase storage])
|
||||
AC_DEFINE(SVN_DISABLE_PLAINTEXT_PASSWORD_STORAGE, 1,
|
||||
[Defined if plaintext password/passphrase storage is disabled])
|
||||
fi
|
||||
])
|
||||
fi
|
||||
|
||||
dnl Build and install rules -------------------
|
||||
|
||||
@ -948,8 +928,9 @@ AC_FUNC_VPRINTF
|
||||
dnl check for functions needed in special file handling
|
||||
AC_CHECK_FUNCS(symlink readlink)
|
||||
|
||||
dnl check for uname
|
||||
dnl check for uname and ELF headers
|
||||
AC_CHECK_HEADERS(sys/utsname.h, [AC_CHECK_FUNCS(uname)], [])
|
||||
AC_CHECK_HEADERS(elf.h)
|
||||
|
||||
dnl check for termios
|
||||
AC_CHECK_HEADER(termios.h,[
|
||||
@ -1153,7 +1134,6 @@ if test "$enable_optimization" = "yes"; then
|
||||
SVN_CFLAGS_ADD_IFELSE([-O1],[],[
|
||||
SVN_CFLAGS_ADD_IFELSE([-O])])])])
|
||||
SVN_CFLAGS_ADD_IFELSE([-Wno-clobbered])
|
||||
SVN_CFLAGS_ADD_IFELSE([-flto])
|
||||
fi
|
||||
fi
|
||||
if test -z ["`echo $CXXUSERFLAGS' ' | $EGREP -- '-O[^ ]* '`"]; then
|
||||
@ -1169,7 +1149,6 @@ if test "$enable_optimization" = "yes"; then
|
||||
SVN_CXXFLAGS_ADD_IFELSE([-O1],[],[
|
||||
SVN_CXXFLAGS_ADD_IFELSE([-O])])])])
|
||||
SVN_CXXFLAGS_ADD_IFELSE([-Wno-clobbered])
|
||||
SVN_CXXFLAGS_ADD_IFELSE([-flto])
|
||||
fi
|
||||
fi
|
||||
elif test "$enable_optimization" = "no"; then
|
||||
@ -1183,9 +1162,11 @@ fi
|
||||
|
||||
dnl Dump the current compiler options
|
||||
AC_MSG_NOTICE([C compiler flags: $CFLAGS])
|
||||
AC_MSG_NOTICE([ language-level: $CMODEFLAGS])
|
||||
AC_MSG_NOTICE([ user-defined: $CUSERFLAGS])
|
||||
AC_MSG_NOTICE([ maintainer-mode: $CMAINTAINERFLAGS])
|
||||
AC_MSG_NOTICE([C++ compiler flags: $CXXFLAGS])
|
||||
AC_MSG_NOTICE([ language-level: $CXXMODEFLAGS])
|
||||
AC_MSG_NOTICE([ user-defined: $CXXUSERFLAGS])
|
||||
AC_MSG_NOTICE([ maintainer-mode: $CXXMAINTAINERFLAGS])
|
||||
|
||||
@ -1292,7 +1273,7 @@ AS_HELP_STRING([--enable-gprof],
|
||||
# Scripting and Bindings languages
|
||||
|
||||
# Python: Used for testsuite, and bindings
|
||||
|
||||
AC_ARG_VAR([PYTHON], [Python interpreter command])
|
||||
|
||||
PYTHON="`$abs_srcdir/build/find_python.sh`"
|
||||
if test -z "$PYTHON"; then
|
||||
@ -1306,7 +1287,7 @@ fi
|
||||
AC_PATH_PROGS(PYTHON, "$PYTHON", none)
|
||||
|
||||
# The minimum version for the JVM runtime for our Java bytecode.
|
||||
JAVA_OLDEST_WORKING_VER='1.6'
|
||||
JAVA_OLDEST_WORKING_VER='1.8'
|
||||
# SVN_CHECK_JDK sets $JAVA_CLASSPATH
|
||||
SVN_CHECK_JDK($JAVA_OLDEST_WORKING_VER)
|
||||
|
||||
@ -1454,6 +1435,69 @@ AC_SUBST(SVN_FS_LIB_DEPS)
|
||||
AC_SUBST(SVN_FS_LIB_INSTALL_DEPS)
|
||||
AC_SUBST(SVN_FS_LIB_LINK)
|
||||
|
||||
# ==== SVN++ =================================================================
|
||||
|
||||
dnl Possibly compile SVN++
|
||||
do_svnxx_build=no
|
||||
AC_ARG_ENABLE(svnxx,
|
||||
AS_HELP_STRING([--enable-svnxx],
|
||||
[Enable compilation of the C++ bindings (requires C++)]),
|
||||
[ if test "$enableval" = "yes" ; then
|
||||
AC_MSG_NOTICE([Enabling the C++ bindings])
|
||||
do_svnxx_build=yes
|
||||
fi
|
||||
])
|
||||
|
||||
dnl Possibly compile SVN++ tests
|
||||
do_svnxx_test_build=no
|
||||
AC_ARG_ENABLE(svnxx-tests,
|
||||
AS_HELP_STRING([--enable-svnxx-tests],
|
||||
[Enable compilation of tests for the C++ bindings
|
||||
(implies --enable-svnxx, requires Boost and Boost.Test)]),
|
||||
[ if test "$enableval" = "yes" ; then
|
||||
AC_MSG_NOTICE([Enabling tests for the C++ bindings])
|
||||
do_svnxx_test_build=yes
|
||||
fi
|
||||
])
|
||||
|
||||
AX_BOOST_BASE([1.58],
|
||||
[
|
||||
if test "$do_svnxx_test_build" = "yes"; then
|
||||
AX_BOOST_UNIT_TEST_FRAMEWORK
|
||||
fi
|
||||
],
|
||||
[
|
||||
if test "$do_svnxx_test_build" = "yes"; then
|
||||
AC_MSG_WARN([Tests for the C++ bindings require Boost and Boost.Test])
|
||||
do_svnxx_test_build=no
|
||||
fi
|
||||
])
|
||||
|
||||
if test "$do_svnxx_test_build" = "yes"; then
|
||||
if test "$want_boost" != "yes"; then
|
||||
AC_MSG_WARN([Tests for the C++ bindings require Boost and Boost.Test])
|
||||
do_svnxx_test_build=no
|
||||
SVN_BUILD_SVNXX_TESTS=false
|
||||
else
|
||||
if test "$do_svnxx_build" != "yes"; then
|
||||
AC_MSG_WARN([Enabling the C++ bindings because their tests are enabled])
|
||||
do_svnxx_build=yes
|
||||
fi
|
||||
SVN_BUILD_SVNXX_TESTS=true
|
||||
fi
|
||||
else
|
||||
SVN_BUILD_SVNXX_TESTS=false
|
||||
fi
|
||||
|
||||
if test "$do_svnxx_build" = "yes"; then
|
||||
SVN_BUILD_SVNXX=true
|
||||
else
|
||||
SVN_BUILD_SVNXX=false
|
||||
fi
|
||||
|
||||
AC_SUBST(SVN_BUILD_SVNXX)
|
||||
AC_SUBST(SVN_BUILD_SVNXX_TESTS)
|
||||
|
||||
# ==== JavaHL ================================================================
|
||||
|
||||
dnl Possibly compile JavaHL
|
||||
@ -1597,7 +1641,7 @@ fi
|
||||
AC_SUBST(SVN_CONFIG_SCRIPT_FILES)
|
||||
|
||||
# Ensure that SWIG is checked after reconfiguration.
|
||||
rm -f .swig_checked
|
||||
rm -f .swig_checked .swig_pl_checked .swig_py_checked .swig_rb_checked
|
||||
|
||||
dnl Provide ${host} for use in compiled code (for svn --version)
|
||||
AC_DEFINE_UNQUOTED([SVN_BUILD_HOST], "${host}",
|
||||
|
@ -112,7 +112,7 @@ INLINE_INHERITED_MEMB = NO
|
||||
# path before files name in the file list and in the header files. If set
|
||||
# to NO the shortest path that makes the file name unique will be used.
|
||||
|
||||
FULL_PATH_NAMES = NO
|
||||
FULL_PATH_NAMES = YES
|
||||
|
||||
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
|
||||
# can be used to strip a user-defined part of the path. Stripping is
|
||||
@ -121,7 +121,7 @@ FULL_PATH_NAMES = NO
|
||||
# If left blank the directory from which doxygen is run is used as the
|
||||
# path to strip.
|
||||
|
||||
STRIP_FROM_PATH =
|
||||
STRIP_FROM_PATH = subversion/include subversion/bindings/cxx/include
|
||||
|
||||
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
|
||||
# the path mentioned in the documentation of a class, which tells
|
||||
@ -130,7 +130,7 @@ STRIP_FROM_PATH =
|
||||
# definition is used. Otherwise one should specify the include paths that
|
||||
# are normally passed to the compiler using the -I flag.
|
||||
|
||||
STRIP_FROM_INC_PATH =
|
||||
STRIP_FROM_INC_PATH = subversion/include subversion/bindings/cxx/include
|
||||
|
||||
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
|
||||
# (but less readable) file names. This can be useful is your file systems
|
||||
@ -280,22 +280,6 @@ SUBGROUPING = YES
|
||||
|
||||
TYPEDEF_HIDES_STRUCT = NO
|
||||
|
||||
# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to
|
||||
# determine which symbols to keep in memory and which to flush to disk.
|
||||
# When the cache is full, less often used symbols will be written to disk.
|
||||
# For small to medium size projects (<1000 input files) the default value is
|
||||
# probably good enough. For larger projects a too small cache size can cause
|
||||
# doxygen to be busy swapping symbols to and from disk most of the time
|
||||
# causing a significant performance penality.
|
||||
# If the system has enough physical memory increasing the cache will improve the
|
||||
# performance by keeping more symbols in memory. Note that the value works on
|
||||
# a logarithmic scale so increasing the size by one will rougly double the
|
||||
# memory usage. The cache size is given by this formula:
|
||||
# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0,
|
||||
# corresponding to a cache size of 2^16 = 65536 symbols
|
||||
|
||||
SYMBOL_CACHE_SIZE = 0
|
||||
|
||||
#---------------------------------------------------------------------------
|
||||
# Build related configuration options
|
||||
#---------------------------------------------------------------------------
|
||||
@ -478,12 +462,6 @@ MAX_INITIALIZER_LINES = 30
|
||||
|
||||
SHOW_USED_FILES = YES
|
||||
|
||||
# If the sources in your project are distributed over multiple directories
|
||||
# then setting the SHOW_DIRECTORIES tag to YES will show the directory hierarchy
|
||||
# in the documentation. The default is NO.
|
||||
|
||||
SHOW_DIRECTORIES = NO
|
||||
|
||||
# Set the SHOW_FILES tag to NO to disable the generation of the Files page.
|
||||
# This will remove the Files entry from the Quick Index and from the
|
||||
# Folder Tree View (if specified). The default is YES.
|
||||
@ -577,6 +555,10 @@ WARN_LOGFILE =
|
||||
# with spaces.
|
||||
|
||||
INPUT = subversion/include \
|
||||
subversion/bindings/cxx/include \
|
||||
subversion/bindings/cxx/include/svnxx \
|
||||
subversion/bindings/cxx/include/svnxx/client \
|
||||
subversion/bindings/cxx/include/svnxx/detail \
|
||||
subversion/include/private/svn_doxygen.h
|
||||
|
||||
# This tag can be used to specify the character encoding of the source files
|
||||
@ -594,7 +576,7 @@ INPUT_ENCODING = UTF-8
|
||||
# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx
|
||||
# *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90
|
||||
|
||||
FILE_PATTERNS = *.h
|
||||
FILE_PATTERNS = *.h *.hpp
|
||||
|
||||
# The RECURSIVE tag can be used to turn specify whether or not subdirectories
|
||||
# should be searched for input files as well. Possible values are YES and NO.
|
||||
@ -805,12 +787,6 @@ HTML_FOOTER =
|
||||
|
||||
HTML_STYLESHEET =
|
||||
|
||||
# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
|
||||
# files or namespaces will be aligned in HTML using tables. If set to
|
||||
# NO a bullet list will be used.
|
||||
|
||||
HTML_ALIGN_MEMBERS = YES
|
||||
|
||||
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
|
||||
# documentation will contain sections that can be hidden and shown after the
|
||||
# page has loaded. For this to work a browser that supports
|
||||
@ -959,11 +935,6 @@ ENUM_VALUES_PER_LINE = 1
|
||||
|
||||
GENERATE_TREEVIEW = NO
|
||||
|
||||
# By enabling USE_INLINE_TREES, doxygen will generate the Groups, Directories,
|
||||
# and Class Hierarchy pages using a tree view instead of an ordered list.
|
||||
|
||||
USE_INLINE_TREES = NO
|
||||
|
||||
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
|
||||
# used to set the initial width (in pixels) of the frame in which the tree
|
||||
# is shown.
|
||||
@ -1151,18 +1122,6 @@ GENERATE_XML = NO
|
||||
|
||||
XML_OUTPUT = xml
|
||||
|
||||
# The XML_SCHEMA tag can be used to specify an XML schema,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_SCHEMA =
|
||||
|
||||
# The XML_DTD tag can be used to specify an XML DTD,
|
||||
# which can be used by a validating XML parser to check the
|
||||
# syntax of the XML files.
|
||||
|
||||
XML_DTD =
|
||||
|
||||
# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
|
||||
# dump the program listings (including syntax highlighting
|
||||
# and cross-referencing information) to the XML output. Note that
|
||||
@ -1378,7 +1337,7 @@ HAVE_DOT = NO
|
||||
# DOTFONTPATH environment variable or by setting DOT_FONTPATH to the directory
|
||||
# containing the font.
|
||||
|
||||
DOT_FONTNAME = FreeSans
|
||||
DOT_FONTNAME =
|
||||
|
||||
# The DOT_FONTSIZE tag can be used to set the size of the font of dot graphs.
|
||||
# The default size is 10pt.
|
||||
|
@ -1,30 +0,0 @@
|
||||
Googlemock and Googletest Suite for Subversion
|
||||
---------------------------------------------
|
||||
|
||||
Googlemock and Googletest are external packages that are downloaded
|
||||
and compiled on request, as part of regular compilations.
|
||||
|
||||
Googlemock is available here:
|
||||
|
||||
https://code.google.com/p/googlemock/
|
||||
|
||||
The source packages already include Googletest, which is available
|
||||
here:
|
||||
|
||||
https://code.google.com/p/googletest/
|
||||
|
||||
Subversion uses Googlemock and Googletest for the C++HL test suite.
|
||||
|
||||
|
||||
|
||||
To configure Subversion to use Googlemock, type
|
||||
|
||||
./get-dep.sh gmock
|
||||
|
||||
This will download Googlemock and put the fused source into the
|
||||
'gmock-fused' directory. Once it's there, configure will pick it up
|
||||
automatically (but you do have to re-run autogen.sh and configure).
|
||||
|
||||
You can disable building Googlemock (and hence the C++HL test suite)
|
||||
with the --disable-gmock configure option. This will tell configure to
|
||||
ignore the gmock-fused directory.
|
@ -240,7 +240,7 @@ while somebody else is in the process of committing.</p>
|
||||
<li>Users commit their day-to-day work on <tt>/trunk</tt>.</li>
|
||||
|
||||
<li>Rule #1: <tt>/trunk</tt> must compile and pass regression tests at
|
||||
all times. Committers who violate this rule are publically
|
||||
all times. Committers who violate this rule are publicly
|
||||
humiliated.</li>
|
||||
|
||||
<li>Rule #2: a single commit (changeset) must not be so large
|
||||
|
@ -48,7 +48,6 @@
|
||||
|
||||
gen_modules = {
|
||||
'make' : ('gen_make', 'Makefiles for POSIX systems'),
|
||||
'dsp' : ('gen_msvc_dsp', 'MSVC 6.x project files'),
|
||||
'vcproj' : ('gen_vcnet_vcproj', 'VC.Net project files'),
|
||||
}
|
||||
|
||||
@ -176,6 +175,8 @@ def _usage_exit(err=None):
|
||||
print("")
|
||||
print(" --with-swig=DIR")
|
||||
print(" look for the swig program in DIR")
|
||||
print(" --with-py3c=DIR")
|
||||
print(" look for the py3c library in DIR")
|
||||
print("")
|
||||
print(" --with-sqlite=DIR")
|
||||
print(" look for sqlite in DIR")
|
||||
@ -215,8 +216,6 @@ def _usage_exit(err=None):
|
||||
print("")
|
||||
print(" --with-apr_memcache=DIR")
|
||||
print(" the apr_memcache sources are in DIR")
|
||||
print(" --disable-gmock")
|
||||
print(" do not use Googlemock")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
@ -252,6 +251,7 @@ def add(self, opt, val, overwrite=True):
|
||||
'with-jdk=',
|
||||
'with-junit=',
|
||||
'with-swig=',
|
||||
'with-py3c=',
|
||||
'with-sqlite=',
|
||||
'with-sasl=',
|
||||
'with-apr_memcache=',
|
||||
@ -264,7 +264,6 @@ def add(self, opt, val, overwrite=True):
|
||||
'disable-shared',
|
||||
'installed-libs=',
|
||||
'vsnet-version=',
|
||||
'disable-gmock',
|
||||
])
|
||||
if len(args) > 1:
|
||||
_usage_exit("Too many arguments")
|
||||
|
50
get-deps.sh
50
get-deps.sh
@ -31,28 +31,24 @@
|
||||
# features already used in the file. Reviewing the history of changes
|
||||
# may be useful as well.
|
||||
|
||||
APR_VERSION=${APR_VERSION:-"1.4.6"}
|
||||
APR_VERSION=${APR_VERSION:-"1.5.0"}
|
||||
APU_VERSION=${APU_VERSION:-"1.5.1"}
|
||||
PY3C_VERSION=${PY3C_VERSION:='1.1'}
|
||||
SERF_VERSION=${SERF_VERSION:-"1.3.8"}
|
||||
ZLIB_VERSION=${ZLIB_VERSION:-"1.2.8"}
|
||||
SQLITE_VERSION=${SQLITE_VERSION:-"3.8.11.1"}
|
||||
# Used to construct the SQLite download URL.
|
||||
SQLITE_VERSION_REL_YEAR=2015
|
||||
GTEST_VERSION=${GMOCK_VERSION:-"1.7.0"}
|
||||
GMOCK_VERSION=${GMOCK_VERSION:-"1.7.0"}
|
||||
HTTPD_VERSION=${HTTPD_VERSION:-"2.4.10"}
|
||||
APR_ICONV_VERSION=${APR_ICONV_VERSION:-"1.2.1"}
|
||||
|
||||
APR=apr-${APR_VERSION}
|
||||
APR_UTIL=apr-util-${APU_VERSION}
|
||||
PY3C=py3c-${PY3C_VERSION}
|
||||
SERF=serf-${SERF_VERSION}
|
||||
ZLIB=zlib-${ZLIB_VERSION}
|
||||
SQLITE_VERSION_LIST=`echo $SQLITE_VERSION | sed -e 's/\./ /g'`
|
||||
SQLITE=sqlite-amalgamation-`printf %d%02d%02d%02d $SQLITE_VERSION_LIST`
|
||||
GTEST=release-${GTEST_VERSION}
|
||||
GTEST_URL=https://github.com/google/googletest/archive
|
||||
GMOCK=release-${GMOCK_VERSION}
|
||||
GMOCK_URL=https://github.com/google/googlemock/archive
|
||||
|
||||
HTTPD=httpd-${HTTPD_VERSION}
|
||||
APR_ICONV=apr-iconv-${APR_ICONV_VERSION}
|
||||
@ -67,12 +63,12 @@ HTTP_FETCH=
|
||||
|
||||
# Need this uncommented if any of the specific versions of the ASF tarballs to
|
||||
# be downloaded are no longer available on the general mirrors.
|
||||
APACHE_MIRROR=http://archive.apache.org/dist
|
||||
APACHE_MIRROR=https://archive.apache.org/dist
|
||||
|
||||
# helpers
|
||||
usage() {
|
||||
echo "Usage: $0"
|
||||
echo "Usage: $0 [ apr | serf | zlib | sqlite | googlemock ] ..."
|
||||
echo "Usage: $0 [ apr | py3c | serf | zlib | sqlite ] ..."
|
||||
exit $1
|
||||
}
|
||||
|
||||
@ -90,6 +86,19 @@ get_apr() {
|
||||
test -d $BASEDIR/apr-util || mv $APR_UTIL apr-util
|
||||
}
|
||||
|
||||
get_py3c() {
|
||||
test -d $BASEDIR/py3c && return
|
||||
py3cdist=v${PY3C_VERSION}.tar.gz
|
||||
|
||||
cd $TEMPDIR
|
||||
$HTTP_FETCH https://github.com/encukou/py3c/archive/${py3cdist}
|
||||
cd $BASEDIR
|
||||
|
||||
gzip -dc $TEMPDIR/${py3cdist} | tar -xf -
|
||||
|
||||
mv $PY3C py3c
|
||||
}
|
||||
|
||||
get_serf() {
|
||||
test -d $BASEDIR/serf && return
|
||||
|
||||
@ -106,7 +115,7 @@ get_zlib() {
|
||||
test -d $BASEDIR/zlib && return
|
||||
|
||||
cd $TEMPDIR
|
||||
$HTTP_FETCH http://sourceforge.net/projects/libpng/files/zlib/$ZLIB_VERSION/$ZLIB.tar.gz
|
||||
$HTTP_FETCH https://sourceforge.net/projects/libpng/files/zlib/$ZLIB_VERSION/$ZLIB.tar.gz
|
||||
cd $BASEDIR
|
||||
|
||||
gzip -dc $TEMPDIR/$ZLIB.tar.gz | tar -xf -
|
||||
@ -127,29 +136,11 @@ get_sqlite() {
|
||||
|
||||
}
|
||||
|
||||
get_googlemock() {
|
||||
test -d $BASEDIR/googlemock && return
|
||||
|
||||
cd $TEMPDIR
|
||||
$HTTP_FETCH ${GTEST_URL}/${GTEST}.zip
|
||||
unzip -q ${GTEST}.zip
|
||||
rm -f ${GTEST}.zip
|
||||
|
||||
$HTTP_FETCH ${GMOCK_URL}/${GMOCK}.zip
|
||||
unzip -q ${GMOCK}.zip
|
||||
rm -f ${GMOCK}.zip
|
||||
|
||||
cd $BASEDIR
|
||||
mkdir googlemock
|
||||
mv $TEMPDIR/googletest-release-${GTEST_VERSION} googlemock/googletest
|
||||
mv $TEMPDIR/googlemock-release-${GMOCK_VERSION} googlemock/googlemock
|
||||
}
|
||||
|
||||
# main()
|
||||
get_deps() {
|
||||
mkdir -p $TEMPDIR
|
||||
|
||||
for i in zlib serf sqlite-amalgamation apr apr-util gmock-fused; do
|
||||
for i in zlib serf sqlite-amalgamation py3c apr apr-util; do
|
||||
if [ -d $i ]; then
|
||||
echo "Local directory '$i' already exists; the downloaded copy won't be used" >&2
|
||||
fi
|
||||
@ -165,6 +156,7 @@ get_deps() {
|
||||
done
|
||||
else
|
||||
get_apr
|
||||
get_py3c
|
||||
get_serf
|
||||
get_zlib
|
||||
get_sqlite
|
||||
|
@ -207,6 +207,17 @@ svn_client__mtcc_check_path(svn_node_kind_t *kind,
|
||||
/** Commits all operations stored in @a mtcc as a new revision and destroys
|
||||
* @a mtcc.
|
||||
*
|
||||
* A log message is obtained from the log message callback in the client
|
||||
* context in @a mtcc.
|
||||
*
|
||||
* @a revprop_table (if non-NULL) supplies additional revision properties;
|
||||
* it may not supply any "svn:*" revision properties.
|
||||
*
|
||||
* As with svn_ra_get_commit_editor3(), after the commit has succeeded,
|
||||
* it will invoke @a commit_callback (if non-NULL) with filled-in
|
||||
* #svn_commit_info_t *, @a commit_baton, and @a scratch_pool or some subpool
|
||||
* thereof as arguments.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
*/
|
||||
svn_error_t *
|
||||
|
@ -281,26 +281,6 @@ svn_client__wc_node_get_origin(svn_client__pathrev_t **origin_p,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Copy the file or directory on URL in some repository to DST_ABSPATH,
|
||||
* copying node information and properties. Resolve URL using PEG_REV and
|
||||
* REVISION.
|
||||
*
|
||||
* If URL specifies a directory, create the copy using depth DEPTH.
|
||||
*
|
||||
* If MAKE_PARENTS is TRUE and DST_ABSPATH doesn't have an added parent
|
||||
* create missing parent directories
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__copy_foreign(const char *url,
|
||||
const char *dst_abspath,
|
||||
svn_opt_revision_t *peg_revision,
|
||||
svn_opt_revision_t *revision,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t make_parents,
|
||||
svn_boolean_t already_locked,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Same as the public svn_client_mergeinfo_log2 API, except for the addition
|
||||
* of the TARGET_MERGEINFO_CATALOG and RESULT_POOL parameters.
|
||||
*
|
||||
@ -341,6 +321,220 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return a diff processor that will print a Subversion-style
|
||||
* (not git-style) diff.
|
||||
*
|
||||
* @a anchor is optional (may be null), and is the 'anchor' path to prefix
|
||||
* to the diff-processor paths before displaying.
|
||||
*
|
||||
* @a orig_path_1 and @a orig_path_2 are the two main root paths to be
|
||||
* diffed; each may be a URL, a local WC path or a local unversioned path.
|
||||
*
|
||||
* Other arguments are as for svn_client_diff7() etc.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__get_diff_writer_svn(
|
||||
svn_diff_tree_processor_t **diff_processor,
|
||||
const char *anchor,
|
||||
const char *orig_path_1,
|
||||
const char *orig_path_2,
|
||||
const apr_array_header_t *options,
|
||||
const char *relative_to_dir,
|
||||
svn_boolean_t no_diff_added,
|
||||
svn_boolean_t no_diff_deleted,
|
||||
svn_boolean_t show_copies_as_adds,
|
||||
svn_boolean_t ignore_content_type,
|
||||
svn_boolean_t ignore_properties,
|
||||
svn_boolean_t properties_only,
|
||||
svn_boolean_t pretty_print_mergeinfo,
|
||||
const char *header_encoding,
|
||||
svn_stream_t *outstream,
|
||||
svn_stream_t *errstream,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/*** Editor for diff summary ***/
|
||||
|
||||
/* Set *DIFF_PROCESSOR to a diff processor that will report a diff summary
|
||||
to SUMMARIZE_FUNC.
|
||||
|
||||
SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
|
||||
created callbacks for each changed item.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__get_diff_summarize_callbacks(
|
||||
svn_diff_tree_processor_t **diff_processor,
|
||||
svn_client_diff_summarize_func_t summarize_func,
|
||||
void *summarize_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Copy a directory tree or a file (according to @a kind) from @a src_url at
|
||||
* @a src_rev, to @a dst_abspath in a WC.
|
||||
*
|
||||
* The caller should be holding a WC write lock that allows @a dst_abspath to
|
||||
* be created, such as on the parent of @a dst_abspath.
|
||||
*
|
||||
* If not same repositories, then remove any svn:mergeinfo property.
|
||||
*
|
||||
* Use @a ra_session to fetch the data. The session may point to any URL
|
||||
* within the source repository.
|
||||
*
|
||||
* This API does not process any externals definitions that may be present
|
||||
* on copied directories.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__repos_to_wc_copy_internal(svn_boolean_t *timestamp_sleep,
|
||||
svn_node_kind_t kind,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_rev,
|
||||
const char *dst_abspath,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Copy a directory tree or a file (according to @a kind) from @a src_url at
|
||||
* @a src_rev, to @a dst_abspath in a WC.
|
||||
*
|
||||
* The caller should be holding a WC write lock that allows @a dst_abspath to
|
||||
* be created, such as on the parent of @a dst_abspath.
|
||||
*
|
||||
* If not same repositories, then remove any svn:mergeinfo property.
|
||||
*
|
||||
* Use @a ra_session to fetch the data. The session may point to a different
|
||||
* URL after returning.
|
||||
*
|
||||
* This API does not process any externals definitions that may be present
|
||||
* on copied directories.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__repos_to_wc_copy_by_editor(svn_boolean_t *timestamp_sleep,
|
||||
svn_node_kind_t kind,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_rev,
|
||||
const char *dst_abspath,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return an editor for applying local modifications to a WC.
|
||||
*
|
||||
* Return an editor in @a *editor_p, @a *edit_baton_p that will apply
|
||||
* local modifications to the WC subdirectory at @a dst_abspath.
|
||||
*
|
||||
* The @a path arguments to the editor methods shall be local WC paths,
|
||||
* relative to @a dst_abspath. The @a copyfrom_path arguments to the
|
||||
* editor methods shall be URLs.
|
||||
*
|
||||
* Send notifications via @a notify_func / @a notify_baton.
|
||||
* ### INCOMPLETE
|
||||
*
|
||||
* @a ra_session is used to fetch the original content for copies.
|
||||
*
|
||||
* Ignore changes to non-regular property (entry-props, DAV/WC-props).
|
||||
*
|
||||
* Acquire the WC write lock in 'open_root' and release it in
|
||||
* 'close_edit', in 'abort_edit', or when @a result_pool is cleared.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__wc_editor(const svn_delta_editor_t **editor_p,
|
||||
void **edit_baton_p,
|
||||
const char *dst_abspath,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/* Return an editor for applying local modifications to a WC.
|
||||
*
|
||||
* Like svn_client__wc_editor() but with additional options.
|
||||
*
|
||||
* If @a root_dir_add is true, then create and schedule for addition
|
||||
* the root directory of this edit, else assume it is already a versioned,
|
||||
* existing directory.
|
||||
*
|
||||
* If @a ignore_mergeinfo_changes is true, ignore any incoming changes
|
||||
* to the 'svn:mergeinfo' property.
|
||||
*
|
||||
* If @a manage_wc_write_lock is true, acquire the WC write lock in
|
||||
* 'open_root' and release it in 'close_edit', in 'abort_edit', or
|
||||
* when @a result_pool is cleared.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__wc_editor_internal(const svn_delta_editor_t **editor_p,
|
||||
void **edit_baton_p,
|
||||
const char *dst_abspath,
|
||||
svn_boolean_t root_dir_add,
|
||||
svn_boolean_t ignore_mergeinfo_changes,
|
||||
svn_boolean_t manage_wc_write_lock,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Send committable changes found in the WC to a delta-editor.
|
||||
*
|
||||
* Committable changes are found in TARGETS:DEPTH:CHANGELISTS.
|
||||
*
|
||||
* Send the changes to @a editor:@a edit_baton. The @a path arguments
|
||||
* to the editor methods are URL-paths relative to the URL of
|
||||
* @a src_wc_abspath.
|
||||
*
|
||||
* ### We will presumably need to change this so that the @a path
|
||||
* arguments to the editor will be local WC relpaths, in order
|
||||
* to handle switched paths.
|
||||
*
|
||||
* The @a copyfrom_path arguments to the editor methods are URLs. As the
|
||||
* WC does not store copied-from-foreign-repository metadata, the URL will
|
||||
* be in the same repository as the URL of its parent path.
|
||||
*
|
||||
* Compared with svn_client__do_commit(), this (like svn_client_commit6)
|
||||
* handles:
|
||||
* - condense targets and find committable paths
|
||||
* - checking only one repository is involved
|
||||
*
|
||||
* Compared with svn_client_commit6(), this does not handle:
|
||||
* - externals
|
||||
* - log message
|
||||
* - revprops
|
||||
* - checking the commit includes both halves of each local move
|
||||
* - changing the copy revision of each local move to ~HEAD
|
||||
* - WC write locks
|
||||
* - bumping revisions in WC
|
||||
* - removing locks and changelists in WC
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__wc_replay(const char *src_wc_abspath,
|
||||
const apr_array_header_t *targets,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Copy local modifications from one WC subtree to another.
|
||||
*
|
||||
* Find local modifications under @a src_wc_abspath, in the same way as
|
||||
* for a commit.
|
||||
*
|
||||
* Edit the WC at @a dst_wc_abspath, applying those modifications to the
|
||||
* current working state to produce a new working state.
|
||||
*
|
||||
* The source and destination may be in the same WC or in different WCs.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__wc_copy_mods(const char *src_wc_abspath,
|
||||
const char *dst_wc_abspath,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
498
subversion/include/private/svn_client_shelf.h
Normal file
498
subversion/include/private/svn_client_shelf.h
Normal file
@ -0,0 +1,498 @@
|
||||
/**
|
||||
* @copyright
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
* @endcopyright
|
||||
*
|
||||
* @file svn_client_shelf.h
|
||||
* @brief Subversion's client library: experimental shelving v3
|
||||
*/
|
||||
|
||||
#ifndef SVN_CLIENT_SHELF_H
|
||||
#define SVN_CLIENT_SHELF_H
|
||||
|
||||
#include <apr.h>
|
||||
#include <apr_pools.h>
|
||||
#include <apr_hash.h>
|
||||
#include <apr_time.h>
|
||||
|
||||
#include "svn_client.h"
|
||||
#include "svn_types.h"
|
||||
#include "svn_string.h"
|
||||
#include "svn_wc.h"
|
||||
#include "svn_diff.h"
|
||||
#include "private/svn_diff_tree.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
/** Shelving v3, with checkpoints
|
||||
*
|
||||
* @defgroup svn_client_shelves_checkpoints Shelves and checkpoints
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** A shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf_t
|
||||
{
|
||||
/* Public fields (read-only for public use) */
|
||||
const char *name;
|
||||
int max_version; /**< @deprecated */
|
||||
|
||||
/* Private fields */
|
||||
const char *wc_root_abspath;
|
||||
const char *shelves_dir;
|
||||
apr_hash_t *revprops; /**< non-null; allocated in POOL */
|
||||
svn_client_ctx_t *ctx;
|
||||
apr_pool_t *pool;
|
||||
} svn_client__shelf_t;
|
||||
|
||||
/** One version of a shelved change-set.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf_version_t
|
||||
{
|
||||
/* Public fields (read-only for public use) */
|
||||
svn_client__shelf_t *shelf;
|
||||
apr_time_t mtime; /**< time-stamp of this version */
|
||||
|
||||
/* Private fields */
|
||||
const char *files_dir_abspath; /**< abspath of the storage area */
|
||||
int version_number; /**< version number starting from 1 */
|
||||
} svn_client__shelf_version_t;
|
||||
|
||||
/** Open an existing shelf or create a new shelf.
|
||||
*
|
||||
* Create a new shelf (containing no versions) if a shelf named @a name
|
||||
* is not found.
|
||||
*
|
||||
* The shelf should be closed after use by calling svn_client_shelf_close().
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_open_or_create(svn_client__shelf_t **shelf_p,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Open an existing shelf named @a name, or error if it doesn't exist.
|
||||
*
|
||||
* The shelf should be closed after use by calling svn_client_shelf_close().
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_open_existing(svn_client__shelf_t **shelf_p,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Close @a shelf.
|
||||
*
|
||||
* If @a shelf is NULL, do nothing; otherwise @a shelf must be an open shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_close(svn_client__shelf_t *shelf,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Delete the shelf named @a name, or error if it doesn't exist.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_delete(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Get an editor that, when driven, will store changes in @a shelf_version.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_mods_editor(const svn_delta_editor_t **editor_p,
|
||||
void **edit_baton_p,
|
||||
svn_client__shelf_version_t *shelf_version,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Save the local modifications found by @a paths, @a depth,
|
||||
* @a changelists as a new version of @a shelf.
|
||||
*
|
||||
* If any paths are shelved, create a new shelf-version and return the new
|
||||
* shelf-version in @a *new_version_p, else set @a *new_version_p to null.
|
||||
* @a new_version_p may be null if that output is not wanted; a new shelf-
|
||||
* version is still saved and may be found through @a shelf.
|
||||
*
|
||||
* @a paths are relative to the CWD, or absolute.
|
||||
*
|
||||
* For each successfully shelved path: call @a shelved_func (if not null)
|
||||
* with @a shelved_baton.
|
||||
*
|
||||
* If any paths cannot be shelved: if @a not_shelved_func is given, call
|
||||
* it with @a not_shelved_baton for each such path, and still create a new
|
||||
* shelf-version if any paths are shelved.
|
||||
*
|
||||
* This function does not revert the changes from the WC; use
|
||||
* svn_client_shelf_unapply() for that.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_save_new_version3(svn_client__shelf_version_t **new_version_p,
|
||||
svn_client__shelf_t *shelf,
|
||||
const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_status_func_t shelved_func,
|
||||
void *shelved_baton,
|
||||
svn_client_status_func_t not_shelved_func,
|
||||
void *not_shelved_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Delete all newer versions of @a shelf newer than @a shelf_version.
|
||||
*
|
||||
* If @a shelf_version is null, delete all versions of @a shelf. (The
|
||||
* shelf will still exist, with any log message and other revprops, but
|
||||
* with no versions in it.)
|
||||
*
|
||||
* Leave the shelf's log message and other revprops unchanged.
|
||||
*
|
||||
* Any #svn_client__shelf_version_t object that refers to a deleted version
|
||||
* will become invalid: attempting to use it will give undefined behaviour.
|
||||
* The given @a shelf_version will remain valid.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_delete_newer_versions(svn_client__shelf_t *shelf,
|
||||
svn_client__shelf_version_t *shelf_version,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a shelf_version an existing version of @a shelf, given its
|
||||
* @a version_number (starting from 1). Error if that version doesn't exist.
|
||||
*
|
||||
* There is no need to "close" it after use.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_version_open(svn_client__shelf_version_t **shelf_version_p,
|
||||
svn_client__shelf_t *shelf,
|
||||
int version_number,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a shelf_version the newest version of @a shelf.
|
||||
*
|
||||
* Set @a shelf_version to null if no versions exist.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_get_newest_version(svn_client__shelf_version_t **shelf_version_p,
|
||||
svn_client__shelf_t *shelf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a versions_p an array of (#svn_client__shelf_version_t *)
|
||||
* containing all versions of @a shelf.
|
||||
*
|
||||
* The versions will be in chronological order, oldest to newest.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_get_all_versions(apr_array_header_t **versions_p,
|
||||
svn_client__shelf_t *shelf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Apply @a shelf_version to the WC.
|
||||
*
|
||||
* If @a dry_run is true, try applying the shelf-version to the WC and
|
||||
* report the full set of notifications about successes and conflicts,
|
||||
* but leave the WC untouched.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_apply(svn_client__shelf_version_t *shelf_version,
|
||||
svn_boolean_t dry_run,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Test whether we can successfully apply the changes for @a file_relpath
|
||||
* in @a shelf_version to the WC.
|
||||
*
|
||||
* Set @a *conflict_p to true if the changes conflict with the WC state,
|
||||
* else to false.
|
||||
*
|
||||
* If @a file_relpath is not found in @a shelf_version, set @a *conflict_p
|
||||
* to FALSE.
|
||||
*
|
||||
* @a file_relpath is relative to the WC root.
|
||||
*
|
||||
* A conflict means the shelf cannot be applied successfully to the WC
|
||||
* because the change to be applied is not compatible with the current
|
||||
* working state of the WC file. Examples are a text conflict, or the
|
||||
* file does not exist or is a directory, or the shelf is trying to add
|
||||
* the file but it already exists, or trying to delete it but it does not
|
||||
* exist.
|
||||
*
|
||||
* Return an error only if something is broken, e.g. unable to read data
|
||||
* from the specified shelf-version.
|
||||
*
|
||||
* Leave the WC untouched.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_test_apply_file(svn_boolean_t *conflict_p,
|
||||
svn_client__shelf_version_t *shelf_version,
|
||||
const char *file_relpath,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Reverse-apply @a shelf_version to the WC.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_unapply(svn_client__shelf_version_t *shelf_version,
|
||||
svn_boolean_t dry_run,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Send committable changes found in a shelf to a delta-editor.
|
||||
*
|
||||
* Push changes from the @a shelf_version subtree at @a top_relpath
|
||||
* to @a editor : @a edit_baton.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_replay(svn_client__shelf_version_t *shelf_version,
|
||||
const char *top_relpath,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *affected_paths to a hash with one entry for each path affected
|
||||
* by the @a shelf_version.
|
||||
*
|
||||
* The hash key is the path of the affected file, relative to the WC root.
|
||||
*
|
||||
* (Future possibility: When moves and copies are supported, the hash key
|
||||
* is the old path and value is the new path.)
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_paths_changed(apr_hash_t **affected_paths,
|
||||
svn_client__shelf_version_t *shelf_version,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a shelf's revprop @a prop_name to @a prop_val.
|
||||
*
|
||||
* This can be used to set or change the shelf's log message
|
||||
* (property name "svn:log" or #SVN_PROP_REVISION_LOG).
|
||||
*
|
||||
* If @a prop_val is NULL, delete the property (if present).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_revprop_set(svn_client__shelf_t *shelf,
|
||||
const char *prop_name,
|
||||
const svn_string_t *prop_val,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a shelf's revprops to @a revprop_table.
|
||||
*
|
||||
* This deletes all previous revprops.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_revprop_set_all(svn_client__shelf_t *shelf,
|
||||
apr_hash_t *revprop_table,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Get @a shelf's revprop @a prop_name into @a *prop_val.
|
||||
*
|
||||
* If the property is not present, set @a *prop_val to NULL.
|
||||
*
|
||||
* This can be used to get the shelf's log message
|
||||
* (property name "svn:log" or #SVN_PROP_REVISION_LOG).
|
||||
*
|
||||
* The lifetime of the result is limited to that of @a shelf and/or
|
||||
* of @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_revprop_get(svn_string_t **prop_val,
|
||||
svn_client__shelf_t *shelf,
|
||||
const char *prop_name,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Get @a shelf's revprops into @a props.
|
||||
*
|
||||
* The lifetime of the result is limited to that of @a shelf and/or
|
||||
* of @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_revprop_list(apr_hash_t **props,
|
||||
svn_client__shelf_t *shelf,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Set the log message in @a shelf to @a log_message.
|
||||
*
|
||||
* If @a log_message is null, delete the log message.
|
||||
*
|
||||
* Similar to svn_client_shelf_revprop_set(... SVN_PROP_REVISION_LOG ...).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_set_log_message(svn_client__shelf_t *shelf,
|
||||
const char *log_message,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Get the log message in @a shelf into @a *log_message.
|
||||
*
|
||||
* Set @a *log_message to NULL if there is no log message.
|
||||
*
|
||||
* Similar to svn_client_shelf_revprop_get(... SVN_PROP_REVISION_LOG ...).
|
||||
*
|
||||
* The result is allocated in @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_get_log_message(char **log_message,
|
||||
svn_client__shelf_t *shelf,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Information about a shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf_info_t
|
||||
{
|
||||
apr_time_t mtime; /**< mtime of the latest change */
|
||||
} svn_client__shelf_info_t;
|
||||
|
||||
/** Set @a *shelf_infos to a hash, keyed by shelf name, of pointers to
|
||||
* @c svn_client_shelf_info_t structures, one for each shelf in the
|
||||
* given WC.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_list(apr_hash_t **shelf_infos,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Report the shelved status of all the shelved paths in @a shelf_version
|
||||
* via @a walk_func(@a walk_baton, ...).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_version_status_walk(svn_client__shelf_version_t *shelf_version,
|
||||
const char *wc_relpath,
|
||||
svn_wc_status_func4_t walk_func,
|
||||
void *walk_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Output the subtree of @a shelf_version rooted at @a shelf_relpath
|
||||
* as a diff to @a diff_processor.
|
||||
*
|
||||
* ### depth and ignore_ancestry are currently ignored.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf_diff(svn_client__shelf_version_t *shelf_version,
|
||||
const char *shelf_relpath,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
const svn_diff_tree_processor_t *diff_processor,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SVN_CLIENT_SHELF_H */
|
467
subversion/include/private/svn_client_shelf2.h
Normal file
467
subversion/include/private/svn_client_shelf2.h
Normal file
@ -0,0 +1,467 @@
|
||||
/**
|
||||
* @copyright
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
* @endcopyright
|
||||
*
|
||||
* @file svn_client_shelf2.h
|
||||
* @brief Subversion's client library: experimental shelving v2
|
||||
*/
|
||||
|
||||
#ifndef SVN_CLIENT_SHELF2_H
|
||||
#define SVN_CLIENT_SHELF2_H
|
||||
|
||||
#include <apr.h>
|
||||
#include <apr_pools.h>
|
||||
#include <apr_hash.h>
|
||||
#include <apr_time.h>
|
||||
|
||||
#include "svn_client.h"
|
||||
#include "svn_types.h"
|
||||
#include "svn_string.h"
|
||||
#include "svn_wc.h"
|
||||
#include "svn_diff.h"
|
||||
#include "private/svn_diff_tree.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
|
||||
/** Shelving v2, with checkpoints
|
||||
*
|
||||
* @defgroup svn_client_shelves_checkpoints Shelves and checkpoints
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** A shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf2_t
|
||||
{
|
||||
/* Public fields (read-only for public use) */
|
||||
const char *name;
|
||||
int max_version; /** @deprecated */
|
||||
|
||||
/* Private fields */
|
||||
const char *wc_root_abspath;
|
||||
const char *shelves_dir;
|
||||
apr_hash_t *revprops; /* non-null; allocated in POOL */
|
||||
svn_client_ctx_t *ctx;
|
||||
apr_pool_t *pool;
|
||||
} svn_client__shelf2_t;
|
||||
|
||||
/** One version of a shelved change-set.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf2_version_t
|
||||
{
|
||||
/* Public fields (read-only for public use) */
|
||||
svn_client__shelf2_t *shelf;
|
||||
apr_time_t mtime; /** time-stamp of this version */
|
||||
|
||||
/* Private fields */
|
||||
const char *files_dir_abspath; /** abspath of the storage area */
|
||||
int version_number; /** version number starting from 1 */
|
||||
} svn_client__shelf2_version_t;
|
||||
|
||||
/** Open an existing shelf or create a new shelf.
|
||||
*
|
||||
* Create a new shelf (containing no versions) if a shelf named @a name
|
||||
* is not found.
|
||||
*
|
||||
* The shelf should be closed after use by calling svn_client_shelf_close().
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_open_or_create(svn_client__shelf2_t **shelf_p,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Open an existing shelf named @a name, or error if it doesn't exist.
|
||||
*
|
||||
* The shelf should be closed after use by calling svn_client_shelf_close().
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_open_existing(svn_client__shelf2_t **shelf_p,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Close @a shelf.
|
||||
*
|
||||
* If @a shelf is NULL, do nothing; otherwise @a shelf must be an open shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_close(svn_client__shelf2_t *shelf,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Delete the shelf named @a name, or error if it doesn't exist.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_delete(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Save the local modifications found by @a paths, @a depth,
|
||||
* @a changelists as a new version of @a shelf.
|
||||
*
|
||||
* If any paths are shelved, create a new shelf-version and return the new
|
||||
* shelf-version in @a *new_version_p, else set @a *new_version_p to null.
|
||||
* @a new_version_p may be null if that output is not wanted; a new shelf-
|
||||
* version is still saved and may be found through @a shelf.
|
||||
*
|
||||
* @a paths are relative to the CWD, or absolute.
|
||||
*
|
||||
* For each successfully shelved path: call @a shelved_func (if not null)
|
||||
* with @a shelved_baton.
|
||||
*
|
||||
* If any paths cannot be shelved: if @a not_shelved_func is given, call
|
||||
* it with @a not_shelved_baton for each such path, and still create a new
|
||||
* shelf-version if any paths are shelved.
|
||||
*
|
||||
* This function does not revert the changes from the WC; use
|
||||
* svn_client_shelf_unapply() for that.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_save_new_version3(svn_client__shelf2_version_t **new_version_p,
|
||||
svn_client__shelf2_t *shelf,
|
||||
const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_status_func_t shelved_func,
|
||||
void *shelved_baton,
|
||||
svn_client_status_func_t not_shelved_func,
|
||||
void *not_shelved_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Delete all newer versions of @a shelf newer than @a shelf_version.
|
||||
*
|
||||
* If @a shelf_version is null, delete all versions of @a shelf. (The
|
||||
* shelf will still exist, with any log message and other revprops, but
|
||||
* with no versions in it.)
|
||||
*
|
||||
* Leave the shelf's log message and other revprops unchanged.
|
||||
*
|
||||
* Any #svn_client_shelf_version_t object that refers to a deleted version
|
||||
* will become invalid: attempting to use it will give undefined behaviour.
|
||||
* The given @a shelf_version will remain valid.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_delete_newer_versions(svn_client__shelf2_t *shelf,
|
||||
svn_client__shelf2_version_t *shelf_version,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a shelf_version an existing version of @a shelf, given its
|
||||
* @a version_number. Error if that version doesn't exist.
|
||||
*
|
||||
* There is no need to "close" it after use.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_version_open(svn_client__shelf2_version_t **shelf_version_p,
|
||||
svn_client__shelf2_t *shelf,
|
||||
int version_number,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a shelf_version the newest version of @a shelf.
|
||||
*
|
||||
* Set @a shelf_version to null if no versions exist.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_get_newest_version(svn_client__shelf2_version_t **shelf_version_p,
|
||||
svn_client__shelf2_t *shelf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return in @a versions_p an array of (#svn_client_shelf_version_t *)
|
||||
* containing all versions of @a shelf.
|
||||
*
|
||||
* The versions will be in chronological order, oldest to newest.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_get_all_versions(apr_array_header_t **versions_p,
|
||||
svn_client__shelf2_t *shelf,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Apply @a shelf_version to the WC.
|
||||
*
|
||||
* If @a dry_run is true, try applying the shelf-version to the WC and
|
||||
* report the full set of notifications about successes and conflicts,
|
||||
* but leave the WC untouched.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_apply(svn_client__shelf2_version_t *shelf_version,
|
||||
svn_boolean_t dry_run,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Test whether we can successfully apply the changes for @a file_relpath
|
||||
* in @a shelf_version to the WC.
|
||||
*
|
||||
* Set @a *conflict_p to true if the changes conflict with the WC state,
|
||||
* else to false.
|
||||
*
|
||||
* If @a file_relpath is not found in @a shelf_version, set @a *conflict_p
|
||||
* to FALSE.
|
||||
*
|
||||
* @a file_relpath is relative to the WC root.
|
||||
*
|
||||
* A conflict means the shelf cannot be applied successfully to the WC
|
||||
* because the change to be applied is not compatible with the current
|
||||
* working state of the WC file. Examples are a text conflict, or the
|
||||
* file does not exist or is a directory, or the shelf is trying to add
|
||||
* the file but it already exists, or trying to delete it but it does not
|
||||
* exist.
|
||||
*
|
||||
* Return an error only if something is broken, e.g. unable to read data
|
||||
* from the specified shelf-version.
|
||||
*
|
||||
* Leave the WC untouched.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_test_apply_file(svn_boolean_t *conflict_p,
|
||||
svn_client__shelf2_version_t *shelf_version,
|
||||
const char *file_relpath,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Reverse-apply @a shelf_version to the WC.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_unapply(svn_client__shelf2_version_t *shelf_version,
|
||||
svn_boolean_t dry_run,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *affected_paths to a hash with one entry for each path affected
|
||||
* by the @a shelf_version.
|
||||
*
|
||||
* The hash key is the path of the affected file, relative to the WC root.
|
||||
*
|
||||
* (Future possibility: When moves and copies are supported, the hash key
|
||||
* is the old path and value is the new path.)
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_paths_changed(apr_hash_t **affected_paths,
|
||||
svn_client__shelf2_version_t *shelf_version,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a shelf's revprop @a prop_name to @a prop_val.
|
||||
*
|
||||
* This can be used to set or change the shelf's log message
|
||||
* (property name "svn:log" or #SVN_PROP_REVISION_LOG).
|
||||
*
|
||||
* If @a prop_val is NULL, delete the property (if present).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_revprop_set(svn_client__shelf2_t *shelf,
|
||||
const char *prop_name,
|
||||
const svn_string_t *prop_val,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a shelf's revprops to @a revprop_table.
|
||||
*
|
||||
* This deletes all previous revprops.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_revprop_set_all(svn_client__shelf2_t *shelf,
|
||||
apr_hash_t *revprop_table,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Get @a shelf's revprop @a prop_name into @a *prop_val.
|
||||
*
|
||||
* If the property is not present, set @a *prop_val to NULL.
|
||||
*
|
||||
* This can be used to get the shelf's log message
|
||||
* (property name "svn:log" or #SVN_PROP_REVISION_LOG).
|
||||
*
|
||||
* The lifetime of the result is limited to that of @a shelf and/or
|
||||
* of @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_revprop_get(svn_string_t **prop_val,
|
||||
svn_client__shelf2_t *shelf,
|
||||
const char *prop_name,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Get @a shelf's revprops into @a props.
|
||||
*
|
||||
* The lifetime of the result is limited to that of @a shelf and/or
|
||||
* of @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_revprop_list(apr_hash_t **props,
|
||||
svn_client__shelf2_t *shelf,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Set the log message in @a shelf to @a log_message.
|
||||
*
|
||||
* If @a log_message is null, delete the log message.
|
||||
*
|
||||
* Similar to svn_client_shelf_revprop_set(... SVN_PROP_REVISION_LOG ...).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_set_log_message(svn_client__shelf2_t *shelf,
|
||||
const char *log_message,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Get the log message in @a shelf into @a *log_message.
|
||||
*
|
||||
* Set @a *log_message to NULL if there is no log message.
|
||||
*
|
||||
* Similar to svn_client_shelf_revprop_get(... SVN_PROP_REVISION_LOG ...).
|
||||
*
|
||||
* The result is allocated in @a result_pool.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_get_log_message(char **log_message,
|
||||
svn_client__shelf2_t *shelf,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Information about a shelf.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client__shelf2_info_t
|
||||
{
|
||||
apr_time_t mtime; /* mtime of the latest change */
|
||||
} svn_client__shelf2_info_t;
|
||||
|
||||
/** Set @a *shelf_infos to a hash, keyed by shelf name, of pointers to
|
||||
* @c svn_client_shelf_info_t structures, one for each shelf in the
|
||||
* given WC.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_list(apr_hash_t **shelf_infos,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Report the shelved status of all the shelved paths in SHELF_VERSION
|
||||
* via WALK_FUNC(WALK_BATON, ...).
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_version_status_walk(svn_client__shelf2_version_t *shelf_version,
|
||||
const char *wc_relpath,
|
||||
svn_wc_status_func4_t walk_func,
|
||||
void *walk_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Output the subtree of @a shelf_version rooted at @a shelf_relpath
|
||||
* as a diff to @a diff_processor.
|
||||
*
|
||||
* ### depth and ignore_ancestry are currently ignored.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__shelf2_diff(svn_client__shelf2_version_t *shelf_version,
|
||||
const char *shelf_relpath,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
const svn_diff_tree_processor_t *diff_processor,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SVN_CLIENT_SHELF2_H */
|
@ -108,12 +108,6 @@ extern "C" {
|
||||
#define APR_OPENINFO 0x00100000
|
||||
#endif
|
||||
|
||||
#if !APR_VERSION_AT_LEAST(1,4,0)
|
||||
#ifndef apr_time_from_msec
|
||||
#define apr_time_from_msec(msec) ((apr_time_t)(msec) * 1000)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/**
|
||||
* APR 1 has volatile qualifier bugs in some atomic prototypes that
|
||||
* are fixed in APR 2:
|
||||
|
@ -321,7 +321,6 @@ svn_diff__tree_processor_create(void *baton,
|
||||
*/ /* Used by libsvn clients repository diff */
|
||||
const svn_diff_tree_processor_t *
|
||||
svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
|
||||
const char *prefix_relpath,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/**
|
||||
|
53
subversion/include/private/svn_dirent_uri_private.h
Normal file
53
subversion/include/private/svn_dirent_uri_private.h
Normal file
@ -0,0 +1,53 @@
|
||||
/*
|
||||
* svn_dirent_uri_private.h : private definitions for dirents and URIs
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
#ifndef SVN_DIRENT_URI_PRIVATE_H
|
||||
#define SVN_DIRENT_URI_PRIVATE_H
|
||||
|
||||
#include <apr_pools.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/**
|
||||
* Convert @a relpath from the local style to the canonical internal style.
|
||||
* "Local style" means native path separators and "." for the empty path.
|
||||
*
|
||||
* Allocates the results in @a result_pool. Uses @a scratch_pool for
|
||||
* temporary allocations.
|
||||
*
|
||||
* @since New in 1.7 (as svn_relpath__internal_style()).
|
||||
* @since Name and signature changed in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_relpath__make_internal(const char **internal_style_relpath,
|
||||
const char *relpath,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SVN_DIRENT_URI_PRIVATE_H */
|
@ -348,7 +348,7 @@ svn_element__content_t *
|
||||
svn_element__tree_get(const svn_element__tree_t *tree,
|
||||
int eid);
|
||||
|
||||
svn_error_t *
|
||||
void
|
||||
svn_element__tree_set(svn_element__tree_t *tree,
|
||||
int eid,
|
||||
const svn_element__content_t *element);
|
||||
|
@ -255,22 +255,6 @@ typedef struct svn_fs_fs__stats_t
|
||||
apr_hash_t *by_extension;
|
||||
} svn_fs_fs__stats_t;
|
||||
|
||||
|
||||
/* Scan all contents of the repository FS and return statistics in *STATS,
|
||||
* allocated in RESULT_POOL. Report progress through PROGRESS_FUNC with
|
||||
* PROGRESS_BATON, if PROGRESS_FUNC is not NULL.
|
||||
* Use SCRATCH_POOL for temporary allocations.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_fs_fs__get_stats(svn_fs_fs__stats_t **stats,
|
||||
svn_fs_t *fs,
|
||||
svn_fs_progress_notify_func_t progress_func,
|
||||
void *progress_baton,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* A node-revision ID in FSFS consists of 3 sub-IDs ("parts") that consist
|
||||
* of a creation REVISION number and some revision- / transaction-local
|
||||
* counter value (NUMBER). Old-style ID parts use global counter values.
|
||||
@ -325,33 +309,60 @@ typedef svn_error_t *
|
||||
void *baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Read the P2L index for the rev / pack file containing REVISION in FS.
|
||||
* For each index entry, invoke CALLBACK_FUNC with CALLBACK_BATON.
|
||||
* If not NULL, call CANCEL_FUNC with CANCEL_BATON from time to time.
|
||||
* Use SCRATCH_POOL for temporary allocations.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_fs_fs__dump_index(svn_fs_t *fs,
|
||||
svn_revnum_t revision,
|
||||
svn_fs_fs__dump_index_func_t callback_func,
|
||||
void *callback_baton,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
typedef struct svn_fs_fs__ioctl_get_stats_input_t
|
||||
{
|
||||
svn_fs_progress_notify_func_t progress_func;
|
||||
void *progress_baton;
|
||||
} svn_fs_fs__ioctl_get_stats_input_t;
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_get_stats_output_t
|
||||
{
|
||||
svn_fs_fs__stats_t *stats;
|
||||
} svn_fs_fs__ioctl_get_stats_output_t;
|
||||
|
||||
/* Rewrite the respective index information of the rev / pack file in FS
|
||||
* containing REVISION and use the svn_fs_fs__p2l_entry_t * array ENTRIES
|
||||
* as the new index contents. Allocate temporaries from SCRATCH_POOL.
|
||||
*
|
||||
* Note that this becomes a no-op if ENTRIES is empty. You may use a zero-
|
||||
* sized empty entry instead.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_fs_fs__load_index(svn_fs_t *fs,
|
||||
svn_revnum_t revision,
|
||||
apr_array_header_t *entries,
|
||||
apr_pool_t *scratch_pool);
|
||||
SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_GET_STATS, SVN_FS_TYPE_FSFS, 1000);
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_dump_index_input_t
|
||||
{
|
||||
svn_revnum_t revision;
|
||||
svn_fs_fs__dump_index_func_t callback_func;
|
||||
void *callback_baton;
|
||||
} svn_fs_fs__ioctl_dump_index_input_t;
|
||||
|
||||
SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_DUMP_INDEX, SVN_FS_TYPE_FSFS, 1001);
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_load_index_input_t
|
||||
{
|
||||
svn_revnum_t revision;
|
||||
/* Array of svn_fs_fs__p2l_entry_t * entries. */
|
||||
apr_array_header_t *entries;
|
||||
} svn_fs_fs__ioctl_load_index_input_t;
|
||||
|
||||
SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_LOAD_INDEX, SVN_FS_TYPE_FSFS, 1002);
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_revision_size_input_t
|
||||
{
|
||||
svn_revnum_t revision;
|
||||
} svn_fs_fs__ioctl_revision_size_input_t;
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_revision_size_output_t
|
||||
{
|
||||
apr_off_t rev_size;
|
||||
} svn_fs_fs__ioctl_revision_size_output_t;
|
||||
|
||||
/* See svn_fs_fs__revision_size(). */
|
||||
SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_REVISION_SIZE, SVN_FS_TYPE_FSFS, 1003);
|
||||
|
||||
typedef struct svn_fs_fs__ioctl_build_rep_cache_input_t
|
||||
{
|
||||
svn_revnum_t start_rev;
|
||||
svn_revnum_t end_rev;
|
||||
svn_fs_progress_notify_func_t progress_func;
|
||||
void *progress_baton;
|
||||
} svn_fs_fs__ioctl_build_rep_cache_input_t;
|
||||
|
||||
/* See svn_fs_fs__build_rep_cache(). */
|
||||
SVN_FS_DECLARE_IOCTL_CODE(SVN_FS_FS__IOCTL_BUILD_REP_CACHE, SVN_FS_TYPE_FSFS, 1004);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
@ -31,6 +31,7 @@
|
||||
|
||||
#include "svn_types.h"
|
||||
#include "svn_repos.h"
|
||||
#include "svn_delta.h"
|
||||
#include "svn_editor.h"
|
||||
#include "svn_config.h"
|
||||
|
||||
@ -85,9 +86,11 @@ svn_repos__validate_prop(const char *name,
|
||||
*
|
||||
* NAME is used to check that VALUE should be normalized, and if this
|
||||
* is the case, VALUE is then normalized, allocated from RESULT_POOL.
|
||||
* If no normalization is required, VALUE will be copied to RESULT_POOL
|
||||
* unchanged. If NORMALIZED_P is not NULL, and the normalization
|
||||
* happened, set *NORMALIZED_P to non-zero. If the property is returned
|
||||
* If no normalization happened, *RESULT_P will be set to VALUE, and
|
||||
* no copying of the value will occur.
|
||||
*
|
||||
* If NORMALIZED_P is not NULL, and the normalization happened,
|
||||
* set *NORMALIZED_P to non-zero. If the property is returned
|
||||
* unchanged and NORMALIZED_P is not NULL, then *NORMALIZED_P will be
|
||||
* set to zero. SCRATCH_POOL will be used for temporary allocations.
|
||||
*/
|
||||
@ -296,6 +299,23 @@ svn_repos__dump_headers(svn_stream_t *stream,
|
||||
svn_repos__dumpfile_headers_t *headers,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Write a magic header record to DUMP_STREAM specifying format version
|
||||
* VERSION.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos__dump_magic_header_record(svn_stream_t *dump_stream,
|
||||
int version,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Write a UUID record to DUMP_STREAM.
|
||||
*
|
||||
* If UUID is NULL then write nothing at all.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos__dump_uuid_header_record(svn_stream_t *dump_stream,
|
||||
const char *uuid,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Write a revision record to DUMP_STREAM for revision REVISION with revision
|
||||
* properies REVPROPS, creating appropriate headers.
|
||||
*
|
||||
@ -349,6 +369,27 @@ svn_repos__dump_node_record(svn_stream_t *dump_stream,
|
||||
svn_boolean_t content_length_always,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Get a dump editor @a editor along with a @a edit_baton allocated in
|
||||
* @a pool. The editor will write output to @a stream.
|
||||
*
|
||||
* @a update_anchor_relpath is the repository relative path of the
|
||||
* anchor of the update-style drive which will happen on @a *editor;
|
||||
* if a replay-style drive will instead be used, it should be passed
|
||||
* as @c NULL.
|
||||
*
|
||||
* In contrast to the dump editor used inside svn_repos_dump_fs4(), this
|
||||
* one supports only deltas mode.
|
||||
*
|
||||
* ### TODO: Unify with the dump editor inside svn_repos_dump_fs4().
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos__get_dump_editor(const svn_delta_editor_t **editor,
|
||||
void **edit_baton,
|
||||
svn_stream_t *stream,
|
||||
const char *update_anchor_relpath,
|
||||
apr_pool_t *pool);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
@ -120,24 +120,27 @@ svn_sort__array_lookup(const apr_array_header_t *array,
|
||||
* @a insert_index, growing the array and shuffling existing elements along to
|
||||
* make room.
|
||||
*
|
||||
* Raise an error if @a insert_index is less than 0 or greater than the length
|
||||
* of the array.
|
||||
*
|
||||
* @note Private. For use by Subversion's own code only.
|
||||
*/
|
||||
void
|
||||
svn_sort__array_insert(apr_array_header_t *array,
|
||||
svn_error_t *
|
||||
svn_sort__array_insert2(apr_array_header_t *array,
|
||||
const void *new_element,
|
||||
int insert_index);
|
||||
|
||||
|
||||
/* Remove @a elements_to_delete elements starting at @a delete_index from the
|
||||
* array @a arr. If @a delete_index is not a valid element of @a arr,
|
||||
* @a elements_to_delete is not greater than zero, or
|
||||
* @a delete_index + @a elements_to_delete is greater than @a arr->nelts,
|
||||
* then do nothing.
|
||||
* array @a arr.
|
||||
*
|
||||
* Raise an error if the indexes to delete extends outside the array bounds
|
||||
* or if @a elements_to_delete is not greater than zero.
|
||||
*
|
||||
* @note Private. For use by Subversion's own code only.
|
||||
*/
|
||||
void
|
||||
svn_sort__array_delete(apr_array_header_t *arr,
|
||||
svn_error_t *
|
||||
svn_sort__array_delete2(apr_array_header_t *arr,
|
||||
int delete_index,
|
||||
int elements_to_delete);
|
||||
|
||||
@ -190,7 +193,7 @@ svn_priority_queue__size(svn_priority_queue__t *queue);
|
||||
|
||||
/**
|
||||
* Returns a reference to the first element in the @a queue. The queue
|
||||
* contents remains unchanged. If the @a queue is empty, #NULL will be
|
||||
* contents remains unchanged. If the @a queue is empty, NULL will be
|
||||
* returned.
|
||||
*/
|
||||
void *
|
||||
@ -212,7 +215,7 @@ svn_priority_queue__pop(svn_priority_queue__t *queue);
|
||||
|
||||
/**
|
||||
* Append the new @a element to the @a queue. @a element must neither be
|
||||
* #NULL nor the first element as returned by #svn_priority_queue__peek.
|
||||
* NULL nor the first element as returned by #svn_priority_queue__peek.
|
||||
*/
|
||||
void
|
||||
svn_priority_queue__push(svn_priority_queue__t *queue, const void *element);
|
||||
|
@ -389,27 +389,27 @@ svn_hash__make(apr_pool_t *pool);
|
||||
|
||||
/** Struct that represents a key value pair read from a serialized hash
|
||||
* representation. There are special cases that can also be represented:
|
||||
* a #NULL @a key signifies the end of the hash, a #NULL @a val for non-
|
||||
* a NULL @a key signifies the end of the hash, a NULL @a val for non-
|
||||
* NULL keys is only possible in incremental mode describes a deletion.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
*/
|
||||
typedef struct svn_hash__entry_t
|
||||
{
|
||||
/** 0-terminated Key. #NULL if this contains no data at all because we
|
||||
/** 0-terminated Key. NULL if this contains no data at all because we
|
||||
* encountered the end of the hash. */
|
||||
char *key;
|
||||
|
||||
/** Length of @a key. Must be 0 if @a key is #NULL. */
|
||||
/** Length of @a key. Must be 0 if @a key is NULL. */
|
||||
apr_size_t keylen;
|
||||
|
||||
/** 0-terminated value stored with the key. If this is #NULL for a
|
||||
/** 0-terminated value stored with the key. If this is NULL for a
|
||||
* non-NULL @a key, then this means that the key shall be removed from
|
||||
* the hash (only used in incremental mode). Must be #NULL if @a key is
|
||||
* #NULL. */
|
||||
* the hash (only used in incremental mode). Must be NULL if @a key is
|
||||
* NULL. */
|
||||
char *val;
|
||||
|
||||
/** Length of @a val. Must be 0 if @a val is #NULL. */
|
||||
/** Length of @a val. Must be 0 if @a val is NULL. */
|
||||
apr_size_t vallen;
|
||||
} svn_hash__entry_t;
|
||||
|
||||
|
@ -348,15 +348,17 @@ svn_wc__get_wcroot(const char **wcroot_abspath,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *dir to the abspath of the directory in which shelved patches
|
||||
* are stored, which is inside the WC's administrative directory, and ensure
|
||||
* the directory exists.
|
||||
/** Set @a *dir to the abspath of the directory in which administrative
|
||||
* data for experimental features may be stored. This directory is inside
|
||||
* the WC's administrative directory. Ensure the directory exists.
|
||||
*
|
||||
* @a local_abspath is any path in the WC, and is used to find the WC root.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_wc__get_shelves_dir(char **dir,
|
||||
svn_wc__get_experimental_dir(char **dir,
|
||||
svn_wc_context_t *wc_ctx,
|
||||
const char *local_abspath,
|
||||
apr_pool_t *result_pool,
|
||||
@ -537,7 +539,7 @@ svn_wc__node_get_origin(svn_boolean_t *is_copy,
|
||||
* If @a base_only is TRUE then only the base node will be examined,
|
||||
* otherwise the current base or working node will be examined.
|
||||
*
|
||||
* If a value is not interesting you can pass #NULL.
|
||||
* If a value is not interesting you can pass NULL.
|
||||
*
|
||||
* If @a local_abspath is not in the working copy, return
|
||||
* @c SVN_ERR_WC_PATH_NOT_FOUND. Use @a scratch_pool for all temporary
|
||||
@ -615,6 +617,42 @@ svn_wc__node_get_base(svn_node_kind_t *kind,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
/* Return an array of const char * elements, which represent local absolute
|
||||
* paths for nodes, within the working copy indicated by WRI_ABSPATH, which
|
||||
* have a basename matching BASENAME and have node kind KIND.
|
||||
* If no such nodes exist, return an empty array.
|
||||
*
|
||||
* This function returns only paths to nodes which are present in the highest
|
||||
* layer of the WC. In other words, paths to deleted and/or excluded nodes are
|
||||
* never returned.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_wc__find_working_nodes_with_basename(apr_array_header_t **abspaths,
|
||||
const char *wri_abspath,
|
||||
const char *basename,
|
||||
svn_node_kind_t kind,
|
||||
svn_wc_context_t *wc_ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Return an array of const char * elements, which represent local absolute
|
||||
* paths for nodes, within the working copy indicated by WRI_ABSPATH, which
|
||||
* are copies of REPOS_RELPATH and have node kind KIND.
|
||||
* If no such nodes exist, return an empty array.
|
||||
*
|
||||
* This function returns only paths to nodes which are present in the highest
|
||||
* layer of the WC. In other words, paths to deleted and/or excluded nodes are
|
||||
* never returned.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_wc__find_copies_of_repos_path(apr_array_header_t **abspaths,
|
||||
const char *wri_abspath,
|
||||
const char *repos_relpath,
|
||||
svn_node_kind_t kind,
|
||||
svn_wc_context_t *wc_ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Get the working revision of @a local_abspath using @a wc_ctx. If @a
|
||||
* local_abspath is not in the working copy, return @c
|
||||
* SVN_ERR_WC_PATH_NOT_FOUND.
|
||||
@ -2044,15 +2082,19 @@ svn_wc__acquire_write_lock_for_resolve(const char **lock_root_abspath,
|
||||
|
||||
/* The implemementation of svn_wc_diff6(), but reporting to a diff processor
|
||||
*
|
||||
* If ROOT_RELPATH is not NULL, set *ROOT_RELPATH to the target of the diff
|
||||
* within the diff namespace. ("" or a single path component).
|
||||
* New mode, when ANCHOR_AT_GIVEN_PATHS is true:
|
||||
*
|
||||
* If ROOT_IS_FILE is NOT NULL set it
|
||||
* the first processor call. (The anchor is LOCAL_ABSPATH or an ancestor of it)
|
||||
* Anchor the DIFF_PROCESSOR at LOCAL_ABSPATH.
|
||||
*
|
||||
* Backward compatibility mode for svn_wc_diff6(),
|
||||
* when ANCHOR_AT_GIVEN_PATHS is false:
|
||||
*
|
||||
* Send diff processor relpaths relative to LOCAL_ABSPATH if it is a
|
||||
* directory; otherwise, relative to the parent of LOCAL_ABSPATH.
|
||||
* This matches the "anchor and target" semantics of svn_wc_diff6().
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_wc__diff7(const char **root_relpath,
|
||||
svn_boolean_t *root_is_dir,
|
||||
svn_wc__diff7(svn_boolean_t anchor_at_given_paths,
|
||||
svn_wc_context_t *wc_ctx,
|
||||
const char *local_abspath,
|
||||
svn_depth_t depth,
|
||||
|
@ -500,7 +500,7 @@ typedef struct svn_client_commit_item3_t
|
||||
* contents in @c incoming_prop_changes->pool, so that it has the
|
||||
* same lifetime as this data structure.
|
||||
*
|
||||
* See http://subversion.tigris.org/issues/show_bug.cgi?id=806 for a
|
||||
* See https://issues.apache.org/jira/browse/SVN-806 for a
|
||||
* description of what would happen if the post-commit process
|
||||
* didn't group these changes together with all other changes to the
|
||||
* item.
|
||||
@ -520,7 +520,7 @@ typedef struct svn_client_commit_item3_t
|
||||
|
||||
/**
|
||||
* When processing the commit this contains the relative path for
|
||||
* the commit session. #NULL until the commit item is preprocessed.
|
||||
* the commit session. NULL until the commit item is preprocessed.
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
const char *session_relpath;
|
||||
@ -736,16 +736,11 @@ typedef svn_error_t *(*svn_client_get_commit_log_t)(
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Callback type used by svn_client_blame5() to notify the caller
|
||||
/** Callback type used by svn_client_blame6() to notify the caller
|
||||
* that line @a line_no of the blamed file was last changed in @a revision
|
||||
* which has the revision properties @a rev_props, and that the contents were
|
||||
* @a line.
|
||||
*
|
||||
* @a start_revnum and @a end_revnum contain the start and end revision
|
||||
* number of the entire blame operation, as determined from the repository
|
||||
* inside svn_client_blame5(). This can be useful for the blame receiver
|
||||
* to format the blame output.
|
||||
*
|
||||
* If svn_client_blame5() was called with @a include_merged_revisions set to
|
||||
* TRUE, @a merged_revision, @a merged_rev_props and @a merged_path will be
|
||||
* set, otherwise they will be NULL. @a merged_path will be set to the
|
||||
@ -758,6 +753,49 @@ typedef svn_error_t *(*svn_client_get_commit_log_t)(
|
||||
* will be true if the reason there is no blame information is that the line
|
||||
* was modified locally. In all other cases @a local_change will be false.
|
||||
*
|
||||
* Character Encoding and Line Splitting:
|
||||
*
|
||||
* It is up to the client to determine the character encoding. The @a line
|
||||
* content is delivered without any encoding conversion. The line splitting
|
||||
* is designed to work with ASCII-compatible encodings including UTF-8. Any
|
||||
* of the byte sequences LF ("\n"), CR ("\n"), CR LF ("\r\n") ends a line
|
||||
* and is not included in @a line. The @a line content can include all other
|
||||
* byte values including zero (ASCII NUL).
|
||||
*
|
||||
* @note That is how line splitting is done on the final file content, from
|
||||
* which this callback is driven. It is not entirely clear whether the line
|
||||
* splitting used to calculate diffs between each revision and assign a
|
||||
* revision number to each line is exactly compatible with this in all cases.
|
||||
*
|
||||
* Blaming files that have <tt>svn:mime-type</tt> set to something other
|
||||
* than <tt>text/...</tt> requires the @a ignore_mime_type flag to be set to
|
||||
* true when calling the svn_client_blame6 function.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
typedef svn_error_t *(*svn_client_blame_receiver4_t)(
|
||||
void *baton,
|
||||
apr_int64_t line_no,
|
||||
svn_revnum_t revision,
|
||||
apr_hash_t *rev_props,
|
||||
svn_revnum_t merged_revision,
|
||||
apr_hash_t *merged_rev_props,
|
||||
const char *merged_path,
|
||||
const svn_string_t *line,
|
||||
svn_boolean_t local_change,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
* Similar to #svn_client_blame_receiver4_t, but with the @a line parameter
|
||||
* as a (const char*) instead of an svn_string_t, and the parameters
|
||||
* @a start_revnum and @a end_revnum contain the start and end revision
|
||||
* number of the entire blame operation, as resolved from the repository
|
||||
* inside svn_client_blame6().
|
||||
*
|
||||
* @deprecated Provided for backward compatibility with the 1.11 API.
|
||||
* To replace @a start_revnum and @a end_revnum, see the corresponding
|
||||
* output parameters in svn_client_blame6().
|
||||
*
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
typedef svn_error_t *(*svn_client_blame_receiver3_t)(
|
||||
@ -1547,6 +1585,38 @@ svn_client_switch(svn_revnum_t *result_rev,
|
||||
|
||||
/** @} */
|
||||
|
||||
/** Callback for svn_client__layout_list()
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef svn_error_t * (*svn_client__layout_func_t)(
|
||||
void *layout_baton,
|
||||
const char *local_abspath,
|
||||
const char *repos_root_url,
|
||||
svn_boolean_t not_present,
|
||||
svn_boolean_t url_changed,
|
||||
const char *url,
|
||||
svn_boolean_t revision_changed,
|
||||
svn_revnum_t revision,
|
||||
svn_boolean_t depth_changed,
|
||||
svn_depth_t depth,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Describe the layout of the working copy below @a local_abspath to
|
||||
* the callback @a layout.
|
||||
*
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client__layout_list(const char *local_abspath,
|
||||
svn_client__layout_func_t layout,
|
||||
void *layout_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
/**
|
||||
* @defgroup Add Begin versioning files/directories in a working copy.
|
||||
*
|
||||
@ -2888,6 +2958,12 @@ svn_client_log(const apr_array_header_t *targets,
|
||||
* #SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE) and the client is 1.9.0 or
|
||||
* newer.
|
||||
*
|
||||
* Before the first call to @a receiver, set @a *start_revnum_p and
|
||||
* @a *end_revnum_p to the start and end revision number of the entire
|
||||
* blame operation, as resolved from the repository. This can be useful
|
||||
* for the blame receiver to format the blame output. Any or both of these
|
||||
* arguments may be @c NULL.
|
||||
*
|
||||
* Use @a diff_options to determine how to compare different revisions of the
|
||||
* target.
|
||||
*
|
||||
@ -2896,8 +2972,33 @@ svn_client_log(const apr_array_header_t *targets,
|
||||
*
|
||||
* Use @a pool for any temporary allocation.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_blame6(svn_revnum_t *start_revnum_p,
|
||||
svn_revnum_t *end_revnum_p,
|
||||
const char *path_or_url,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
const svn_opt_revision_t *start,
|
||||
const svn_opt_revision_t *end,
|
||||
const svn_diff_file_options_t *diff_options,
|
||||
svn_boolean_t ignore_mime_type,
|
||||
svn_boolean_t include_merged_revisions,
|
||||
svn_client_blame_receiver4_t receiver,
|
||||
void *receiver_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
|
||||
/**
|
||||
* Similar to svn_client_blame6(), but with #svn_client_blame_receiver3_t
|
||||
* as the receiver.
|
||||
*
|
||||
* @deprecated Provided for backwards compatibility with the 1.11 API.
|
||||
*
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_client_blame5(const char *path_or_url,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
@ -2911,9 +3012,8 @@ svn_client_blame5(const char *path_or_url,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
|
||||
/**
|
||||
* Similar to svn_client_blame5(), but with #svn_client_blame_receiver3_t
|
||||
* Similar to svn_client_blame5(), but with #svn_client_blame_receiver2_t
|
||||
* as the receiver.
|
||||
*
|
||||
* @deprecated Provided for backwards compatibility with the 1.6 API.
|
||||
@ -3060,11 +3160,17 @@ svn_client_blame(const char *path_or_url,
|
||||
* The above two options are mutually exclusive. It is an error to set
|
||||
* both to TRUE.
|
||||
*
|
||||
* If @a pretty_print_mergeinfo is true, then describe 'svn:mergeinfo'
|
||||
* property changes in a human-readable form that says what changes were
|
||||
* merged or reverse merged; otherwise (or if the mergeinfo property values
|
||||
* don't parse correctly) display them just like any other property.
|
||||
*
|
||||
* Generated headers are encoded using @a header_encoding.
|
||||
*
|
||||
* Diff output will not be generated for binary files, unless @a
|
||||
* ignore_content_type is TRUE, in which case diffs will be shown
|
||||
* regardless of the content types.
|
||||
* If either side has an svn:mime-type property that indicates 'binary'
|
||||
* content, then if @a ignore_content_type is set, attempt to produce the
|
||||
* diff in the usual way, otherwise produce a 'GIT binary diff' in git mode
|
||||
* or print a warning message in non-git mode.
|
||||
*
|
||||
* @a diff_options (an array of <tt>const char *</tt>) is used to pass
|
||||
* additional command line options to the diff processes invoked to compare
|
||||
@ -3090,8 +3196,39 @@ svn_client_blame(const char *path_or_url,
|
||||
* @note @a relative_to_dir doesn't affect the path index generated by
|
||||
* external diff programs.
|
||||
*
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_diff7(const apr_array_header_t *diff_options,
|
||||
const char *path_or_url1,
|
||||
const svn_opt_revision_t *revision1,
|
||||
const char *path_or_url2,
|
||||
const svn_opt_revision_t *revision2,
|
||||
const char *relative_to_dir,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
svn_boolean_t no_diff_added,
|
||||
svn_boolean_t no_diff_deleted,
|
||||
svn_boolean_t show_copies_as_adds,
|
||||
svn_boolean_t ignore_content_type,
|
||||
svn_boolean_t ignore_properties,
|
||||
svn_boolean_t properties_only,
|
||||
svn_boolean_t use_git_diff_format,
|
||||
svn_boolean_t pretty_print_mergeinfo,
|
||||
const char *header_encoding,
|
||||
svn_stream_t *outstream,
|
||||
svn_stream_t *errstream,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Similar to svn_client_diff7(), but with @a pretty_print_mergeinfo
|
||||
* always passed as @c TRUE.
|
||||
*
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
* @since New in 1.8.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_client_diff6(const apr_array_header_t *diff_options,
|
||||
const char *path_or_url1,
|
||||
@ -3249,14 +3386,45 @@ svn_client_diff(const apr_array_header_t *diff_options,
|
||||
* be either a working-copy path or URL.
|
||||
*
|
||||
* If @a peg_revision is #svn_opt_revision_unspecified, behave
|
||||
* identically to svn_client_diff6(), using @a path_or_url for both of that
|
||||
* identically to svn_client_diff7(), using @a path_or_url for both of that
|
||||
* function's @a path_or_url1 and @a path_or_url2 arguments.
|
||||
*
|
||||
* All other options are handled identically to svn_client_diff6().
|
||||
* All other options are handled identically to svn_client_diff7().
|
||||
*
|
||||
* @since New in 1.8.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_diff_peg7(const apr_array_header_t *diff_options,
|
||||
const char *path_or_url,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
const svn_opt_revision_t *start_revision,
|
||||
const svn_opt_revision_t *end_revision,
|
||||
const char *relative_to_dir,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
svn_boolean_t no_diff_added,
|
||||
svn_boolean_t no_diff_deleted,
|
||||
svn_boolean_t show_copies_as_adds,
|
||||
svn_boolean_t ignore_content_type,
|
||||
svn_boolean_t ignore_properties,
|
||||
svn_boolean_t properties_only,
|
||||
svn_boolean_t use_git_diff_format,
|
||||
svn_boolean_t pretty_print_mergeinfo,
|
||||
const char *header_encoding,
|
||||
svn_stream_t *outstream,
|
||||
svn_stream_t *errstream,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Similar to svn_client_diff_peg7(), but with @a pretty_print_mergeinfo
|
||||
* always passed as @c TRUE.
|
||||
*
|
||||
* @deprecated Provided for backward compatibility with the 1.7 API.
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_client_diff_peg6(const apr_array_header_t *diff_options,
|
||||
const char *path_or_url,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
@ -3419,7 +3587,7 @@ svn_client_diff_peg(const apr_array_header_t *diff_options,
|
||||
* Calls @a summarize_func with @a summarize_baton for each difference
|
||||
* with a #svn_client_diff_summarize_t structure describing the difference.
|
||||
*
|
||||
* See svn_client_diff6() for a description of the other parameters.
|
||||
* See svn_client_diff7() for a description of the other parameters.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
*/
|
||||
@ -4274,17 +4442,23 @@ svn_client_relocate(const char *dir,
|
||||
|
||||
/**
|
||||
* Restore the pristine version of working copy @a paths,
|
||||
* effectively undoing any local mods. For each path in @a paths,
|
||||
* revert it if it is a file. Else if it is a directory, revert
|
||||
* according to @a depth:
|
||||
* effectively undoing any local mods. This means returning each
|
||||
* path's versioned status to 'unmodified' and changing its on-disk
|
||||
* state to match that.
|
||||
*
|
||||
* If an item was in a state of conflict, reverting also marks the
|
||||
* conflict as resolved. If there are conflict marker files attached
|
||||
* to the item, these are removed.
|
||||
*
|
||||
* @a paths is an array of (const char *) local WC paths.
|
||||
*
|
||||
* If @a depth is #svn_depth_empty, revert just the properties on
|
||||
* the directory; else if #svn_depth_files, revert the properties
|
||||
* For each path in @a paths, revert it if it is a file. Else if it is
|
||||
* a directory, revert according to @a depth:
|
||||
* If @a depth is #svn_depth_empty, revert just
|
||||
* the directory; else if #svn_depth_files, revert the directory
|
||||
* and any files immediately under the directory; else if
|
||||
* #svn_depth_immediates, revert all of the preceding plus
|
||||
* properties on immediate subdirectories; else if #svn_depth_infinity,
|
||||
* immediate subdirectories; else if #svn_depth_infinity,
|
||||
* revert path and everything under it fully recursively.
|
||||
*
|
||||
* @a changelists is an array of <tt>const char *</tt> changelist
|
||||
@ -4296,9 +4470,18 @@ svn_client_relocate(const char *dir,
|
||||
* If @a clear_changelists is TRUE, then changelist information for the
|
||||
* paths is cleared while reverting.
|
||||
*
|
||||
* If @a metadata_only is TRUE, the files and directories aren't changed
|
||||
* by the operation. If there are conflict marker files attached to the
|
||||
* targets these are removed.
|
||||
* The @a metadata_only and @a added_keep_local options control the
|
||||
* extent of reverting. If @a metadata_only is TRUE, the working copy
|
||||
* files are untouched, but if there are conflict marker files attached
|
||||
* to these files these markers are removed. Otherwise, if
|
||||
* @a added_keep_local is TRUE, then all items are reverted except an
|
||||
* item that was scheduled as plain 'add' (not a copy) will not be
|
||||
* removed from the working copy. Otherwise, all items are reverted and
|
||||
* their on-disk state changed to match.
|
||||
*
|
||||
* Consult the @c SVN_CONFIG_OPTION_USE_COMMIT_TIMES option in @a ctx to
|
||||
* determine whether or not to revert timestamp to the time of last
|
||||
* commit ('use-commit-times = yes').
|
||||
*
|
||||
* If @a ctx->notify_func2 is non-NULL, then for each item reverted,
|
||||
* call @a ctx->notify_func2 with @a ctx->notify_baton2 and the path of
|
||||
@ -4308,9 +4491,29 @@ svn_client_relocate(const char *dir,
|
||||
* then do not error, just invoke @a ctx->notify_func2 with @a
|
||||
* ctx->notify_baton2, using notification code #svn_wc_notify_skip.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
* @warning The 'revert' command intentionally and permanently loses
|
||||
* local modifications.
|
||||
*
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_revert4(const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_boolean_t clear_changelists,
|
||||
svn_boolean_t metadata_only,
|
||||
svn_boolean_t added_keep_local,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Similar to svn_client_revert4(), but with @a added_keep_local set to
|
||||
* TRUE.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
* @deprecated Provided for backwards compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_client_revert3(const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
@ -4427,7 +4630,18 @@ typedef enum svn_client_conflict_option_id_t {
|
||||
svn_client_conflict_option_incoming_move_dir_merge,
|
||||
|
||||
/* Options for local move vs incoming edit on merge. */
|
||||
svn_client_conflict_option_local_move_file_text_merge
|
||||
svn_client_conflict_option_local_move_file_text_merge,
|
||||
svn_client_conflict_option_local_move_dir_merge, /**< @since New in 1.11. */
|
||||
|
||||
/* Options for local missing vs incoming edit on merge. */
|
||||
svn_client_conflict_option_sibling_move_file_text_merge, /**< @since New in 1.11. */
|
||||
svn_client_conflict_option_sibling_move_dir_merge, /**< @since New in 1.11. */
|
||||
|
||||
/* Options for local move vs incoming move on merge. */
|
||||
svn_client_conflict_option_both_moved_file_merge, /*< @since New in 1.12 */
|
||||
svn_client_conflict_option_both_moved_file_move_merge, /*< @since New in 1.12 */
|
||||
svn_client_conflict_option_both_moved_dir_merge, /*< @since New in 1.12 */
|
||||
svn_client_conflict_option_both_moved_dir_move_merge, /*< @since New in 1.12 */
|
||||
} svn_client_conflict_option_id_t;
|
||||
|
||||
/**
|
||||
@ -4448,26 +4662,45 @@ svn_client_conflict_option_set_merged_propval(
|
||||
const svn_string_t *merged_propval);
|
||||
|
||||
/**
|
||||
* Get a list of possible repository paths which can be applied to the
|
||||
* svn_client_conflict_option_incoming_move_file_text_merge or
|
||||
* svn_client_conflict_option_incoming_move_dir_merge resolution
|
||||
* @a option. (If a different option is passed in, this function will
|
||||
* raise an assertion failure.)
|
||||
* Get a list of possible repository paths which can be applied to @a option.
|
||||
*
|
||||
* In some situations, there can be multiple possible destinations for an
|
||||
* incoming move. One such situation is where a file was copied and moved
|
||||
* in the same revision: svn cp a b; svn mv a c; svn commit
|
||||
* In some situations, there can be multiple possible destinations for a move.
|
||||
* One such situation is where a file was copied and moved in the same revision:
|
||||
* svn cp a b; svn mv a c; svn commit
|
||||
* When this move is merged elsewhere, both b and c will appear as valid move
|
||||
* destinations to the conflict resolver. To resolve such ambiguity, the client
|
||||
* may call this function to obtain a list of possible destinations the user
|
||||
* may choose from.
|
||||
*
|
||||
* @a *possible_moved_to_repos_relpaths is set to NULL if the @a option does
|
||||
* not support multiple move targets. API users may assume that only one option
|
||||
* among those which can be applied to a conflict supports move targets.
|
||||
*
|
||||
* The array is allocated in @a result_pool and will have "const char *"
|
||||
* elements pointing to strings also allocated in @a result_pool.
|
||||
* All paths are relpaths, and relative to the repository root.
|
||||
*
|
||||
* @see svn_client_conflict_option_set_moved_to_repos_relpath()
|
||||
* @see svn_client_conflict_option_set_moved_to_repos_relpath2()
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_get_moved_to_repos_relpath_candidates2(
|
||||
apr_array_header_t **possible_moved_to_repos_relpaths,
|
||||
svn_client_conflict_option_t *option,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Get a list of possible repository paths which can be applied to the
|
||||
* svn_client_conflict_option_incoming_move_file_text_merge, or the
|
||||
* svn_client_conflict_option_incoming_move_dir_merge resolution @a option.
|
||||
*
|
||||
* In SVN 1.10, if a different option is passed in, this function will
|
||||
* raise an assertion failure. Otherwise this function behaves just like
|
||||
* svn_client_conflict_option_get_moved_to_repos_relpath_candidates2().
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @deprecated use svn_client_conflict_option_get_moved_to_repos_relpath_candidates2()
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_get_moved_to_repos_relpath_candidates(
|
||||
@ -4477,9 +4710,8 @@ svn_client_conflict_option_get_moved_to_repos_relpath_candidates(
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Set the preferred moved target repository path for the
|
||||
* svn_client_conflict_option_incoming_move_file_text_merge or
|
||||
* svn_client_conflict_option_incoming_move_dir_merge resolution option.
|
||||
* Set the preferred moved target repository path. If @a option is not
|
||||
* applicable to a moved target repository path, do nothing.
|
||||
*
|
||||
* @a preferred_move_target_idx must be a valid index into the list returned
|
||||
* by svn_client_conflict_option_get_moved_to_repos_relpath_candidates().
|
||||
@ -4489,7 +4721,23 @@ svn_client_conflict_option_get_moved_to_repos_relpath_candidates(
|
||||
* svn_client_conflict_option_get_description(). Call these functions again
|
||||
* to get updated descriptions containing the newly selected move target.
|
||||
*
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_set_moved_to_repos_relpath2(
|
||||
svn_client_conflict_option_t *option,
|
||||
int preferred_move_target_idx,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Like svn_client_conflict_option_set_moved_to_repos_relpath2(), except
|
||||
* that in SVN 1.10 it raises an assertion failure if an option other
|
||||
* than svn_client_conflict_option_incoming_move_file_text_merge or
|
||||
* svn_client_conflict_option_incoming_move_dir_merge is passed.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @deprecated use svn_client_conflict_option_set_moved_to_repos_relpath2()
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_set_moved_to_repos_relpath(
|
||||
@ -4500,24 +4748,45 @@ svn_client_conflict_option_set_moved_to_repos_relpath(
|
||||
|
||||
/**
|
||||
* Get a list of possible moved-to abspaths in the working copy which can be
|
||||
* applied to the svn_client_conflict_option_incoming_move_file_text_merge
|
||||
* or svn_client_conflict_option_incoming_move_dir_merge resolution @a option.
|
||||
* (If a different option is passed in, this function will raise an assertion
|
||||
* failure.)
|
||||
* applied to @a option.
|
||||
*
|
||||
* All paths in the returned list correspond to the repository path which
|
||||
* is assumed to be the destination of the incoming move operation.
|
||||
* To support cases where this destination path is ambiguous, the client may
|
||||
* call svn_client_conflict_option_get_moved_to_repos_relpath_candidates()
|
||||
* before calling this function to let the user select a repository path first.
|
||||
* All working copy paths in the returned list correspond to one repository
|
||||
* path which is be one of the possible destinations of a move operation.
|
||||
* More than one repository-side move target candidate may exist; call
|
||||
* svn_client_conflict_option_get_moved_to_repos_relpath_candidates() before
|
||||
* calling this function to let the user select a repository path first.
|
||||
* Otherwise, one of the repository-side paths will be selected internally.
|
||||
*
|
||||
* @a *possible_moved_to_abspaths is set to NULL if the @a option does not
|
||||
* support multiple move targets. API users may assume that only one option
|
||||
* among those which can be applied to a conflict supports move targets.
|
||||
*
|
||||
* If no possible moved-to paths can be found, return an empty array.
|
||||
* This doesn't mean that no move happened in the repository. It is possible
|
||||
* that the move destination is outside the scope of the current working copy,
|
||||
* for example, in which case the conflict must be resolved in some other way.
|
||||
*
|
||||
* @see svn_client_conflict_option_set_moved_to_abspath()
|
||||
* @see svn_client_conflict_option_set_moved_to_abspath2()
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_get_moved_to_abspath_candidates2(
|
||||
apr_array_header_t **possible_moved_to_abspaths,
|
||||
svn_client_conflict_option_t *option,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Get a list of possible moved-to abspaths in the working copy which can be
|
||||
* svn_client_conflict_option_incoming_move_file_text_merge, or the
|
||||
* svn_client_conflict_option_incoming_move_dir_merge resolution @a option.
|
||||
*
|
||||
* In SVN 1.10, if a different option is passed in, this function will
|
||||
* raise an assertion failure. Otherwise this function behaves just like
|
||||
* svn_client_conflict_option_get_moved_to_abspath_candidates2().
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @deprecated use svn_client_conflict_option_get_moved_to_abspath_candidates2()
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_get_moved_to_abspath_candidates(
|
||||
@ -4527,14 +4796,34 @@ svn_client_conflict_option_get_moved_to_abspath_candidates(
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Set the preferred moved target abspath for the
|
||||
* svn_client_conflict_option_incoming_move_file_text_merge or
|
||||
* svn_client_conflict_option_incoming_move_dir_merge resolution option.
|
||||
* Set the preferred moved target working copy path. If @a option is not
|
||||
* applicable to a moved target working copy path, do nothing.
|
||||
*
|
||||
* @a preferred_move_target_idx must be a valid index into the list
|
||||
* returned by svn_client_conflict_option_get_moved_to_abspath_candidates().
|
||||
* returned by svn_client_conflict_option_get_moved_to_abspath_candidates2().
|
||||
*
|
||||
* This function can be called multiple times.
|
||||
* It affects the output of svn_client_conflict_tree_get_description() and
|
||||
* svn_client_conflict_option_get_description(). Call these functions again
|
||||
* to get updated descriptions containing the newly selected move target.
|
||||
*
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_set_moved_to_abspath2(
|
||||
svn_client_conflict_option_t *option,
|
||||
int preferred_move_target_idx,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Like svn_client_conflict_option_set_moved_to_abspath2(), except that
|
||||
* in SVN 1.10 this function raises an assertion failure if an option
|
||||
* other than svn_client_conflict_option_incoming_move_file_text_merge or
|
||||
* svn_client_conflict_option_incoming_move_dir_merge is passed.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @deprecated use svn_client_conflict_option_set_moved_to_abspath2()
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client_conflict_option_set_moved_to_abspath(
|
||||
@ -4583,7 +4872,7 @@ typedef svn_error_t *(*svn_client_conflict_walk_func_t)(
|
||||
|
||||
/**
|
||||
* Walk all conflicts within the specified @a depth of @a local_abspath.
|
||||
* Pass each conflict found during the walk to the @conflict_walk_func
|
||||
* Pass each conflict found during the walk to the @a conflict_walk_func
|
||||
* callback, along with @a conflict_walk_func_baton.
|
||||
* Use cancellation and notification support provided by client context @a ctx.
|
||||
*
|
||||
@ -4881,7 +5170,7 @@ svn_client_conflict_get_repos_info(const char **repos_root_url,
|
||||
* Any output parameter may be set to @c NULL by the caller to indicate that
|
||||
* a particular piece of information should not be returned.
|
||||
*
|
||||
* In case of tree conflicts, this path@revision does not necessarily exist
|
||||
* In case of tree conflicts, this "path@revision" does not necessarily exist
|
||||
* in the repository, and it does not necessarily represent the incoming
|
||||
* change which is responsible for the occurance of the tree conflict.
|
||||
* The responsible incoming change is generally located somewhere between
|
||||
@ -6549,7 +6838,7 @@ svn_client_list2(const char *path_or_url,
|
||||
|
||||
/**
|
||||
* Similar to svn_client_list2(), but with @a recurse instead of @a depth.
|
||||
* If @a recurse is TRUE, pass #svn_depth_files for @a depth; else
|
||||
* If @a recurse is FALSE, pass #svn_depth_immediates for @a depth; else
|
||||
* pass #svn_depth_infinity.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
@ -6714,169 +7003,12 @@ svn_client_cat(svn_stream_t *out,
|
||||
/** @} end group: cat */
|
||||
|
||||
|
||||
|
||||
/** Shelving commands
|
||||
*
|
||||
* @defgroup svn_client_shelve_funcs Client Shelving Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Shelve a change.
|
||||
*
|
||||
* Shelve as @a name the local modifications found by @a paths, @a depth,
|
||||
* @a changelists. Revert the shelved change from the WC unless @a keep_local
|
||||
* is true.
|
||||
*
|
||||
* If @a dry_run is true, don't actually do it.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelve(const char *name,
|
||||
const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_boolean_t keep_local,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Unshelve the shelved change @a name.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
* Rename the shelved patch to add a '.bak' extension unless @a keep is true.
|
||||
*
|
||||
* If @a dry_run is true, don't actually do it.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_unshelve(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t keep,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Delete the shelved patch @a name.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* If @a dry_run is true, don't actually do it.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelves_delete(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Information about a shelved patch.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
typedef struct svn_client_shelved_patch_info_t
|
||||
{
|
||||
const char *message; /* first line of log message */
|
||||
const char *patch_path; /* abspath of the patch file */
|
||||
svn_io_dirent2_t *dirent; /* info about the patch file */
|
||||
apr_time_t mtime; /* a copy of dirent->mtime */
|
||||
} svn_client_shelved_patch_info_t;
|
||||
|
||||
/** Set @a *shelved_patch_infos to a hash, keyed by patch name, of pointers to
|
||||
* @c svn_client_shelved_patch_info_t structures.
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelves_list(apr_hash_t **shelved_patch_infos,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *any_shelved to indicate if there are any shelved changes in this WC.
|
||||
*
|
||||
* This shall provide the answer fast, regardless of how many changes
|
||||
* are stored, unlike svn_client_shelves_list().
|
||||
*
|
||||
* ### Initial implementation isn't O(1) fast -- it just calls
|
||||
* svn_client_shelves_list().
|
||||
*
|
||||
* @a local_abspath is any path in the WC and is used to find the WC root.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelves_any(svn_boolean_t *any_shelved,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *affected_paths to a hash with one entry for each path affected
|
||||
* by the shelf @a name. The hash key is the old path and value is
|
||||
* the new path, both relative to the WC root. The key and value are the
|
||||
* same except when a path is moved or copied.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelf_get_paths(apr_hash_t **affected_paths,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Set @a *has_changes to indicate whether the shelf @a name
|
||||
* contains any modifications, in other words if svn_client_shelf_get_paths()
|
||||
* would return a non-empty set of paths.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @warning EXPERIMENTAL.
|
||||
*/
|
||||
SVN_EXPERIMENTAL
|
||||
svn_error_t *
|
||||
svn_client_shelf_has_changes(svn_boolean_t *has_changes,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** Changelist commands
|
||||
*
|
||||
* @defgroup svn_client_changelist_funcs Client Changelist Functions
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** Implementation note:
|
||||
*
|
||||
* For now, changelists are implemented by scattering the
|
||||
* associations across multiple .svn/entries files in a working copy.
|
||||
* However, this client API was written so that we have the option of
|
||||
* changing the underlying implementation -- we may someday want to
|
||||
* store changelist definitions in a centralized database.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Add each path in @a paths (recursing to @a depth as necessary) to
|
||||
* @a changelist. If a path is already a member of another
|
||||
|
@ -44,8 +44,8 @@ extern "C" {
|
||||
/**************************************************************************
|
||||
*** ***
|
||||
*** For a description of the SVN configuration file syntax, see ***
|
||||
*** your ~/.subversion/README, which is written out automatically by ***
|
||||
*** svn_config_ensure(). ***
|
||||
*** your ~/.subversion/README.txt, which is written out automatically ***
|
||||
*** by svn_config_ensure(). ***
|
||||
*** ***
|
||||
**************************************************************************/
|
||||
|
||||
|
@ -495,6 +495,10 @@ svn_txdelta_send_contents(const unsigned char *contents,
|
||||
* since there's nothing else in the delta application's context to
|
||||
* supply a path for error messages.)
|
||||
*
|
||||
* The @a source stream will NOT be closed. The @a target stream will be
|
||||
* closed when the window handler is given a null window to signal the
|
||||
* end of the delta.
|
||||
*
|
||||
* @note To avoid lifetime issues, @a error_info is copied into
|
||||
* @a pool or a subpool thereof.
|
||||
*/
|
||||
@ -859,7 +863,7 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
|
||||
* @c apply_textdelta / @c apply_textdelta_stream and @c close_file
|
||||
* should not refer to a parent directory baton UNLESS the editor has
|
||||
* taken precautions to allocate it in a pool of the appropriate
|
||||
* lifetime (the @a dir_pool passed to @c open_directory and
|
||||
* lifetime (the @a result_pool passed to @c open_directory and
|
||||
* @c add_directory definitely does not have the proper lifetime).
|
||||
* In general, it is recommended to simply avoid keeping a parent
|
||||
* directory baton in a file baton.
|
||||
@ -1285,24 +1289,47 @@ svn_delta_depth_filter_editor(const svn_delta_editor_t **editor,
|
||||
/** Callback function type for svn_delta_path_driver().
|
||||
*
|
||||
* The handler of this callback is given the callback baton @a
|
||||
* callback_baton, @a path which is a relpath relative to the
|
||||
* callback_baton, @a editor and @a edit_baton which represent the
|
||||
* editor being driven, @a relpath which is a relpath relative to the
|
||||
* root of the edit, and the @a parent_baton which represents
|
||||
* path's parent directory as created by the editor passed to
|
||||
* svn_delta_path_driver().
|
||||
* @a relpath's parent directory as created by the editor.
|
||||
*
|
||||
* If @a path represents a directory, the handler must return a @a
|
||||
* *dir_baton for @a path, generated from the same editor (so that the
|
||||
* driver can later close that directory).
|
||||
* If the handler deletes the node at @a relpath (and does not replace it
|
||||
* with an added directory) it must set @a *dir_baton to null or leave
|
||||
* it unchanged.
|
||||
*
|
||||
* If, however, @a path represents a file, the handler should NOT
|
||||
* return any file batons. It can close any opened or added files
|
||||
* immediately, or delay that close until the end of the edit when
|
||||
* svn_delta_path_driver() returns.
|
||||
* If the handler opens (or adds) a directory at @a relpath, it must set
|
||||
* @a *dir_baton to the directory baton for @a relpath, generated from
|
||||
* the same editor. The driver will close the directory later.
|
||||
*
|
||||
* If the handler opens (or adds) a file at @a relpath, the handler must
|
||||
* set @a *dir_baton to null or leave it unchanged. The handler must
|
||||
* either close the file immediately, or delay that close until the end
|
||||
* of the edit when svn_delta_path_driver() returns.
|
||||
*
|
||||
* Finally, if @a parent_baton is @c NULL, then the root of the edit
|
||||
* is also one of the paths passed to svn_delta_path_driver(). The
|
||||
* handler of this callback must call the editor's open_root()
|
||||
* function and return the top-level root dir baton in @a *dir_baton.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
typedef svn_error_t *(*svn_delta_path_driver_cb_func2_t)(
|
||||
void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *relpath,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Like #svn_delta_path_driver_cb_func2_t but without the @a editor and
|
||||
* @a edit_baton parameters. The user must arrange for the editor to be
|
||||
* passed through @a callback_baton (if required, which it usually is).
|
||||
* And @a path could possibly have a '/' prefix instead of being a relpath;
|
||||
* see the note on svn_delta_path_driver2().
|
||||
*
|
||||
* @deprecated Provided for backward compatibility with the 1.11 API.
|
||||
*/
|
||||
typedef svn_error_t *(*svn_delta_path_driver_cb_func_t)(
|
||||
void **dir_baton,
|
||||
@ -1312,24 +1339,51 @@ typedef svn_error_t *(*svn_delta_path_driver_cb_func_t)(
|
||||
apr_pool_t *pool);
|
||||
|
||||
|
||||
/** Drive @a editor (with its @a edit_baton) to visit each path in @a paths.
|
||||
/** Drive @a editor (with its @a edit_baton) to visit each path in @a relpaths.
|
||||
*
|
||||
* As each path is hit as part of the editor drive, use
|
||||
* @a callback_func and @a callback_baton to allow the caller to handle
|
||||
* the portion of the editor drive related to that path.
|
||||
*
|
||||
* Each path in @a paths is a (const char *) relpath, relative
|
||||
* to the root path of the @a edit. The editor drive will be
|
||||
* performed in the same order as @a paths. The paths should be sorted
|
||||
* using something like svn_sort_compare_paths to ensure that a depth-first
|
||||
* pattern is observed for directory/file baton creation. If @a sort_paths
|
||||
* Each path in @a relpaths is a (const char *) relpath, relative
|
||||
* to the root path of the edit. The editor drive will be
|
||||
* performed in the same order as @a relpaths. The paths should be sorted
|
||||
* using something like svn_sort_compare_paths() to ensure that each
|
||||
* directory in the depth-first walk is visited only once. If @a sort_paths
|
||||
* is set, the function will sort the paths for you. Some callers may need
|
||||
* further customization of the order (ie. libsvn_delta/compat.c).
|
||||
*
|
||||
* If the first target path (after any requested sorting) is @c "" (the
|
||||
* root of the edit), the callback function will be responsible for
|
||||
* calling the editor's @c open_root method; otherwise, this function
|
||||
* will call @c open_root.
|
||||
*
|
||||
* Use @a scratch_pool for all necessary allocations.
|
||||
*
|
||||
* @since New in 1.8.
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_delta_path_driver3(const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
const apr_array_header_t *relpaths,
|
||||
svn_boolean_t sort_paths,
|
||||
svn_delta_path_driver_cb_func2_t callback_func,
|
||||
void *callback_baton,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Like svn_delta_path_driver3() but with a different callback function
|
||||
* signature.
|
||||
*
|
||||
* Optionally, paths in @a paths could have a '/' prefix instead of being
|
||||
* relpaths. If any of them do, then (since 1.12) ALL paths sent to the
|
||||
* callback will have a '/' prefix.
|
||||
*
|
||||
* @deprecated Provided for backward compatibility with the 1.11 API.
|
||||
* @since New in 1.8. Before 1.12, paths sent to the callback were the
|
||||
* exact paths passed in @a paths.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
const apr_array_header_t *paths,
|
||||
@ -1358,6 +1412,80 @@ svn_delta_path_driver(const svn_delta_editor_t *editor,
|
||||
void *callback_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
/** A state object for the path driver that is obtained from
|
||||
* svn_delta_path_driver_start() and driven by
|
||||
* svn_delta_path_driver_step() and svn_delta_path_driver_finish().
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
typedef struct svn_delta_path_driver_state_t svn_delta_path_driver_state_t;
|
||||
|
||||
/** Return a path driver object that can drive @a editor (with its
|
||||
* @a edit_baton) to visit a series of paths.
|
||||
*
|
||||
* As each path is hit as part of the editor drive, the path driver will
|
||||
* call @a callback_func and @a callback_baton to allow the caller to handle
|
||||
* the portion of the editor drive related to that path.
|
||||
*
|
||||
* This will not call the editor's open_root method; for that, see
|
||||
* svn_delta_path_driver_step().
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_start(svn_delta_path_driver_state_t **state_p,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
svn_delta_path_driver_cb_func2_t callback_func,
|
||||
void *callback_baton,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Visit @a relpath.
|
||||
*
|
||||
* @a state is the object returned by svn_delta_path_driver_start().
|
||||
*
|
||||
* @a relpath is a relpath relative to the root path of the edit.
|
||||
*
|
||||
* This function uses the editor and the callback that were originally
|
||||
* supplied to svn_delta_path_driver_start().
|
||||
*
|
||||
* This drives the editor in a depth-first order, closing and then opening
|
||||
* directories if necessary to move from the last visited path to the new
|
||||
* path, as required by the editor driving rules.
|
||||
*
|
||||
* This then calls the callback to allow the caller to handle
|
||||
* the portion of the editor drive related to that path.
|
||||
*
|
||||
* If the first path to visit is @c "" (the root of the edit), the
|
||||
* callback function will be responsible for calling the editor's
|
||||
* @c open_root method; otherwise, this function will call @c open_root.
|
||||
*
|
||||
* The order of paths to visit should in general be sorted using something
|
||||
* like svn_sort_compare_paths() to ensure that each directory in the
|
||||
* depth-first walk is visited only once. Some editors may rely on such a
|
||||
* restriction.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_step(svn_delta_path_driver_state_t *state,
|
||||
const char *relpath,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Finish driving the editor.
|
||||
*
|
||||
* @a state is the object returned by svn_delta_path_driver_start().
|
||||
*
|
||||
* This drives the editor to close any open directories and then calls
|
||||
* the editor's @c close_edit method.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_finish(svn_delta_path_driver_state_t *state,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
@ -60,12 +60,14 @@
|
||||
* form, except:
|
||||
*
|
||||
* - @c svn_dirent_canonicalize()
|
||||
* - @c svn_dirent_canonicalize_safe()
|
||||
* - @c svn_dirent_is_canonical()
|
||||
* - @c svn_dirent_internal_style()
|
||||
* - @c svn_relpath_canonicalize()
|
||||
* - @c svn_relpath_canonicalize_safe()
|
||||
* - @c svn_relpath_is_canonical()
|
||||
* - @c svn_relpath__internal_style()
|
||||
* - @c svn_uri_canonicalize()
|
||||
* - @c svn_uri_canonicalize_safe()
|
||||
* - @c svn_uri_is_canonical()
|
||||
*
|
||||
* The Subversion codebase also recognizes some other classes of path:
|
||||
@ -144,17 +146,47 @@ extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/** Convert @a dirent from the local style to the canonical internal style.
|
||||
/**
|
||||
* Convert @a dirent from the local style to the canonical internal style.
|
||||
* "Local style" means native path separators and "." for the empty path.
|
||||
*
|
||||
* Allocate the result in @a result_pool.
|
||||
*
|
||||
* @warning This function may call @c abort() if the @a dirent parameter
|
||||
* is not a valid local-style path.
|
||||
* Use svn_dirent_internal_style_safe() for tainted input.
|
||||
*
|
||||
* @since New in 1.6.
|
||||
*/
|
||||
const char *
|
||||
svn_dirent_internal_style(const char *dirent,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/**
|
||||
* Convert @a dirent from the local style to the canonical internal style
|
||||
* and return it in @a *internal_style_dirent. "Local style" means native
|
||||
* path separators and "." for the empty path.
|
||||
*
|
||||
* Similar to svn_dirent_internal_style() (which see), but returns an error
|
||||
* if the @a dirent can not be canonicalized or of the result does not pass
|
||||
* the svn_dirent_is_canonical() test.
|
||||
*
|
||||
* If the function fails and @a non_canonical_result is not @c NULL, the
|
||||
* result of the failed canonicalization attempt (which may be @c NULL)
|
||||
* will be returned in @a *non_canonical_result.
|
||||
*
|
||||
* Allocates the results in @a result_pool. Uses @a scratch_pool for
|
||||
* temporary allocations.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_dirent_internal_style_safe(const char **internal_style_dirent,
|
||||
const char **non_canonical_result,
|
||||
const char *dirent,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Convert @a dirent from the internal style to the local style.
|
||||
* "Local style" means native path separators and "." for the empty path.
|
||||
* If the input is not canonical, the output may not be canonical.
|
||||
@ -167,18 +199,6 @@ const char *
|
||||
svn_dirent_local_style(const char *dirent,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/** Convert @a relpath from the local style to the canonical internal style.
|
||||
* "Local style" means native path separators and "." for the empty path.
|
||||
*
|
||||
* Allocate the result in @a result_pool.
|
||||
*
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
const char *
|
||||
svn_relpath__internal_style(const char *relpath,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
|
||||
/** Join a base dirent (@a base) with a component (@a component).
|
||||
*
|
||||
* If either @a base or @a component is the empty string, then the other
|
||||
@ -453,7 +473,8 @@ svn_boolean_t
|
||||
svn_uri_is_root(const char *uri,
|
||||
apr_size_t len);
|
||||
|
||||
/** Return a new dirent like @a dirent, but transformed such that some types
|
||||
/**
|
||||
* Return a new dirent like @a dirent, but transformed such that some types
|
||||
* of dirent specification redundancies are removed.
|
||||
*
|
||||
* This involves:
|
||||
@ -467,14 +488,43 @@ svn_uri_is_root(const char *uri,
|
||||
*
|
||||
* Allocate the result in @a result_pool.
|
||||
*
|
||||
* @warning This function may call @c abort() if @a dirent can not be
|
||||
* canonicalized.
|
||||
* Use svn_dirent_canonicalize_safe() for tainted input.
|
||||
*
|
||||
* @since New in 1.6.
|
||||
*/
|
||||
const char *
|
||||
svn_dirent_canonicalize(const char *dirent,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/**
|
||||
* Return a new @a *canonical_dirent like @a dirent, but transformed such
|
||||
* that some types of dirent specification redundancies are removed.
|
||||
*
|
||||
* Similar to svn_dirent_canonicalize() (which see), but returns an error
|
||||
* if the @a dirent can not be canonicalized or of the result does not pass
|
||||
* the svn_dirent_is_canonical() test.
|
||||
*
|
||||
* If the function fails and @a non_canonical_result is not @c NULL, the
|
||||
* result of the failed canonicalization attempt (which may be @c NULL)
|
||||
* will be returned in @a *non_canonical_result.
|
||||
*
|
||||
* Allocates the results in @a result_pool. Uses @a scratch_pool for
|
||||
* temporary allocations.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_dirent_canonicalize_safe(const char **canonical_dirent,
|
||||
const char **non_canonical_result,
|
||||
const char *dirent,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Return a new relpath like @a relpath, but transformed such that some types
|
||||
|
||||
/**
|
||||
* Return a new relpath like @a relpath, but transformed such that some types
|
||||
* of relpath specification redundancies are removed.
|
||||
*
|
||||
* This involves:
|
||||
@ -486,14 +536,44 @@ svn_dirent_canonicalize(const char *dirent,
|
||||
*
|
||||
* Allocate the result in @a result_pool.
|
||||
*
|
||||
* @warning This function may call @c abort() if @a relpath can not be
|
||||
* canonicalized.
|
||||
* Use svn_relpath_canonicalize_safe() for tainted input.
|
||||
*
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
const char *
|
||||
svn_relpath_canonicalize(const char *relpath,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/**
|
||||
* Return a new @a *canonical_relpath like @a relpath, but transformed such
|
||||
* that some types of relpath specification redundancies are removed.
|
||||
*
|
||||
* Similar to svn_relpath_canonicalize() (which see), but returns an error
|
||||
* if the @a relpath can not be canonicalized or of the result does not
|
||||
* pass the svn_relpath_is_canonical() test.
|
||||
*
|
||||
* If the function fails and @a non_canonical_result is not @c NULL, the
|
||||
* result of the failed canonicalization attempt (which may be @c NULL)
|
||||
* will be returned in @a *non_canonical_result.
|
||||
*
|
||||
* Allocates the results in @a result_pool. Uses @a scratch_pool for
|
||||
* temporary allocations.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
|
||||
/** Return a new uri like @a uri, but transformed such that some types
|
||||
svn_error_t *
|
||||
svn_relpath_canonicalize_safe(const char **canonical_relpath,
|
||||
const char **non_canonical_result,
|
||||
const char *relpath,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
/**
|
||||
* Return a new uri like @a uri, but transformed such that some types
|
||||
* of uri specification redundancies are removed.
|
||||
*
|
||||
* This involves:
|
||||
@ -509,6 +589,10 @@ svn_relpath_canonicalize(const char *relpath,
|
||||
* and possibly other semantically inoperative transformations.
|
||||
*
|
||||
* Allocate the result in @a result_pool.
|
||||
*
|
||||
* @warning This function may call @c abort() if @a uri can not be
|
||||
* canonicalized.
|
||||
* Use svn_uri_canonicalize_safe() for tainted input.
|
||||
*
|
||||
* @since New in 1.7.
|
||||
*/
|
||||
@ -516,6 +600,31 @@ const char *
|
||||
svn_uri_canonicalize(const char *uri,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
/**
|
||||
* Return a new @a *canonical_uri like @a uri, but transformed such that
|
||||
* some types of uri specification redundancies are removed.
|
||||
*
|
||||
* Similar to svn_uri_canonicalize() (which see), but returns an error if
|
||||
* the @a uri can not be canonicalized or of the result does not pass the
|
||||
* svn_uri_is_canonical() test.
|
||||
*
|
||||
* If the function fails and @a non_canonical_result is not @c NULL, the
|
||||
* result of the failed canonicalization attempt (which may be @c NULL)
|
||||
* will be returned in @a *non_canonical_result.
|
||||
*
|
||||
* Allocates the results in @a result_pool. Uses @a scratch_pool for
|
||||
* temporary allocations.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_uri_canonicalize_safe(const char **canonical_uri,
|
||||
const char **non_canonical_result,
|
||||
const char *uri,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
/** Return @c TRUE iff @a dirent is canonical.
|
||||
*
|
||||
* Use @a scratch_pool for temporary allocations.
|
||||
|
@ -888,6 +888,21 @@ SVN_ERROR_START
|
||||
SVN_ERR_FS_CATEGORY_START + 67,
|
||||
"Content checksums supposedly match but content does not.")
|
||||
|
||||
/** @since New in 1.13. */
|
||||
SVN_ERRDEF(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE,
|
||||
SVN_ERR_FS_CATEGORY_START + 68,
|
||||
"Unrecognized filesystem I/O control code")
|
||||
|
||||
/** @since New in 1.14. */
|
||||
SVN_ERRDEF(SVN_ERR_FS_REP_SHARING_NOT_ALLOWED,
|
||||
SVN_ERR_FS_CATEGORY_START + 69,
|
||||
"Rep-sharing is not allowed.")
|
||||
|
||||
/** @since New in 1.14. */
|
||||
SVN_ERRDEF(SVN_ERR_FS_REP_SHARING_NOT_SUPPORTED,
|
||||
SVN_ERR_FS_CATEGORY_START + 70,
|
||||
"Rep-sharing is not supported.")
|
||||
|
||||
/* repos errors */
|
||||
|
||||
SVN_ERRDEF(SVN_ERR_REPOS_LOCKED,
|
||||
@ -1482,6 +1497,11 @@ SVN_ERROR_START
|
||||
SVN_ERR_MISC_CATEGORY_START + 46,
|
||||
"LZ4 decompression failed")
|
||||
|
||||
/** @since New in 1.12. */
|
||||
SVN_ERRDEF(SVN_ERR_CANONICALIZATION_FAILED,
|
||||
SVN_ERR_MISC_CATEGORY_START + 47,
|
||||
"Could not canonicalize path or URI")
|
||||
|
||||
/* command-line client errors */
|
||||
|
||||
SVN_ERRDEF(SVN_ERR_CL_ARG_PARSING_ERROR,
|
||||
@ -1769,7 +1789,7 @@ SVN_ERROR_START
|
||||
|
||||
SVN_ERRDEF(SVN_ERR_X509_CERT_VERIFY_FAILED,
|
||||
SVN_ERR_X509_CATEGORY_START + 19,
|
||||
"Certficate verification failed")
|
||||
"Certificate verification failed")
|
||||
|
||||
SVN_ERROR_END
|
||||
|
||||
|
@ -1744,7 +1744,7 @@ svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator,
|
||||
*
|
||||
* Use @a pool for all allocations, including the hash and its values.
|
||||
*
|
||||
* @note Retrieving the #node_rev_id element of #svn_fs_path_change2_t may
|
||||
* @note Retrieving the #svn_fs_path_change2_t.node_rev_id element may
|
||||
* be expensive in some FS backends.
|
||||
*
|
||||
* @since New in 1.6.
|
||||
@ -1828,9 +1828,9 @@ svn_fs_node_history(svn_fs_history_t **history_p,
|
||||
* the same as the original. This will happen if the original
|
||||
* location was an interesting one (where the node was modified, or
|
||||
* took place in a copy event). This behavior allows looping callers
|
||||
* to avoid the calling svn_fs_history_location() on the object
|
||||
* returned by svn_fs_node_history(), and instead go ahead and begin
|
||||
* calling svn_fs_history_prev().
|
||||
* to avoid calling svn_fs_history_location() on the object returned
|
||||
* by svn_fs_node_history(), and instead go ahead and begin calling
|
||||
* svn_fs_history_prev().
|
||||
*
|
||||
* @note This function uses node-id ancestry alone to determine
|
||||
* modifiedness, and therefore does NOT claim that in any of the
|
||||
@ -2492,7 +2492,7 @@ svn_fs_file_md5_checksum(unsigned char digest[],
|
||||
* svn_fs_file_contents(). In that case, the result of reading from
|
||||
* @a *contents is undefined.
|
||||
*
|
||||
* ### @todo kff: I am worried about lifetime issues with this pool vs
|
||||
* @todo kff: I am worried about lifetime issues with this pool vs
|
||||
* the trail created farther down the call stack. Trace this function
|
||||
* to investigate...
|
||||
*/
|
||||
@ -3503,6 +3503,54 @@ svn_fs_info_dup(const void *info,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* A structure specifying the filesystem-specific input/output operation.
|
||||
*
|
||||
* @see svn_fs_ioctl()
|
||||
*
|
||||
* @since New in 1.13.
|
||||
*/
|
||||
typedef struct svn_fs_ioctl_code_t
|
||||
{
|
||||
const char *fs_type;
|
||||
int code;
|
||||
} svn_fs_ioctl_code_t;
|
||||
|
||||
/**
|
||||
* A convenience macro to declare #svn_fs_ioctl_code_t codes.
|
||||
*
|
||||
* @since New in 1.13.
|
||||
*/
|
||||
#define SVN_FS_DECLARE_IOCTL_CODE(name, fs_type, code) \
|
||||
static const svn_fs_ioctl_code_t name = { fs_type, code }
|
||||
|
||||
/**
|
||||
* Issue a filesystem-specific input/output operation defined by @a ctlcode
|
||||
* (usually, a low-level operation which cannot be expressed by other
|
||||
* filesystem APIs). If @a fs is @c NULL, issue a global operation.
|
||||
* If @a fs is not @c NULL, issue an operation that is specific to this
|
||||
* filesystem instance.
|
||||
*
|
||||
* If the filesystem cannot handle this ioctl code, return the
|
||||
* #SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE error.
|
||||
*
|
||||
* Allocate the result in @a result_pool, use @a scratch_pool for temporary
|
||||
* allocations.
|
||||
*
|
||||
* @see #svn_fs_ioctl_code_t
|
||||
*
|
||||
* @since New in 1.13.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_fs_ioctl(svn_fs_t *fs,
|
||||
svn_fs_ioctl_code_t ctlcode,
|
||||
void *input,
|
||||
void **output_p,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -27,6 +27,8 @@
|
||||
#ifndef SVN_OPT_H
|
||||
#define SVN_OPT_H
|
||||
|
||||
#include "svn_opt_impl.h"
|
||||
|
||||
#include <apr.h>
|
||||
#include <apr_pools.h>
|
||||
#include <apr_getopt.h>
|
||||
@ -69,15 +71,51 @@ typedef svn_error_t *(svn_opt_subcommand_t)(
|
||||
/** The maximum number of options that can be accepted by a subcommand. */
|
||||
#define SVN_OPT_MAX_OPTIONS 50
|
||||
|
||||
/** The maximum number of paragraphs of help text a subcommand can have.
|
||||
* @since New in 1.11. */
|
||||
#define SVN_OPT_MAX_PARAGRAPHS 100
|
||||
|
||||
/** Options that have no short option char should use an identifying
|
||||
* integer equal to or greater than this.
|
||||
*/
|
||||
#define SVN_OPT_FIRST_LONGOPT_ID 256
|
||||
|
||||
|
||||
/** One element of a subcommand dispatch table.
|
||||
*
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
typedef struct svn_opt_subcommand_desc3_t
|
||||
{
|
||||
/** The full name of this command. */
|
||||
const char *name;
|
||||
|
||||
/** The function this command invokes. */
|
||||
svn_opt_subcommand_t *cmd_func;
|
||||
|
||||
/** A list of alias names for this command (e.g., 'up' for 'update'). */
|
||||
const char *aliases[SVN_OPT_MAX_ALIASES];
|
||||
|
||||
/** A multi-paragraph string describing this command. */
|
||||
const char *help[SVN_OPT_MAX_PARAGRAPHS];
|
||||
|
||||
/** A list of options accepted by this command. Each value in the
|
||||
* array is a unique enum (the 2nd field in apr_getopt_option_t)
|
||||
*/
|
||||
int valid_options[SVN_OPT_MAX_OPTIONS];
|
||||
|
||||
/** A list of option help descriptions, keyed by the option unique enum
|
||||
* (the 2nd field in apr_getopt_option_t), which override the generic
|
||||
* descriptions given in an apr_getopt_option_t on a per-subcommand basis.
|
||||
*/
|
||||
struct { int optch; const char *desc; } desc_overrides[SVN_OPT_MAX_OPTIONS];
|
||||
} svn_opt_subcommand_desc3_t;
|
||||
|
||||
|
||||
/** One element of a subcommand dispatch table.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
typedef struct svn_opt_subcommand_desc2_t
|
||||
{
|
||||
@ -139,8 +177,21 @@ typedef struct svn_opt_subcommand_desc_t
|
||||
* Return the entry in @a table whose name matches @a cmd_name, or @c NULL if
|
||||
* none. @a cmd_name may be an alias.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
const svn_opt_subcommand_desc3_t *
|
||||
svn_opt_get_canonical_subcommand3(const svn_opt_subcommand_desc3_t *table,
|
||||
const char *cmd_name);
|
||||
|
||||
|
||||
/**
|
||||
* Same as svn_opt_get_canonical_subcommand3(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
const svn_opt_subcommand_desc2_t *
|
||||
svn_opt_get_canonical_subcommand2(const svn_opt_subcommand_desc2_t *table,
|
||||
const char *cmd_name);
|
||||
@ -170,9 +221,23 @@ svn_opt_get_canonical_subcommand(const svn_opt_subcommand_desc_t *table,
|
||||
*
|
||||
* The returned value may be statically allocated, or allocated in @a pool.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
const apr_getopt_option_t *
|
||||
svn_opt_get_option_from_code3(int code,
|
||||
const apr_getopt_option_t *option_table,
|
||||
const svn_opt_subcommand_desc3_t *command,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
* Same as svn_opt_get_option_from_code3(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
const apr_getopt_option_t *
|
||||
svn_opt_get_option_from_code2(int code,
|
||||
const apr_getopt_option_t *option_table,
|
||||
const svn_opt_subcommand_desc2_t *command,
|
||||
@ -198,9 +263,22 @@ svn_opt_get_option_from_code(int code,
|
||||
* non-NULL, it is a zero-terminated array, and all subcommands take
|
||||
* the options listed in it.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_boolean_t
|
||||
svn_opt_subcommand_takes_option4(const svn_opt_subcommand_desc3_t *command,
|
||||
int option_code,
|
||||
const int *global_options);
|
||||
|
||||
/**
|
||||
* Same as svn_opt_subcommand_takes_option4(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_boolean_t
|
||||
svn_opt_subcommand_takes_option3(const svn_opt_subcommand_desc2_t *command,
|
||||
int option_code,
|
||||
const int *global_options);
|
||||
@ -235,7 +313,7 @@ svn_opt_subcommand_takes_option(const svn_opt_subcommand_desc_t *command,
|
||||
/**
|
||||
* Print a generic (not command-specific) usage message to @a stream.
|
||||
*
|
||||
* ### @todo Why is @a stream a stdio file instead of an svn stream?
|
||||
* @todo Why is @a stream a stdio file instead of an svn stream?
|
||||
*
|
||||
* If @a header is non-NULL, print @a header followed by a newline. Then
|
||||
* loop over @a cmd_table printing the usage for each command (getting
|
||||
@ -244,9 +322,25 @@ svn_opt_subcommand_takes_option(const svn_opt_subcommand_desc_t *command,
|
||||
*
|
||||
* Use @a pool for temporary allocation.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
void
|
||||
svn_opt_print_generic_help3(const char *header,
|
||||
const svn_opt_subcommand_desc3_t *cmd_table,
|
||||
const apr_getopt_option_t *opt_table,
|
||||
const char *footer,
|
||||
apr_pool_t *pool,
|
||||
FILE *stream);
|
||||
|
||||
/**
|
||||
* Same as svn_opt_print_generic_help3(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.4.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
void
|
||||
svn_opt_print_generic_help2(const char *header,
|
||||
const svn_opt_subcommand_desc2_t *cmd_table,
|
||||
const apr_getopt_option_t *opt_table,
|
||||
@ -297,9 +391,24 @@ svn_opt_format_option(const char **string,
|
||||
* use that second name as an alias for the first name. This additional
|
||||
* behaviour is new in 1.7.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
void
|
||||
svn_opt_subcommand_help4(const char *subcommand,
|
||||
const svn_opt_subcommand_desc3_t *table,
|
||||
const apr_getopt_option_t *options_table,
|
||||
const int *global_options,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
* Same as svn_opt_subcommand_help4(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
void
|
||||
svn_opt_subcommand_help3(const char *subcommand,
|
||||
const svn_opt_subcommand_desc2_t *table,
|
||||
const apr_getopt_option_t *options_table,
|
||||
@ -336,43 +445,7 @@ svn_opt_subcommand_help(const char *subcommand,
|
||||
|
||||
|
||||
/* Parsing revision and date options. */
|
||||
|
||||
/**
|
||||
* Various ways of specifying revisions.
|
||||
*
|
||||
* @note
|
||||
* In contexts where local mods are relevant, the `working' kind
|
||||
* refers to the uncommitted "working" revision, which may be modified
|
||||
* with respect to its base revision. In other contexts, `working'
|
||||
* should behave the same as `committed' or `current'.
|
||||
*/
|
||||
enum svn_opt_revision_kind {
|
||||
/** No revision information given. */
|
||||
svn_opt_revision_unspecified,
|
||||
|
||||
/** revision given as number */
|
||||
svn_opt_revision_number,
|
||||
|
||||
/** revision given as date */
|
||||
svn_opt_revision_date,
|
||||
|
||||
/** rev of most recent change */
|
||||
svn_opt_revision_committed,
|
||||
|
||||
/** (rev of most recent change) - 1 */
|
||||
svn_opt_revision_previous,
|
||||
|
||||
/** .svn/entries current revision */
|
||||
svn_opt_revision_base,
|
||||
|
||||
/** current, plus local mods */
|
||||
svn_opt_revision_working,
|
||||
|
||||
/** repository youngest */
|
||||
svn_opt_revision_head
|
||||
|
||||
/* please update svn_opt__revision_to_string() when extending this enum */
|
||||
};
|
||||
/* NOTE: svn_opt_revision_kind is defined in svn_opt_impl.h */
|
||||
|
||||
/**
|
||||
* A revision value, which can be specified as a number or a date.
|
||||
@ -700,9 +773,30 @@ svn_opt_parse_path(svn_opt_revision_t *rev,
|
||||
* --version flag *and* subcommand arguments on a help command line.
|
||||
* The logic for handling such a situation should be in one place.
|
||||
*
|
||||
* @since New in 1.8.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_opt_print_help5(apr_getopt_t *os,
|
||||
const char *pgm_name,
|
||||
svn_boolean_t print_version,
|
||||
svn_boolean_t quiet,
|
||||
svn_boolean_t verbose,
|
||||
const char *version_footer,
|
||||
const char *header,
|
||||
const svn_opt_subcommand_desc3_t *cmd_table,
|
||||
const apr_getopt_option_t *option_table,
|
||||
const int *global_options,
|
||||
const char *footer,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
* Same as svn_opt_print_help5(), but with a different
|
||||
* version of the subcommand description table.
|
||||
*
|
||||
* @since New in 1.8.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_opt_print_help4(apr_getopt_t *os,
|
||||
const char *pgm_name,
|
||||
|
86
subversion/include/svn_opt_impl.h
Normal file
86
subversion/include/svn_opt_impl.h
Normal file
@ -0,0 +1,86 @@
|
||||
/**
|
||||
* @copyright
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
* @endcopyright
|
||||
*
|
||||
* @file svn_opt_impl.h
|
||||
* @brief Option and argument parsing for Subversion command lines
|
||||
* (common implementation)
|
||||
*
|
||||
* @warning This is a @b private implementation-specific header file.
|
||||
* User code should include @ref svn_opt.h instead.
|
||||
*/
|
||||
|
||||
/* NOTE:
|
||||
* This file *must not* include or depend on any other header except
|
||||
* the C standard library headers.
|
||||
*/
|
||||
|
||||
#ifndef SVN_OPT_IMPL_H
|
||||
#define SVN_OPT_IMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
/**
|
||||
* Various ways of specifying revisions.
|
||||
*
|
||||
* @note
|
||||
* In contexts where local mods are relevant, the `working' kind
|
||||
* refers to the uncommitted "working" revision, which may be modified
|
||||
* with respect to its base revision. In other contexts, `working'
|
||||
* should behave the same as `committed' or `current'.
|
||||
*/
|
||||
/* NOTE: Update svnxx/revision.hpp when changing this enum. */
|
||||
enum svn_opt_revision_kind {
|
||||
/** No revision information given. */
|
||||
svn_opt_revision_unspecified,
|
||||
|
||||
/** revision given as number */
|
||||
svn_opt_revision_number,
|
||||
|
||||
/** revision given as date */
|
||||
svn_opt_revision_date,
|
||||
|
||||
/** rev of most recent change */
|
||||
svn_opt_revision_committed,
|
||||
|
||||
/** (rev of most recent change) - 1 */
|
||||
svn_opt_revision_previous,
|
||||
|
||||
/** .svn/entries current revision */
|
||||
svn_opt_revision_base,
|
||||
|
||||
/** current, plus local mods */
|
||||
svn_opt_revision_working,
|
||||
|
||||
/** repository youngest */
|
||||
svn_opt_revision_head
|
||||
|
||||
/* please update svn_opt__revision_to_string() when extending this enum */
|
||||
};
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SVN_OPT_IMPL_H */
|
@ -415,19 +415,26 @@ svn_prop_name_is_valid(const char *prop_name);
|
||||
/** Describes external items to check out into this directory.
|
||||
*
|
||||
* The format is a series of lines, each in the following format:
|
||||
*
|
||||
* [-r REV] URL[@PEG] LOCALPATH
|
||||
*
|
||||
* LOCALPATH is relative to the directory having this property.
|
||||
* REV pins the external to revision REV.
|
||||
* URL may be a full URL or a relative URL starting with one of:
|
||||
*
|
||||
* ../ to the parent directory of the extracted external
|
||||
* ^/ to the repository root
|
||||
* / to the server root
|
||||
* // to the URL scheme
|
||||
*
|
||||
* The following format is supported for interoperability with
|
||||
* Subversion 1.4 and earlier clients:
|
||||
*
|
||||
* LOCALPATH [-r PEG] URL
|
||||
*
|
||||
* The ambiguous format 'relative_path relative_path' is taken as
|
||||
* 'relative_url relative_path' with peg revision support.
|
||||
*
|
||||
* Lines starting with a '#' character are ignored.
|
||||
*/
|
||||
#define SVN_PROP_EXTERNALS SVN_PROP_PREFIX "externals"
|
||||
|
@ -65,7 +65,7 @@ svn_ra_version(void);
|
||||
* @a close_baton as appropriate.
|
||||
*
|
||||
* @a path is relative to the "root" of the session, defined by the
|
||||
* @a repos_URL passed to svn_ra_open4() vtable call.
|
||||
* @a repos_URL passed to svn_ra_open5() vtable call.
|
||||
*
|
||||
* @a name is the name of the property to fetch. If the property is present,
|
||||
* then it is returned in @a value. Otherwise, @a *value is set to @c NULL.
|
||||
@ -229,7 +229,7 @@ typedef void (*svn_ra_progress_notify_func_t)(apr_off_t progress,
|
||||
*
|
||||
* @a revision is the target revision number of the received replay report.
|
||||
*
|
||||
* @a editor and @a edit_baton should provided by the callback implementation.
|
||||
* @a *editor and @a *edit_baton should provided by the callback implementation.
|
||||
*
|
||||
* @a replay_baton is the baton as originally passed to replay_range.
|
||||
*
|
||||
@ -253,7 +253,7 @@ typedef svn_error_t *(*svn_ra_replay_revstart_callback_t)(
|
||||
*
|
||||
* @a revision is the target revision number of the received replay report.
|
||||
*
|
||||
* @a editor and @a edit_baton should provided by the callback implementation.
|
||||
* @a editor and @a edit_baton are the values provided by the REVSTART callback.
|
||||
*
|
||||
* @a replay_baton is the baton as originally passed to replay_range.
|
||||
*
|
||||
@ -369,7 +369,7 @@ typedef struct svn_ra_reporter3_t
|
||||
* implementor should assume the directory has no entries or props.
|
||||
*
|
||||
* This will *override* any previous set_path() calls made on parent
|
||||
* paths. @a path is relative to the URL specified in svn_ra_open4().
|
||||
* paths. @a path is relative to the URL specified in svn_ra_open5().
|
||||
*
|
||||
* If @a lock_token is non-NULL, it is the lock token for @a path in the WC.
|
||||
*
|
||||
@ -520,7 +520,7 @@ typedef struct svn_ra_reporter_t
|
||||
/** A collection of callbacks implemented by libsvn_client which allows
|
||||
* an RA layer to "pull" information from the client application, or
|
||||
* possibly store information. libsvn_client passes this vtable to
|
||||
* svn_ra_open4().
|
||||
* svn_ra_open5().
|
||||
*
|
||||
* Each routine takes a @a callback_baton originally provided with the
|
||||
* vtable.
|
||||
@ -555,9 +555,9 @@ typedef struct svn_ra_callbacks2_t
|
||||
|
||||
/** Fetch working copy properties.
|
||||
*
|
||||
*<pre> ### we might have a problem if the RA layer ever wants a property
|
||||
* ### that corresponds to a different revision of the file than
|
||||
* ### what is in the WC. we'll cross that bridge one day...</pre>
|
||||
* @note we might have a problem if the RA layer ever wants a property
|
||||
* that corresponds to a different revision of the file than
|
||||
* what is in the WC. we'll cross that bridge one day...
|
||||
*/
|
||||
svn_ra_get_wc_prop_func_t get_wc_prop;
|
||||
|
||||
@ -710,6 +710,14 @@ typedef struct svn_ra_session_t svn_ra_session_t;
|
||||
* within the new repository root URL that @a repos_URL pointed to within
|
||||
* the old repository root URL.
|
||||
*
|
||||
* If @a redirect_url is not NULL and a @corrected_url is returned, then
|
||||
* @a redirect_url contains a non-canonicalized version of @a corrected_url,
|
||||
* as communicated in the network protocol used by the RA provider.
|
||||
* THe @a redirect_url should be used for to detect redirection loops.
|
||||
* Canonicalization may change the protocol-level URL in a way that
|
||||
* makes detection of redirect loops impossible in some cases since URLs which
|
||||
* are different at the protocol layer could map to the same canonicalized URL.
|
||||
*
|
||||
* Return @c SVN_ERR_RA_UUID_MISMATCH if @a uuid is non-NULL and not equal
|
||||
* to the UUID of the repository at @c repos_URL.
|
||||
*
|
||||
@ -728,9 +736,27 @@ typedef struct svn_ra_session_t svn_ra_session_t;
|
||||
*
|
||||
* @see svn_client_open_ra_session().
|
||||
*
|
||||
* @since New in 1.7.
|
||||
* @since New in 1.14.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_ra_open5(svn_ra_session_t **session_p,
|
||||
const char **corrected_url,
|
||||
const char **redirect_url,
|
||||
const char *repos_URL,
|
||||
const char *uuid,
|
||||
const svn_ra_callbacks2_t *callbacks,
|
||||
void *callback_baton,
|
||||
apr_hash_t *config,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Similar to svn_ra_open5(), but with @a redirect_url always passed
|
||||
* as @c NULL.
|
||||
*
|
||||
* @since New in 1.7.
|
||||
* @deprecated Provided for backward compatibility with the 1.13 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_ra_open4(svn_ra_session_t **session_p,
|
||||
const char **corrected_url,
|
||||
const char *repos_URL,
|
||||
@ -1857,7 +1883,7 @@ svn_ra_get_location_segments(svn_ra_session_t *session,
|
||||
* @note Prior to Subversion 1.9, this function may request delta handlers
|
||||
* from @a handler even for empty text deltas. Starting with 1.9, the
|
||||
* delta handler / baton return arguments passed to @a handler will be
|
||||
* #NULL unless there is an actual difference in the file contents between
|
||||
* NULL unless there is an actual difference in the file contents between
|
||||
* the current and the previous call.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
|
@ -861,7 +861,7 @@ typedef svn_error_t *(*svn_repos_freeze_func_t)(void *baton, apr_pool_t *pool);
|
||||
* @since New in 1.8.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos_freeze(apr_array_header_t *paths,
|
||||
svn_repos_freeze(const apr_array_header_t *paths,
|
||||
svn_repos_freeze_func_t freeze_func,
|
||||
void *freeze_baton,
|
||||
apr_pool_t *pool);
|
||||
@ -1036,7 +1036,10 @@ svn_repos_hooks_setenv(svn_repos_t *repos,
|
||||
*
|
||||
* @a send_copyfrom_args instructs the driver to send 'copyfrom'
|
||||
* arguments to the editor's add_file() and add_directory() methods,
|
||||
* whenever it deems feasible.
|
||||
* and therefore to send their content as deltas against the copy source,
|
||||
* whenever it deems feasible. The implementation only does so for
|
||||
* add_file(), and only when the file itself is the copy root (not when
|
||||
* the file is part of a copied subtree).
|
||||
*
|
||||
* Use @a authz_read_func and @a authz_read_baton (if not @c NULL) to
|
||||
* avoid sending data through @a editor/@a edit_baton which is not
|
||||
@ -2404,7 +2407,7 @@ svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
|
||||
* @note Prior to Subversion 1.9, this function may request delta handlers
|
||||
* from @a handler even for empty text deltas. Starting with 1.9, the
|
||||
* delta handler / baton return arguments passed to @a handler will be
|
||||
* #NULL unless there is an actual difference in the file contents between
|
||||
* NULL unless there is an actual difference in the file contents between
|
||||
* the current and the previous call.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
@ -3803,7 +3806,7 @@ typedef struct svn_repos_parse_fns3_t
|
||||
*
|
||||
* @since New in 1.8.
|
||||
|
||||
* @since Starting in 1.10, @a parse_fns may contain #NULL pointers for
|
||||
* @since Starting in 1.10, @a parse_fns may contain NULL pointers for
|
||||
* those callbacks that the caller is not interested in.
|
||||
*/
|
||||
svn_error_t *
|
||||
@ -4143,6 +4146,19 @@ typedef struct svn_authz_t svn_authz_t;
|
||||
svn_error_t *
|
||||
svn_repos_authz_initialize(apr_pool_t *pool);
|
||||
|
||||
/**
|
||||
* Callback for reporting authz file parsing warnings.
|
||||
*
|
||||
* The implementation may use @a scratch_pool for temporary
|
||||
* allocations but should not assume that the lifetime of that pool
|
||||
* persists past the callback invocation.
|
||||
*
|
||||
* The implementation @e must @e not clear @a error.
|
||||
*/
|
||||
typedef void (*svn_repos_authz_warning_func_t)(void *baton,
|
||||
const svn_error_t *error,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Read authz configuration data from @a path (a dirent, an absolute file url
|
||||
* or a registry path) into @a *authz_p, allocated in @a pool.
|
||||
@ -4161,9 +4177,32 @@ svn_repos_authz_initialize(apr_pool_t *pool);
|
||||
* repository instance. Otherwise, set it to NULL and the repositories will
|
||||
* be opened as needed.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* If the @a warning_func callback is not @c NULL, it is called
|
||||
* (with @a warning_baton) to report non-fatal warnings emitted by
|
||||
* the parser.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos_authz_read4(svn_authz_t **authz_p,
|
||||
const char *path,
|
||||
const char *groups_path,
|
||||
svn_boolean_t must_exist,
|
||||
svn_repos_t *repos_hint,
|
||||
svn_repos_authz_warning_func_t warning_func,
|
||||
void *warning_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Similar to svn_repos_authz_read3(), but with @a warning_func and
|
||||
* @a warning_baton set to @c NULL.
|
||||
*
|
||||
* @since New in 1.10.
|
||||
* @deprecated Provided for backward compatibility with the 1.11 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_repos_authz_read3(svn_authz_t **authz_p,
|
||||
const char *path,
|
||||
const char *groups_path,
|
||||
@ -4203,13 +4242,36 @@ svn_repos_authz_read(svn_authz_t **authz_p,
|
||||
|
||||
/**
|
||||
* Read authz configuration data from @a stream into @a *authz_p,
|
||||
* allocated in @a pool.
|
||||
* allocated in @a result_pool.
|
||||
*
|
||||
* If @a groups_stream is set, use the global groups parsed from it.
|
||||
*
|
||||
* @since New in 1.8.
|
||||
* If the @a warning_func callback is not @c NULL, it is called
|
||||
* (with @a warning_baton) to report non-fatal warnings emitted by
|
||||
* the parser.
|
||||
*
|
||||
* Uses @a scratch_pool for temporary aloocations.
|
||||
*
|
||||
* @since New in 1.12.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_repos_authz_parse2(svn_authz_t **authz_p,
|
||||
svn_stream_t *stream,
|
||||
svn_stream_t *groups_stream,
|
||||
svn_repos_authz_warning_func_t warning_func,
|
||||
void *warning_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/**
|
||||
* Similar to svn_repos_authz_parse2(), but with @a warning_func and
|
||||
* @a warning_baton set to @c NULL.
|
||||
*
|
||||
* @since New in 1.8.
|
||||
* @deprecated Provided for backward compatibility with the 1.11 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_repos_authz_parse(svn_authz_t **authz_p,
|
||||
svn_stream_t *stream,
|
||||
svn_stream_t *groups_stream,
|
||||
|
@ -38,14 +38,21 @@ extern "C" {
|
||||
|
||||
|
||||
/** Convert @a when to a <tt>const char *</tt> representation allocated
|
||||
* in @a pool. Use svn_time_from_cstring() for the reverse
|
||||
* conversion.
|
||||
* in @a pool.
|
||||
*
|
||||
* @see svn_time_from_cstring() for the reverse conversion.
|
||||
*/
|
||||
const char *
|
||||
svn_time_to_cstring(apr_time_t when,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/** Convert @a data to an @c apr_time_t @a when.
|
||||
*
|
||||
* @see svn_time_to_cstring() for the reverse conversion.
|
||||
*
|
||||
* @deprecated Also accepts a format that was used before Subversion 0.14.
|
||||
* See implementation for details. Use of this format is deprecated.
|
||||
*
|
||||
* Use @a pool for temporary memory allocation.
|
||||
*/
|
||||
svn_error_t *
|
||||
|
@ -27,6 +27,8 @@
|
||||
#ifndef SVN_TYPES_H
|
||||
#define SVN_TYPES_H
|
||||
|
||||
#include "svn_types_impl.h"
|
||||
|
||||
/* ### this should go away, but it causes too much breakage right now */
|
||||
#include <stdlib.h>
|
||||
#include <limits.h> /* for ULONG_MAX */
|
||||
@ -246,35 +248,6 @@ typedef struct svn_version_t svn_version_t;
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
/** @defgroup apr_hash_utilities APR Hash Table Helpers
|
||||
* These functions enable the caller to dereference an APR hash table index
|
||||
* without type casts or temporary variables.
|
||||
*
|
||||
* These functions are provided by APR itself from version 1.5.
|
||||
* Definitions are provided here for when using older versions of APR.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#if !APR_VERSION_AT_LEAST(1, 5, 0)
|
||||
|
||||
/** Return the key of the hash table entry indexed by @a hi. */
|
||||
const void *
|
||||
apr_hash_this_key(apr_hash_index_t *hi);
|
||||
|
||||
/** Return the key length of the hash table entry indexed by @a hi. */
|
||||
apr_ssize_t
|
||||
apr_hash_this_key_len(apr_hash_index_t *hi);
|
||||
|
||||
/** Return the value of the hash table entry indexed by @a hi. */
|
||||
void *
|
||||
apr_hash_this_val(apr_hash_index_t *hi);
|
||||
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
|
||||
/** On Windows, APR_STATUS_IS_ENOTDIR includes several kinds of
|
||||
* invalid-pathname error but not ERROR_INVALID_NAME, so we include it.
|
||||
@ -303,28 +276,7 @@ apr_hash_this_val(apr_hash_index_t *hi);
|
||||
|
||||
|
||||
|
||||
/** The various types of nodes in the Subversion filesystem. */
|
||||
typedef enum svn_node_kind_t
|
||||
{
|
||||
/** absent */
|
||||
svn_node_none,
|
||||
|
||||
/** regular file */
|
||||
svn_node_file,
|
||||
|
||||
/** directory */
|
||||
svn_node_dir,
|
||||
|
||||
/** something's here, but we don't know what */
|
||||
svn_node_unknown,
|
||||
|
||||
/**
|
||||
* symbolic link
|
||||
* @note This value is not currently used by the public API.
|
||||
* @since New in 1.8.
|
||||
*/
|
||||
svn_node_symlink
|
||||
} svn_node_kind_t;
|
||||
/* NOTE: svn_node_kind_t is defined in svn_types_impl.h */
|
||||
|
||||
/** Return a constant string expressing @a kind as an English word, e.g.,
|
||||
* "file", "dir", etc. The string is not localized, as it may be used for
|
||||
@ -346,23 +298,7 @@ svn_node_kind_t
|
||||
svn_node_kind_from_word(const char *word);
|
||||
|
||||
|
||||
/** Generic three-state property to represent an unknown value for values
|
||||
* that are just like booleans. The values have been set deliberately to
|
||||
* make tristates disjoint from #svn_boolean_t.
|
||||
*
|
||||
* @note It is unsafe to use apr_pcalloc() to allocate these, since '0' is
|
||||
* not a valid value.
|
||||
*
|
||||
* @since New in 1.7. */
|
||||
typedef enum svn_tristate_t
|
||||
{
|
||||
/** state known to be false (the constant does not evaulate to false) */
|
||||
svn_tristate_false = 2,
|
||||
/** state known to be true */
|
||||
svn_tristate_true,
|
||||
/** state could be true or false */
|
||||
svn_tristate_unknown
|
||||
} svn_tristate_t;
|
||||
/* NOTE: svn_tristate_t is defined in svn_types_impl.h */
|
||||
|
||||
/** Return a constant string "true", "false" or NULL representing the value of
|
||||
* @a tristate.
|
||||
@ -422,15 +358,11 @@ svn_tristate__from_word(const char * word);
|
||||
|
||||
|
||||
|
||||
/** A revision number. */
|
||||
typedef long int svn_revnum_t;
|
||||
/* NOTE: svn_revnum_t and SVN_INVALID_REVNUM are defined in svn_types_impl.h */
|
||||
|
||||
/** Valid revision numbers begin at 0 */
|
||||
#define SVN_IS_VALID_REVNUM(n) ((n) >= 0)
|
||||
|
||||
/** The 'official' invalid revision num */
|
||||
#define SVN_INVALID_REVNUM ((svn_revnum_t) -1)
|
||||
|
||||
/** Not really invalid...just unimportant -- one day, this can be its
|
||||
* own unique value, for now, just make it the same as
|
||||
* #SVN_INVALID_REVNUM.
|
||||
@ -494,55 +426,7 @@ enum svn_recurse_kind
|
||||
svn_recursive
|
||||
};
|
||||
|
||||
/** The concept of depth for directories.
|
||||
*
|
||||
* @note This is similar to, but not exactly the same as, the WebDAV
|
||||
* and LDAP concepts of depth.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
*/
|
||||
typedef enum svn_depth_t
|
||||
{
|
||||
/* The order of these depths is important: the higher the number,
|
||||
the deeper it descends. This allows us to compare two depths
|
||||
numerically to decide which should govern. */
|
||||
|
||||
/** Depth undetermined or ignored. In some contexts, this means the
|
||||
client should choose an appropriate default depth. The server
|
||||
will generally treat it as #svn_depth_infinity. */
|
||||
svn_depth_unknown = -2,
|
||||
|
||||
/** Exclude (i.e., don't descend into) directory D.
|
||||
@note In Subversion 1.5, svn_depth_exclude is *not* supported
|
||||
anywhere in the client-side (libsvn_wc/libsvn_client/etc) code;
|
||||
it is only supported as an argument to set_path functions in the
|
||||
ra and repos reporters. (This will enable future versions of
|
||||
Subversion to run updates, etc, against 1.5 servers with proper
|
||||
svn_depth_exclude behavior, once we get a chance to implement
|
||||
client-side support for svn_depth_exclude.)
|
||||
*/
|
||||
svn_depth_exclude = -1,
|
||||
|
||||
/** Just the named directory D, no entries. Updates will not pull in
|
||||
any files or subdirectories not already present. */
|
||||
svn_depth_empty = 0,
|
||||
|
||||
/** D + its file children, but not subdirs. Updates will pull in any
|
||||
files not already present, but not subdirectories. */
|
||||
svn_depth_files = 1,
|
||||
|
||||
/** D + immediate children (D and its entries). Updates will pull in
|
||||
any files or subdirectories not already present; those
|
||||
subdirectories' this_dir entries will have depth-empty. */
|
||||
svn_depth_immediates = 2,
|
||||
|
||||
/** D + all descendants (full recursion from D). Updates will pull
|
||||
in any files or subdirectories not already present; those
|
||||
subdirectories' this_dir entries will have depth-infinity.
|
||||
Equivalent to the pre-1.5 default update behavior. */
|
||||
svn_depth_infinity = 3
|
||||
|
||||
} svn_depth_t;
|
||||
/* NOTE: svn_depth_t is defined in svn_types_impl.h */
|
||||
|
||||
/** Return a constant string expressing @a depth as an English word,
|
||||
* e.g., "infinity", "immediates", etc. The string is not localized,
|
||||
|
157
subversion/include/svn_types_impl.h
Normal file
157
subversion/include/svn_types_impl.h
Normal file
@ -0,0 +1,157 @@
|
||||
/**
|
||||
* @copyright
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
* @endcopyright
|
||||
*
|
||||
* @file svn_types_impl.h
|
||||
* @brief Subversion's data types (common implementation)
|
||||
*
|
||||
* @warning This is a @b private implementation-specific header file.
|
||||
* User code should include @ref svn_types.h instead.
|
||||
*/
|
||||
|
||||
/* NOTE:
|
||||
* This file *must not* include or depend on any other header except
|
||||
* the C standard library headers.
|
||||
*/
|
||||
|
||||
#ifndef SVN_TYPES_IMPL_H
|
||||
#define SVN_TYPES_IMPL_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
|
||||
#ifndef DOXYGEN
|
||||
/* Forward declaration of the error object. */
|
||||
struct svn_error_t;
|
||||
#endif
|
||||
|
||||
|
||||
/** The various types of nodes in the Subversion filesystem. */
|
||||
typedef enum svn_node_kind_t
|
||||
{
|
||||
/** absent */
|
||||
svn_node_none,
|
||||
|
||||
/** regular file */
|
||||
svn_node_file,
|
||||
|
||||
/** directory */
|
||||
svn_node_dir,
|
||||
|
||||
/** something's here, but we don't know what */
|
||||
svn_node_unknown,
|
||||
|
||||
/**
|
||||
* symbolic link
|
||||
* @note This value is not currently used by the public API.
|
||||
* @since New in 1.8.
|
||||
*/
|
||||
svn_node_symlink
|
||||
} svn_node_kind_t;
|
||||
|
||||
|
||||
/** Generic three-state property to represent an unknown value for values
|
||||
* that are just like booleans. The values have been set deliberately to
|
||||
* make tristates disjoint from #svn_boolean_t.
|
||||
*
|
||||
* @note It is unsafe to use apr_pcalloc() to allocate these, since '0' is
|
||||
* not a valid value.
|
||||
*
|
||||
* @since New in 1.7. */
|
||||
/* NOTE: Update svnxx/tristate.hpp when changing this enum. */
|
||||
typedef enum svn_tristate_t
|
||||
{
|
||||
/** state known to be false (the constant does not evaulate to false) */
|
||||
svn_tristate_false = 2,
|
||||
/** state known to be true */
|
||||
svn_tristate_true,
|
||||
/** state could be true or false */
|
||||
svn_tristate_unknown
|
||||
} svn_tristate_t;
|
||||
|
||||
|
||||
/** A revision number. */
|
||||
/* NOTE: Update svnxx/revision.hpp when changing this typedef. */
|
||||
typedef long int svn_revnum_t;
|
||||
|
||||
/** The 'official' invalid revision number. */
|
||||
/* NOTE: Update svnxx/revision.hpp when changing this definition. */
|
||||
#define SVN_INVALID_REVNUM ((svn_revnum_t) -1)
|
||||
|
||||
|
||||
/** The concept of depth for directories.
|
||||
*
|
||||
* @note This is similar to, but not exactly the same as, the WebDAV
|
||||
* and LDAP concepts of depth.
|
||||
*
|
||||
* @since New in 1.5.
|
||||
*/
|
||||
/* NOTE: Update svnxx/depth.hpp when changing this enum. */
|
||||
typedef enum svn_depth_t
|
||||
{
|
||||
/* The order of these depths is important: the higher the number,
|
||||
the deeper it descends. This allows us to compare two depths
|
||||
numerically to decide which should govern. */
|
||||
|
||||
/** Depth undetermined or ignored. In some contexts, this means the
|
||||
client should choose an appropriate default depth. The server
|
||||
will generally treat it as #svn_depth_infinity. */
|
||||
svn_depth_unknown = -2,
|
||||
|
||||
/** Exclude (i.e., don't descend into) directory D.
|
||||
@note In Subversion 1.5, svn_depth_exclude is *not* supported
|
||||
anywhere in the client-side (libsvn_wc/libsvn_client/etc) code;
|
||||
it is only supported as an argument to set_path functions in the
|
||||
ra and repos reporters. (This will enable future versions of
|
||||
Subversion to run updates, etc, against 1.5 servers with proper
|
||||
svn_depth_exclude behavior, once we get a chance to implement
|
||||
client-side support for svn_depth_exclude.)
|
||||
*/
|
||||
svn_depth_exclude = -1,
|
||||
|
||||
/** Just the named directory D, no entries. Updates will not pull in
|
||||
any files or subdirectories not already present. */
|
||||
svn_depth_empty = 0,
|
||||
|
||||
/** D + its file children, but not subdirs. Updates will pull in any
|
||||
files not already present, but not subdirectories. */
|
||||
svn_depth_files = 1,
|
||||
|
||||
/** D + immediate children (D and its entries). Updates will pull in
|
||||
any files or subdirectories not already present; those
|
||||
subdirectories' this_dir entries will have depth-empty. */
|
||||
svn_depth_immediates = 2,
|
||||
|
||||
/** D + all descendants (full recursion from D). Updates will pull
|
||||
in any files or subdirectories not already present; those
|
||||
subdirectories' this_dir entries will have depth-infinity.
|
||||
Equivalent to the pre-1.5 default update behavior. */
|
||||
svn_depth_infinity = 3
|
||||
|
||||
} svn_depth_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* SVN_TYPES_IMPL_H */
|
@ -212,7 +212,7 @@ svn_utf_cstring_from_utf8_ex(const char **dest,
|
||||
* so when we can detect that at configure time, things will change.
|
||||
* Also, this should (?) be moved to apr/apu eventually.
|
||||
*
|
||||
* See http://subversion.tigris.org/issues/show_bug.cgi?id=807 for
|
||||
* See https://issues.apache.org/jira/browse/SVN-807 for
|
||||
* details.
|
||||
*/
|
||||
const char *
|
||||
|
@ -61,7 +61,7 @@ extern "C" {
|
||||
* Modify when new functionality is added or new interfaces are
|
||||
* defined, but all changes are backward compatible.
|
||||
*/
|
||||
#define SVN_VER_MINOR 10
|
||||
#define SVN_VER_MINOR 14
|
||||
|
||||
/**
|
||||
* Patch number.
|
||||
@ -70,7 +70,7 @@ extern "C" {
|
||||
*
|
||||
* @since New in 1.1.
|
||||
*/
|
||||
#define SVN_VER_PATCH 2
|
||||
#define SVN_VER_PATCH 0
|
||||
|
||||
|
||||
/** @deprecated Provided for backward compatibility with the 1.0 API. */
|
||||
@ -93,7 +93,7 @@ extern "C" {
|
||||
*
|
||||
* Always change this at the same time as SVN_VER_NUMTAG.
|
||||
*/
|
||||
#define SVN_VER_TAG " (r1835932)"
|
||||
#define SVN_VER_TAG " (r1876290)"
|
||||
|
||||
|
||||
/** Number tag: a string describing the version.
|
||||
@ -117,7 +117,7 @@ extern "C" {
|
||||
* file version. Its value remains 0 in the repository except in release
|
||||
* tags where it is the revision from which the tag was created.
|
||||
*/
|
||||
#define SVN_VER_REVISION 1835932
|
||||
#define SVN_VER_REVISION 1876290
|
||||
|
||||
|
||||
/* Version strings composed from the above definitions. */
|
||||
|
@ -7602,9 +7602,14 @@ svn_wc_relocate(const char *path,
|
||||
* If @a clear_changelists is TRUE, then changelist information for the
|
||||
* paths is cleared.
|
||||
*
|
||||
* If @a metadata_only is TRUE, the working copy files are untouched, but
|
||||
* if there are conflict marker files attached to these files these
|
||||
* markers are removed.
|
||||
* The @a metadata_only and @a added_keep_local options control the
|
||||
* extent of reverting. If @a metadata_only is TRUE, the working copy
|
||||
* files are untouched, but if there are conflict marker files attached
|
||||
* to these files these markers are removed. Otherwise, if
|
||||
* @a added_keep_local is TRUE, then all items are reverted except an
|
||||
* item that was scheduled as plain 'add' (not a copy) will not be
|
||||
* removed from the working copy. Otherwise, all items are reverted and
|
||||
* their on-disk state changed to match.
|
||||
*
|
||||
* If @a cancel_func is non-NULL, call it with @a cancel_baton at
|
||||
* various points during the reversion process. If it returns an
|
||||
@ -7622,9 +7627,31 @@ svn_wc_relocate(const char *path,
|
||||
* If @a path is not under version control, return the error
|
||||
* #SVN_ERR_UNVERSIONED_RESOURCE.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
* @since New in 1.11.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_wc_revert6(svn_wc_context_t *wc_ctx,
|
||||
const char *local_abspath,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t use_commit_times,
|
||||
const apr_array_header_t *changelist_filter,
|
||||
svn_boolean_t clear_changelists,
|
||||
svn_boolean_t metadata_only,
|
||||
svn_boolean_t added_keep_local,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/** Similar to svn_wc_revert6() but with @a added_keep_local always
|
||||
* set to TRUE.
|
||||
*
|
||||
* @since New in 1.9.
|
||||
* @deprecated Provided for backward compatibility with the 1.10 API.
|
||||
*/
|
||||
SVN_DEPRECATED
|
||||
svn_error_t *
|
||||
svn_wc_revert5(svn_wc_context_t *wc_ctx,
|
||||
const char *local_abspath,
|
||||
svn_depth_t depth,
|
||||
|
@ -7,6 +7,6 @@ Name: libsvn_auth_gnome_keyring
|
||||
Description: Subversion GNOME Keyring Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_subr @SVN_GNOME_KEYRING_PCLIBS@
|
||||
Libs: -L${libdir} -lsvn_auth_gnome_keyring
|
||||
Cflags: -I${includedir}
|
||||
Requires.private: libsvn_subr, @SVN_GNOME_KEYRING_PCLIBS@
|
||||
Libs: -L${libdir} -lsvn_auth_gnome_keyring-1
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
@ -227,10 +227,10 @@ kwallet_password_get(svn_boolean_t *done,
|
||||
KLocalizedString::setApplicationDomain("subversion"); /* translation domain */
|
||||
|
||||
/* componentName appears in KDE GUI prompts */
|
||||
KAboutData aboutData(QStringLiteral("subversion"), /* componentName */
|
||||
KAboutData aboutData(QString("subversion"), /* componentName */
|
||||
i18n(get_application_name(parameters,
|
||||
pool)), /* displayName */
|
||||
QStringLiteral(SVN_VER_NUMBER));
|
||||
QString(SVN_VER_NUMBER));
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
#else
|
||||
KCmdLineArgs::init(q_argc, q_argv,
|
||||
@ -309,10 +309,10 @@ kwallet_password_set(svn_boolean_t *done,
|
||||
KLocalizedString::setApplicationDomain("subversion"); /* translation domain */
|
||||
|
||||
/* componentName appears in KDE GUI prompts */
|
||||
KAboutData aboutData(QStringLiteral("subversion"), /* componentName */
|
||||
KAboutData aboutData(QString("subversion"), /* componentName */
|
||||
i18n(get_application_name(parameters,
|
||||
pool)), /* displayName */
|
||||
QStringLiteral(SVN_VER_NUMBER));
|
||||
QString(SVN_VER_NUMBER));
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
#else
|
||||
KCmdLineArgs::init(q_argc, q_argv,
|
||||
|
@ -8,5 +8,5 @@ Description: Subversion KWallet Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_auth_kwallet @SVN_KWALLET_LIBS@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lsvn_auth_kwallet-1 @SVN_KWALLET_LIBS@
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
@ -983,12 +983,13 @@ svn_client_add5(const char *path,
|
||||
|
||||
static svn_error_t *
|
||||
path_driver_cb_func(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *path,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const svn_delta_editor_t *editor = callback_baton;
|
||||
SVN_ERR(svn_path_check_valid(path, pool));
|
||||
return editor->add_directory(path, parent_baton, NULL,
|
||||
SVN_INVALID_REVNUM, pool, dir_baton);
|
||||
@ -1177,8 +1178,8 @@ mkdir_urls(const apr_array_header_t *urls,
|
||||
|
||||
/* Call the path-based editor driver. */
|
||||
err = svn_error_trace(
|
||||
svn_delta_path_driver2(editor, edit_baton, targets, TRUE,
|
||||
path_driver_cb_func, (void *)editor, pool));
|
||||
svn_delta_path_driver3(editor, edit_baton, targets, TRUE,
|
||||
path_driver_cb_func, NULL, pool));
|
||||
|
||||
if (err)
|
||||
{
|
||||
|
@ -656,14 +656,16 @@ normalize_blames(struct blame_chain *chain,
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_blame5(const char *target,
|
||||
svn_client_blame6(svn_revnum_t *start_revnum_p,
|
||||
svn_revnum_t *end_revnum_p,
|
||||
const char *target,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
const svn_opt_revision_t *start,
|
||||
const svn_opt_revision_t *end,
|
||||
const svn_diff_file_options_t *diff_options,
|
||||
svn_boolean_t ignore_mime_type,
|
||||
svn_boolean_t include_merged_revisions,
|
||||
svn_client_blame_receiver3_t receiver,
|
||||
svn_client_blame_receiver4_t receiver,
|
||||
void *receiver_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
@ -696,10 +698,13 @@ svn_client_blame5(const char *target,
|
||||
SVN_ERR(svn_client__get_revision_number(&start_revnum, NULL, ctx->wc_ctx,
|
||||
target_abspath_or_url, ra_session,
|
||||
start, pool));
|
||||
|
||||
if (start_revnum_p)
|
||||
*start_revnum_p = start_revnum;
|
||||
SVN_ERR(svn_client__get_revision_number(&end_revnum, NULL, ctx->wc_ctx,
|
||||
target_abspath_or_url, ra_session,
|
||||
end, pool));
|
||||
if (end_revnum_p)
|
||||
*end_revnum_p = end_revnum;
|
||||
|
||||
{
|
||||
svn_client__pathrev_t *loc;
|
||||
@ -941,18 +946,21 @@ svn_client_blame5(const char *target,
|
||||
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
|
||||
if (!eof || sb->len)
|
||||
{
|
||||
svn_string_t line;
|
||||
line.data = sb->data;
|
||||
line.len = sb->len;
|
||||
if (walk->rev)
|
||||
SVN_ERR(receiver(receiver_baton, start_revnum, end_revnum,
|
||||
SVN_ERR(receiver(receiver_baton,
|
||||
line_no, walk->rev->revision,
|
||||
walk->rev->rev_props, merged_rev,
|
||||
merged_rev_props, merged_path,
|
||||
sb->data, FALSE, iterpool));
|
||||
&line, FALSE, iterpool));
|
||||
else
|
||||
SVN_ERR(receiver(receiver_baton, start_revnum, end_revnum,
|
||||
SVN_ERR(receiver(receiver_baton,
|
||||
line_no, SVN_INVALID_REVNUM,
|
||||
NULL, SVN_INVALID_REVNUM,
|
||||
NULL, NULL,
|
||||
sb->data, TRUE, iterpool));
|
||||
&line, TRUE, iterpool));
|
||||
}
|
||||
if (eof) break;
|
||||
}
|
||||
|
@ -682,34 +682,6 @@ svn_client__get_diff_editor2(const svn_delta_editor_t **editor,
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
|
||||
/*** Editor for diff summary ***/
|
||||
|
||||
/* Set *DIFF_PROCESSOR to a diff processor that will report a diff summary
|
||||
to SUMMARIZE_FUNC.
|
||||
|
||||
P_ROOT_RELPATH will return a pointer to a string that must be set to
|
||||
the root of the operation before the processor is called.
|
||||
|
||||
ORIGINAL_PATH specifies the original path and will be used with
|
||||
**ANCHOR_PATH to create paths as the user originally provided them
|
||||
to the diff function.
|
||||
|
||||
SUMMARIZE_FUNC is called with SUMMARIZE_BATON as parameter by the
|
||||
created callbacks for each changed item.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__get_diff_summarize_callbacks(
|
||||
const svn_diff_tree_processor_t **diff_processor,
|
||||
const char ***p_root_relpath,
|
||||
svn_client_diff_summarize_func_t summarize_func,
|
||||
void *summarize_baton,
|
||||
const char *original_target,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* ---------------------------------------------------------------- */
|
||||
|
||||
|
||||
/*** Copy Stuff ***/
|
||||
|
||||
/* This structure is used to associate a specific copy or move SRC with a
|
||||
@ -754,40 +726,23 @@ typedef struct svn_client__copy_pair_t
|
||||
|
||||
/*** Commit Stuff ***/
|
||||
|
||||
/* WARNING: This is all new, untested, un-peer-reviewed conceptual
|
||||
stuff.
|
||||
/* The "Harvest Committables" System
|
||||
|
||||
The day that 'svn switch' came into existence, our old commit
|
||||
crawler (svn_wc_crawl_local_mods) became obsolete. It relied far
|
||||
too heavily on the on-disk hierarchy of files and directories, and
|
||||
simply had no way to support disjoint working copy trees or nest
|
||||
working copies. The primary reason for this is that commit
|
||||
process, in order to guarantee atomicity, is a single drive of a
|
||||
The commit process requires, per repository, a single drive of a
|
||||
commit editor which is based not on working copy paths, but on
|
||||
URLs. With the completion of 'svn switch', it became all too
|
||||
likely that the on-disk working copy hierarchy would no longer be
|
||||
guaranteed to map to a similar in-repository hierarchy.
|
||||
URLs. The on-disk working copy hierarchy does not, in general,
|
||||
map to a similar in-repository hierarchy, due to switched subtrees
|
||||
and disjoint working copies.
|
||||
|
||||
Aside from this new brokenness of the old system, an unrelated
|
||||
feature request had cropped up -- the ability to know in advance of
|
||||
your commit, exactly what would be committed (so that log messages
|
||||
could be initially populated with this information). Since the old
|
||||
crawler discovered commit candidates while in the process of
|
||||
committing, it was impossible to harvest this information upfront.
|
||||
As a workaround, svn_wc_statuses() was used to stat the whole
|
||||
working copy for changes before the commit started...and then the
|
||||
commit would again stat the whole tree for changes.
|
||||
|
||||
Enter the new system.
|
||||
Also we wish to know exactly what would be committed, in advance of
|
||||
the commit, so that a log message editor can be initially populated
|
||||
with this information.
|
||||
|
||||
The primary goal of this system is very straightforward: harvest
|
||||
all commit candidate information up front, and cache enough info in
|
||||
the process to use this to drive a URL-sorted commit.
|
||||
|
||||
*** END-OF-KNOWLEDGE ***
|
||||
|
||||
The prototypes below are still in development. In general, the
|
||||
idea is that commit-y processes ('svn mkdir URL', 'svn delete URL',
|
||||
The idea is that commit-y processes ('svn mkdir URL', 'svn delete URL',
|
||||
'svn commit', 'svn copy WC_PATH URL', 'svn copy URL1 URL2', 'svn
|
||||
move URL1 URL2', others?) generate the cached commit candidate
|
||||
information, and hand this information off to a consumer which is
|
||||
@ -844,7 +799,7 @@ typedef svn_error_t *(*svn_client__check_url_kind_t)(void *baton,
|
||||
- if the candidate has a lock token, add it to the LOCK_TOKENS hash.
|
||||
|
||||
- if the candidate is a directory scheduled for deletion, crawl
|
||||
the directories children recursively for any lock tokens and
|
||||
the directory's children recursively for any lock tokens and
|
||||
add them to the LOCK_TOKENS array.
|
||||
|
||||
At the successful return of this function, COMMITTABLES will point
|
||||
@ -915,6 +870,18 @@ svn_client__condense_commit_items(const char **base_url,
|
||||
apr_array_header_t *commit_items,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Rewrite the COMMIT_ITEMS array to be sorted by URL.
|
||||
Rewrite the items' URLs to be relative to BASE_URL.
|
||||
|
||||
COMMIT_ITEMS is an array of (svn_client_commit_item3_t *) items.
|
||||
|
||||
Afterwards, some of the items in COMMIT_ITEMS may contain data
|
||||
allocated in POOL. */
|
||||
svn_error_t *
|
||||
svn_client__condense_commit_items2(const char *base_url,
|
||||
apr_array_header_t *commit_items,
|
||||
apr_pool_t *pool);
|
||||
|
||||
/* Commit the items in the COMMIT_ITEMS array using EDITOR/EDIT_BATON
|
||||
to describe the committed local mods. Prior to this call,
|
||||
COMMIT_ITEMS should have been run through (and BASE_URL generated
|
||||
@ -1129,24 +1096,26 @@ svn_client__resolve_conflicts(svn_boolean_t *conflicts_remain,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Produce a diff with depth DEPTH between two files or two directories at
|
||||
* LEFT_ABSPATH1 and RIGHT_ABSPATH, using the provided diff callbacks to
|
||||
* show changes in files. The files and directories involved may be part of
|
||||
* a working copy or they may be unversioned. For versioned files, show
|
||||
* property changes, too.
|
||||
/* Produce a diff with depth DEPTH between the file or directory at
|
||||
* LEFT_ABSPATH and the file or directory at RIGHT_ABSPATH, reporting
|
||||
* differences to DIFF_PROCESSOR.
|
||||
*
|
||||
* If ANCHOR_ABSPATH is not null, set it to the anchor of the diff before
|
||||
* the first processor call. (The anchor is LEFT_ABSPATH or an ancestor of it)
|
||||
* The files and directories involved may be part of a working copy or
|
||||
* they may be unversioned. For versioned files, show property changes,
|
||||
* too.
|
||||
*
|
||||
* No copy or move information is reported to the diff processor.
|
||||
*
|
||||
* Anchor the DIFF_PROCESSOR at the requested diff targets (LEFT_ABSPATH,
|
||||
* RIGHT_ABSPATH). As any children reached by recursion are matched by
|
||||
* name, a diff processor relpath applies equally to both sides of the diff.
|
||||
*/
|
||||
svn_error_t *
|
||||
svn_client__arbitrary_nodes_diff(const char **root_relpath,
|
||||
svn_boolean_t *root_is_dir,
|
||||
const char *left_abspath,
|
||||
svn_client__arbitrary_nodes_diff(const char *left_abspath,
|
||||
const char *right_abspath,
|
||||
svn_depth_t depth,
|
||||
const svn_diff_tree_processor_t *diff_processor,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
|
||||
|
@ -500,6 +500,129 @@ append_externals_as_explicit_targets(apr_array_header_t *rel_targets,
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Crawl the working copy for commit items.
|
||||
*/
|
||||
static svn_error_t *
|
||||
harvest_committables(apr_array_header_t **commit_items_p,
|
||||
apr_hash_t **committables_by_path_p,
|
||||
apr_hash_t **lock_tokens,
|
||||
const char *base_dir_abspath,
|
||||
const apr_array_header_t *targets,
|
||||
int depth_empty_start,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t just_locked,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct check_url_kind_baton cukb;
|
||||
svn_client__committables_t *committables;
|
||||
apr_hash_index_t *hi;
|
||||
|
||||
/* Prepare for when we have a copy containing not-present nodes. */
|
||||
cukb.pool = scratch_pool;
|
||||
cukb.session = NULL; /* ### Can we somehow reuse session? */
|
||||
cukb.repos_root_url = NULL;
|
||||
cukb.ctx = ctx;
|
||||
|
||||
SVN_ERR(svn_client__harvest_committables(&committables, lock_tokens,
|
||||
base_dir_abspath, targets,
|
||||
depth_empty_start, depth,
|
||||
just_locked,
|
||||
changelists,
|
||||
check_url_kind, &cukb,
|
||||
ctx, result_pool, scratch_pool));
|
||||
if (apr_hash_count(committables->by_repository) == 0)
|
||||
{
|
||||
*commit_items_p = NULL;
|
||||
return SVN_NO_ERROR; /* Nothing to do */
|
||||
}
|
||||
else if (apr_hash_count(committables->by_repository) > 1)
|
||||
{
|
||||
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
|
||||
_("Commit can only commit to a single repository at a time.\n"
|
||||
"Are all targets part of the same working copy?"));
|
||||
}
|
||||
|
||||
hi = apr_hash_first(scratch_pool, committables->by_repository);
|
||||
*commit_items_p = apr_hash_this_val(hi);
|
||||
if (committables_by_path_p)
|
||||
*committables_by_path_p = committables->by_path;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__wc_replay(const char *src_wc_abspath,
|
||||
const apr_array_header_t *targets,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const char *base_abspath;
|
||||
apr_array_header_t *rel_targets;
|
||||
apr_hash_t *lock_tokens;
|
||||
apr_array_header_t *commit_items;
|
||||
svn_client__pathrev_t *base;
|
||||
const char *base_url;
|
||||
svn_wc_notify_func2_t saved_notify_func;
|
||||
void *saved_notify_baton;
|
||||
|
||||
/* Condense the target list. This makes all targets absolute. */
|
||||
SVN_ERR(svn_dirent_condense_targets(&base_abspath, &rel_targets, targets,
|
||||
FALSE, pool, pool));
|
||||
|
||||
/* No targets means nothing to commit, so just return. */
|
||||
if (base_abspath == NULL)
|
||||
return SVN_NO_ERROR;
|
||||
|
||||
SVN_ERR_ASSERT(rel_targets != NULL);
|
||||
|
||||
/* If we calculated only a base and no relative targets, this
|
||||
must mean that we are being asked to commit (effectively) a
|
||||
single path. */
|
||||
if (rel_targets->nelts == 0)
|
||||
APR_ARRAY_PUSH(rel_targets, const char *) = "";
|
||||
|
||||
/* Crawl the working copy for commit items. */
|
||||
SVN_ERR(harvest_committables(&commit_items, NULL /*committables_by_path_p*/,
|
||||
&lock_tokens,
|
||||
base_abspath, rel_targets,
|
||||
-1 /*depth_empty_start*/,
|
||||
depth,
|
||||
FALSE /*just_locked*/,
|
||||
changelists,
|
||||
ctx, pool, pool));
|
||||
if (!commit_items)
|
||||
{
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
SVN_ERR(svn_client__wc_node_get_base(&base,
|
||||
src_wc_abspath, ctx->wc_ctx, pool, pool));
|
||||
base_url = base->url;
|
||||
/* Sort our COMMIT_ITEMS by URL and find their relative URL-paths. */
|
||||
SVN_ERR(svn_client__condense_commit_items2(base_url, commit_items, pool));
|
||||
|
||||
saved_notify_func = ctx->notify_func2;
|
||||
saved_notify_baton = ctx->notify_baton2;
|
||||
ctx->notify_func2 = notify_func;
|
||||
ctx->notify_baton2 = notify_baton;
|
||||
/* BASE_URL is only used here in notifications & errors */
|
||||
SVN_ERR(svn_client__do_commit(base_url, commit_items,
|
||||
editor, edit_baton,
|
||||
NULL /*notify_prefix*/, NULL /*sha1_checksums*/,
|
||||
ctx, pool, pool));
|
||||
ctx->notify_func2 = saved_notify_func;
|
||||
ctx->notify_baton2 = saved_notify_baton;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_commit6(const apr_array_header_t *targets,
|
||||
svn_depth_t depth,
|
||||
@ -525,7 +648,7 @@ svn_client_commit6(const apr_array_header_t *targets,
|
||||
apr_array_header_t *rel_targets;
|
||||
apr_array_header_t *lock_targets;
|
||||
apr_array_header_t *locks_obtained;
|
||||
svn_client__committables_t *committables;
|
||||
apr_hash_t *committables_by_path;
|
||||
apr_hash_t *lock_tokens;
|
||||
apr_hash_t *sha1_checksums;
|
||||
apr_array_header_t *commit_items;
|
||||
@ -615,17 +738,8 @@ svn_client_commit6(const apr_array_header_t *targets,
|
||||
pool);
|
||||
|
||||
/* Crawl the working copy for commit items. */
|
||||
{
|
||||
struct check_url_kind_baton cukb;
|
||||
|
||||
/* Prepare for when we have a copy containing not-present nodes. */
|
||||
cukb.pool = iterpool;
|
||||
cukb.session = NULL; /* ### Can we somehow reuse session? */
|
||||
cukb.repos_root_url = NULL;
|
||||
cukb.ctx = ctx;
|
||||
|
||||
cmt_err = svn_error_trace(
|
||||
svn_client__harvest_committables(&committables,
|
||||
harvest_committables(&commit_items, &committables_by_path,
|
||||
&lock_tokens,
|
||||
base_abspath,
|
||||
rel_targets,
|
||||
@ -633,37 +747,18 @@ svn_client_commit6(const apr_array_header_t *targets,
|
||||
depth,
|
||||
! keep_locks,
|
||||
changelists,
|
||||
check_url_kind,
|
||||
&cukb,
|
||||
ctx,
|
||||
pool,
|
||||
iterpool));
|
||||
|
||||
svn_pool_clear(iterpool);
|
||||
}
|
||||
|
||||
if (cmt_err)
|
||||
goto cleanup;
|
||||
|
||||
if (apr_hash_count(committables->by_repository) == 0)
|
||||
if (!commit_items)
|
||||
{
|
||||
goto cleanup; /* Nothing to do */
|
||||
}
|
||||
else if (apr_hash_count(committables->by_repository) > 1)
|
||||
{
|
||||
cmt_err = svn_error_create(
|
||||
SVN_ERR_UNSUPPORTED_FEATURE, NULL,
|
||||
_("Commit can only commit to a single repository at a time.\n"
|
||||
"Are all targets part of the same working copy?"));
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
{
|
||||
apr_hash_index_t *hi = apr_hash_first(iterpool,
|
||||
committables->by_repository);
|
||||
|
||||
commit_items = apr_hash_this_val(hi);
|
||||
}
|
||||
|
||||
/* If our array of targets contains only locks (and no actual file
|
||||
or prop modifications), then we return here to avoid committing a
|
||||
@ -713,7 +808,7 @@ svn_client_commit6(const apr_array_header_t *targets,
|
||||
if (moved_from_abspath && delete_op_root_abspath)
|
||||
{
|
||||
svn_client_commit_item3_t *delete_half =
|
||||
svn_hash_gets(committables->by_path, delete_op_root_abspath);
|
||||
svn_hash_gets(committables_by_path, delete_op_root_abspath);
|
||||
|
||||
if (!delete_half)
|
||||
{
|
||||
@ -769,7 +864,7 @@ svn_client_commit6(const apr_array_header_t *targets,
|
||||
|
||||
if (moved_to_abspath && copy_op_root_abspath &&
|
||||
strcmp(moved_to_abspath, copy_op_root_abspath) == 0 &&
|
||||
svn_hash_gets(committables->by_path, copy_op_root_abspath)
|
||||
svn_hash_gets(committables_by_path, copy_op_root_abspath)
|
||||
== NULL)
|
||||
{
|
||||
cmt_err = svn_error_createf(
|
||||
|
@ -1392,6 +1392,29 @@ sort_commit_item_urls(const void *a, const void *b)
|
||||
}
|
||||
|
||||
|
||||
svn_error_t *
|
||||
svn_client__condense_commit_items2(const char *base_url,
|
||||
apr_array_header_t *commit_items,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
apr_array_header_t *ci = commit_items; /* convenience */
|
||||
int i;
|
||||
|
||||
/* Sort our commit items by their URLs. */
|
||||
svn_sort__array(ci, sort_commit_item_urls);
|
||||
|
||||
/* Hack BASE_URL off each URL; store the result as session_relpath. */
|
||||
for (i = 0; i < ci->nelts; i++)
|
||||
{
|
||||
svn_client_commit_item3_t *this_item
|
||||
= APR_ARRAY_IDX(ci, i, svn_client_commit_item3_t *);
|
||||
|
||||
this_item->session_relpath = svn_uri_skip_ancestor(base_url,
|
||||
this_item->url, pool);
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__condense_commit_items(const char **base_url,
|
||||
@ -1501,8 +1524,6 @@ struct file_mod_t
|
||||
/* A baton for use while driving a path-based editor driver for commit */
|
||||
struct item_commit_baton
|
||||
{
|
||||
const svn_delta_editor_t *editor; /* commit editor */
|
||||
void *edit_baton; /* commit editor's baton */
|
||||
apr_hash_t *file_mods; /* hash: path->file_mod_t */
|
||||
const char *notify_path_prefix; /* notification path prefix
|
||||
(NULL is okay, else abs path) */
|
||||
@ -1524,6 +1545,8 @@ struct item_commit_baton
|
||||
* This implements svn_delta_path_driver_cb_func_t. */
|
||||
static svn_error_t *
|
||||
do_item_commit(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *path,
|
||||
@ -1535,7 +1558,6 @@ do_item_commit(void **dir_baton,
|
||||
svn_node_kind_t kind = item->kind;
|
||||
void *file_baton = NULL;
|
||||
apr_pool_t *file_pool = NULL;
|
||||
const svn_delta_editor_t *editor = icb->editor;
|
||||
apr_hash_t *file_mods = icb->file_mods;
|
||||
svn_client_ctx_t *ctx = icb->ctx;
|
||||
svn_error_t *err;
|
||||
@ -1737,7 +1759,7 @@ do_item_commit(void **dir_baton,
|
||||
{
|
||||
if (! parent_baton)
|
||||
{
|
||||
err = editor->open_root(icb->edit_baton, item->revision,
|
||||
err = editor->open_root(edit_baton, item->revision,
|
||||
pool, dir_baton);
|
||||
}
|
||||
else
|
||||
@ -1871,8 +1893,6 @@ svn_client__do_commit(const char *base_url,
|
||||
}
|
||||
|
||||
/* Setup the callback baton. */
|
||||
cb_baton.editor = editor;
|
||||
cb_baton.edit_baton = edit_baton;
|
||||
cb_baton.file_mods = file_mods;
|
||||
cb_baton.notify_path_prefix = notify_path_prefix;
|
||||
cb_baton.ctx = ctx;
|
||||
@ -1880,7 +1900,7 @@ svn_client__do_commit(const char *base_url,
|
||||
cb_baton.base_url = base_url;
|
||||
|
||||
/* Drive the commit editor! */
|
||||
SVN_ERR(svn_delta_path_driver2(editor, edit_baton, paths, TRUE,
|
||||
SVN_ERR(svn_delta_path_driver3(editor, edit_baton, paths, TRUE,
|
||||
do_item_commit, &cb_baton, scratch_pool));
|
||||
|
||||
/* Transmit outstanding text deltas. */
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -578,7 +578,7 @@ pin_externals_prop(svn_string_t **pinned_externals,
|
||||
static svn_error_t *
|
||||
resolve_pinned_externals(apr_hash_t **pinned_externals,
|
||||
const apr_hash_t *externals_to_pin,
|
||||
svn_client__copy_pair_t *pair,
|
||||
const svn_client__copy_pair_t *pair,
|
||||
svn_ra_session_t *ra_session,
|
||||
const char *repos_root_url,
|
||||
svn_client_ctx_t *ctx,
|
||||
@ -1099,13 +1099,12 @@ verify_wc_dsts(const apr_array_header_t *copy_pairs,
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Verify that the WC sources in COPY_PAIRS exist, and set pair->src_kind
|
||||
for each.
|
||||
*/
|
||||
static svn_error_t *
|
||||
verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
|
||||
svn_boolean_t make_parents,
|
||||
svn_boolean_t is_move,
|
||||
svn_boolean_t metadata_only,
|
||||
verify_wc_srcs(const apr_array_header_t *copy_pairs,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
int i;
|
||||
@ -1133,10 +1132,6 @@ verify_wc_srcs_and_dsts(const apr_array_header_t *copy_pairs,
|
||||
pair->src_abspath_or_url,
|
||||
scratch_pool));
|
||||
}
|
||||
|
||||
SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only, ctx,
|
||||
result_pool, iterpool));
|
||||
|
||||
svn_pool_destroy(iterpool);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -1163,10 +1158,6 @@ typedef struct path_driver_info_t
|
||||
or move operation. */
|
||||
struct path_driver_cb_baton
|
||||
{
|
||||
/* The editor (and its state) used to perform the operation. */
|
||||
const svn_delta_editor_t *editor;
|
||||
void *edit_baton;
|
||||
|
||||
/* A hash of path -> path_driver_info_t *'s. */
|
||||
apr_hash_t *action_hash;
|
||||
|
||||
@ -1176,6 +1167,8 @@ struct path_driver_cb_baton
|
||||
|
||||
static svn_error_t *
|
||||
path_driver_cb_func(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *path,
|
||||
@ -1196,7 +1189,7 @@ path_driver_cb_func(void **dir_baton,
|
||||
/* Check to see if we need to add the path as a parent directory. */
|
||||
if (path_info->dir_add)
|
||||
{
|
||||
return cb_baton->editor->add_directory(path, parent_baton, NULL,
|
||||
return editor->add_directory(path, parent_baton, NULL,
|
||||
SVN_INVALID_REVNUM, pool,
|
||||
dir_baton);
|
||||
}
|
||||
@ -1230,7 +1223,7 @@ path_driver_cb_func(void **dir_baton,
|
||||
|
||||
if (do_delete)
|
||||
{
|
||||
SVN_ERR(cb_baton->editor->delete_entry(path, SVN_INVALID_REVNUM,
|
||||
SVN_ERR(editor->delete_entry(path, SVN_INVALID_REVNUM,
|
||||
parent_baton, pool));
|
||||
}
|
||||
if (do_add)
|
||||
@ -1240,25 +1233,25 @@ path_driver_cb_func(void **dir_baton,
|
||||
if (path_info->src_kind == svn_node_file)
|
||||
{
|
||||
void *file_baton;
|
||||
SVN_ERR(cb_baton->editor->add_file(path, parent_baton,
|
||||
SVN_ERR(editor->add_file(path, parent_baton,
|
||||
path_info->src_url,
|
||||
path_info->src_revnum,
|
||||
pool, &file_baton));
|
||||
if (path_info->mergeinfo)
|
||||
SVN_ERR(cb_baton->editor->change_file_prop(file_baton,
|
||||
SVN_ERR(editor->change_file_prop(file_baton,
|
||||
SVN_PROP_MERGEINFO,
|
||||
path_info->mergeinfo,
|
||||
pool));
|
||||
SVN_ERR(cb_baton->editor->close_file(file_baton, NULL, pool));
|
||||
SVN_ERR(editor->close_file(file_baton, NULL, pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(cb_baton->editor->add_directory(path, parent_baton,
|
||||
SVN_ERR(editor->add_directory(path, parent_baton,
|
||||
path_info->src_url,
|
||||
path_info->src_revnum,
|
||||
pool, dir_baton));
|
||||
if (path_info->mergeinfo)
|
||||
SVN_ERR(cb_baton->editor->change_dir_prop(*dir_baton,
|
||||
SVN_ERR(editor->change_dir_prop(*dir_baton,
|
||||
SVN_PROP_MERGEINFO,
|
||||
path_info->mergeinfo,
|
||||
pool));
|
||||
@ -1268,11 +1261,11 @@ path_driver_cb_func(void **dir_baton,
|
||||
if (path_info->externals)
|
||||
{
|
||||
if (*dir_baton == NULL)
|
||||
SVN_ERR(cb_baton->editor->open_directory(path, parent_baton,
|
||||
SVN_ERR(editor->open_directory(path, parent_baton,
|
||||
SVN_INVALID_REVNUM,
|
||||
pool, dir_baton));
|
||||
|
||||
SVN_ERR(cb_baton->editor->change_dir_prop(*dir_baton, SVN_PROP_EXTERNALS,
|
||||
SVN_ERR(editor->change_dir_prop(*dir_baton, SVN_PROP_EXTERNALS,
|
||||
path_info->externals, pool));
|
||||
}
|
||||
|
||||
@ -1857,13 +1850,11 @@ repos_to_repos_copy(const apr_array_header_t *copy_pairs,
|
||||
pool));
|
||||
|
||||
/* Setup the callback baton. */
|
||||
cb_baton.editor = editor;
|
||||
cb_baton.edit_baton = edit_baton;
|
||||
cb_baton.action_hash = action_hash;
|
||||
cb_baton.is_move = is_move;
|
||||
|
||||
/* Call the path-based editor driver. */
|
||||
err = svn_delta_path_driver2(editor, edit_baton, paths, TRUE,
|
||||
err = svn_delta_path_driver3(editor, edit_baton, paths, TRUE,
|
||||
path_driver_cb_func, &cb_baton, pool);
|
||||
if (err)
|
||||
{
|
||||
@ -2318,9 +2309,15 @@ struct notification_adjust_baton
|
||||
};
|
||||
|
||||
/* A svn_wc_notify_func2_t function that wraps BATON->inner_func (whose
|
||||
* baton is BATON->inner_baton) and adjusts the notification paths that
|
||||
* start with BATON->checkout_abspath to start instead with
|
||||
* BATON->final_abspath. */
|
||||
* baton is BATON->inner_baton) to turn the result of a 'checkout' into
|
||||
* what we want to see for a 'copy to WC' operation.
|
||||
*
|
||||
* - Adjust the notification paths that start with BATON->checkout_abspath
|
||||
* to start instead with BATON->final_abspath.
|
||||
* - Change start-of-update notification into a plain WC 'add' for the root.
|
||||
* - Change checkout 'add' notifications into a plain WC 'add'.
|
||||
* - Discard 'update_completed' notifications.
|
||||
*/
|
||||
static void
|
||||
notification_adjust_func(void *baton,
|
||||
const svn_wc_notify_t *notify,
|
||||
@ -2333,18 +2330,372 @@ notification_adjust_func(void *baton,
|
||||
relpath = svn_dirent_skip_ancestor(nb->checkout_abspath, notify->path);
|
||||
inner_notify->path = svn_dirent_join(nb->final_abspath, relpath, pool);
|
||||
|
||||
/* Convert 'update' notifications to plain 'add' notifications; discard
|
||||
notifications about checkout/update starting/finishing. */
|
||||
if (notify->action == svn_wc_notify_update_started /* root */
|
||||
|| notify->action == svn_wc_notify_update_add) /* non-root */
|
||||
{
|
||||
inner_notify->action = svn_wc_notify_add;
|
||||
}
|
||||
else if (notify->action == svn_wc_notify_update_update
|
||||
|| notify->action == svn_wc_notify_update_completed)
|
||||
{
|
||||
/* update_update happens only for a prop mod on root; the root was
|
||||
already notified so discard this */
|
||||
return;
|
||||
}
|
||||
|
||||
if (nb->inner_func)
|
||||
nb->inner_func(nb->inner_baton, inner_notify, pool);
|
||||
}
|
||||
|
||||
/** Copy a directory tree from a remote repository.
|
||||
*
|
||||
* Copy from RA_SESSION:LOCATION to WC_CTX:DST_ABSPATH.
|
||||
*
|
||||
* Create the directory DST_ABSPATH, if not present. Its parent should be
|
||||
* already under version control in the WC and in a suitable state for
|
||||
* scheduling the addition of a child.
|
||||
*
|
||||
* Ignore any incoming non-regular properties (entry-props, DAV/WC-props).
|
||||
* Remove any incoming 'svn:mergeinfo' properties.
|
||||
*/
|
||||
static svn_error_t *
|
||||
copy_foreign_dir(svn_ra_session_t *ra_session,
|
||||
const svn_client__pathrev_t *location,
|
||||
const char *dst_abspath,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const svn_delta_editor_t *editor;
|
||||
void *eb;
|
||||
const svn_delta_editor_t *wrapped_editor;
|
||||
void *wrapped_baton;
|
||||
const svn_ra_reporter3_t *reporter;
|
||||
void *reporter_baton;
|
||||
|
||||
/* Get a WC editor. It does not need an RA session because we will not
|
||||
be sending it any 'copy from' requests, only 'add' requests. */
|
||||
SVN_ERR(svn_client__wc_editor_internal(&editor, &eb,
|
||||
dst_abspath,
|
||||
TRUE /*root_dir_add*/,
|
||||
TRUE /*ignore_mergeinfo_changes*/,
|
||||
FALSE /*manage_wc_write_lock*/,
|
||||
notify_func, notify_baton,
|
||||
NULL /*ra_session*/,
|
||||
ctx, scratch_pool));
|
||||
|
||||
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
|
||||
editor, eb,
|
||||
&wrapped_editor, &wrapped_baton,
|
||||
scratch_pool));
|
||||
|
||||
SVN_ERR(svn_ra_do_update3(ra_session, &reporter, &reporter_baton,
|
||||
location->rev, "", svn_depth_infinity,
|
||||
FALSE, FALSE, wrapped_editor, wrapped_baton,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
SVN_ERR(reporter->set_path(reporter_baton, "", location->rev,
|
||||
svn_depth_infinity /* irrelevant */,
|
||||
TRUE /*start_empty*/,
|
||||
NULL, scratch_pool));
|
||||
|
||||
SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Implementation of svn_client__repos_to_wc_copy() for a dir.
|
||||
*/
|
||||
static svn_error_t *
|
||||
svn_client__repos_to_wc_copy_dir(svn_boolean_t *timestamp_sleep,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_revnum,
|
||||
const char *dst_abspath,
|
||||
svn_boolean_t same_repositories,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *tmpdir_abspath, *tmp_abspath;
|
||||
|
||||
SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
|
||||
|
||||
if (!same_repositories)
|
||||
{
|
||||
svn_client__pathrev_t *location;
|
||||
|
||||
*timestamp_sleep = TRUE;
|
||||
|
||||
/* ### Reparenting "ra_session" can't be right, can it? As this is
|
||||
a foreign repo, surely we need a new RA session? */
|
||||
SVN_ERR(svn_client__pathrev_create_with_session(&location, ra_session,
|
||||
src_revnum, src_url,
|
||||
scratch_pool));
|
||||
SVN_ERR(svn_ra_reparent(ra_session, src_url, scratch_pool));
|
||||
SVN_ERR(copy_foreign_dir(ra_session, location,
|
||||
dst_abspath,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
ctx, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Find a temporary location in which to check out the copy source. */
|
||||
SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
/* Get a temporary path. The crude way we do this is to create a
|
||||
temporary file, remember its name, and let it be deleted immediately. */
|
||||
SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
|
||||
svn_io_file_del_on_close,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
/* Make a new checkout of the requested source. While doing so,
|
||||
* resolve copy_src_revnum to an actual revision number in case it
|
||||
* was until now 'invalid' meaning 'head'. Ask this function not to
|
||||
* sleep for timestamps, by passing a sleep_needed output param.
|
||||
* Send notifications for all nodes except the root node, and adjust
|
||||
* them to refer to the destination rather than this temporary path. */
|
||||
{
|
||||
svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
|
||||
void *old_notify_baton2 = ctx->notify_baton2;
|
||||
struct notification_adjust_baton nb;
|
||||
svn_error_t *err;
|
||||
svn_opt_revision_t copy_src_revision;
|
||||
|
||||
copy_src_revision.kind = svn_opt_revision_number;
|
||||
copy_src_revision.value.number = src_revnum;
|
||||
|
||||
nb.inner_func = ctx->notify_func2;
|
||||
nb.inner_baton = ctx->notify_baton2;
|
||||
nb.checkout_abspath = tmp_abspath;
|
||||
nb.final_abspath = dst_abspath;
|
||||
ctx->notify_func2 = notification_adjust_func;
|
||||
ctx->notify_baton2 = &nb;
|
||||
|
||||
err = svn_client__checkout_internal(NULL /*result_rev*/, timestamp_sleep,
|
||||
src_url,
|
||||
tmp_abspath,
|
||||
©_src_revision,
|
||||
©_src_revision,
|
||||
svn_depth_infinity,
|
||||
TRUE /*ignore_externals*/,
|
||||
FALSE, /* we don't allow obstructions */
|
||||
ra_session, ctx, scratch_pool);
|
||||
|
||||
ctx->notify_func2 = old_notify_func2;
|
||||
ctx->notify_baton2 = old_notify_baton2;
|
||||
|
||||
SVN_ERR(err);
|
||||
}
|
||||
|
||||
/* Schedule dst_path for addition in parent, with copy history.
|
||||
Don't send any notification here.
|
||||
Then remove the temporary checkout's .svn dir in preparation for
|
||||
moving the rest of it into the final destination. */
|
||||
SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
|
||||
TRUE /* metadata_only */,
|
||||
NULL, NULL, /* don't allow user to cancel here */
|
||||
NULL, NULL, scratch_pool));
|
||||
SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, tmp_abspath,
|
||||
FALSE, scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_wc_remove_from_revision_control2(ctx->wc_ctx,
|
||||
tmp_abspath,
|
||||
FALSE, FALSE,
|
||||
NULL, NULL, /* don't cancel */
|
||||
scratch_pool));
|
||||
|
||||
/* Move the temporary disk tree into place. */
|
||||
SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Implementation of svn_client__repos_to_wc_copy() for a file.
|
||||
*
|
||||
* This has no 'ignore_externals' parameter because we don't support the
|
||||
* 'svn:externals' property being set on a file.
|
||||
*/
|
||||
static svn_error_t *
|
||||
svn_client__repos_to_wc_copy_file(svn_boolean_t *timestamp_sleep,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_rev,
|
||||
const char *dst_abspath,
|
||||
svn_boolean_t same_repositories,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *src_rel;
|
||||
apr_hash_t *new_props;
|
||||
svn_stream_t *new_base_contents = svn_stream_buffered(scratch_pool);
|
||||
|
||||
SVN_ERR(svn_ra_get_path_relative_to_session(ra_session, &src_rel, src_url,
|
||||
scratch_pool));
|
||||
/* Fetch the file content. */
|
||||
SVN_ERR(svn_ra_get_file(ra_session, src_rel, src_rev,
|
||||
new_base_contents, NULL, &new_props,
|
||||
scratch_pool));
|
||||
if (!same_repositories)
|
||||
svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
|
||||
|
||||
*timestamp_sleep = TRUE;
|
||||
SVN_ERR(svn_wc_add_repos_file4(
|
||||
ctx->wc_ctx, dst_abspath,
|
||||
new_base_contents, NULL, new_props, NULL,
|
||||
same_repositories ? src_url : NULL,
|
||||
same_repositories ? src_rev : SVN_INVALID_REVNUM,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
scratch_pool));
|
||||
/* Do our own notification for the root node, even if we could possibly
|
||||
have delegated it. See also issue #2198. */
|
||||
if (ctx->notify_func2)
|
||||
{
|
||||
svn_wc_notify_t *notify
|
||||
= svn_wc_create_notify(dst_abspath, svn_wc_notify_add, scratch_pool);
|
||||
|
||||
notify->kind = svn_node_file;
|
||||
ctx->notify_func2(ctx->notify_baton2, notify, scratch_pool);
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Are RA_SESSION and the versioned *parent* dir of WC_TARGET_ABSPATH in
|
||||
* the same repository?
|
||||
*/
|
||||
static svn_error_t *
|
||||
is_same_repository(svn_boolean_t *same_repository,
|
||||
svn_ra_session_t *ra_session,
|
||||
const char *wc_target_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *src_uuid, *dst_uuid;
|
||||
|
||||
/* Get the repository UUIDs of copy source URL and WC parent path */
|
||||
SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, scratch_pool));
|
||||
SVN_ERR(svn_client_get_repos_root(NULL /*root_url*/, &dst_uuid,
|
||||
svn_dirent_dirname(wc_target_abspath,
|
||||
scratch_pool),
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
*same_repository = (strcmp(src_uuid, dst_uuid) == 0);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__repos_to_wc_copy_internal(svn_boolean_t *timestamp_sleep,
|
||||
svn_node_kind_t kind,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_rev,
|
||||
const char *dst_abspath,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *old_session_url;
|
||||
svn_boolean_t timestamp_sleep_ignored;
|
||||
svn_boolean_t same_repositories;
|
||||
|
||||
SVN_ERR(svn_client__ensure_ra_session_url(&old_session_url, ra_session,
|
||||
src_url, scratch_pool));
|
||||
|
||||
SVN_ERR(is_same_repository(&same_repositories,
|
||||
ra_session, dst_abspath, ctx, scratch_pool));
|
||||
|
||||
if (!timestamp_sleep)
|
||||
timestamp_sleep = ×tamp_sleep_ignored;
|
||||
|
||||
if (kind == svn_node_dir)
|
||||
{
|
||||
SVN_ERR(svn_client__repos_to_wc_copy_dir(timestamp_sleep,
|
||||
src_url, src_rev,
|
||||
dst_abspath,
|
||||
same_repositories,
|
||||
ra_session,
|
||||
ctx, scratch_pool));
|
||||
}
|
||||
else if (kind == svn_node_file)
|
||||
{
|
||||
SVN_ERR(svn_client__repos_to_wc_copy_file(timestamp_sleep,
|
||||
src_url, src_rev,
|
||||
dst_abspath,
|
||||
same_repositories,
|
||||
ra_session,
|
||||
ctx, scratch_pool));
|
||||
}
|
||||
|
||||
/* Reparent the session back to the original URL. */
|
||||
SVN_ERR(svn_ra_reparent(ra_session, old_session_url, scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__repos_to_wc_copy_by_editor(svn_boolean_t *timestamp_sleep,
|
||||
svn_node_kind_t kind,
|
||||
const char *src_url,
|
||||
svn_revnum_t src_rev,
|
||||
const char *dst_abspath,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const svn_delta_editor_t *editor;
|
||||
void *eb;
|
||||
const char *src_anchor = svn_uri_dirname(src_url, scratch_pool);
|
||||
const char *dst_target = svn_dirent_basename(dst_abspath, scratch_pool);
|
||||
void *rb, *db;
|
||||
|
||||
SVN_ERR(svn_ra_reparent(ra_session, src_anchor, scratch_pool));
|
||||
|
||||
SVN_ERR(svn_client__wc_editor_internal(
|
||||
&editor, &eb,
|
||||
svn_dirent_dirname(dst_abspath, scratch_pool),
|
||||
FALSE /*root_dir_add*/,
|
||||
FALSE /*ignore_mergeinfo_changes*/,
|
||||
FALSE /*manage_wc_write_lock*/,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
ra_session,
|
||||
ctx, scratch_pool));
|
||||
|
||||
SVN_ERR(editor->open_root(eb, SVN_INVALID_REVNUM, scratch_pool, &rb));
|
||||
if (kind == svn_node_dir)
|
||||
{
|
||||
SVN_ERR(editor->add_directory(dst_target, rb,
|
||||
src_url, src_rev,
|
||||
scratch_pool,
|
||||
&db));
|
||||
SVN_ERR(editor->close_directory(db, scratch_pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(editor->add_file(dst_target, rb,
|
||||
src_url, src_rev,
|
||||
scratch_pool,
|
||||
&db));
|
||||
SVN_ERR(editor->close_file(db, NULL, scratch_pool));
|
||||
}
|
||||
SVN_ERR(editor->close_edit(eb, scratch_pool));
|
||||
|
||||
if (timestamp_sleep)
|
||||
*timestamp_sleep = TRUE;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Peform each individual copy operation for a repos -> wc copy. A
|
||||
helper for repos_to_wc_copy().
|
||||
|
||||
Resolve PAIR->src_revnum to a real revision number if it isn't already. */
|
||||
PAIR->src_revnum PAIR->src_abspath_or_url should already have been
|
||||
resolved to the operative revision number and operative URL.
|
||||
*/
|
||||
static svn_error_t *
|
||||
repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
|
||||
svn_client__copy_pair_t *pair,
|
||||
svn_boolean_t same_repositories,
|
||||
const svn_client__copy_pair_t *pair,
|
||||
svn_boolean_t ignore_externals,
|
||||
svn_boolean_t pin_externals,
|
||||
const apr_hash_t *externals_to_pin,
|
||||
@ -2354,9 +2705,14 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
|
||||
{
|
||||
apr_hash_t *src_mergeinfo;
|
||||
const char *dst_abspath = pair->dst_abspath_or_url;
|
||||
svn_boolean_t same_repositories;
|
||||
|
||||
SVN_ERR_ASSERT(SVN_IS_VALID_REVNUM(pair->src_revnum));
|
||||
SVN_ERR_ASSERT(svn_path_is_url(pair->src_abspath_or_url));
|
||||
SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
|
||||
|
||||
SVN_ERR(is_same_repository(&same_repositories,
|
||||
ra_session, dst_abspath, ctx, pool));
|
||||
if (!same_repositories && ctx->notify_func2)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
@ -2372,109 +2728,31 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
|
||||
SVN_ERR(ctx->cancel_func(ctx->cancel_baton));
|
||||
}
|
||||
|
||||
if (pair->src_kind == svn_node_dir)
|
||||
SVN_ERR(svn_client__repos_to_wc_copy_by_editor(
|
||||
timestamp_sleep,
|
||||
pair->src_kind,
|
||||
pair->src_abspath_or_url,
|
||||
pair->src_revnum,
|
||||
dst_abspath,
|
||||
ra_session, ctx, pool));
|
||||
|
||||
/* Fetch externals, pinning them if requested */
|
||||
if (!ignore_externals && pair->src_kind == svn_node_dir)
|
||||
{
|
||||
if (same_repositories)
|
||||
{
|
||||
const char *tmpdir_abspath, *tmp_abspath;
|
||||
const char *repos_root_url;
|
||||
apr_hash_t *new_externals;
|
||||
apr_hash_t *new_depths;
|
||||
|
||||
/* Find a temporary location in which to check out the copy source. */
|
||||
SVN_ERR(svn_wc__get_tmpdir(&tmpdir_abspath, ctx->wc_ctx, dst_abspath,
|
||||
pool, pool));
|
||||
|
||||
SVN_ERR(svn_io_open_unique_file3(NULL, &tmp_abspath, tmpdir_abspath,
|
||||
svn_io_file_del_on_close, pool, pool));
|
||||
|
||||
/* Make a new checkout of the requested source. While doing so,
|
||||
* resolve pair->src_revnum to an actual revision number in case it
|
||||
* was until now 'invalid' meaning 'head'. Ask this function not to
|
||||
* sleep for timestamps, by passing a sleep_needed output param.
|
||||
* Send notifications for all nodes except the root node, and adjust
|
||||
* them to refer to the destination rather than this temporary path. */
|
||||
{
|
||||
svn_wc_notify_func2_t old_notify_func2 = ctx->notify_func2;
|
||||
void *old_notify_baton2 = ctx->notify_baton2;
|
||||
struct notification_adjust_baton nb;
|
||||
svn_error_t *err;
|
||||
|
||||
nb.inner_func = ctx->notify_func2;
|
||||
nb.inner_baton = ctx->notify_baton2;
|
||||
nb.checkout_abspath = tmp_abspath;
|
||||
nb.final_abspath = dst_abspath;
|
||||
ctx->notify_func2 = notification_adjust_func;
|
||||
ctx->notify_baton2 = &nb;
|
||||
|
||||
/* Avoid a chicken-and-egg problem:
|
||||
* If pinning externals we'll need to adjust externals
|
||||
* properties before checking out any externals.
|
||||
* But copy needs to happen before pinning because else there
|
||||
* are no svn:externals properties to pin. */
|
||||
if (pin_externals)
|
||||
ignore_externals = TRUE;
|
||||
|
||||
err = svn_client__checkout_internal(&pair->src_revnum, timestamp_sleep,
|
||||
pair->src_original,
|
||||
tmp_abspath,
|
||||
&pair->src_peg_revision,
|
||||
&pair->src_op_revision,
|
||||
svn_depth_infinity,
|
||||
ignore_externals, FALSE,
|
||||
ra_session, ctx, pool);
|
||||
|
||||
ctx->notify_func2 = old_notify_func2;
|
||||
ctx->notify_baton2 = old_notify_baton2;
|
||||
|
||||
SVN_ERR(err);
|
||||
}
|
||||
|
||||
*timestamp_sleep = TRUE;
|
||||
|
||||
/* Schedule dst_path for addition in parent, with copy history.
|
||||
Don't send any notification here.
|
||||
Then remove the temporary checkout's .svn dir in preparation for
|
||||
moving the rest of it into the final destination. */
|
||||
SVN_ERR(svn_wc_copy3(ctx->wc_ctx, tmp_abspath, dst_abspath,
|
||||
TRUE /* metadata_only */,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
NULL, NULL, pool));
|
||||
SVN_ERR(svn_wc__acquire_write_lock(NULL, ctx->wc_ctx, tmp_abspath,
|
||||
FALSE, pool, pool));
|
||||
SVN_ERR(svn_wc_remove_from_revision_control2(ctx->wc_ctx,
|
||||
tmp_abspath,
|
||||
FALSE, FALSE,
|
||||
ctx->cancel_func,
|
||||
ctx->cancel_baton,
|
||||
pool));
|
||||
|
||||
/* Move the temporary disk tree into place. */
|
||||
SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
*timestamp_sleep = TRUE;
|
||||
|
||||
SVN_ERR(svn_client__copy_foreign(pair->src_abspath_or_url,
|
||||
dst_abspath,
|
||||
&pair->src_peg_revision,
|
||||
&pair->src_op_revision,
|
||||
svn_depth_infinity,
|
||||
FALSE /* make_parents */,
|
||||
TRUE /* already_locked */,
|
||||
ctx, pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
|
||||
|
||||
if (pin_externals)
|
||||
{
|
||||
apr_hash_t *pinned_externals;
|
||||
apr_hash_index_t *hi;
|
||||
apr_pool_t *iterpool;
|
||||
const char *repos_root_url;
|
||||
apr_hash_t *new_externals;
|
||||
apr_hash_t *new_depths;
|
||||
|
||||
SVN_ERR(svn_ra_get_repos_root2(ra_session, &repos_root_url, pool));
|
||||
SVN_ERR(resolve_pinned_externals(&pinned_externals,
|
||||
externals_to_pin, pair,
|
||||
ra_session, repos_root_url,
|
||||
@ -2502,6 +2780,8 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
|
||||
NULL, NULL, /* no extra notification */
|
||||
iterpool));
|
||||
}
|
||||
svn_pool_destroy(iterpool);
|
||||
}
|
||||
|
||||
/* Now update all externals in the newly created copy. */
|
||||
SVN_ERR(svn_wc__externals_gather_definitions(&new_externals,
|
||||
@ -2509,65 +2789,30 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
|
||||
ctx->wc_ctx,
|
||||
dst_abspath,
|
||||
svn_depth_infinity,
|
||||
iterpool, iterpool));
|
||||
pool, pool));
|
||||
SVN_ERR(svn_client__handle_externals(new_externals,
|
||||
new_depths,
|
||||
repos_root_url, dst_abspath,
|
||||
svn_depth_infinity,
|
||||
timestamp_sleep,
|
||||
ra_session,
|
||||
ctx, iterpool));
|
||||
svn_pool_destroy(iterpool);
|
||||
ctx, pool));
|
||||
}
|
||||
}
|
||||
} /* end directory case */
|
||||
|
||||
else if (pair->src_kind == svn_node_file)
|
||||
if (same_repositories)
|
||||
{
|
||||
apr_hash_t *new_props;
|
||||
const char *src_rel;
|
||||
svn_stream_t *new_base_contents = svn_stream_buffered(pool);
|
||||
|
||||
SVN_ERR(svn_ra_get_path_relative_to_session(ra_session, &src_rel,
|
||||
/* Record the implied mergeinfo. */
|
||||
SVN_ERR(svn_client__get_repos_mergeinfo(&src_mergeinfo, ra_session,
|
||||
pair->src_abspath_or_url,
|
||||
pair->src_revnum,
|
||||
svn_mergeinfo_inherited,
|
||||
TRUE /*squelch_incapable*/,
|
||||
pool));
|
||||
/* Fetch the file content. While doing so, resolve pair->src_revnum
|
||||
* to an actual revision number if it's 'invalid' meaning 'head'. */
|
||||
SVN_ERR(svn_ra_get_file(ra_session, src_rel, pair->src_revnum,
|
||||
new_base_contents,
|
||||
&pair->src_revnum, &new_props, pool));
|
||||
|
||||
if (new_props && ! same_repositories)
|
||||
svn_hash_sets(new_props, SVN_PROP_MERGEINFO, NULL);
|
||||
|
||||
*timestamp_sleep = TRUE;
|
||||
|
||||
SVN_ERR(svn_wc_add_repos_file4(
|
||||
ctx->wc_ctx, dst_abspath,
|
||||
new_base_contents, NULL, new_props, NULL,
|
||||
same_repositories ? pair->src_abspath_or_url : NULL,
|
||||
same_repositories ? pair->src_revnum : SVN_INVALID_REVNUM,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
pool));
|
||||
}
|
||||
|
||||
/* Record the implied mergeinfo (before the notification callback
|
||||
is invoked for the root node). */
|
||||
SVN_ERR(svn_client__get_repos_mergeinfo(
|
||||
&src_mergeinfo, ra_session,
|
||||
pair->src_abspath_or_url, pair->src_revnum,
|
||||
svn_mergeinfo_inherited, TRUE /*squelch_incapable*/, pool));
|
||||
SVN_ERR(extend_wc_mergeinfo(dst_abspath, src_mergeinfo, ctx, pool));
|
||||
|
||||
/* Do our own notification for the root node, even if we could possibly
|
||||
have delegated it. See also issue #1552.
|
||||
|
||||
### Maybe this notification should mention the mergeinfo change. */
|
||||
if (ctx->notify_func2)
|
||||
{
|
||||
svn_wc_notify_t *notify = svn_wc_create_notify(
|
||||
dst_abspath, svn_wc_notify_add, pool);
|
||||
notify->kind = pair->src_kind;
|
||||
ctx->notify_func2(ctx->notify_baton2, notify, pool);
|
||||
/* ### Maybe the notification should mention this mergeinfo change. */
|
||||
/* ### Maybe we should do this during rather than after the copy. */
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -2585,38 +2830,8 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
int i;
|
||||
svn_boolean_t same_repositories;
|
||||
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
|
||||
|
||||
/* We've already checked for physical obstruction by a working file.
|
||||
But there could also be logical obstruction by an entry whose
|
||||
working file happens to be missing.*/
|
||||
SVN_ERR(verify_wc_dsts(copy_pairs, FALSE, FALSE, FALSE /* metadata_only */,
|
||||
ctx, scratch_pool, iterpool));
|
||||
|
||||
/* Decide whether the two repositories are the same or not. */
|
||||
{
|
||||
const char *parent_abspath;
|
||||
const char *src_uuid, *dst_uuid;
|
||||
|
||||
/* Get the repository uuid of SRC_URL */
|
||||
SVN_ERR(svn_ra_get_uuid2(ra_session, &src_uuid, iterpool));
|
||||
|
||||
/* Get repository uuid of dst's parent directory, since dst may
|
||||
not exist. ### TODO: we should probably walk up the wc here,
|
||||
in case the parent dir has an imaginary URL. */
|
||||
if (copy_pairs->nelts == 1)
|
||||
parent_abspath = svn_dirent_dirname(top_dst_abspath, scratch_pool);
|
||||
else
|
||||
parent_abspath = top_dst_abspath;
|
||||
|
||||
SVN_ERR(svn_client_get_repos_root(NULL /* root_url */, &dst_uuid,
|
||||
parent_abspath, ctx,
|
||||
iterpool, iterpool));
|
||||
/* ### Also check repos_root_url? */
|
||||
same_repositories = (strcmp(src_uuid, dst_uuid) == 0);
|
||||
}
|
||||
|
||||
/* Perform the move for each of the copy_pairs. */
|
||||
for (i = 0; i < copy_pairs->nelts; i++)
|
||||
{
|
||||
@ -2629,7 +2844,6 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
|
||||
SVN_ERR(repos_to_wc_copy_single(timestamp_sleep,
|
||||
APR_ARRAY_IDX(copy_pairs, i,
|
||||
svn_client__copy_pair_t *),
|
||||
same_repositories,
|
||||
ignore_externals,
|
||||
pin_externals, externals_to_pin,
|
||||
ra_session, ctx, iterpool));
|
||||
@ -2642,7 +2856,6 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
|
||||
static svn_error_t *
|
||||
repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
|
||||
const apr_array_header_t *copy_pairs,
|
||||
svn_boolean_t make_parents,
|
||||
svn_boolean_t ignore_externals,
|
||||
svn_boolean_t pin_externals,
|
||||
const apr_hash_t *externals_to_pin,
|
||||
@ -2696,8 +2909,6 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
|
||||
{
|
||||
svn_client__copy_pair_t *pair = APR_ARRAY_IDX(copy_pairs, i,
|
||||
svn_client__copy_pair_t *);
|
||||
svn_node_kind_t dst_parent_kind, dst_kind;
|
||||
const char *dst_parent;
|
||||
const char *src_rel;
|
||||
|
||||
svn_pool_clear(iterpool);
|
||||
@ -2721,33 +2932,6 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
|
||||
_("Path '%s' not found in head revision"),
|
||||
pair->src_abspath_or_url);
|
||||
}
|
||||
|
||||
/* Figure out about dst. */
|
||||
SVN_ERR(svn_io_check_path(pair->dst_abspath_or_url, &dst_kind,
|
||||
iterpool));
|
||||
if (dst_kind != svn_node_none)
|
||||
{
|
||||
return svn_error_createf(
|
||||
SVN_ERR_ENTRY_EXISTS, NULL,
|
||||
_("Path '%s' already exists"),
|
||||
svn_dirent_local_style(pair->dst_abspath_or_url, pool));
|
||||
}
|
||||
|
||||
/* Make sure the destination parent is a directory and produce a clear
|
||||
error message if it is not. */
|
||||
dst_parent = svn_dirent_dirname(pair->dst_abspath_or_url, iterpool);
|
||||
SVN_ERR(svn_io_check_path(dst_parent, &dst_parent_kind, iterpool));
|
||||
if (make_parents && dst_parent_kind == svn_node_none)
|
||||
{
|
||||
SVN_ERR(svn_client__make_local_parents(dst_parent, TRUE, ctx,
|
||||
iterpool));
|
||||
}
|
||||
else if (dst_parent_kind != svn_node_dir)
|
||||
{
|
||||
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
|
||||
_("Path '%s' is not a directory"),
|
||||
svn_dirent_local_style(dst_parent, pool));
|
||||
}
|
||||
}
|
||||
svn_pool_destroy(iterpool);
|
||||
|
||||
@ -3070,8 +3254,9 @@ try_copy(svn_boolean_t *timestamp_sleep,
|
||||
/* Now, call the right handler for the operation. */
|
||||
if ((! srcs_are_urls) && (! dst_is_url))
|
||||
{
|
||||
SVN_ERR(verify_wc_srcs_and_dsts(copy_pairs, make_parents, is_move,
|
||||
metadata_only, ctx, pool, pool));
|
||||
SVN_ERR(verify_wc_srcs(copy_pairs, ctx, pool));
|
||||
SVN_ERR(verify_wc_dsts(copy_pairs, make_parents, is_move, metadata_only,
|
||||
ctx, pool, pool));
|
||||
|
||||
/* Copy or move all targets. */
|
||||
if (is_move)
|
||||
@ -3101,9 +3286,13 @@ try_copy(svn_boolean_t *timestamp_sleep,
|
||||
}
|
||||
else if ((srcs_are_urls) && (! dst_is_url))
|
||||
{
|
||||
SVN_ERR(verify_wc_dsts(copy_pairs, make_parents,
|
||||
FALSE, FALSE /* metadata_only */,
|
||||
ctx, pool, pool));
|
||||
|
||||
return svn_error_trace(
|
||||
repos_to_wc_copy(timestamp_sleep,
|
||||
copy_pairs, make_parents, ignore_externals,
|
||||
copy_pairs, ignore_externals,
|
||||
pin_externals, externals_to_pin, ctx, pool));
|
||||
}
|
||||
else
|
||||
|
@ -1,575 +0,0 @@
|
||||
/*
|
||||
* copy_foreign.c: copy from other repository support.
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
/*** Includes. ***/
|
||||
|
||||
#include <string.h>
|
||||
#include "svn_hash.h"
|
||||
#include "svn_client.h"
|
||||
#include "svn_delta.h"
|
||||
#include "svn_dirent_uri.h"
|
||||
#include "svn_error.h"
|
||||
#include "svn_error_codes.h"
|
||||
#include "svn_path.h"
|
||||
#include "svn_pools.h"
|
||||
#include "svn_props.h"
|
||||
#include "svn_ra.h"
|
||||
#include "svn_wc.h"
|
||||
|
||||
#include <apr_md5.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "private/svn_subr_private.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
#include "svn_private_config.h"
|
||||
|
||||
struct edit_baton_t
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
const char *anchor_abspath;
|
||||
|
||||
svn_wc_context_t *wc_ctx;
|
||||
svn_wc_notify_func2_t notify_func;
|
||||
void *notify_baton;
|
||||
};
|
||||
|
||||
struct dir_baton_t
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
|
||||
struct dir_baton_t *pb;
|
||||
struct edit_baton_t *eb;
|
||||
|
||||
const char *local_abspath;
|
||||
|
||||
svn_boolean_t created;
|
||||
apr_hash_t *properties;
|
||||
|
||||
int users;
|
||||
};
|
||||
|
||||
/* svn_delta_editor_t function */
|
||||
static svn_error_t *
|
||||
edit_open(void *edit_baton,
|
||||
svn_revnum_t base_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **root_baton)
|
||||
{
|
||||
struct edit_baton_t *eb = edit_baton;
|
||||
apr_pool_t *dir_pool = svn_pool_create(eb->pool);
|
||||
struct dir_baton_t *db = apr_pcalloc(dir_pool, sizeof(*db));
|
||||
|
||||
db->pool = dir_pool;
|
||||
db->eb = eb;
|
||||
db->users = 1;
|
||||
db->local_abspath = eb->anchor_abspath;
|
||||
|
||||
SVN_ERR(svn_io_make_dir_recursively(eb->anchor_abspath, dir_pool));
|
||||
|
||||
*root_baton = db;
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* svn_delta_editor_t function */
|
||||
static svn_error_t *
|
||||
edit_close(void *edit_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_add(const char *path,
|
||||
void *parent_baton,
|
||||
const char *copyfrom_path,
|
||||
svn_revnum_t copyfrom_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **child_baton)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
apr_pool_t *dir_pool = svn_pool_create(pb->pool);
|
||||
struct dir_baton_t *db = apr_pcalloc(dir_pool, sizeof(*db));
|
||||
svn_boolean_t under_root;
|
||||
|
||||
pb->users++;
|
||||
|
||||
db->pb = pb;
|
||||
db->eb = pb->eb;
|
||||
db->pool = dir_pool;
|
||||
db->users = 1;
|
||||
|
||||
SVN_ERR(svn_dirent_is_under_root(&under_root, &db->local_abspath,
|
||||
eb->anchor_abspath, path, db->pool));
|
||||
if (! under_root)
|
||||
{
|
||||
return svn_error_createf(
|
||||
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("Path '%s' is not in the working copy"),
|
||||
svn_dirent_local_style(path, db->pool));
|
||||
}
|
||||
|
||||
SVN_ERR(svn_io_make_dir_recursively(db->local_abspath, db->pool));
|
||||
|
||||
*child_baton = db;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_change_prop(void *dir_baton,
|
||||
const char *name,
|
||||
const svn_string_t *value,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct dir_baton_t *db = dir_baton;
|
||||
struct edit_baton_t *eb = db->eb;
|
||||
svn_prop_kind_t prop_kind;
|
||||
|
||||
prop_kind = svn_property_kind2(name);
|
||||
|
||||
if (prop_kind != svn_prop_regular_kind
|
||||
|| ! strcmp(name, SVN_PROP_MERGEINFO))
|
||||
{
|
||||
/* We can't handle DAV, ENTRY and merge specific props here */
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
if (! db->created)
|
||||
{
|
||||
/* We can still store them in the hash for immediate addition
|
||||
with the svn_wc_add_from_disk3() call */
|
||||
if (! db->properties)
|
||||
db->properties = apr_hash_make(db->pool);
|
||||
|
||||
if (value != NULL)
|
||||
svn_hash_sets(db->properties, apr_pstrdup(db->pool, name),
|
||||
svn_string_dup(value, db->pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
/* We have already notified for this directory, so don't do that again */
|
||||
SVN_ERR(svn_wc_prop_set4(eb->wc_ctx, db->local_abspath, name, value,
|
||||
svn_depth_empty, FALSE, NULL,
|
||||
NULL, NULL, /* Cancellation */
|
||||
NULL, NULL, /* Notification */
|
||||
scratch_pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Releases the directory baton if there are no more users */
|
||||
static svn_error_t *
|
||||
maybe_done(struct dir_baton_t *db)
|
||||
{
|
||||
db->users--;
|
||||
|
||||
if (db->users == 0)
|
||||
{
|
||||
struct dir_baton_t *pb = db->pb;
|
||||
|
||||
svn_pool_clear(db->pool);
|
||||
|
||||
if (pb)
|
||||
SVN_ERR(maybe_done(pb));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
ensure_added(struct dir_baton_t *db,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
if (db->created)
|
||||
return SVN_NO_ERROR;
|
||||
|
||||
if (db->pb)
|
||||
SVN_ERR(ensure_added(db->pb, scratch_pool));
|
||||
|
||||
db->created = TRUE;
|
||||
|
||||
/* Add the directory with all the already collected properties */
|
||||
SVN_ERR(svn_wc_add_from_disk3(db->eb->wc_ctx,
|
||||
db->local_abspath,
|
||||
db->properties,
|
||||
TRUE /* skip checks */,
|
||||
db->eb->notify_func,
|
||||
db->eb->notify_baton,
|
||||
scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_close(void *dir_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct dir_baton_t *db = dir_baton;
|
||||
/*struct edit_baton_t *eb = db->eb;*/
|
||||
|
||||
SVN_ERR(ensure_added(db, scratch_pool));
|
||||
|
||||
SVN_ERR(maybe_done(db));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
struct file_baton_t
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
|
||||
struct dir_baton_t *pb;
|
||||
struct edit_baton_t *eb;
|
||||
|
||||
const char *local_abspath;
|
||||
apr_hash_t *properties;
|
||||
|
||||
svn_boolean_t writing;
|
||||
unsigned char digest[APR_MD5_DIGESTSIZE];
|
||||
|
||||
const char *tmp_path;
|
||||
};
|
||||
|
||||
static svn_error_t *
|
||||
file_add(const char *path,
|
||||
void *parent_baton,
|
||||
const char *copyfrom_path,
|
||||
svn_revnum_t copyfrom_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **file_baton)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
apr_pool_t *file_pool = svn_pool_create(pb->pool);
|
||||
struct file_baton_t *fb = apr_pcalloc(file_pool, sizeof(*fb));
|
||||
svn_boolean_t under_root;
|
||||
|
||||
pb->users++;
|
||||
|
||||
fb->pool = file_pool;
|
||||
fb->eb = eb;
|
||||
fb->pb = pb;
|
||||
|
||||
SVN_ERR(svn_dirent_is_under_root(&under_root, &fb->local_abspath,
|
||||
eb->anchor_abspath, path, fb->pool));
|
||||
if (! under_root)
|
||||
{
|
||||
return svn_error_createf(
|
||||
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("Path '%s' is not in the working copy"),
|
||||
svn_dirent_local_style(path, fb->pool));
|
||||
}
|
||||
|
||||
*file_baton = fb;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_change_prop(void *file_baton,
|
||||
const char *name,
|
||||
const svn_string_t *value,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
svn_prop_kind_t prop_kind;
|
||||
|
||||
prop_kind = svn_property_kind2(name);
|
||||
|
||||
if (prop_kind != svn_prop_regular_kind
|
||||
|| ! strcmp(name, SVN_PROP_MERGEINFO))
|
||||
{
|
||||
/* We can't handle DAV, ENTRY and merge specific props here */
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* We store all properties in the hash for immediate addition
|
||||
with the svn_wc_add_from_disk3() call */
|
||||
if (! fb->properties)
|
||||
fb->properties = apr_hash_make(fb->pool);
|
||||
|
||||
if (value != NULL)
|
||||
svn_hash_sets(fb->properties, apr_pstrdup(fb->pool, name),
|
||||
svn_string_dup(value, fb->pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_textdelta(void *file_baton,
|
||||
const char *base_checksum,
|
||||
apr_pool_t *result_pool,
|
||||
svn_txdelta_window_handler_t *handler,
|
||||
void **handler_baton)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
svn_stream_t *target;
|
||||
|
||||
SVN_ERR_ASSERT(! fb->writing);
|
||||
|
||||
SVN_ERR(svn_stream_open_writable(&target, fb->local_abspath, fb->pool,
|
||||
fb->pool));
|
||||
|
||||
fb->writing = TRUE;
|
||||
svn_txdelta_apply(svn_stream_empty(fb->pool) /* source */,
|
||||
target,
|
||||
fb->digest,
|
||||
fb->local_abspath,
|
||||
fb->pool,
|
||||
/* Provide the handler directly */
|
||||
handler, handler_baton);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_close(void *file_baton,
|
||||
const char *text_checksum,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
struct edit_baton_t *eb = fb->eb;
|
||||
struct dir_baton_t *pb = fb->pb;
|
||||
|
||||
SVN_ERR(ensure_added(pb, fb->pool));
|
||||
|
||||
if (text_checksum)
|
||||
{
|
||||
svn_checksum_t *expected_checksum;
|
||||
svn_checksum_t *actual_checksum;
|
||||
|
||||
SVN_ERR(svn_checksum_parse_hex(&expected_checksum, svn_checksum_md5,
|
||||
text_checksum, fb->pool));
|
||||
actual_checksum = svn_checksum__from_digest_md5(fb->digest, fb->pool);
|
||||
|
||||
if (! svn_checksum_match(expected_checksum, actual_checksum))
|
||||
return svn_error_trace(
|
||||
svn_checksum_mismatch_err(expected_checksum,
|
||||
actual_checksum,
|
||||
fb->pool,
|
||||
_("Checksum mismatch for '%s'"),
|
||||
svn_dirent_local_style(
|
||||
fb->local_abspath,
|
||||
fb->pool)));
|
||||
}
|
||||
|
||||
SVN_ERR(svn_wc_add_from_disk3(eb->wc_ctx, fb->local_abspath, fb->properties,
|
||||
TRUE /* skip checks */,
|
||||
eb->notify_func, eb->notify_baton,
|
||||
fb->pool));
|
||||
|
||||
svn_pool_destroy(fb->pool);
|
||||
SVN_ERR(maybe_done(pb));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
copy_foreign_dir(svn_ra_session_t *ra_session,
|
||||
svn_client__pathrev_t *location,
|
||||
svn_wc_context_t *wc_ctx,
|
||||
const char *dst_abspath,
|
||||
svn_depth_t depth,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct edit_baton_t eb;
|
||||
svn_delta_editor_t *editor = svn_delta_default_editor(scratch_pool);
|
||||
const svn_delta_editor_t *wrapped_editor;
|
||||
void *wrapped_baton;
|
||||
const svn_ra_reporter3_t *reporter;
|
||||
void *reporter_baton;
|
||||
|
||||
eb.pool = scratch_pool;
|
||||
eb.anchor_abspath = dst_abspath;
|
||||
|
||||
eb.wc_ctx = wc_ctx;
|
||||
eb.notify_func = notify_func;
|
||||
eb.notify_baton = notify_baton;
|
||||
|
||||
editor->open_root = edit_open;
|
||||
editor->close_edit = edit_close;
|
||||
|
||||
editor->add_directory = dir_add;
|
||||
editor->change_dir_prop = dir_change_prop;
|
||||
editor->close_directory = dir_close;
|
||||
|
||||
editor->add_file = file_add;
|
||||
editor->change_file_prop = file_change_prop;
|
||||
editor->apply_textdelta = file_textdelta;
|
||||
editor->close_file = file_close;
|
||||
|
||||
SVN_ERR(svn_delta_get_cancellation_editor(cancel_func, cancel_baton,
|
||||
editor, &eb,
|
||||
&wrapped_editor, &wrapped_baton,
|
||||
scratch_pool));
|
||||
|
||||
SVN_ERR(svn_ra_do_update3(ra_session, &reporter, &reporter_baton,
|
||||
location->rev, "", svn_depth_infinity,
|
||||
FALSE, FALSE, wrapped_editor, wrapped_baton,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
SVN_ERR(reporter->set_path(reporter_baton, "", location->rev, depth,
|
||||
TRUE /* incomplete */,
|
||||
NULL, scratch_pool));
|
||||
|
||||
SVN_ERR(reporter->finish_report(reporter_baton, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
svn_error_t *
|
||||
svn_client__copy_foreign(const char *url,
|
||||
const char *dst_abspath,
|
||||
svn_opt_revision_t *peg_revision,
|
||||
svn_opt_revision_t *revision,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t make_parents,
|
||||
svn_boolean_t already_locked,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
svn_ra_session_t *ra_session;
|
||||
svn_client__pathrev_t *loc;
|
||||
svn_node_kind_t kind;
|
||||
svn_node_kind_t wc_kind;
|
||||
const char *dir_abspath;
|
||||
|
||||
SVN_ERR_ASSERT(svn_path_is_url(url));
|
||||
SVN_ERR_ASSERT(svn_dirent_is_absolute(dst_abspath));
|
||||
|
||||
/* Do we need to validate/update revisions? */
|
||||
|
||||
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
|
||||
url, NULL,
|
||||
peg_revision,
|
||||
revision, ctx,
|
||||
scratch_pool));
|
||||
|
||||
SVN_ERR(svn_ra_check_path(ra_session, "", loc->rev, &kind, scratch_pool));
|
||||
|
||||
if (kind != svn_node_file && kind != svn_node_dir)
|
||||
return svn_error_createf(
|
||||
SVN_ERR_ILLEGAL_TARGET, NULL,
|
||||
_("'%s' is not a valid location inside a repository"),
|
||||
url);
|
||||
|
||||
SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dst_abspath, FALSE, TRUE,
|
||||
scratch_pool));
|
||||
|
||||
if (wc_kind != svn_node_none)
|
||||
{
|
||||
return svn_error_createf(
|
||||
SVN_ERR_ENTRY_EXISTS, NULL,
|
||||
_("'%s' is already under version control"),
|
||||
svn_dirent_local_style(dst_abspath, scratch_pool));
|
||||
}
|
||||
|
||||
dir_abspath = svn_dirent_dirname(dst_abspath, scratch_pool);
|
||||
SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dir_abspath,
|
||||
FALSE, FALSE, scratch_pool));
|
||||
|
||||
if (wc_kind == svn_node_none)
|
||||
{
|
||||
if (make_parents)
|
||||
SVN_ERR(svn_client__make_local_parents(dir_abspath, make_parents, ctx,
|
||||
scratch_pool));
|
||||
|
||||
SVN_ERR(svn_wc_read_kind2(&wc_kind, ctx->wc_ctx, dir_abspath,
|
||||
FALSE, FALSE, scratch_pool));
|
||||
}
|
||||
|
||||
if (wc_kind != svn_node_dir)
|
||||
return svn_error_createf(
|
||||
SVN_ERR_ENTRY_NOT_FOUND, NULL,
|
||||
_("Can't add '%s', because no parent directory is found"),
|
||||
svn_dirent_local_style(dst_abspath, scratch_pool));
|
||||
|
||||
|
||||
if (kind == svn_node_file)
|
||||
{
|
||||
svn_stream_t *target;
|
||||
apr_hash_t *props;
|
||||
apr_hash_index_t *hi;
|
||||
SVN_ERR(svn_stream_open_writable(&target, dst_abspath, scratch_pool,
|
||||
scratch_pool));
|
||||
|
||||
SVN_ERR(svn_ra_get_file(ra_session, "", loc->rev, target, NULL, &props,
|
||||
scratch_pool));
|
||||
|
||||
if (props != NULL)
|
||||
for (hi = apr_hash_first(scratch_pool, props); hi;
|
||||
hi = apr_hash_next(hi))
|
||||
{
|
||||
const char *name = apr_hash_this_key(hi);
|
||||
|
||||
if (svn_property_kind2(name) != svn_prop_regular_kind
|
||||
|| ! strcmp(name, SVN_PROP_MERGEINFO))
|
||||
{
|
||||
/* We can't handle DAV, ENTRY and merge specific props here */
|
||||
svn_hash_sets(props, name, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
if (!already_locked)
|
||||
SVN_WC__CALL_WITH_WRITE_LOCK(
|
||||
svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
|
||||
TRUE /* skip checks */,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
scratch_pool),
|
||||
ctx->wc_ctx, dir_abspath, FALSE, scratch_pool);
|
||||
else
|
||||
SVN_ERR(svn_wc_add_from_disk3(ctx->wc_ctx, dst_abspath, props,
|
||||
TRUE /* skip checks */,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
scratch_pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!already_locked)
|
||||
SVN_WC__CALL_WITH_WRITE_LOCK(
|
||||
copy_foreign_dir(ra_session, loc,
|
||||
ctx->wc_ctx, dst_abspath,
|
||||
depth,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
scratch_pool),
|
||||
ctx->wc_ctx, dir_abspath, FALSE, scratch_pool);
|
||||
else
|
||||
SVN_ERR(copy_foreign_dir(ra_session, loc,
|
||||
ctx->wc_ctx, dst_abspath,
|
||||
depth,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
scratch_pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
@ -181,12 +181,13 @@ can_delete_node(svn_boolean_t *target_missing,
|
||||
|
||||
static svn_error_t *
|
||||
path_driver_cb_func(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *path,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const svn_delta_editor_t *editor = callback_baton;
|
||||
*dir_baton = NULL;
|
||||
return editor->delete_entry(path, SVN_INVALID_REVNUM, parent_baton, pool);
|
||||
}
|
||||
@ -248,8 +249,8 @@ single_repos_delete(svn_ra_session_t *ra_session,
|
||||
pool));
|
||||
|
||||
/* Call the path-based editor driver. */
|
||||
err = svn_delta_path_driver2(editor, edit_baton, relpaths, TRUE,
|
||||
path_driver_cb_func, (void *)editor, pool);
|
||||
err = svn_delta_path_driver3(editor, edit_baton, relpaths, TRUE,
|
||||
path_driver_cb_func, NULL, pool);
|
||||
|
||||
if (err)
|
||||
{
|
||||
|
@ -166,6 +166,61 @@ svn_client_mkdir(svn_client_commit_info_t **commit_info_p,
|
||||
}
|
||||
|
||||
/*** From blame.c ***/
|
||||
struct blame_receiver_wrapper_baton3 {
|
||||
void *baton;
|
||||
svn_client_blame_receiver3_t receiver;
|
||||
svn_revnum_t start_revnum;
|
||||
svn_revnum_t end_revnum;
|
||||
};
|
||||
|
||||
static svn_error_t *
|
||||
blame_wrapper_receiver3(void *baton,
|
||||
apr_int64_t line_no,
|
||||
svn_revnum_t revision,
|
||||
apr_hash_t *rev_props,
|
||||
svn_revnum_t merged_revision,
|
||||
apr_hash_t *merged_rev_props,
|
||||
const char *merged_path,
|
||||
const svn_string_t *line,
|
||||
svn_boolean_t local_change,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct blame_receiver_wrapper_baton3 *brwb = baton;
|
||||
|
||||
if (brwb->receiver)
|
||||
return brwb->receiver(brwb->baton, brwb->start_revnum, brwb->end_revnum,
|
||||
line_no,
|
||||
revision, rev_props, merged_revision,
|
||||
merged_rev_props, merged_path, line->data,
|
||||
local_change, pool);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_blame5(const char *target,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
const svn_opt_revision_t *start,
|
||||
const svn_opt_revision_t *end,
|
||||
const svn_diff_file_options_t *diff_options,
|
||||
svn_boolean_t ignore_mime_type,
|
||||
svn_boolean_t include_merged_revisions,
|
||||
svn_client_blame_receiver3_t receiver,
|
||||
void *receiver_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct blame_receiver_wrapper_baton3 baton;
|
||||
|
||||
baton.receiver = receiver;
|
||||
baton.baton = receiver_baton;
|
||||
|
||||
return svn_client_blame6(&baton.start_revnum, &baton.end_revnum,
|
||||
target, peg_revision, start, end,
|
||||
diff_options,
|
||||
ignore_mime_type, include_merged_revisions,
|
||||
blame_wrapper_receiver3, &baton, ctx, pool);
|
||||
}
|
||||
|
||||
struct blame_receiver_wrapper_baton2 {
|
||||
void *baton;
|
||||
@ -935,6 +990,42 @@ svn_client_delete(svn_client_commit_info_t **commit_info_p,
|
||||
|
||||
/*** From diff.c ***/
|
||||
|
||||
svn_error_t *
|
||||
svn_client_diff6(const apr_array_header_t *diff_options,
|
||||
const char *path_or_url1,
|
||||
const svn_opt_revision_t *revision1,
|
||||
const char *path_or_url2,
|
||||
const svn_opt_revision_t *revision2,
|
||||
const char *relative_to_dir,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
svn_boolean_t no_diff_added,
|
||||
svn_boolean_t no_diff_deleted,
|
||||
svn_boolean_t show_copies_as_adds,
|
||||
svn_boolean_t ignore_content_type,
|
||||
svn_boolean_t ignore_properties,
|
||||
svn_boolean_t properties_only,
|
||||
svn_boolean_t use_git_diff_format,
|
||||
const char *header_encoding,
|
||||
svn_stream_t *outstream,
|
||||
svn_stream_t *errstream,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
return svn_client_diff7(diff_options,
|
||||
path_or_url1, revision1,
|
||||
path_or_url2, revision2,
|
||||
relative_to_dir, depth,
|
||||
ignore_ancestry, no_diff_added,
|
||||
no_diff_deleted, show_copies_as_adds,
|
||||
ignore_content_type, ignore_properties,
|
||||
properties_only, use_git_diff_format,
|
||||
TRUE /*pretty_print_mergeinfo*/,
|
||||
header_encoding,
|
||||
outstream, errstream, changelists, ctx, pool);
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_diff5(const apr_array_header_t *diff_options,
|
||||
const char *path1,
|
||||
@ -1057,6 +1148,53 @@ svn_client_diff(const apr_array_header_t *options,
|
||||
outfile, errfile, ctx, pool);
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_diff_peg6(const apr_array_header_t *options,
|
||||
const char *path_or_url,
|
||||
const svn_opt_revision_t *peg_revision,
|
||||
const svn_opt_revision_t *start_revision,
|
||||
const svn_opt_revision_t *end_revision,
|
||||
const char *relative_to_dir,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t ignore_ancestry,
|
||||
svn_boolean_t no_diff_added,
|
||||
svn_boolean_t no_diff_deleted,
|
||||
svn_boolean_t show_copies_as_adds,
|
||||
svn_boolean_t ignore_content_type,
|
||||
svn_boolean_t ignore_properties,
|
||||
svn_boolean_t properties_only,
|
||||
svn_boolean_t use_git_diff_format,
|
||||
const char *header_encoding,
|
||||
svn_stream_t *outstream,
|
||||
svn_stream_t *errstream,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
return svn_client_diff_peg7(options,
|
||||
path_or_url,
|
||||
peg_revision,
|
||||
start_revision,
|
||||
end_revision,
|
||||
relative_to_dir,
|
||||
depth,
|
||||
ignore_ancestry,
|
||||
no_diff_added,
|
||||
no_diff_deleted,
|
||||
show_copies_as_adds,
|
||||
ignore_content_type,
|
||||
ignore_properties,
|
||||
properties_only,
|
||||
use_git_diff_format,
|
||||
TRUE /*pretty_print_mergeinfo*/,
|
||||
header_encoding,
|
||||
outstream,
|
||||
errstream,
|
||||
changelists,
|
||||
ctx,
|
||||
pool);
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_diff_peg5(const apr_array_header_t *diff_options,
|
||||
const char *path,
|
||||
@ -1643,7 +1781,7 @@ svn_client_log(const apr_array_header_t *targets,
|
||||
* we just invoke the receiver manually on a hand-constructed log
|
||||
* message for revision 0.
|
||||
*
|
||||
* See also http://subversion.tigris.org/issues/show_bug.cgi?id=692.
|
||||
* See also https://issues.apache.org/jira/browse/SVN-692.
|
||||
*/
|
||||
if (err && (err->apr_err == SVN_ERR_FS_NO_SUCH_REVISION)
|
||||
&& (start->kind == svn_opt_revision_head)
|
||||
@ -2852,6 +2990,22 @@ svn_client_resolved(const char *path,
|
||||
svn_wc_conflict_choose_merged, ctx, pool);
|
||||
}
|
||||
/*** From revert.c ***/
|
||||
svn_error_t *
|
||||
svn_client_revert3(const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_boolean_t clear_changelists,
|
||||
svn_boolean_t metadata_only,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
SVN_ERR(svn_client_revert4(paths, depth, changelists,
|
||||
clear_changelists, metadata_only,
|
||||
TRUE /*added_keep_local*/,
|
||||
ctx, pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_revert2(const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -647,20 +647,17 @@ do_dir_diff(const char *left_abspath,
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__arbitrary_nodes_diff(const char **root_relpath,
|
||||
svn_boolean_t *root_is_dir,
|
||||
const char *left_abspath,
|
||||
svn_client__arbitrary_nodes_diff(const char *left_abspath,
|
||||
const char *right_abspath,
|
||||
svn_depth_t depth,
|
||||
const svn_diff_tree_processor_t *diff_processor,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
svn_node_kind_t left_kind;
|
||||
svn_node_kind_t right_kind;
|
||||
const char *left_root_abspath;
|
||||
const char *right_root_abspath;
|
||||
const char *left_root_abspath = left_abspath;
|
||||
const char *right_root_abspath = right_abspath;
|
||||
svn_boolean_t left_before_right = TRUE; /* Future argument? */
|
||||
|
||||
if (depth == svn_depth_unknown)
|
||||
@ -669,28 +666,6 @@ svn_client__arbitrary_nodes_diff(const char **root_relpath,
|
||||
SVN_ERR(svn_io_check_resolved_path(left_abspath, &left_kind, scratch_pool));
|
||||
SVN_ERR(svn_io_check_resolved_path(right_abspath, &right_kind, scratch_pool));
|
||||
|
||||
if (left_kind == svn_node_dir && right_kind == svn_node_dir)
|
||||
{
|
||||
left_root_abspath = left_abspath;
|
||||
right_root_abspath = right_abspath;
|
||||
|
||||
if (root_relpath)
|
||||
*root_relpath = "";
|
||||
if (root_is_dir)
|
||||
*root_is_dir = TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
svn_dirent_split(&left_root_abspath, root_relpath, left_abspath,
|
||||
scratch_pool);
|
||||
right_root_abspath = svn_dirent_dirname(right_abspath, scratch_pool);
|
||||
|
||||
if (root_relpath)
|
||||
*root_relpath = apr_pstrdup(result_pool, *root_relpath);
|
||||
if (root_is_dir)
|
||||
*root_is_dir = FALSE;
|
||||
}
|
||||
|
||||
if (left_kind == svn_node_dir && right_kind == svn_node_dir)
|
||||
{
|
||||
SVN_ERR(do_dir_diff(left_abspath, right_abspath,
|
||||
@ -710,30 +685,7 @@ svn_client__arbitrary_nodes_diff(const char **root_relpath,
|
||||
else if (left_kind == svn_node_file || left_kind == svn_node_dir
|
||||
|| right_kind == svn_node_file || right_kind == svn_node_dir)
|
||||
{
|
||||
void *dir_baton;
|
||||
svn_boolean_t skip = FALSE;
|
||||
svn_boolean_t skip_children = FALSE;
|
||||
svn_diff_source_t *left_src;
|
||||
svn_diff_source_t *right_src;
|
||||
|
||||
left_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
|
||||
right_src = svn_diff__source_create(SVN_INVALID_REVNUM, scratch_pool);
|
||||
|
||||
/* The root is replaced... */
|
||||
/* Report delete and/or add */
|
||||
|
||||
SVN_ERR(diff_processor->dir_opened(&dir_baton, &skip, &skip_children, "",
|
||||
left_src,
|
||||
right_src,
|
||||
NULL /* copyfrom_src */,
|
||||
NULL,
|
||||
diff_processor,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
if (skip)
|
||||
return SVN_NO_ERROR;
|
||||
else if (!skip_children)
|
||||
{
|
||||
/* The root is added/deleted/replaced. Report delete and/or add. */
|
||||
if (left_before_right)
|
||||
{
|
||||
if (left_kind == svn_node_file)
|
||||
@ -776,14 +728,6 @@ svn_client__arbitrary_nodes_diff(const char **root_relpath,
|
||||
diff_processor, ctx, scratch_pool));
|
||||
}
|
||||
}
|
||||
|
||||
SVN_ERR(diff_processor->dir_closed("",
|
||||
left_src,
|
||||
right_src,
|
||||
dir_baton,
|
||||
diff_processor,
|
||||
scratch_pool));
|
||||
}
|
||||
else
|
||||
return svn_error_createf(SVN_ERR_NODE_UNEXPECTED_KIND, NULL,
|
||||
_("'%s' is not a file or directory"),
|
||||
|
@ -36,11 +36,6 @@
|
||||
|
||||
/* Diff callbacks baton. */
|
||||
struct summarize_baton_t {
|
||||
apr_pool_t *baton_pool; /* For allocating skip_path */
|
||||
|
||||
/* The target path of the diff, relative to the anchor; "" if target == anchor. */
|
||||
const char *skip_relpath;
|
||||
|
||||
/* The summarize callback passed down from the API */
|
||||
svn_client_diff_summarize_func_t summarize_func;
|
||||
|
||||
@ -49,9 +44,8 @@ struct summarize_baton_t {
|
||||
};
|
||||
|
||||
/* Call B->summarize_func with B->summarize_func_baton, passing it a
|
||||
* summary object composed from PATH (but made to be relative to the target
|
||||
* of the diff), SUMMARIZE_KIND, PROP_CHANGED (or FALSE if the action is an
|
||||
* add or delete) and NODE_KIND. */
|
||||
* summary object composed from PATH, SUMMARIZE_KIND, PROP_CHANGED (or
|
||||
* FALSE if the action is an add or delete) and NODE_KIND. */
|
||||
static svn_error_t *
|
||||
send_summary(struct summarize_baton_t *b,
|
||||
const char *path,
|
||||
@ -65,9 +59,7 @@ send_summary(struct summarize_baton_t *b,
|
||||
SVN_ERR_ASSERT(summarize_kind != svn_client_diff_summarize_kind_normal
|
||||
|| prop_changed);
|
||||
|
||||
/* PATH is relative to the anchor of the diff, but SUM->path needs to be
|
||||
relative to the target of the diff. */
|
||||
sum->path = svn_relpath_skip_ancestor(b->skip_relpath, path);
|
||||
sum->path = path;
|
||||
sum->summarize_kind = summarize_kind;
|
||||
if (summarize_kind == svn_client_diff_summarize_kind_modified
|
||||
|| summarize_kind == svn_client_diff_summarize_kind_normal)
|
||||
@ -265,18 +257,15 @@ diff_file_deleted(const char *relpath,
|
||||
|
||||
svn_error_t *
|
||||
svn_client__get_diff_summarize_callbacks(
|
||||
const svn_diff_tree_processor_t **diff_processor,
|
||||
const char ***p_root_relpath,
|
||||
svn_diff_tree_processor_t **diff_processor,
|
||||
svn_client_diff_summarize_func_t summarize_func,
|
||||
void *summarize_baton,
|
||||
const char *original_target,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
svn_diff_tree_processor_t *dp;
|
||||
struct summarize_baton_t *b = apr_pcalloc(result_pool, sizeof(*b));
|
||||
|
||||
b->baton_pool = result_pool;
|
||||
b->summarize_func = summarize_func;
|
||||
b->summarize_func_baton = summarize_baton;
|
||||
|
||||
@ -293,7 +282,6 @@ svn_client__get_diff_summarize_callbacks(
|
||||
dp->dir_added = diff_dir_added;
|
||||
|
||||
*diff_processor = dp;
|
||||
*p_root_relpath = &b->skip_relpath;
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
@ -453,12 +453,12 @@ export_node(void *baton,
|
||||
* If PATH exists but is a file, then error with SVN_ERR_WC_NOT_WORKING_COPY.
|
||||
*
|
||||
* If PATH is a already a directory, then error with
|
||||
* SVN_ERR_WC_OBSTRUCTED_UPDATE, unless FORCE, in which case just
|
||||
* SVN_ERR_WC_OBSTRUCTED_UPDATE, unless OVERWRITE, in which case just
|
||||
* export into PATH with no error.
|
||||
*/
|
||||
static svn_error_t *
|
||||
open_root_internal(const char *path,
|
||||
svn_boolean_t force,
|
||||
svn_boolean_t overwrite,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
apr_pool_t *pool)
|
||||
@ -472,7 +472,7 @@ open_root_internal(const char *path,
|
||||
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
|
||||
_("'%s' exists and is not a directory"),
|
||||
svn_dirent_local_style(path, pool));
|
||||
else if ((kind != svn_node_dir) || (! force))
|
||||
else if ((kind != svn_node_dir) || (! overwrite))
|
||||
return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("'%s' already exists"),
|
||||
svn_dirent_local_style(path, pool));
|
||||
@ -501,7 +501,7 @@ struct edit_baton
|
||||
const char *repos_root_url;
|
||||
const char *root_path;
|
||||
const char *root_url;
|
||||
svn_boolean_t force;
|
||||
svn_boolean_t overwrite;
|
||||
svn_revnum_t *target_revision;
|
||||
apr_hash_t *externals;
|
||||
const char *native_eol;
|
||||
@ -587,7 +587,7 @@ open_root(void *edit_baton,
|
||||
struct edit_baton *eb = edit_baton;
|
||||
struct dir_baton *db = apr_pcalloc(pool, sizeof(*db));
|
||||
|
||||
SVN_ERR(open_root_internal(eb->root_path, eb->force,
|
||||
SVN_ERR(open_root_internal(eb->root_path, eb->overwrite,
|
||||
eb->notify_func, eb->notify_baton, pool));
|
||||
|
||||
/* Build our dir baton. */
|
||||
@ -621,7 +621,7 @@ add_directory(const char *path,
|
||||
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
|
||||
_("'%s' exists and is not a directory"),
|
||||
svn_dirent_local_style(full_path, pool));
|
||||
else if (! (kind == svn_node_dir && eb->force))
|
||||
else if (! (kind == svn_node_dir && eb->overwrite))
|
||||
return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("'%s' already exists"),
|
||||
svn_dirent_local_style(full_path, pool));
|
||||
@ -1077,7 +1077,7 @@ add_directory_ev2(void *baton,
|
||||
return svn_error_createf(SVN_ERR_WC_NOT_WORKING_COPY, NULL,
|
||||
_("'%s' exists and is not a directory"),
|
||||
svn_dirent_local_style(full_path, scratch_pool));
|
||||
else if (! (kind == svn_node_dir && eb->force))
|
||||
else if (! (kind == svn_node_dir && eb->overwrite))
|
||||
return svn_error_createf(SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("'%s' already exists"),
|
||||
svn_dirent_local_style(full_path, scratch_pool));
|
||||
@ -1141,7 +1141,7 @@ get_editor_ev2(const svn_delta_editor_t **export_editor,
|
||||
exb, result_pool));
|
||||
|
||||
/* Create the root of the export. */
|
||||
SVN_ERR(open_root_internal(eb->root_path, eb->force, eb->notify_func,
|
||||
SVN_ERR(open_root_internal(eb->root_path, eb->overwrite, eb->notify_func,
|
||||
eb->notify_baton, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -1153,7 +1153,6 @@ export_file_ev2(const char *from_url,
|
||||
struct edit_baton *eb,
|
||||
svn_client__pathrev_t *loc,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_boolean_t overwrite,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
apr_hash_t *props;
|
||||
@ -1177,7 +1176,7 @@ export_file_ev2(const char *from_url,
|
||||
SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool));
|
||||
|
||||
if ((to_kind == svn_node_file || to_kind == svn_node_unknown) &&
|
||||
! overwrite)
|
||||
! eb->overwrite)
|
||||
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
|
||||
_("Destination file '%s' exists, and "
|
||||
"will not be overwritten unless forced"),
|
||||
@ -1207,7 +1206,6 @@ export_file(const char *from_url,
|
||||
struct edit_baton *eb,
|
||||
svn_client__pathrev_t *loc,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_boolean_t overwrite,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
apr_hash_t *props;
|
||||
@ -1232,7 +1230,7 @@ export_file(const char *from_url,
|
||||
SVN_ERR(svn_io_check_path(to_path, &to_kind, scratch_pool));
|
||||
|
||||
if ((to_kind == svn_node_file || to_kind == svn_node_unknown) &&
|
||||
! overwrite)
|
||||
! eb->overwrite)
|
||||
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
|
||||
_("Destination file '%s' exists, and "
|
||||
"will not be overwritten unless forced"),
|
||||
@ -1289,7 +1287,6 @@ export_directory(const char *from_url,
|
||||
struct edit_baton *eb,
|
||||
svn_client__pathrev_t *loc,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_boolean_t overwrite,
|
||||
svn_boolean_t ignore_externals,
|
||||
svn_boolean_t ignore_keywords,
|
||||
svn_depth_t depth,
|
||||
@ -1344,7 +1341,7 @@ export_directory(const char *from_url,
|
||||
SVN_ERR(svn_io_check_path(to_path, &kind, scratch_pool));
|
||||
if (kind == svn_node_none)
|
||||
SVN_ERR(open_root_internal
|
||||
(to_path, overwrite, ctx->notify_func2,
|
||||
(to_path, eb->overwrite, ctx->notify_func2,
|
||||
ctx->notify_baton2, scratch_pool));
|
||||
|
||||
if (! ignore_externals && depth == svn_depth_infinity)
|
||||
@ -1415,7 +1412,7 @@ svn_client_export5(svn_revnum_t *result_rev,
|
||||
SVN_ERR(svn_ra_get_repos_root2(ra_session, &eb->repos_root_url, pool));
|
||||
eb->root_path = to_path;
|
||||
eb->root_url = loc->url;
|
||||
eb->force = overwrite;
|
||||
eb->overwrite = overwrite;
|
||||
eb->target_revision = &edit_revision;
|
||||
eb->externals = apr_hash_make(pool);
|
||||
eb->native_eol = native_eol;
|
||||
@ -1431,15 +1428,15 @@ svn_client_export5(svn_revnum_t *result_rev,
|
||||
{
|
||||
if (!ENABLE_EV2_IMPL)
|
||||
SVN_ERR(export_file(from_url, to_path, eb, loc, ra_session,
|
||||
overwrite, pool));
|
||||
pool));
|
||||
else
|
||||
SVN_ERR(export_file_ev2(from_url, to_path, eb, loc,
|
||||
ra_session, overwrite, pool));
|
||||
ra_session, pool));
|
||||
}
|
||||
else if (kind == svn_node_dir)
|
||||
{
|
||||
SVN_ERR(export_directory(from_url, to_path,
|
||||
eb, loc, ra_session, overwrite,
|
||||
eb, loc, ra_session,
|
||||
ignore_externals, ignore_keywords, depth,
|
||||
native_eol, ctx, pool));
|
||||
}
|
||||
|
@ -167,7 +167,8 @@ build_info_from_dirent(svn_client_info2_t **info,
|
||||
#define DIRENT_FIELDS (SVN_DIRENT_KIND | \
|
||||
SVN_DIRENT_CREATED_REV | \
|
||||
SVN_DIRENT_TIME | \
|
||||
SVN_DIRENT_LAST_AUTHOR)
|
||||
SVN_DIRENT_LAST_AUTHOR | \
|
||||
SVN_DIRENT_SIZE)
|
||||
|
||||
|
||||
/* Helper func for recursively fetching svn_dirent_t's from a remote
|
||||
@ -267,6 +268,7 @@ same_resource_in_head(svn_boolean_t *same_p,
|
||||
ctx, pool);
|
||||
if (err &&
|
||||
((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) ||
|
||||
(err->apr_err == SVN_ERR_FS_NOT_DIRECTORY) ||
|
||||
(err->apr_err == SVN_ERR_FS_NOT_FOUND)))
|
||||
{
|
||||
svn_error_clear(err);
|
||||
|
289
subversion/libsvn_client/layout.c
Normal file
289
subversion/libsvn_client/layout.c
Normal file
@ -0,0 +1,289 @@
|
||||
/*
|
||||
* layout.c: code to list and update the working copy layout
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
|
||||
|
||||
/*** Includes. ***/
|
||||
|
||||
#include "svn_hash.h"
|
||||
#include "svn_dirent_uri.h"
|
||||
#include "svn_path.h"
|
||||
#include "svn_wc.h"
|
||||
#include "svn_client.h"
|
||||
#include "svn_error.h"
|
||||
#include "svn_pools.h"
|
||||
#include "client.h"
|
||||
|
||||
#include "svn_private_config.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
|
||||
struct layout_item_t
|
||||
{
|
||||
const char *local_abspath;
|
||||
const char *url;
|
||||
svn_revnum_t revision;
|
||||
svn_depth_t depth;
|
||||
struct layout_item_t *ancestor;
|
||||
apr_pool_t *pool;
|
||||
};
|
||||
|
||||
struct client_layout_baton_t
|
||||
{
|
||||
const char *root_abspath;
|
||||
svn_wc_context_t *wc_ctx;
|
||||
const char *repos_root_url;
|
||||
|
||||
struct layout_item_t *stack;
|
||||
apr_pool_t *root_pool;
|
||||
|
||||
svn_client__layout_func_t layout;
|
||||
void *layout_baton;
|
||||
};
|
||||
|
||||
|
||||
static svn_error_t *
|
||||
layout_set_path(void *report_baton,
|
||||
const char *path,
|
||||
svn_revnum_t revision,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t start_empty,
|
||||
const char *lock_token,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct client_layout_baton_t *lb = report_baton;
|
||||
const char *local_abspath = svn_dirent_join(lb->root_abspath, path, pool);
|
||||
struct layout_item_t *it;
|
||||
apr_pool_t *item_pool;
|
||||
svn_depth_t expected_depth;
|
||||
|
||||
while (lb->stack
|
||||
&& !svn_dirent_is_ancestor(lb->stack->local_abspath, local_abspath))
|
||||
{
|
||||
it = lb->stack;
|
||||
lb->stack = it->ancestor;
|
||||
svn_pool_destroy(it->pool);
|
||||
}
|
||||
|
||||
item_pool = svn_pool_create(lb->stack ? lb->stack->pool
|
||||
: lb->root_pool);
|
||||
|
||||
it = apr_pcalloc(item_pool, sizeof(*it));
|
||||
it->pool = item_pool;
|
||||
it->local_abspath = apr_pstrdup(item_pool, local_abspath);
|
||||
it->depth = depth;
|
||||
it->revision = revision;
|
||||
if (lb->stack)
|
||||
{
|
||||
it->url = svn_path_url_add_component2(
|
||||
lb->stack->url,
|
||||
svn_dirent_skip_ancestor(lb->stack->local_abspath,
|
||||
local_abspath),
|
||||
item_pool);
|
||||
}
|
||||
else
|
||||
{
|
||||
const char *repos_relpath, *repos_root_url;
|
||||
|
||||
SVN_ERR(svn_wc__node_get_base(NULL, NULL, &repos_relpath,
|
||||
&repos_root_url, NULL, NULL,
|
||||
lb->wc_ctx, local_abspath,
|
||||
FALSE /* ignore_enoent */,
|
||||
pool, pool));
|
||||
|
||||
lb->repos_root_url = apr_pstrdup(lb->root_pool, repos_root_url);
|
||||
it->url = svn_path_url_add_component2(repos_root_url, repos_relpath,
|
||||
item_pool);
|
||||
}
|
||||
it->ancestor = lb->stack;
|
||||
lb->stack = it;
|
||||
|
||||
if (!it->ancestor)
|
||||
expected_depth = depth;
|
||||
else if (it->ancestor->depth == svn_depth_infinity)
|
||||
expected_depth = svn_depth_infinity;
|
||||
else
|
||||
expected_depth = svn_depth_empty;
|
||||
|
||||
return svn_error_trace(lb->layout(lb->layout_baton,
|
||||
it->local_abspath,
|
||||
lb->repos_root_url,
|
||||
FALSE /* not-present */,
|
||||
FALSE /* url changed */,
|
||||
it->url,
|
||||
it->ancestor
|
||||
? it->ancestor->revision != it->revision
|
||||
: FALSE,
|
||||
it->revision,
|
||||
(depth != expected_depth),
|
||||
it->depth,
|
||||
pool));
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
layout_link_path(void *report_baton,
|
||||
const char *path,
|
||||
const char *url,
|
||||
svn_revnum_t revision,
|
||||
svn_depth_t depth,
|
||||
svn_boolean_t start_empty,
|
||||
const char *lock_token,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct client_layout_baton_t *lb = report_baton;
|
||||
const char *local_abspath = svn_dirent_join(lb->root_abspath, path, pool);
|
||||
struct layout_item_t *it;
|
||||
apr_pool_t *item_pool;
|
||||
svn_depth_t expected_depth;
|
||||
|
||||
SVN_ERR_ASSERT(lb->stack); /* Always below root entry */
|
||||
|
||||
while (!svn_dirent_is_ancestor(lb->stack->local_abspath, local_abspath))
|
||||
{
|
||||
it = lb->stack;
|
||||
lb->stack = it->ancestor;
|
||||
svn_pool_destroy(it->pool);
|
||||
}
|
||||
|
||||
item_pool = svn_pool_create(lb->stack ? lb->stack->pool
|
||||
: lb->root_pool);
|
||||
|
||||
it = apr_pcalloc(item_pool, sizeof(*it));
|
||||
it->pool = item_pool;
|
||||
it->local_abspath = apr_pstrdup(item_pool, local_abspath);
|
||||
it->depth = depth;
|
||||
it->revision = revision;
|
||||
it->url = apr_pstrdup(item_pool, url);
|
||||
|
||||
it->ancestor = lb->stack;
|
||||
lb->stack = it;
|
||||
|
||||
if (it->ancestor->depth == svn_depth_infinity)
|
||||
expected_depth = svn_depth_infinity;
|
||||
else
|
||||
expected_depth = svn_depth_empty;
|
||||
|
||||
return svn_error_trace(lb->layout(lb->layout_baton,
|
||||
it->local_abspath,
|
||||
lb->repos_root_url,
|
||||
FALSE /* not-present */,
|
||||
TRUE /* url changed */,
|
||||
it->url,
|
||||
it->ancestor
|
||||
? it->ancestor->revision != it->revision
|
||||
: FALSE,
|
||||
it->revision,
|
||||
(depth != expected_depth),
|
||||
it->depth,
|
||||
pool));
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
layout_delete_path(void *report_baton,
|
||||
const char *path,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct client_layout_baton_t *lb = report_baton;
|
||||
const char *local_abspath = svn_dirent_join(lb->root_abspath, path, pool);
|
||||
struct layout_item_t *it;
|
||||
|
||||
SVN_ERR_ASSERT(lb->stack); /* Always below root entry */
|
||||
|
||||
while (!svn_dirent_is_ancestor(lb->stack->local_abspath, local_abspath))
|
||||
{
|
||||
it = lb->stack;
|
||||
lb->stack = it->ancestor;
|
||||
svn_pool_destroy(it->pool);
|
||||
}
|
||||
|
||||
return svn_error_trace(lb->layout(lb->layout_baton,
|
||||
local_abspath,
|
||||
lb->repos_root_url,
|
||||
TRUE /* not-present */,
|
||||
FALSE /* url changed */,
|
||||
NULL /* no-url */,
|
||||
FALSE /* revision changed */,
|
||||
SVN_INVALID_REVNUM,
|
||||
FALSE /* depth changed */,
|
||||
svn_depth_unknown,
|
||||
pool));
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
layout_finish_report(void *report_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
/*struct client_layout_baton_t *lb = report_baton;*/
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
layout_abort_report(void *report_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
/*struct client_layout_baton_t *lb = report_baton;*/
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static const svn_ra_reporter3_t layout_reporter =
|
||||
{
|
||||
layout_set_path,
|
||||
layout_delete_path,
|
||||
layout_link_path,
|
||||
layout_finish_report,
|
||||
layout_abort_report
|
||||
};
|
||||
|
||||
svn_error_t *
|
||||
svn_client__layout_list(const char *local_abspath,
|
||||
svn_client__layout_func_t layout,
|
||||
void *layout_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct client_layout_baton_t lb;
|
||||
|
||||
lb.root_abspath = local_abspath;
|
||||
lb.root_pool = scratch_pool;
|
||||
lb.wc_ctx = ctx->wc_ctx;
|
||||
lb.repos_root_url = NULL; /* Filled in later */
|
||||
lb.stack = NULL;
|
||||
|
||||
lb.layout = layout;
|
||||
lb.layout_baton = layout_baton;
|
||||
|
||||
/* Drive the reporter structure, describing the revisions within
|
||||
LOCAL_ABSPATH. */
|
||||
SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, local_abspath,
|
||||
&layout_reporter, &lb,
|
||||
FALSE /* restore_files */,
|
||||
svn_depth_infinity,
|
||||
TRUE /* honor_depth_exclude */,
|
||||
FALSE /* depth_compatibility_trick */,
|
||||
FALSE /* use_commit_times */,
|
||||
ctx->cancel_func, ctx->cancel_baton,
|
||||
ctx->notify_func2, ctx->notify_baton2,
|
||||
scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
@ -7,6 +7,6 @@ Name: libsvn_client
|
||||
Description: Subversion Client Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_client
|
||||
Cflags: -I${includedir}
|
||||
Requires.private: libsvn_wc, libsvn_ra, libsvn_delta, libsvn_diff, libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_client-1
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
@ -394,7 +394,7 @@ list_internal(const char *path_or_url,
|
||||
svn_membuf__create(&scratch_buffer, 256, pool);
|
||||
|
||||
/* Report the dirent for the target. */
|
||||
if (match_patterns(svn_dirent_dirname(fs_path, pool), patterns,
|
||||
if (match_patterns(svn_dirent_basename(fs_path, pool), patterns,
|
||||
&scratch_buffer))
|
||||
SVN_ERR(list_func(baton, "", dirent, locks
|
||||
? (svn_hash_gets(locks, fs_path))
|
||||
|
@ -215,6 +215,21 @@
|
||||
|
||||
/*** Repos-Diff Editor Callbacks ***/
|
||||
|
||||
struct merge_cmd_baton_t;
|
||||
|
||||
struct notify_begin_state_t
|
||||
{
|
||||
/* Cache of which abspath was last notified. */
|
||||
const char *last_abspath;
|
||||
|
||||
/* Reference to the main merge baton */
|
||||
struct merge_cmd_baton_t *merge_b;
|
||||
|
||||
/* the wrapped notification callback */
|
||||
svn_wc_notify_func2_t notify_func2;
|
||||
void *notify_baton2;
|
||||
};
|
||||
|
||||
typedef struct merge_cmd_baton_t {
|
||||
svn_boolean_t force_delete; /* Delete a file/dir even if modified */
|
||||
svn_boolean_t dry_run;
|
||||
@ -242,11 +257,15 @@ typedef struct merge_cmd_baton_t {
|
||||
|
||||
/* Rangelist containing single range which describes the gap, if any,
|
||||
in the natural history of the merge source currently being processed.
|
||||
See http://subversion.tigris.org/issues/show_bug.cgi?id=3432.
|
||||
See https://issues.apache.org/jira/browse/SVN-3432.
|
||||
Updated during each call to do_directory_merge(). May be NULL if there
|
||||
is no gap. */
|
||||
svn_rangelist_t *implicit_src_gap;
|
||||
|
||||
/* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
|
||||
comment) or a similar list for single-file-merges */
|
||||
const apr_array_header_t *children_with_mergeinfo;
|
||||
|
||||
svn_client_ctx_t *ctx; /* Client context for callbacks, etc. */
|
||||
|
||||
/* The list of any paths which remained in conflict after a
|
||||
@ -319,17 +338,10 @@ typedef struct merge_cmd_baton_t {
|
||||
or do_file_merge() in do_merge(). */
|
||||
apr_pool_t *pool;
|
||||
|
||||
|
||||
/* State for notify_merge_begin() */
|
||||
struct notify_begin_state_t
|
||||
{
|
||||
/* Cache of which abspath was last notified. */
|
||||
const char *last_abspath;
|
||||
|
||||
/* Reference to the one-and-only CHILDREN_WITH_MERGEINFO (see global
|
||||
comment) or a similar list for single-file-merges */
|
||||
const apr_array_header_t *nodes_with_mergeinfo;
|
||||
} notify_begin;
|
||||
/* Our notification callback, that adds a 'begin' notification */
|
||||
svn_wc_notify_func2_t notify_func;
|
||||
void *notify_baton;
|
||||
struct notify_begin_state_t notify_begin;
|
||||
|
||||
} merge_cmd_baton_t;
|
||||
|
||||
@ -340,17 +352,25 @@ typedef struct merge_cmd_baton_t {
|
||||
merge source is an ancestor of the right-side (or vice-versa), the merge
|
||||
source is in the same repository as the merge target, and we are not
|
||||
ignoring mergeinfo. */
|
||||
#define HONOR_MERGEINFO(merge_b) ((merge_b)->mergeinfo_capable \
|
||||
&& (merge_b)->merge_source.ancestral \
|
||||
&& (merge_b)->same_repos \
|
||||
&& (! (merge_b)->ignore_mergeinfo))
|
||||
static svn_boolean_t
|
||||
HONOR_MERGEINFO(const merge_cmd_baton_t *merge_b)
|
||||
{
|
||||
return (merge_b->mergeinfo_capable
|
||||
&& merge_b->merge_source.ancestral
|
||||
&& merge_b->same_repos
|
||||
&& (!merge_b->ignore_mergeinfo));
|
||||
}
|
||||
|
||||
|
||||
/* Return TRUE iff we should be recording mergeinfo for the merge described
|
||||
by MERGE_B. Specifically, that is if we are honoring mergeinfo and the
|
||||
merge is not a dry run. */
|
||||
#define RECORD_MERGEINFO(merge_b) (HONOR_MERGEINFO(merge_b) \
|
||||
&& !(merge_b)->dry_run)
|
||||
static svn_boolean_t
|
||||
RECORD_MERGEINFO(const merge_cmd_baton_t *merge_b)
|
||||
{
|
||||
return (HONOR_MERGEINFO(merge_b)
|
||||
&& !merge_b->dry_run);
|
||||
}
|
||||
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
@ -1226,13 +1246,6 @@ struct merge_file_baton_t
|
||||
svn_boolean_t add_is_replace; /* Add is second part of replace */
|
||||
};
|
||||
|
||||
/* Forward declaration */
|
||||
static svn_error_t *
|
||||
notify_merge_begin(merge_cmd_baton_t *merge_b,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t delete_action,
|
||||
apr_pool_t *scratch_pool);
|
||||
|
||||
/* Record the skip for future processing and (later) produce the
|
||||
skip notification */
|
||||
static svn_error_t *
|
||||
@ -1253,17 +1266,15 @@ record_skip(merge_cmd_baton_t *merge_b,
|
||||
store_path(merge_b->skipped_abspaths, local_abspath);
|
||||
}
|
||||
|
||||
if (merge_b->ctx->notify_func2)
|
||||
if (merge_b->notify_func)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
|
||||
|
||||
notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
|
||||
notify->kind = kind;
|
||||
notify->content_state = notify->prop_state = state;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
|
||||
merge_b->notify_func(merge_b->notify_baton, notify,
|
||||
scratch_pool);
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
@ -1364,7 +1375,7 @@ record_tree_conflict(merge_cmd_baton_t *merge_b,
|
||||
* but figure out the actual revision range merged. */
|
||||
(void)find_nearest_ancestor_with_intersecting_ranges(
|
||||
&(range.start), &(range.end),
|
||||
merge_b->notify_begin.nodes_with_mergeinfo,
|
||||
merge_b->children_with_mergeinfo,
|
||||
action != svn_wc_conflict_action_delete,
|
||||
local_abspath);
|
||||
loc1 = svn_client__pathrev_dup(merge_b->merge_source.loc1,
|
||||
@ -1423,17 +1434,15 @@ record_tree_conflict(merge_cmd_baton_t *merge_b,
|
||||
}
|
||||
|
||||
/* On a replacement we currently get two tree conflicts */
|
||||
if (merge_b->ctx->notify_func2 && notify_tc)
|
||||
if (merge_b->notify_func && notify_tc)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
|
||||
|
||||
notify = svn_wc_create_notify(local_abspath, svn_wc_notify_tree_conflict,
|
||||
scratch_pool);
|
||||
notify->kind = local_node_kind;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
|
||||
merge_b->notify_func(merge_b->notify_baton, notify,
|
||||
scratch_pool);
|
||||
}
|
||||
|
||||
@ -1455,20 +1464,18 @@ record_update_add(merge_cmd_baton_t *merge_b,
|
||||
store_path(merge_b->merged_abspaths, local_abspath);
|
||||
}
|
||||
|
||||
if (merge_b->ctx->notify_func2)
|
||||
if (merge_b->notify_func)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
svn_wc_notify_action_t action = svn_wc_notify_update_add;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
|
||||
|
||||
if (notify_replaced)
|
||||
action = svn_wc_notify_update_replace;
|
||||
|
||||
notify = svn_wc_create_notify(local_abspath, action, scratch_pool);
|
||||
notify->kind = kind;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
|
||||
merge_b->notify_func(merge_b->notify_baton, notify,
|
||||
scratch_pool);
|
||||
}
|
||||
|
||||
@ -1490,19 +1497,17 @@ record_update_update(merge_cmd_baton_t *merge_b,
|
||||
store_path(merge_b->merged_abspaths, local_abspath);
|
||||
}
|
||||
|
||||
if (merge_b->ctx->notify_func2)
|
||||
if (merge_b->notify_func)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE, scratch_pool));
|
||||
|
||||
notify = svn_wc_create_notify(local_abspath, svn_wc_notify_update_update,
|
||||
scratch_pool);
|
||||
notify->kind = kind;
|
||||
notify->content_state = content_state;
|
||||
notify->prop_state = prop_state;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
|
||||
merge_b->notify_func(merge_b->notify_baton, notify,
|
||||
scratch_pool);
|
||||
}
|
||||
|
||||
@ -1529,8 +1534,6 @@ record_update_delete(merge_cmd_baton_t *merge_b,
|
||||
store_path(merge_b->merged_abspaths, local_abspath);
|
||||
}
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, TRUE, scratch_pool));
|
||||
|
||||
if (parent_db)
|
||||
{
|
||||
const char *dup_abspath = apr_pstrdup(parent_db->pool, local_abspath);
|
||||
@ -1552,7 +1555,7 @@ handle_pending_notifications(merge_cmd_baton_t *merge_b,
|
||||
struct merge_dir_baton_t *db,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
if (merge_b->ctx->notify_func2 && db->pending_deletes)
|
||||
if (merge_b->notify_func && db->pending_deletes)
|
||||
{
|
||||
apr_hash_index_t *hi;
|
||||
|
||||
@ -1569,7 +1572,7 @@ handle_pending_notifications(merge_cmd_baton_t *merge_b,
|
||||
notify->kind = svn_node_kind_from_word(
|
||||
apr_hash_this_val(hi));
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
|
||||
merge_b->notify_func(merge_b->notify_baton,
|
||||
notify, scratch_pool);
|
||||
}
|
||||
|
||||
@ -1620,13 +1623,10 @@ mark_dir_edited(merge_cmd_baton_t *merge_b,
|
||||
for clarity we produce a skip for this node that
|
||||
most likely isn't touched by the merge itself */
|
||||
|
||||
if (merge_b->ctx->notify_func2)
|
||||
if (merge_b->notify_func)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
|
||||
scratch_pool));
|
||||
|
||||
notify = svn_wc_create_notify(
|
||||
local_abspath,
|
||||
(db->tree_conflict_reason == CONFLICT_REASON_SKIP)
|
||||
@ -1636,7 +1636,7 @@ mark_dir_edited(merge_cmd_baton_t *merge_b,
|
||||
notify->kind = svn_node_dir;
|
||||
notify->content_state = notify->prop_state = db->skip_reason;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
|
||||
merge_b->notify_func(merge_b->notify_baton,
|
||||
notify,
|
||||
scratch_pool);
|
||||
}
|
||||
@ -1706,19 +1706,16 @@ mark_file_edited(merge_cmd_baton_t *merge_b,
|
||||
for clarity we produce a skip for this node that
|
||||
most likely isn't touched by the merge itself */
|
||||
|
||||
if (merge_b->ctx->notify_func2)
|
||||
if (merge_b->notify_func)
|
||||
{
|
||||
svn_wc_notify_t *notify;
|
||||
|
||||
SVN_ERR(notify_merge_begin(merge_b, local_abspath, FALSE,
|
||||
scratch_pool));
|
||||
|
||||
notify = svn_wc_create_notify(local_abspath, svn_wc_notify_skip,
|
||||
scratch_pool);
|
||||
notify->kind = svn_node_file;
|
||||
notify->content_state = notify->prop_state = fb->skip_reason;
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2,
|
||||
merge_b->notify_func(merge_b->notify_baton,
|
||||
notify,
|
||||
scratch_pool);
|
||||
}
|
||||
@ -3413,6 +3410,49 @@ merge_node_absent(const char *relpath,
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Return a diff processor that will apply the merge to the WC.
|
||||
*/
|
||||
static svn_diff_tree_processor_t *
|
||||
merge_apply_processor(merge_cmd_baton_t *merge_cmd_baton,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
svn_diff_tree_processor_t *merge_processor;
|
||||
|
||||
merge_processor = svn_diff__tree_processor_create(merge_cmd_baton,
|
||||
result_pool);
|
||||
|
||||
merge_processor->dir_opened = merge_dir_opened;
|
||||
merge_processor->dir_changed = merge_dir_changed;
|
||||
merge_processor->dir_added = merge_dir_added;
|
||||
merge_processor->dir_deleted = merge_dir_deleted;
|
||||
merge_processor->dir_closed = merge_dir_closed;
|
||||
|
||||
merge_processor->file_opened = merge_file_opened;
|
||||
merge_processor->file_changed = merge_file_changed;
|
||||
merge_processor->file_added = merge_file_added;
|
||||
merge_processor->file_deleted = merge_file_deleted;
|
||||
/* Not interested in file_closed() */
|
||||
|
||||
merge_processor->node_absent = merge_node_absent;
|
||||
|
||||
return merge_processor;
|
||||
}
|
||||
|
||||
/* Initialize minimal dir baton to allow calculating 'R'eplace
|
||||
from 'D'elete + 'A'dd. */
|
||||
static void *
|
||||
open_dir_for_replace_single_file(apr_pool_t *result_pool)
|
||||
{
|
||||
struct merge_dir_baton_t *dir_baton = apr_pcalloc(result_pool, sizeof(*dir_baton));
|
||||
|
||||
dir_baton->pool = result_pool;
|
||||
dir_baton->tree_conflict_reason = CONFLICT_REASON_NONE;
|
||||
dir_baton->tree_conflict_action = svn_wc_conflict_action_edit;
|
||||
dir_baton->skip_reason = svn_wc_notify_state_unknown;
|
||||
|
||||
return dir_baton;
|
||||
}
|
||||
|
||||
/*-----------------------------------------------------------------------*/
|
||||
|
||||
/*** Merge Notification ***/
|
||||
@ -3608,20 +3648,9 @@ notify_merge_completed(const char *target_abspath,
|
||||
}
|
||||
}
|
||||
|
||||
/* Is the notification the result of a real operative merge? */
|
||||
#define IS_OPERATIVE_NOTIFICATION(notify) \
|
||||
(notify->content_state == svn_wc_notify_state_conflicted \
|
||||
|| notify->content_state == svn_wc_notify_state_merged \
|
||||
|| notify->content_state == svn_wc_notify_state_changed \
|
||||
|| notify->prop_state == svn_wc_notify_state_conflicted \
|
||||
|| notify->prop_state == svn_wc_notify_state_merged \
|
||||
|| notify->prop_state == svn_wc_notify_state_changed \
|
||||
|| notify->action == svn_wc_notify_update_add \
|
||||
|| notify->action == svn_wc_notify_tree_conflict)
|
||||
|
||||
|
||||
/* Remove merge source gaps from range used for merge notifications.
|
||||
See http://subversion.tigris.org/issues/show_bug.cgi?id=4138
|
||||
See https://issues.apache.org/jira/browse/SVN-4138
|
||||
|
||||
If IMPLICIT_SRC_GAP is not NULL then it is a rangelist containing a
|
||||
single range (see the implicit_src_gap member of merge_cmd_baton_t).
|
||||
@ -3656,27 +3685,28 @@ remove_source_gap(svn_merge_range_t *range,
|
||||
* This calls the client's notification receiver (as found in the client
|
||||
* context), with a WC abspath.
|
||||
*/
|
||||
static svn_error_t *
|
||||
notify_merge_begin(merge_cmd_baton_t *merge_b,
|
||||
static void
|
||||
notify_merge_begin(struct notify_begin_state_t *notify_begin_state,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t delete_action,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
merge_cmd_baton_t *merge_b = notify_begin_state->merge_b;
|
||||
svn_wc_notify_t *notify;
|
||||
svn_merge_range_t n_range =
|
||||
{SVN_INVALID_REVNUM, SVN_INVALID_REVNUM, TRUE};
|
||||
const char *notify_abspath;
|
||||
|
||||
if (! merge_b->ctx->notify_func2)
|
||||
return SVN_NO_ERROR;
|
||||
if (! notify_begin_state->notify_func2)
|
||||
return;
|
||||
|
||||
/* If our merge sources are ancestors of one another... */
|
||||
if (merge_b->merge_source.ancestral)
|
||||
{
|
||||
const svn_client__merge_path_t *child;
|
||||
/* Find NOTIFY->PATH's nearest ancestor in
|
||||
NOTIFY->CHILDREN_WITH_MERGEINFO. Normally we consider a child in
|
||||
NOTIFY->CHILDREN_WITH_MERGEINFO representing PATH to be an
|
||||
/* Find LOCAL_ABSPATH's nearest ancestor in
|
||||
CHILDREN_WITH_MERGEINFO. Normally we consider a child in
|
||||
CHILDREN_WITH_MERGEINFO representing PATH to be an
|
||||
ancestor of PATH, but if this is a deletion of PATH then the
|
||||
notification must be for a proper ancestor of PATH. This ensures
|
||||
we don't get notifications like:
|
||||
@ -3692,47 +3722,47 @@ notify_merge_begin(merge_cmd_baton_t *merge_b,
|
||||
|
||||
child = find_nearest_ancestor_with_intersecting_ranges(
|
||||
&(n_range.start), &(n_range.end),
|
||||
merge_b->notify_begin.nodes_with_mergeinfo,
|
||||
merge_b->children_with_mergeinfo,
|
||||
! delete_action, local_abspath);
|
||||
|
||||
if (!child && delete_action)
|
||||
{
|
||||
/* Triggered by file replace in single-file-merge */
|
||||
child = find_nearest_ancestor(merge_b->notify_begin.nodes_with_mergeinfo,
|
||||
child = find_nearest_ancestor(merge_b->children_with_mergeinfo,
|
||||
TRUE, local_abspath);
|
||||
}
|
||||
|
||||
assert(child != NULL); /* Should always find the merge anchor */
|
||||
|
||||
if (! child)
|
||||
return SVN_NO_ERROR;
|
||||
return;
|
||||
|
||||
if (merge_b->notify_begin.last_abspath != NULL
|
||||
&& strcmp(child->abspath, merge_b->notify_begin.last_abspath) == 0)
|
||||
if (notify_begin_state->last_abspath != NULL
|
||||
&& strcmp(child->abspath, notify_begin_state->last_abspath) == 0)
|
||||
{
|
||||
/* Don't notify the same merge again */
|
||||
return SVN_NO_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
merge_b->notify_begin.last_abspath = child->abspath;
|
||||
notify_begin_state->last_abspath = child->abspath;
|
||||
|
||||
if (child->absent || child->remaining_ranges->nelts == 0
|
||||
|| !SVN_IS_VALID_REVNUM(n_range.start))
|
||||
{
|
||||
/* No valid information for an header */
|
||||
return SVN_NO_ERROR;
|
||||
return;
|
||||
}
|
||||
|
||||
notify_abspath = child->abspath;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (merge_b->notify_begin.last_abspath)
|
||||
return SVN_NO_ERROR; /* already notified */
|
||||
if (notify_begin_state->last_abspath)
|
||||
return; /* already notified */
|
||||
|
||||
notify_abspath = merge_b->target->abspath;
|
||||
/* Store something in last_abspath. Any value would do */
|
||||
merge_b->notify_begin.last_abspath = merge_b->target->abspath;
|
||||
notify_begin_state->last_abspath = merge_b->target->abspath;
|
||||
}
|
||||
|
||||
notify = svn_wc_create_notify(notify_abspath,
|
||||
@ -3753,10 +3783,23 @@ notify_merge_begin(merge_cmd_baton_t *merge_b,
|
||||
notify->merge_range = NULL;
|
||||
}
|
||||
|
||||
merge_b->ctx->notify_func2(merge_b->ctx->notify_baton2, notify,
|
||||
notify_begin_state->notify_func2(notify_begin_state->notify_baton2, notify,
|
||||
scratch_pool);
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
/* Our notification callback, that adds a 'begin' notification */
|
||||
static void
|
||||
notify_merging(void *baton,
|
||||
const svn_wc_notify_t *notify,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct notify_begin_state_t *b = baton;
|
||||
|
||||
notify_merge_begin(b, notify->path,
|
||||
notify->action == svn_wc_notify_update_delete,
|
||||
pool);
|
||||
|
||||
b->notify_func2(b->notify_baton2, notify, pool);
|
||||
}
|
||||
|
||||
/* Set *OUT_RANGELIST to the intersection of IN_RANGELIST with the simple
|
||||
@ -5445,7 +5488,7 @@ record_skips_in_mergeinfo(const char *mergeinfo_path,
|
||||
### TODO: An empty range is fine if the skipped path doesn't
|
||||
### inherit any mergeinfo from a parent, but if it does
|
||||
### we need to account for that. See issue #3440
|
||||
### http://subversion.tigris.org/issues/show_bug.cgi?id=3440. */
|
||||
### https://issues.apache.org/jira/browse/SVN-3440. */
|
||||
svn_hash_sets(merges, skipped_abspath,
|
||||
apr_array_make(scratch_pool, 0,
|
||||
sizeof(svn_merge_range_t *)));
|
||||
@ -5554,7 +5597,7 @@ svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report,
|
||||
defined in get_mergeinfo_paths(). Remove any paths absent from disk
|
||||
or scheduled for deletion from CHILDREN_WITH_MERGEINFO which are equal to
|
||||
or are descendants of TARGET_WCPATH by setting those children to NULL. */
|
||||
static void
|
||||
static svn_error_t *
|
||||
remove_absent_children(const char *target_wcpath,
|
||||
apr_array_header_t *children_with_mergeinfo)
|
||||
{
|
||||
@ -5569,9 +5612,10 @@ remove_absent_children(const char *target_wcpath,
|
||||
if ((child->absent || child->scheduled_for_deletion)
|
||||
&& svn_dirent_is_ancestor(target_wcpath, child->abspath))
|
||||
{
|
||||
svn_sort__array_delete(children_with_mergeinfo, i--, 1);
|
||||
SVN_ERR(svn_sort__array_delete2(children_with_mergeinfo, i--, 1));
|
||||
}
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Helper for do_directory_merge() to handle the case where a merge editor
|
||||
@ -5586,14 +5630,14 @@ remove_absent_children(const char *target_wcpath,
|
||||
MERGE_B->target->abspath, this must always be present in
|
||||
CHILDREN_WITH_MERGEINFO so this is never removed by this
|
||||
function. */
|
||||
static void
|
||||
static svn_error_t *
|
||||
remove_children_with_deleted_mergeinfo(merge_cmd_baton_t *merge_b,
|
||||
apr_array_header_t *children_with_mergeinfo)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (!merge_b->paths_with_deleted_mergeinfo)
|
||||
return;
|
||||
return SVN_NO_ERROR;
|
||||
|
||||
/* CHILDREN_WITH_MERGEINFO[0] is the always the merge target
|
||||
so start at the first child. */
|
||||
@ -5604,9 +5648,10 @@ remove_children_with_deleted_mergeinfo(merge_cmd_baton_t *merge_b,
|
||||
|
||||
if (svn_hash_gets(merge_b->paths_with_deleted_mergeinfo, child->abspath))
|
||||
{
|
||||
svn_sort__array_delete(children_with_mergeinfo, i--, 1);
|
||||
SVN_ERR(svn_sort__array_delete2(children_with_mergeinfo, i--, 1));
|
||||
}
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Helper for do_directory_merge().
|
||||
@ -5932,7 +5977,7 @@ get_most_inclusive_rev(const apr_array_header_t *children_with_mergeinfo,
|
||||
remaining_ranges is inclusive of END_REV, Slice the first range in
|
||||
to two at END_REV. All the allocations are persistent and allocated
|
||||
from POOL. */
|
||||
static void
|
||||
static svn_error_t *
|
||||
slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
|
||||
svn_boolean_t is_rollback, svn_revnum_t end_rev,
|
||||
apr_pool_t *pool)
|
||||
@ -5962,10 +6007,12 @@ slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
|
||||
split_range2->start = end_rev;
|
||||
APR_ARRAY_IDX(child->remaining_ranges, 0,
|
||||
svn_merge_range_t *) = split_range1;
|
||||
svn_sort__array_insert(child->remaining_ranges, &split_range2, 1);
|
||||
SVN_ERR(svn_sort__array_insert2(child->remaining_ranges,
|
||||
&split_range2, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Helper for do_directory_merge().
|
||||
@ -5977,7 +6024,7 @@ slice_remaining_ranges(apr_array_header_t *children_with_mergeinfo,
|
||||
If a range is removed from a child's remaining_ranges array, allocate the
|
||||
new remaining_ranges array in POOL.
|
||||
*/
|
||||
static void
|
||||
static svn_error_t *
|
||||
remove_first_range_from_remaining_ranges(svn_revnum_t revision,
|
||||
apr_array_header_t
|
||||
*children_with_mergeinfo,
|
||||
@ -5998,10 +6045,11 @@ remove_first_range_from_remaining_ranges(svn_revnum_t revision,
|
||||
APR_ARRAY_IDX(child->remaining_ranges, 0, svn_merge_range_t *);
|
||||
if (first_range->end == revision)
|
||||
{
|
||||
svn_sort__array_delete(child->remaining_ranges, 0, 1);
|
||||
SVN_ERR(svn_sort__array_delete2(child->remaining_ranges, 0, 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Get a file's content and properties from the repository.
|
||||
@ -6087,7 +6135,7 @@ get_child_with_mergeinfo(const apr_array_header_t *children_with_mergeinfo,
|
||||
out of order and then sort afterwards. (One caller is doing a qsort
|
||||
after calling this anyway.)
|
||||
*/
|
||||
static void
|
||||
static svn_error_t *
|
||||
insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
|
||||
const svn_client__merge_path_t *insert_element,
|
||||
apr_pool_t *pool)
|
||||
@ -6101,7 +6149,9 @@ insert_child_to_merge(apr_array_header_t *children_with_mergeinfo,
|
||||
compare_merge_path_t_as_paths);
|
||||
|
||||
new_element = svn_client__merge_path_dup(insert_element, pool);
|
||||
svn_sort__array_insert(children_with_mergeinfo, &new_element, insert_index);
|
||||
SVN_ERR(svn_sort__array_insert2(children_with_mergeinfo,
|
||||
&new_element, insert_index));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Helper for get_mergeinfo_paths().
|
||||
@ -6162,7 +6212,7 @@ insert_parent_and_sibs_of_sw_absent_del_subtree(
|
||||
parent->missing_child = child->absent;
|
||||
parent->switched_child = child->switched;
|
||||
/* Insert PARENT into CHILDREN_WITH_MERGEINFO. */
|
||||
insert_child_to_merge(children_with_mergeinfo, parent, pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo, parent, pool));
|
||||
/* Increment for loop index so we don't process the inserted element. */
|
||||
(*curr_index)++;
|
||||
} /*(parent == NULL) */
|
||||
@ -6199,8 +6249,8 @@ insert_parent_and_sibs_of_sw_absent_del_subtree(
|
||||
|
||||
sibling_of_missing = svn_client__merge_path_create(child_abspath,
|
||||
pool);
|
||||
insert_child_to_merge(children_with_mergeinfo, sibling_of_missing,
|
||||
pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
sibling_of_missing, pool));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6541,8 +6591,8 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
svn_client__merge_path_t *switched_child =
|
||||
svn_client__merge_path_create(wc_path, result_pool);
|
||||
switched_child->switched = TRUE;
|
||||
insert_child_to_merge(children_with_mergeinfo, switched_child,
|
||||
result_pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
switched_child, result_pool));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6594,8 +6644,8 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
}
|
||||
|
||||
if (new_shallow_child)
|
||||
insert_child_to_merge(children_with_mergeinfo, shallow_child,
|
||||
result_pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
shallow_child, result_pool));
|
||||
}
|
||||
}
|
||||
|
||||
@ -6624,8 +6674,8 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
svn_client__merge_path_t *absent_child =
|
||||
svn_client__merge_path_create(wc_path, result_pool);
|
||||
absent_child->absent = TRUE;
|
||||
insert_child_to_merge(children_with_mergeinfo, absent_child,
|
||||
result_pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
absent_child, result_pool));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6638,8 +6688,8 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
svn_client__merge_path_t *target_child =
|
||||
svn_client__merge_path_create(target->abspath,
|
||||
result_pool);
|
||||
insert_child_to_merge(children_with_mergeinfo, target_child,
|
||||
result_pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo, target_child,
|
||||
result_pool));
|
||||
}
|
||||
|
||||
/* Case 8: Path is an immediate *directory* child of
|
||||
@ -6682,8 +6732,8 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
&& depth == svn_depth_immediates)
|
||||
immediate_child->immediate_child_dir = TRUE;
|
||||
|
||||
insert_child_to_merge(children_with_mergeinfo,
|
||||
immediate_child, result_pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
immediate_child, result_pool));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -6775,9 +6825,9 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
|
||||
child_of_noninheritable =
|
||||
svn_client__merge_path_create(child_abspath, result_pool);
|
||||
child_of_noninheritable->child_of_noninheritable = TRUE;
|
||||
insert_child_to_merge(children_with_mergeinfo,
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
child_of_noninheritable,
|
||||
result_pool);
|
||||
result_pool));
|
||||
if (!dry_run && same_repos)
|
||||
{
|
||||
svn_mergeinfo_t mergeinfo;
|
||||
@ -7201,7 +7251,7 @@ normalize_merge_sources_internal(apr_array_header_t **merge_sources_p,
|
||||
new_segment->path = original_repos_relpath;
|
||||
new_segment->range_start = original_revision;
|
||||
new_segment->range_end = original_revision;
|
||||
svn_sort__array_insert(segments, &new_segment, 0);
|
||||
SVN_ERR(svn_sort__array_insert2(segments, &new_segment, 0));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -7596,16 +7646,15 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
|
||||
/* ### Create a fake copy of merge_target as we don't keep
|
||||
remaining_ranges in sync (yet). */
|
||||
target_info = apr_pcalloc(scratch_pool, sizeof(*target_info));
|
||||
|
||||
target_info->abspath = merge_target->abspath;
|
||||
target_info = svn_client__merge_path_create(merge_target->abspath,
|
||||
scratch_pool);
|
||||
target_info->remaining_ranges = ranges_to_merge;
|
||||
|
||||
APR_ARRAY_PUSH(child_with_mergeinfo, svn_client__merge_path_t *)
|
||||
= target_info;
|
||||
|
||||
/* And store in baton to allow using it from notify_merge_begin() */
|
||||
merge_b->notify_begin.nodes_with_mergeinfo = child_with_mergeinfo;
|
||||
merge_b->children_with_mergeinfo = child_with_mergeinfo;
|
||||
}
|
||||
|
||||
while (ranges_to_merge->nelts > 0)
|
||||
@ -7648,19 +7697,10 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
do a text-n-props merge; otherwise, do a delete-n-add merge. */
|
||||
if (! (merge_b->diff_ignore_ancestry || sources_related))
|
||||
{
|
||||
struct merge_dir_baton_t dir_baton;
|
||||
void *dir_baton = open_dir_for_replace_single_file(iterpool);
|
||||
void *file_baton;
|
||||
svn_boolean_t skip;
|
||||
|
||||
/* Initialize minimal dir baton to allow calculating 'R'eplace
|
||||
from 'D'elete + 'A'dd. */
|
||||
|
||||
memset(&dir_baton, 0, sizeof(dir_baton));
|
||||
dir_baton.pool = iterpool;
|
||||
dir_baton.tree_conflict_reason = CONFLICT_REASON_NONE;
|
||||
dir_baton.tree_conflict_action = svn_wc_conflict_action_edit;
|
||||
dir_baton.skip_reason = svn_wc_notify_state_unknown;
|
||||
|
||||
/* Delete... */
|
||||
file_baton = NULL;
|
||||
skip = FALSE;
|
||||
@ -7668,7 +7708,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
left_source,
|
||||
NULL /* right_source */,
|
||||
NULL /* copyfrom_source */,
|
||||
&dir_baton,
|
||||
dir_baton,
|
||||
processor,
|
||||
iterpool, iterpool));
|
||||
if (! skip)
|
||||
@ -7687,7 +7727,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
NULL /* left_source */,
|
||||
right_source,
|
||||
NULL /* copyfrom_source */,
|
||||
&dir_baton,
|
||||
dir_baton,
|
||||
processor,
|
||||
iterpool, iterpool));
|
||||
if (! skip)
|
||||
@ -7758,7 +7798,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
(This list is used from notify_merge_begin)
|
||||
|
||||
Directory merges use remove_first_range_from_remaining_ranges() */
|
||||
svn_sort__array_delete(ranges_to_merge, 0, 1);
|
||||
SVN_ERR(svn_sort__array_delete2(ranges_to_merge, 0, 1));
|
||||
}
|
||||
merge_b->notify_begin.last_abspath = NULL;
|
||||
} /* !merge_b->record_only */
|
||||
@ -7819,7 +7859,7 @@ do_file_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
}
|
||||
}
|
||||
|
||||
merge_b->notify_begin.nodes_with_mergeinfo = NULL;
|
||||
merge_b->children_with_mergeinfo = NULL;
|
||||
|
||||
svn_pool_destroy(iterpool);
|
||||
|
||||
@ -7878,7 +7918,7 @@ process_children_with_new_mergeinfo(merge_cmd_baton_t *merge_b,
|
||||
was added (with preexisting mergeinfo) by the merge. That's actually
|
||||
more correct, since the inherited mergeinfo likely describes
|
||||
non-existent or unrelated merge history, but it's not quite so simple
|
||||
as that, see http://subversion.tigris.org/issues/show_bug.cgi?id=4309
|
||||
as that, see https://issues.apache.org/jira/browse/SVN-4309
|
||||
*/
|
||||
|
||||
/* Get the path's new explicit mergeinfo... */
|
||||
@ -7945,7 +7985,8 @@ process_children_with_new_mergeinfo(merge_cmd_baton_t *merge_b,
|
||||
/* Set the path's remaining_ranges equal to its parent's. */
|
||||
new_child->remaining_ranges = svn_rangelist_dup(
|
||||
parent->remaining_ranges, pool);
|
||||
insert_child_to_merge(children_with_mergeinfo, new_child, pool);
|
||||
SVN_ERR(insert_child_to_merge(children_with_mergeinfo,
|
||||
new_child, pool));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -8269,7 +8310,7 @@ flag_subtrees_needing_mergeinfo(svn_boolean_t operative_merge,
|
||||
merge_b->target->abspath, depth, merge_b->ctx->wc_ctx,
|
||||
merge_b->ra_session1, scratch_pool, iterpool));
|
||||
|
||||
/* Issue #4056: Walk NOTIFY_B->CHILDREN_WITH_MERGEINFO reverse depth-first
|
||||
/* Issue #4056: Walk CHILDREN_WITH_MERGEINFO reverse depth-first
|
||||
order. This way each child knows if it has operative missing/switched
|
||||
children which necessitates non-inheritable mergeinfo. */
|
||||
for (i = children_with_mergeinfo->nelts - 1; i >= 0; i--)
|
||||
@ -8432,7 +8473,7 @@ flag_subtrees_needing_mergeinfo(svn_boolean_t operative_merge,
|
||||
}
|
||||
else /* child->record_mergeinfo */
|
||||
{
|
||||
/* If CHILD is in NOTIFY_B->CHILDREN_WITH_MERGEINFO simply
|
||||
/* If CHILD is in CHILDREN_WITH_MERGEINFO simply
|
||||
because it had no explicit mergeinfo of its own at the
|
||||
start of the merge but is the child of of some path with
|
||||
non-inheritable mergeinfo, then the explicit mergeinfo it
|
||||
@ -8457,7 +8498,7 @@ flag_subtrees_needing_mergeinfo(svn_boolean_t operative_merge,
|
||||
If RESULT_CATALOG is NULL then record mergeinfo describing a merge of
|
||||
MERGED_RANGE->START:MERGED_RANGE->END from the repository relative path
|
||||
MERGEINFO_FSPATH to the merge target (and possibly its subtrees) described
|
||||
by NOTIFY_B->CHILDREN_WITH_MERGEINFO -- see the global comment
|
||||
by CHILDREN_WITH_MERGEINFO -- see the global comment
|
||||
'THE CHILDREN_WITH_MERGEINFO ARRAY'. Obviously this should only
|
||||
be called if recording mergeinfo -- see doc string for RECORD_MERGEINFO().
|
||||
|
||||
@ -8508,10 +8549,10 @@ record_mergeinfo_for_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
range.inheritable = TRUE;
|
||||
|
||||
/* Remove absent children at or under MERGE_B->target->abspath from
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO
|
||||
CHILDREN_WITH_MERGEINFO
|
||||
before we calculate the merges performed. */
|
||||
remove_absent_children(merge_b->target->abspath,
|
||||
children_with_mergeinfo);
|
||||
SVN_ERR(remove_absent_children(merge_b->target->abspath,
|
||||
children_with_mergeinfo));
|
||||
|
||||
/* Determine which subtrees of interest need mergeinfo recorded... */
|
||||
SVN_ERR(flag_subtrees_needing_mergeinfo(operative_merge, &range,
|
||||
@ -9334,7 +9375,7 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
/* Point our RA_SESSION to the URL of our youngest merge source side. */
|
||||
ra_session = is_rollback ? merge_b->ra_session1 : merge_b->ra_session2;
|
||||
|
||||
/* Fill NOTIFY_B->CHILDREN_WITH_MERGEINFO with child paths (const
|
||||
/* Fill CHILDREN_WITH_MERGEINFO with child paths (const
|
||||
svn_client__merge_path_t *) which might have intersecting merges
|
||||
because they meet one or more of the criteria described in
|
||||
get_mergeinfo_paths(). Here the paths are arranged in a depth
|
||||
@ -9344,13 +9385,13 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
merge_b->dry_run, merge_b->same_repos,
|
||||
merge_b->ctx, scratch_pool, scratch_pool));
|
||||
|
||||
/* The first item from the NOTIFY_B->CHILDREN_WITH_MERGEINFO is always
|
||||
/* The first item from the CHILDREN_WITH_MERGEINFO is always
|
||||
the target thanks to depth-first ordering. */
|
||||
target_merge_path = APR_ARRAY_IDX(children_with_mergeinfo, 0,
|
||||
svn_client__merge_path_t *);
|
||||
|
||||
/* If we are honoring mergeinfo, then for each item in
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO, we need to calculate what needs to be
|
||||
CHILDREN_WITH_MERGEINFO, we need to calculate what needs to be
|
||||
merged, and then merge it. Otherwise, we just merge what we were asked
|
||||
to merge across the whole tree. */
|
||||
SVN_ERR(populate_remaining_ranges(children_with_mergeinfo,
|
||||
@ -9370,7 +9411,7 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
|
||||
/* The merge target TARGET_ABSPATH and/or its subtrees may not need all
|
||||
of SOURCE->rev1:rev2 applied. So examine
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the oldest starting
|
||||
CHILDREN_WITH_MERGEINFO to find the oldest starting
|
||||
revision that actually needs to be merged (for reverse merges this is
|
||||
the youngest starting revision).
|
||||
|
||||
@ -9408,7 +9449,7 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
/* Is there anything to merge? */
|
||||
if (SVN_IS_VALID_REVNUM(start_rev))
|
||||
{
|
||||
/* Now examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the oldest
|
||||
/* Now examine CHILDREN_WITH_MERGEINFO to find the oldest
|
||||
ending revision that actually needs to be merged (for reverse
|
||||
merges this is the youngest ending revision). */
|
||||
svn_revnum_t end_rev =
|
||||
@ -9417,7 +9458,7 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
|
||||
/* While END_REV is valid, do the following:
|
||||
|
||||
1. Tweak each NOTIFY_B->CHILDREN_WITH_MERGEINFO element so that
|
||||
1. Tweak each CHILDREN_WITH_MERGEINFO element so that
|
||||
the element's remaining_ranges member has as its first element
|
||||
a range that ends with end_rev.
|
||||
|
||||
@ -9425,17 +9466,17 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
on MERGE_B->target->abspath for start_rev:end_rev.
|
||||
|
||||
3. Remove the first element from each
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO element's remaining_ranges
|
||||
CHILDREN_WITH_MERGEINFO element's remaining_ranges
|
||||
member.
|
||||
|
||||
4. Again examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the most
|
||||
4. Again examine CHILDREN_WITH_MERGEINFO to find the most
|
||||
inclusive starting revision that actually needs to be merged and
|
||||
update start_rev. This prevents us from needlessly contacting the
|
||||
repository and doing a diff where we describe the entire target
|
||||
tree as *not* needing any of the requested range. This can happen
|
||||
whenever we have mergeinfo with gaps in it for the merge source.
|
||||
|
||||
5. Again examine NOTIFY_B->CHILDREN_WITH_MERGEINFO to find the most
|
||||
5. Again examine CHILDREN_WITH_MERGEINFO to find the most
|
||||
inclusive ending revision that actually needs to be merged and
|
||||
update end_rev.
|
||||
|
||||
@ -9477,8 +9518,9 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
|
||||
svn_pool_clear(iterpool);
|
||||
|
||||
slice_remaining_ranges(children_with_mergeinfo,
|
||||
is_rollback, end_rev, scratch_pool);
|
||||
SVN_ERR(slice_remaining_ranges(children_with_mergeinfo,
|
||||
is_rollback, end_rev,
|
||||
scratch_pool));
|
||||
|
||||
/* Reset variables that must be reset for every drive */
|
||||
merge_b->notify_begin.last_abspath = NULL;
|
||||
@ -9496,23 +9538,23 @@ do_mergeinfo_aware_dir_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
/* If any paths picked up explicit mergeinfo as a result of
|
||||
the merge we need to make sure any mergeinfo those paths
|
||||
inherited is recorded and then add these paths to
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO.*/
|
||||
CHILDREN_WITH_MERGEINFO.*/
|
||||
SVN_ERR(process_children_with_new_mergeinfo(
|
||||
merge_b, children_with_mergeinfo,
|
||||
scratch_pool));
|
||||
|
||||
/* If any subtrees had their explicit mergeinfo deleted as a
|
||||
result of the merge then remove these paths from
|
||||
NOTIFY_B->CHILDREN_WITH_MERGEINFO since there is no need
|
||||
CHILDREN_WITH_MERGEINFO since there is no need
|
||||
to consider these subtrees for subsequent editor drives
|
||||
nor do we want to record mergeinfo on them describing
|
||||
the merge itself. */
|
||||
remove_children_with_deleted_mergeinfo(
|
||||
merge_b, children_with_mergeinfo);
|
||||
SVN_ERR(remove_children_with_deleted_mergeinfo(
|
||||
merge_b, children_with_mergeinfo));
|
||||
|
||||
/* Prepare for the next iteration (if any). */
|
||||
remove_first_range_from_remaining_ranges(
|
||||
end_rev, children_with_mergeinfo, scratch_pool);
|
||||
SVN_ERR(remove_first_range_from_remaining_ranges(
|
||||
end_rev, children_with_mergeinfo, scratch_pool));
|
||||
|
||||
/* If we raised any conflicts, break out and report how much
|
||||
we have merged. */
|
||||
@ -9634,7 +9676,7 @@ do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
apr_array_make(scratch_pool, 16, sizeof(svn_client__merge_path_t *));
|
||||
|
||||
/* And make it read-only accessible from the baton */
|
||||
merge_b->notify_begin.nodes_with_mergeinfo = children_with_mergeinfo;
|
||||
merge_b->children_with_mergeinfo = children_with_mergeinfo;
|
||||
|
||||
/* If we are not honoring mergeinfo we can skip right to the
|
||||
business of merging changes! */
|
||||
@ -9652,7 +9694,7 @@ do_directory_merge(svn_mergeinfo_catalog_t result_catalog,
|
||||
processor, depth,
|
||||
merge_b, result_pool, scratch_pool));
|
||||
|
||||
merge_b->notify_begin.nodes_with_mergeinfo = NULL;
|
||||
merge_b->children_with_mergeinfo = NULL;
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
@ -9889,28 +9931,13 @@ do_merge(apr_hash_t **modified_subtrees,
|
||||
merge_cmd_baton.added_abspaths = apr_hash_make(result_pool);
|
||||
merge_cmd_baton.tree_conflicted_abspaths = apr_hash_make(result_pool);
|
||||
|
||||
{
|
||||
svn_diff_tree_processor_t *merge_processor;
|
||||
merge_cmd_baton.notify_func = notify_merging;
|
||||
merge_cmd_baton.notify_baton = &merge_cmd_baton.notify_begin;
|
||||
merge_cmd_baton.notify_begin.merge_b = &merge_cmd_baton;
|
||||
merge_cmd_baton.notify_begin.notify_func2 = ctx->notify_func2;
|
||||
merge_cmd_baton.notify_begin.notify_baton2 = ctx->notify_baton2;
|
||||
|
||||
merge_processor = svn_diff__tree_processor_create(&merge_cmd_baton,
|
||||
scratch_pool);
|
||||
|
||||
merge_processor->dir_opened = merge_dir_opened;
|
||||
merge_processor->dir_changed = merge_dir_changed;
|
||||
merge_processor->dir_added = merge_dir_added;
|
||||
merge_processor->dir_deleted = merge_dir_deleted;
|
||||
merge_processor->dir_closed = merge_dir_closed;
|
||||
|
||||
merge_processor->file_opened = merge_file_opened;
|
||||
merge_processor->file_changed = merge_file_changed;
|
||||
merge_processor->file_added = merge_file_added;
|
||||
merge_processor->file_deleted = merge_file_deleted;
|
||||
/* Not interested in file_closed() */
|
||||
|
||||
merge_processor->node_absent = merge_node_absent;
|
||||
|
||||
processor = merge_processor;
|
||||
}
|
||||
processor = merge_apply_processor(&merge_cmd_baton, scratch_pool);
|
||||
|
||||
if (src_session)
|
||||
{
|
||||
|
@ -343,7 +343,9 @@ strip_path(const char **result, const char *path, int strip_count,
|
||||
components = svn_path_decompose(path, scratch_pool);
|
||||
if (strip_count > components->nelts)
|
||||
return svn_error_createf(SVN_ERR_CLIENT_PATCH_BAD_STRIP_COUNT, NULL,
|
||||
_("Cannot strip %u components from '%s'"),
|
||||
Q_("Cannot strip %u component from '%s'",
|
||||
"Cannot strip %u components from '%s'",
|
||||
strip_count),
|
||||
strip_count,
|
||||
svn_dirent_local_style(path, scratch_pool));
|
||||
|
||||
@ -1018,6 +1020,7 @@ init_patch_target(patch_target_t **patch_target,
|
||||
target_content_t *content;
|
||||
svn_boolean_t has_text_changes = FALSE;
|
||||
svn_boolean_t follow_moves;
|
||||
const char *tempdir_abspath;
|
||||
|
||||
has_text_changes = ((patch->hunks && patch->hunks->nelts > 0)
|
||||
|| patch->binary_patch);
|
||||
@ -1223,8 +1226,10 @@ init_patch_target(patch_target_t **patch_target,
|
||||
}
|
||||
|
||||
/* Open a temporary file to write the patched result to. */
|
||||
SVN_ERR(svn_wc__get_tmpdir(&tempdir_abspath, wc_ctx,
|
||||
target->local_abspath, scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_io_open_unique_file3(&target->patched_file,
|
||||
&target->patched_path, NULL,
|
||||
&target->patched_path, tempdir_abspath,
|
||||
remove_tempfiles ?
|
||||
svn_io_file_del_on_pool_cleanup :
|
||||
svn_io_file_del_none,
|
||||
@ -1236,7 +1241,7 @@ init_patch_target(patch_target_t **patch_target,
|
||||
|
||||
/* Open a temporary stream to write rejected hunks to. */
|
||||
SVN_ERR(svn_stream_open_unique(&target->reject_stream,
|
||||
&target->reject_path, NULL,
|
||||
&target->reject_path, tempdir_abspath,
|
||||
remove_tempfiles ?
|
||||
svn_io_file_del_on_pool_cleanup :
|
||||
svn_io_file_del_none,
|
||||
@ -2145,8 +2150,8 @@ reject_hunk(patch_target_t *target, target_content_t *content,
|
||||
if (prop_name)
|
||||
{
|
||||
/* ### Print 'Added', 'Deleted' or 'Modified' instead of 'Property'. */
|
||||
svn_stream_printf(target->reject_stream,
|
||||
pool, "Property: %s" APR_EOL_STR, prop_name);
|
||||
SVN_ERR(svn_stream_printf(target->reject_stream,
|
||||
pool, "Property: %s" APR_EOL_STR, prop_name));
|
||||
atat = prop_atat;
|
||||
}
|
||||
else
|
||||
|
@ -402,8 +402,7 @@ svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
|
||||
}
|
||||
}
|
||||
|
||||
/* If the caller allows for auto-following redirections, and the
|
||||
RA->open() call above reveals a CORRECTED_URL, try the new URL.
|
||||
/* If the caller allows for auto-following redirections, try the new URL.
|
||||
We'll do this in a loop up to some maximum number follow-and-retry
|
||||
attempts. */
|
||||
if (corrected_url)
|
||||
@ -414,12 +413,14 @@ svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
|
||||
*corrected_url = NULL;
|
||||
while (attempts_left--)
|
||||
{
|
||||
const char *corrected = NULL;
|
||||
const char *corrected = NULL; /* canonicalized version */
|
||||
const char *redirect_url = NULL; /* non-canonicalized version */
|
||||
|
||||
/* Try to open the RA session. If this is our last attempt,
|
||||
don't accept corrected URLs from the RA provider. */
|
||||
SVN_ERR(svn_ra_open4(ra_session,
|
||||
SVN_ERR(svn_ra_open5(ra_session,
|
||||
attempts_left == 0 ? NULL : &corrected,
|
||||
attempts_left == 0 ? NULL : &redirect_url,
|
||||
base_url, uuid, cbtable, cb, ctx->config,
|
||||
result_pool));
|
||||
|
||||
@ -441,19 +442,28 @@ svn_client__open_ra_session_internal(svn_ra_session_t **ra_session,
|
||||
*corrected_url = corrected;
|
||||
|
||||
/* Make sure we've not attempted this URL before. */
|
||||
if (svn_hash_gets(attempted, corrected))
|
||||
if (svn_hash_gets(attempted, redirect_url))
|
||||
return svn_error_createf(SVN_ERR_CLIENT_CYCLE_DETECTED, NULL,
|
||||
_("Redirect cycle detected for URL '%s'"),
|
||||
corrected);
|
||||
redirect_url);
|
||||
|
||||
/*
|
||||
* Remember this redirect URL so we don't wind up in a loop.
|
||||
*
|
||||
* Store the non-canonicalized version of the URL. The canonicalized
|
||||
* version is insufficient for loop detection because we might not get
|
||||
* an exact match against URLs used by the RA protocol-layer (the URL
|
||||
* used by the protocol may contain trailing slashes, for example,
|
||||
* which are stripped during canonicalization).
|
||||
*/
|
||||
svn_hash_sets(attempted, redirect_url, (void *)1);
|
||||
|
||||
/* Remember this CORRECTED_URL so we don't wind up in a loop. */
|
||||
svn_hash_sets(attempted, corrected, (void *)1);
|
||||
base_url = corrected;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(svn_ra_open4(ra_session, NULL, base_url,
|
||||
SVN_ERR(svn_ra_open5(ra_session, NULL, NULL, base_url,
|
||||
uuid, cbtable, cb, ctx->config, result_pool));
|
||||
}
|
||||
|
||||
|
@ -51,6 +51,7 @@
|
||||
#include "private/svn_subr_private.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
#include "private/svn_editor.h"
|
||||
#include "private/svn_sorts_private.h"
|
||||
|
||||
/* Overall crawler editor baton. */
|
||||
struct edit_baton {
|
||||
@ -380,10 +381,10 @@ get_file_from_ra(struct file_baton *fb,
|
||||
way. Hence this little hack: We populate FILE_BATON->PROPCHANGES only
|
||||
with *actual* property changes.
|
||||
|
||||
See http://subversion.tigris.org/issues/show_bug.cgi?id=3657#desc9 and
|
||||
See https://issues.apache.org/jira/browse/SVN-3657#desc9 and
|
||||
http://svn.haxx.se/dev/archive-2010-08/0351.shtml for more details.
|
||||
*/
|
||||
static void
|
||||
static svn_error_t *
|
||||
remove_non_prop_changes(apr_hash_t *pristine_props,
|
||||
apr_array_header_t *changes)
|
||||
{
|
||||
@ -391,7 +392,7 @@ remove_non_prop_changes(apr_hash_t *pristine_props,
|
||||
|
||||
/* For added nodes, there is nothing to filter. */
|
||||
if (apr_hash_count(pristine_props) == 0)
|
||||
return;
|
||||
return SVN_NO_ERROR;
|
||||
|
||||
for (i = 0; i < changes->nelts; i++)
|
||||
{
|
||||
@ -404,18 +405,13 @@ remove_non_prop_changes(apr_hash_t *pristine_props,
|
||||
|
||||
if (old_val && svn_string_compare(old_val, change->value))
|
||||
{
|
||||
int j;
|
||||
|
||||
/* Remove the matching change by shifting the rest */
|
||||
for (j = i; j < changes->nelts - 1; j++)
|
||||
{
|
||||
APR_ARRAY_IDX(changes, j, svn_prop_t)
|
||||
= APR_ARRAY_IDX(changes, j+1, svn_prop_t);
|
||||
}
|
||||
changes->nelts--;
|
||||
/* Remove the matching change and re-check the current index */
|
||||
SVN_ERR(svn_sort__array_delete2(changes, i, 1));
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Get the empty file associated with the edit baton. This is cached so
|
||||
@ -1015,7 +1011,7 @@ close_file(void *file_baton,
|
||||
}
|
||||
|
||||
if (fb->pristine_props)
|
||||
remove_non_prop_changes(fb->pristine_props, fb->propchanges);
|
||||
SVN_ERR(remove_non_prop_changes(fb->pristine_props, fb->propchanges));
|
||||
|
||||
right_props = svn_prop__patch(fb->pristine_props, fb->propchanges,
|
||||
fb->pool);
|
||||
@ -1088,7 +1084,7 @@ close_directory(void *dir_baton,
|
||||
|
||||
if (db->propchanges->nelts > 0)
|
||||
{
|
||||
remove_non_prop_changes(pristine_props, db->propchanges);
|
||||
SVN_ERR(remove_non_prop_changes(pristine_props, db->propchanges));
|
||||
}
|
||||
|
||||
if (db->propchanges->nelts > 0 || db->added)
|
||||
|
@ -51,42 +51,32 @@ struct revert_with_write_lock_baton {
|
||||
const apr_array_header_t *changelists;
|
||||
svn_boolean_t clear_changelists;
|
||||
svn_boolean_t metadata_only;
|
||||
svn_boolean_t added_keep_local;
|
||||
svn_client_ctx_t *ctx;
|
||||
};
|
||||
|
||||
/* (Note: All arguments are in the baton above.)
|
||||
|
||||
Attempt to revert LOCAL_ABSPATH.
|
||||
Attempt to revert LOCAL_ABSPATH by calling svn_wc_revert6(), which
|
||||
see for further details.
|
||||
|
||||
If DEPTH is svn_depth_empty, revert just the properties on the
|
||||
directory; else if svn_depth_files, revert the properties and any
|
||||
files immediately under the directory; else if
|
||||
svn_depth_immediates, revert all of the preceding plus properties
|
||||
on immediate subdirectories; else if svn_depth_infinity, revert
|
||||
path and everything under it fully recursively.
|
||||
|
||||
CHANGELISTS is an array of const char * changelist names, used as a
|
||||
restrictive filter on items reverted; that is, don't revert any
|
||||
item unless it's a member of one of those changelists. If
|
||||
CHANGELISTS is empty (or altogether NULL), no changelist filtering occurs.
|
||||
|
||||
Consult CTX to determine whether or not to revert timestamp to the
|
||||
time of last commit ('use-commit-times = yes').
|
||||
|
||||
If PATH is unversioned, return SVN_ERR_UNVERSIONED_RESOURCE. */
|
||||
If the target isn't versioned, send a 'skip' notification and return
|
||||
no error.
|
||||
*/
|
||||
static svn_error_t *
|
||||
revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct revert_with_write_lock_baton *b = baton;
|
||||
svn_error_t *err;
|
||||
|
||||
err = svn_wc_revert5(b->ctx->wc_ctx,
|
||||
err = svn_wc_revert6(b->ctx->wc_ctx,
|
||||
b->local_abspath,
|
||||
b->depth,
|
||||
b->use_commit_times,
|
||||
b->changelists,
|
||||
b->clear_changelists,
|
||||
b->metadata_only,
|
||||
b->added_keep_local,
|
||||
b->ctx->cancel_func, b->ctx->cancel_baton,
|
||||
b->ctx->notify_func2, b->ctx->notify_baton2,
|
||||
scratch_pool);
|
||||
@ -123,11 +113,12 @@ revert(void *baton, apr_pool_t *result_pool, apr_pool_t *scratch_pool)
|
||||
|
||||
|
||||
svn_error_t *
|
||||
svn_client_revert3(const apr_array_header_t *paths,
|
||||
svn_client_revert4(const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_boolean_t clear_changelists,
|
||||
svn_boolean_t metadata_only,
|
||||
svn_boolean_t added_keep_local,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
@ -183,6 +174,7 @@ svn_client_revert3(const apr_array_header_t *paths,
|
||||
baton.changelists = changelists;
|
||||
baton.clear_changelists = clear_changelists;
|
||||
baton.metadata_only = metadata_only;
|
||||
baton.added_keep_local = added_keep_local;
|
||||
baton.ctx = ctx;
|
||||
|
||||
err = svn_wc__is_wcroot(&wc_root, ctx->wc_ctx, local_abspath, iterpool);
|
||||
|
@ -146,7 +146,14 @@ svn_client__get_revision_number(svn_revnum_t *revnum,
|
||||
scratch_pool));
|
||||
|
||||
if (revision->kind == svn_opt_revision_previous)
|
||||
(*revnum)--;
|
||||
{
|
||||
if (*revnum == 0)
|
||||
return svn_error_createf(
|
||||
SVN_ERR_CLIENT_BAD_REVISION, NULL,
|
||||
_("Path '%s' has no previous revision"),
|
||||
svn_dirent_local_style(local_abspath, scratch_pool));
|
||||
--(*revnum);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
|
1274
subversion/libsvn_client/shelf.c
Normal file
1274
subversion/libsvn_client/shelf.c
Normal file
File diff suppressed because it is too large
Load Diff
2124
subversion/libsvn_client/shelf2.c
Normal file
2124
subversion/libsvn_client/shelf2.c
Normal file
File diff suppressed because it is too large
Load Diff
@ -1,552 +0,0 @@
|
||||
/*
|
||||
* shelve.c: implementation of the 'shelve' commands
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
/* We define this here to remove any further warnings about the usage of
|
||||
experimental functions in this file. */
|
||||
#define SVN_EXPERIMENTAL
|
||||
|
||||
#include "svn_client.h"
|
||||
#include "svn_wc.h"
|
||||
#include "svn_pools.h"
|
||||
#include "svn_dirent_uri.h"
|
||||
#include "svn_path.h"
|
||||
#include "svn_hash.h"
|
||||
#include "svn_utf.h"
|
||||
#include "svn_ctype.h"
|
||||
|
||||
#include "client.h"
|
||||
#include "private/svn_client_private.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
#include "svn_private_config.h"
|
||||
|
||||
|
||||
static svn_error_t *
|
||||
shelf_name_encode(char **encoded_name_p,
|
||||
const char *name,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
char *encoded_name
|
||||
= apr_palloc(result_pool, strlen(name) * 2 + 1);
|
||||
char *out_pos = encoded_name;
|
||||
|
||||
if (name[0] == '\0')
|
||||
return svn_error_create(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
|
||||
_("Shelf name cannot be the empty string"));
|
||||
|
||||
while (*name)
|
||||
{
|
||||
apr_snprintf(out_pos, 3, "%02x", (unsigned char)(*name++));
|
||||
out_pos += 2;
|
||||
}
|
||||
*encoded_name_p = encoded_name;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
shelf_name_decode(char **decoded_name_p,
|
||||
const char *codename,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
svn_stringbuf_t *sb
|
||||
= svn_stringbuf_create_ensure(strlen(codename) / 2, result_pool);
|
||||
const char *input = codename;
|
||||
|
||||
while (*input)
|
||||
{
|
||||
int c;
|
||||
int nchars;
|
||||
int nitems = sscanf(input, "%02x%n", &c, &nchars);
|
||||
|
||||
if (nitems != 1 || nchars != 2)
|
||||
return svn_error_createf(SVN_ERR_BAD_CHANGELIST_NAME, NULL,
|
||||
_("Shelve: Bad encoded name '%s'"), codename);
|
||||
svn_stringbuf_appendbyte(sb, c);
|
||||
input += 2;
|
||||
}
|
||||
*decoded_name_p = sb->data;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Set *NAME to the shelf name from FILENAME. */
|
||||
static svn_error_t *
|
||||
shelf_name_from_filename(char **name,
|
||||
const char *filename,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
size_t len = strlen(filename);
|
||||
|
||||
if (len > 6 && strcmp(filename + len - 6, ".patch") == 0)
|
||||
{
|
||||
char *codename = apr_pstrndup(result_pool, filename, len - 6);
|
||||
SVN_ERR(shelf_name_decode(name, codename, result_pool));
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Set *PATCH_ABSPATH to the abspath of the patch file for shelved change
|
||||
* NAME, no matter whether it exists.
|
||||
*/
|
||||
static svn_error_t *
|
||||
get_patch_abspath(char **patch_abspath,
|
||||
const char *name,
|
||||
const char *wc_root_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
char *dir;
|
||||
char *filename;
|
||||
|
||||
SVN_ERR(svn_wc__get_shelves_dir(&dir, ctx->wc_ctx, wc_root_abspath,
|
||||
scratch_pool, scratch_pool));
|
||||
SVN_ERR(shelf_name_encode(&filename, name, scratch_pool));
|
||||
filename = apr_pstrcat(scratch_pool, filename, ".patch", SVN_VA_NULL);
|
||||
*patch_abspath = svn_dirent_join(dir, filename, result_pool);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/** Write local changes to a patch file for shelved change @a name.
|
||||
*
|
||||
* @a message: An optional log message.
|
||||
*
|
||||
* @a wc_root_abspath: The WC root dir.
|
||||
*
|
||||
* @a overwrite_existing: If a file at @a patch_abspath exists, overwrite it.
|
||||
*
|
||||
* @a paths, @a depth, @a changelists: The selection of local paths to diff.
|
||||
*/
|
||||
static svn_error_t *
|
||||
shelf_write_patch(const char *name,
|
||||
const char *message,
|
||||
const char *wc_root_abspath,
|
||||
svn_boolean_t overwrite_existing,
|
||||
const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
char *patch_abspath;
|
||||
apr_int32_t flag;
|
||||
apr_file_t *outfile;
|
||||
svn_stream_t *outstream;
|
||||
svn_stream_t *errstream;
|
||||
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
|
||||
int i;
|
||||
svn_opt_revision_t peg_revision = {svn_opt_revision_unspecified, {0}};
|
||||
svn_opt_revision_t start_revision = {svn_opt_revision_base, {0}};
|
||||
svn_opt_revision_t end_revision = {svn_opt_revision_working, {0}};
|
||||
|
||||
SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
|
||||
/* Get streams for the output and any error output of the diff. */
|
||||
/* ### svn_stream_open_writable() doesn't work here: the buffering
|
||||
goes wrong so that diff headers appear after their hunks.
|
||||
For now, fix by opening the file without APR_BUFFERED. */
|
||||
flag = APR_FOPEN_WRITE | APR_FOPEN_CREATE | APR_FOPEN_TRUNCATE;
|
||||
if (! overwrite_existing)
|
||||
flag |= APR_FOPEN_EXCL;
|
||||
SVN_ERR(svn_io_file_open(&outfile, patch_abspath,
|
||||
flag, APR_FPROT_OS_DEFAULT, scratch_pool));
|
||||
outstream = svn_stream_from_aprfile2(outfile, FALSE /*disown*/, scratch_pool);
|
||||
SVN_ERR(svn_stream_for_stderr(&errstream, scratch_pool));
|
||||
|
||||
/* Write the patch file header (log message, etc.) */
|
||||
if (message)
|
||||
{
|
||||
SVN_ERR(svn_stream_printf(outstream, scratch_pool, "%s\n",
|
||||
message));
|
||||
}
|
||||
SVN_ERR(svn_stream_printf(outstream, scratch_pool,
|
||||
"--This line, and those below, will be ignored--\n\n"));
|
||||
SVN_ERR(svn_stream_printf(outstream, scratch_pool,
|
||||
"--This patch was generated by 'svn shelve'--\n\n"));
|
||||
|
||||
for (i = 0; i < paths->nelts; i++)
|
||||
{
|
||||
const char *path = APR_ARRAY_IDX(paths, i, const char *);
|
||||
|
||||
if (svn_path_is_url(path))
|
||||
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
|
||||
_("'%s' is not a local path"), path);
|
||||
SVN_ERR(svn_dirent_get_absolute(&path, path, scratch_pool));
|
||||
|
||||
SVN_ERR(svn_client_diff_peg6(
|
||||
NULL /*options*/,
|
||||
path,
|
||||
&peg_revision,
|
||||
&start_revision,
|
||||
&end_revision,
|
||||
wc_root_abspath,
|
||||
depth,
|
||||
TRUE /*notice_ancestry*/,
|
||||
FALSE /*no_diff_added*/,
|
||||
FALSE /*no_diff_deleted*/,
|
||||
TRUE /*show_copies_as_adds*/,
|
||||
FALSE /*ignore_content_type: FALSE -> omit binary files*/,
|
||||
FALSE /*ignore_properties*/,
|
||||
FALSE /*properties_only*/,
|
||||
FALSE /*use_git_diff_format*/,
|
||||
SVN_APR_LOCALE_CHARSET,
|
||||
outstream,
|
||||
errstream,
|
||||
changelists,
|
||||
ctx, iterpool));
|
||||
}
|
||||
SVN_ERR(svn_stream_close(outstream));
|
||||
SVN_ERR(svn_stream_close(errstream));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/** Apply the patch file for shelved change @a name to the WC.
|
||||
*
|
||||
* @a wc_root_abspath: The WC root dir.
|
||||
*
|
||||
* @a reverse: Apply the patch in reverse.
|
||||
*
|
||||
* @a dry_run: Don't really apply the changes, just notify what would be done.
|
||||
*/
|
||||
static svn_error_t *
|
||||
shelf_apply_patch(const char *name,
|
||||
const char *wc_root_abspath,
|
||||
svn_boolean_t reverse,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
char *patch_abspath;
|
||||
|
||||
SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_client_patch(patch_abspath, wc_root_abspath,
|
||||
dry_run, 0 /*strip*/,
|
||||
reverse,
|
||||
FALSE /*ignore_whitespace*/,
|
||||
TRUE /*remove_tempfiles*/, NULL, NULL,
|
||||
ctx, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/** Delete the patch file for shelved change @a name.
|
||||
*
|
||||
* @a wc_root_abspath: The WC root dir.
|
||||
*/
|
||||
static svn_error_t *
|
||||
shelf_delete_patch(const char *name,
|
||||
const char *wc_root_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
char *patch_abspath, *to_abspath;
|
||||
|
||||
SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
to_abspath = apr_pstrcat(scratch_pool, patch_abspath, ".bak", SVN_VA_NULL);
|
||||
|
||||
/* remove any previous backup */
|
||||
SVN_ERR(svn_io_remove_file2(to_abspath, TRUE /*ignore_enoent*/,
|
||||
scratch_pool));
|
||||
|
||||
/* move the patch to a backup file */
|
||||
SVN_ERR(svn_io_file_rename2(patch_abspath, to_abspath, FALSE /*flush_to_disk*/,
|
||||
scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelve(const char *name,
|
||||
const apr_array_header_t *paths,
|
||||
svn_depth_t depth,
|
||||
const apr_array_header_t *changelists,
|
||||
svn_boolean_t keep_local,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const char *local_abspath;
|
||||
const char *wc_root_abspath;
|
||||
const char *message = "";
|
||||
svn_error_t *err;
|
||||
|
||||
/* ### TODO: check all paths are in same WC; for now use first path */
|
||||
SVN_ERR(svn_dirent_get_absolute(&local_abspath,
|
||||
APR_ARRAY_IDX(paths, 0, char *), pool));
|
||||
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
|
||||
local_abspath, ctx, pool, pool));
|
||||
|
||||
/* Fetch the log message and any other revprops */
|
||||
if (SVN_CLIENT__HAS_LOG_MSG_FUNC(ctx))
|
||||
{
|
||||
const char *tmp_file;
|
||||
apr_array_header_t *commit_items = apr_array_make(pool, 1, sizeof(void *));
|
||||
|
||||
SVN_ERR(svn_client__get_log_msg(&message, &tmp_file, commit_items,
|
||||
ctx, pool));
|
||||
if (! message)
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
err = shelf_write_patch(name, message, wc_root_abspath,
|
||||
FALSE /*overwrite_existing*/,
|
||||
paths, depth, changelists,
|
||||
ctx, pool);
|
||||
if (err && APR_STATUS_IS_EEXIST(err->apr_err))
|
||||
{
|
||||
return svn_error_quick_wrapf(err,
|
||||
"Shelved change '%s' already exists",
|
||||
name);
|
||||
}
|
||||
else
|
||||
SVN_ERR(err);
|
||||
|
||||
if (!keep_local)
|
||||
{
|
||||
/* Reverse-apply the patch. This should be a safer way to remove those
|
||||
changes from the WC than running a 'revert' operation. */
|
||||
SVN_ERR(shelf_apply_patch(name, wc_root_abspath,
|
||||
TRUE /*reverse*/, dry_run,
|
||||
ctx, pool));
|
||||
}
|
||||
|
||||
if (dry_run)
|
||||
{
|
||||
SVN_ERR(shelf_delete_patch(name, wc_root_abspath,
|
||||
ctx, pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_unshelve(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t keep,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const char *wc_root_abspath;
|
||||
svn_error_t *err;
|
||||
|
||||
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
|
||||
local_abspath, ctx, pool, pool));
|
||||
|
||||
/* Apply the patch. */
|
||||
err = shelf_apply_patch(name, wc_root_abspath,
|
||||
FALSE /*reverse*/, dry_run,
|
||||
ctx, pool);
|
||||
if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
|
||||
{
|
||||
return svn_error_quick_wrapf(err,
|
||||
"Shelved change '%s' not found",
|
||||
name);
|
||||
}
|
||||
else
|
||||
SVN_ERR(err);
|
||||
|
||||
/* Remove the patch. */
|
||||
if (! keep && ! dry_run)
|
||||
{
|
||||
SVN_ERR(shelf_delete_patch(name, wc_root_abspath,
|
||||
ctx, pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelves_delete(const char *name,
|
||||
const char *local_abspath,
|
||||
svn_boolean_t dry_run,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
const char *wc_root_abspath;
|
||||
|
||||
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
|
||||
local_abspath, ctx, pool, pool));
|
||||
|
||||
/* Remove the patch. */
|
||||
if (! dry_run)
|
||||
{
|
||||
svn_error_t *err;
|
||||
|
||||
err = shelf_delete_patch(name, wc_root_abspath,
|
||||
ctx, pool);
|
||||
if (err && APR_STATUS_IS_ENOENT(err->apr_err))
|
||||
{
|
||||
return svn_error_quick_wrapf(err,
|
||||
"Shelved change '%s' not found",
|
||||
name);
|
||||
}
|
||||
else
|
||||
SVN_ERR(err);
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelf_get_paths(apr_hash_t **affected_paths,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *wc_root_abspath;
|
||||
char *patch_abspath;
|
||||
svn_patch_file_t *patch_file;
|
||||
apr_pool_t *iterpool = svn_pool_create(scratch_pool);
|
||||
apr_hash_t *paths = apr_hash_make(result_pool);
|
||||
|
||||
SVN_ERR(svn_client_get_wc_root(&wc_root_abspath,
|
||||
local_abspath, ctx, scratch_pool, scratch_pool));
|
||||
SVN_ERR(get_patch_abspath(&patch_abspath, name, wc_root_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_diff_open_patch_file(&patch_file, patch_abspath, result_pool));
|
||||
|
||||
while (1)
|
||||
{
|
||||
svn_patch_t *patch;
|
||||
|
||||
svn_pool_clear(iterpool);
|
||||
SVN_ERR(svn_diff_parse_next_patch(&patch, patch_file,
|
||||
FALSE /*reverse*/,
|
||||
FALSE /*ignore_whitespace*/,
|
||||
iterpool, iterpool));
|
||||
if (! patch)
|
||||
break;
|
||||
svn_hash_sets(paths,
|
||||
apr_pstrdup(result_pool, patch->old_filename),
|
||||
apr_pstrdup(result_pool, patch->new_filename));
|
||||
}
|
||||
SVN_ERR(svn_diff_close_patch_file(patch_file, iterpool));
|
||||
svn_pool_destroy(iterpool);
|
||||
|
||||
*affected_paths = paths;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelf_has_changes(svn_boolean_t *has_changes,
|
||||
const char *name,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
apr_hash_t *patch_paths;
|
||||
|
||||
SVN_ERR(svn_client_shelf_get_paths(&patch_paths, name, local_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
*has_changes = (apr_hash_count(patch_paths) != 0);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Set *LOGMSG to the log message stored in the file PATCH_ABSPATH.
|
||||
*
|
||||
* ### Currently just reads the first line.
|
||||
*/
|
||||
static svn_error_t *
|
||||
read_logmsg_from_patch(const char **logmsg,
|
||||
const char *patch_abspath,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
apr_file_t *file;
|
||||
svn_stream_t *stream;
|
||||
svn_boolean_t eof;
|
||||
svn_stringbuf_t *line;
|
||||
|
||||
SVN_ERR(svn_io_file_open(&file, patch_abspath,
|
||||
APR_FOPEN_READ, APR_FPROT_OS_DEFAULT, scratch_pool));
|
||||
stream = svn_stream_from_aprfile2(file, FALSE /*disown*/, scratch_pool);
|
||||
SVN_ERR(svn_stream_readline(stream, &line, "\n", &eof, result_pool));
|
||||
SVN_ERR(svn_stream_close(stream));
|
||||
*logmsg = line->data;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelves_list(apr_hash_t **shelved_patch_infos,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
char *shelves_dir;
|
||||
apr_hash_t *dirents;
|
||||
apr_hash_index_t *hi;
|
||||
|
||||
SVN_ERR(svn_wc__get_shelves_dir(&shelves_dir, ctx->wc_ctx, local_abspath,
|
||||
scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_io_get_dirents3(&dirents, shelves_dir, FALSE /*only_check_type*/,
|
||||
result_pool, scratch_pool));
|
||||
|
||||
*shelved_patch_infos = apr_hash_make(result_pool);
|
||||
|
||||
/* Remove non-shelves */
|
||||
for (hi = apr_hash_first(scratch_pool, dirents); hi; hi = apr_hash_next(hi))
|
||||
{
|
||||
const char *filename = apr_hash_this_key(hi);
|
||||
svn_io_dirent2_t *dirent = apr_hash_this_val(hi);
|
||||
char *name = NULL;
|
||||
|
||||
svn_error_clear(shelf_name_from_filename(&name, filename, result_pool));
|
||||
if (name && dirent->kind == svn_node_file)
|
||||
{
|
||||
svn_client_shelved_patch_info_t *info
|
||||
= apr_palloc(result_pool, sizeof(*info));
|
||||
|
||||
info->dirent = dirent;
|
||||
info->mtime = info->dirent->mtime;
|
||||
info->patch_path
|
||||
= svn_dirent_join(shelves_dir, filename, result_pool);
|
||||
SVN_ERR(read_logmsg_from_patch(&info->message, info->patch_path,
|
||||
result_pool, scratch_pool));
|
||||
|
||||
svn_hash_sets(*shelved_patch_infos, name, info);
|
||||
}
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client_shelves_any(svn_boolean_t *any_shelved,
|
||||
const char *local_abspath,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
apr_hash_t *shelved_patch_infos;
|
||||
|
||||
SVN_ERR(svn_client_shelves_list(&shelved_patch_infos, local_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
*any_shelved = apr_hash_count(shelved_patch_infos) != 0;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
@ -23,6 +23,9 @@
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
/* We define this here to remove any further warnings about the usage of
|
||||
experimental functions in this file. */
|
||||
#define SVN_EXPERIMENTAL
|
||||
|
||||
|
||||
/*** Includes. ***/
|
||||
@ -41,6 +44,7 @@
|
||||
#include "svn_error.h"
|
||||
#include "svn_hash.h"
|
||||
|
||||
#include "private/svn_client_shelf.h"
|
||||
#include "private/svn_client_private.h"
|
||||
#include "private/svn_sorts_private.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
@ -329,6 +333,79 @@ do_external_status(svn_client_ctx_t *ctx,
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Run status on shelf SHELF_NAME, if it exists.
|
||||
*/
|
||||
static svn_error_t *
|
||||
shelf_status(const char *shelf_name,
|
||||
const char *target_abspath,
|
||||
svn_wc_status_func4_t status_func,
|
||||
void *status_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
svn_error_t *err;
|
||||
svn_client__shelf_t *shelf;
|
||||
svn_client__shelf_version_t *shelf_version;
|
||||
const char *wc_relpath;
|
||||
|
||||
err = svn_client__shelf_open_existing(&shelf,
|
||||
shelf_name, target_abspath,
|
||||
ctx, scratch_pool);
|
||||
if (err && err->apr_err == SVN_ERR_ILLEGAL_TARGET)
|
||||
{
|
||||
svn_error_clear(err);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
else
|
||||
SVN_ERR(err);
|
||||
|
||||
SVN_ERR(svn_client__shelf_version_open(&shelf_version,
|
||||
shelf, shelf->max_version,
|
||||
scratch_pool, scratch_pool));
|
||||
wc_relpath = svn_dirent_skip_ancestor(shelf->wc_root_abspath, target_abspath);
|
||||
SVN_ERR(svn_client__shelf_version_status_walk(shelf_version, wc_relpath,
|
||||
status_func, status_baton,
|
||||
scratch_pool));
|
||||
SVN_ERR(svn_client__shelf_close(shelf, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Run status on all shelves named in CHANGELISTS by a changelist name
|
||||
* of the form "svn:shelf:SHELF_NAME", if they exist.
|
||||
*/
|
||||
static svn_error_t *
|
||||
shelves_status(const apr_array_header_t *changelists,
|
||||
const char *target_abspath,
|
||||
svn_wc_status_func4_t status_func,
|
||||
void *status_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
static const char PREFIX[] = "svn:shelf:";
|
||||
static const int PREFIX_LEN = 10;
|
||||
int i;
|
||||
|
||||
if (! changelists)
|
||||
return SVN_NO_ERROR;
|
||||
for (i = 0; i < changelists->nelts; i++)
|
||||
{
|
||||
const char *cl = APR_ARRAY_IDX(changelists, i, const char *);
|
||||
|
||||
if (strncmp(cl, PREFIX, PREFIX_LEN) == 0)
|
||||
{
|
||||
const char *shelf_name = cl + PREFIX_LEN;
|
||||
|
||||
SVN_ERR(shelf_status(shelf_name, target_abspath,
|
||||
status_func, status_baton,
|
||||
ctx, scratch_pool));
|
||||
}
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/*** Public Interface. ***/
|
||||
|
||||
@ -586,6 +663,9 @@ svn_client_status6(svn_revnum_t *result_rev,
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(shelves_status(changelists, target_abspath,
|
||||
tweak_status, &sb,
|
||||
ctx, pool));
|
||||
err = svn_wc_walk_status(ctx->wc_ctx, target_abspath,
|
||||
depth, get_all, no_ignore, FALSE, ignores,
|
||||
tweak_status, &sb,
|
||||
|
@ -615,7 +615,7 @@ svn_client__update_internal(svn_revnum_t *result_rev,
|
||||
{
|
||||
const char *anchor_abspath, *lockroot_abspath;
|
||||
svn_error_t *err;
|
||||
svn_opt_revision_t peg_revision = *revision;
|
||||
svn_opt_revision_t opt_rev = *revision; /* operative revision */
|
||||
apr_hash_t *conflicted_paths
|
||||
= ctx->conflict_func2 ? apr_hash_make(pool) : NULL;
|
||||
|
||||
@ -668,7 +668,7 @@ svn_client__update_internal(svn_revnum_t *result_rev,
|
||||
|
||||
err = update_internal(result_rev, timestamp_sleep, conflicted_paths,
|
||||
&ra_session, missing_parent,
|
||||
anchor_abspath, &peg_revision, svn_depth_empty,
|
||||
anchor_abspath, &opt_rev, svn_depth_empty,
|
||||
FALSE, ignore_externals,
|
||||
allow_unver_obstructions, adds_as_modification,
|
||||
FALSE, ctx, pool, iterpool);
|
||||
@ -679,8 +679,8 @@ svn_client__update_internal(svn_revnum_t *result_rev,
|
||||
/* If we successfully updated a missing parent, let's re-use
|
||||
the returned revision number for future updates for the
|
||||
sake of consistency. */
|
||||
peg_revision.kind = svn_opt_revision_number;
|
||||
peg_revision.value.number = *result_rev;
|
||||
opt_rev.kind = svn_opt_revision_number;
|
||||
opt_rev.value.number = *result_rev;
|
||||
}
|
||||
|
||||
svn_pool_destroy(iterpool);
|
||||
@ -696,7 +696,7 @@ svn_client__update_internal(svn_revnum_t *result_rev,
|
||||
err = update_internal(result_rev, timestamp_sleep, conflicted_paths,
|
||||
&ra_session,
|
||||
local_abspath, anchor_abspath,
|
||||
&peg_revision, depth, depth_is_sticky,
|
||||
&opt_rev, depth, depth_is_sticky,
|
||||
ignore_externals, allow_unver_obstructions,
|
||||
adds_as_modification,
|
||||
TRUE, ctx, pool, pool);
|
||||
|
@ -303,7 +303,7 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
|
||||
{
|
||||
apr_hash_index_t *hi;
|
||||
apr_pool_t *iterpool;
|
||||
apr_pool_t *iterpool2;
|
||||
apr_pool_t *inner_iterpool;
|
||||
apr_hash_t *externals;
|
||||
svn_opt_revision_t rev = {svn_opt_revision_unspecified, {0}};
|
||||
|
||||
@ -317,7 +317,7 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
|
||||
scratch_pool, scratch_pool));
|
||||
|
||||
iterpool = svn_pool_create(scratch_pool);
|
||||
iterpool2 = svn_pool_create(scratch_pool);
|
||||
inner_iterpool = svn_pool_create(scratch_pool);
|
||||
|
||||
for (hi = apr_hash_first(scratch_pool, externals); hi;
|
||||
hi = apr_hash_next(hi))
|
||||
@ -351,14 +351,12 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
|
||||
iterpool, iterpool);
|
||||
|
||||
if (!err)
|
||||
externals_parent_url = svn_path_url_add_component2(
|
||||
externals_parent_repos_root_url,
|
||||
externals_parent_repos_relpath,
|
||||
iterpool);
|
||||
if (!err)
|
||||
{
|
||||
err = svn_wc_parse_externals_description3(
|
||||
&externals_p, svn_dirent_dirname(local_abspath, iterpool),
|
||||
external_desc->data, FALSE, iterpool);
|
||||
}
|
||||
|
||||
if (err)
|
||||
{
|
||||
svn_wc_notify_t *notify =
|
||||
@ -376,24 +374,29 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
|
||||
continue;
|
||||
}
|
||||
|
||||
externals_parent_url = svn_path_url_add_component2(
|
||||
externals_parent_repos_root_url,
|
||||
externals_parent_repos_relpath,
|
||||
iterpool);
|
||||
|
||||
for (i = 0; i < externals_p->nelts; i++)
|
||||
{
|
||||
svn_wc_external_item2_t *item;
|
||||
|
||||
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
|
||||
|
||||
svn_pool_clear(iterpool2);
|
||||
svn_pool_clear(inner_iterpool);
|
||||
err = upgrade_external_item(ctx, externals_parent_abspath,
|
||||
externals_parent_url,
|
||||
externals_parent_repos_root_url,
|
||||
item, info_baton, iterpool2);
|
||||
item, info_baton, inner_iterpool);
|
||||
|
||||
if (err)
|
||||
{
|
||||
svn_wc_notify_t *notify =
|
||||
svn_wc_create_notify(svn_dirent_join(externals_parent_abspath,
|
||||
item->target_dir,
|
||||
iterpool2),
|
||||
inner_iterpool),
|
||||
svn_wc_notify_failed_external,
|
||||
scratch_pool);
|
||||
notify->err = err;
|
||||
@ -405,8 +408,8 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
|
||||
}
|
||||
}
|
||||
|
||||
svn_pool_destroy(inner_iterpool);
|
||||
svn_pool_destroy(iterpool);
|
||||
svn_pool_destroy(iterpool2);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
@ -93,6 +93,7 @@ svn_client__pathrev_create_with_session(svn_client__pathrev_t **pathrev_p,
|
||||
pathrev->rev = rev;
|
||||
pathrev->url = apr_pstrdup(result_pool, url);
|
||||
*pathrev_p = pathrev;
|
||||
SVN_ERR_ASSERT(svn_uri__is_ancestor(pathrev->repos_root_url, url));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
|
655
subversion/libsvn_client/wc_editor.c
Normal file
655
subversion/libsvn_client/wc_editor.c
Normal file
@ -0,0 +1,655 @@
|
||||
/*
|
||||
* wc_editor.c: editing the local modifications in the WC.
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
|
||||
/* ==================================================================== */
|
||||
|
||||
/*** Includes. ***/
|
||||
|
||||
#include <string.h>
|
||||
#include "svn_hash.h"
|
||||
#include "svn_client.h"
|
||||
#include "svn_delta.h"
|
||||
#include "svn_dirent_uri.h"
|
||||
#include "svn_error.h"
|
||||
#include "svn_error_codes.h"
|
||||
#include "svn_pools.h"
|
||||
#include "svn_props.h"
|
||||
#include "svn_wc.h"
|
||||
|
||||
#include <apr_md5.h>
|
||||
|
||||
#include "client.h"
|
||||
#include "private/svn_subr_private.h"
|
||||
#include "private/svn_wc_private.h"
|
||||
#include "svn_private_config.h"
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/* WC Modifications Editor.
|
||||
*
|
||||
* This editor applies incoming modifications onto the current working state
|
||||
* of the working copy, to produce a new working state.
|
||||
*
|
||||
* Currently, it assumes the working state matches what the edit driver
|
||||
* expects to find, and may throw an error if not.
|
||||
*
|
||||
* For simplicity, we apply incoming edits as they arrive, rather than
|
||||
* queueing them up to apply in a batch.
|
||||
*
|
||||
* TODO:
|
||||
* - tests
|
||||
* - use for all existing scenarios ('svn add', 'svn propset', etc.)
|
||||
* - Instead of 'root_dir_add' option, probably the driver should anchor
|
||||
* at the parent dir.
|
||||
* - Instead of 'ignore_mergeinfo' option, implement that as a wrapper.
|
||||
* - Option to quietly accept changes that seem to be already applied
|
||||
* in the versioned state and/or on disk.
|
||||
* Consider 'svn add' which assumes items to be added are found on disk.
|
||||
* - Notification.
|
||||
*/
|
||||
|
||||
/* Everything we need to know about the edit session.
|
||||
*/
|
||||
struct edit_baton_t
|
||||
{
|
||||
const char *anchor_abspath;
|
||||
svn_boolean_t manage_wc_write_lock;
|
||||
const char *lock_root_abspath; /* the path locked, when locked */
|
||||
|
||||
/* True => 'open_root' method will act as 'add_directory' */
|
||||
svn_boolean_t root_dir_add;
|
||||
/* True => filter out any incoming svn:mergeinfo property changes */
|
||||
svn_boolean_t ignore_mergeinfo_changes;
|
||||
|
||||
svn_ra_session_t *ra_session;
|
||||
|
||||
svn_wc_context_t *wc_ctx;
|
||||
svn_client_ctx_t *ctx;
|
||||
svn_wc_notify_func2_t notify_func;
|
||||
void *notify_baton;
|
||||
};
|
||||
|
||||
/* Everything we need to know about a directory that's open for edits.
|
||||
*/
|
||||
struct dir_baton_t
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
|
||||
struct edit_baton_t *eb;
|
||||
|
||||
const char *local_abspath;
|
||||
};
|
||||
|
||||
/* Join PATH onto ANCHOR_ABSPATH.
|
||||
* Throw an error if the result is outside ANCHOR_ABSPATH.
|
||||
*/
|
||||
static svn_error_t *
|
||||
get_path(const char **local_abspath_p,
|
||||
const char *anchor_abspath,
|
||||
const char *path,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
svn_boolean_t under_root;
|
||||
|
||||
SVN_ERR(svn_dirent_is_under_root(&under_root, local_abspath_p,
|
||||
anchor_abspath, path, result_pool));
|
||||
if (! under_root)
|
||||
{
|
||||
return svn_error_createf(
|
||||
SVN_ERR_WC_OBSTRUCTED_UPDATE, NULL,
|
||||
_("Path '%s' is not in the working copy"),
|
||||
svn_dirent_local_style(path, result_pool));
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Create a directory on disk and add it to version control,
|
||||
* with no properties.
|
||||
*/
|
||||
static svn_error_t *
|
||||
mkdir(const char *abspath,
|
||||
struct edit_baton_t *eb,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
SVN_ERR(svn_io_make_dir_recursively(abspath, scratch_pool));
|
||||
SVN_ERR(svn_wc_add_from_disk3(eb->wc_ctx, abspath,
|
||||
NULL /*properties*/,
|
||||
TRUE /* skip checks */,
|
||||
eb->notify_func, eb->notify_baton,
|
||||
scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Prepare to open or add a directory: initialize a new dir baton.
|
||||
*
|
||||
* If PATH is "" and PB is null, it represents the root directory of
|
||||
* the edit; otherwise PATH is not "" and PB is not null.
|
||||
*/
|
||||
static svn_error_t *
|
||||
dir_open_or_add(struct dir_baton_t **child_dir_baton,
|
||||
const char *path,
|
||||
struct dir_baton_t *pb,
|
||||
struct edit_baton_t *eb,
|
||||
apr_pool_t *dir_pool)
|
||||
{
|
||||
struct dir_baton_t *db = apr_pcalloc(dir_pool, sizeof(*db));
|
||||
|
||||
db->pool = dir_pool;
|
||||
db->eb = eb;
|
||||
|
||||
SVN_ERR(get_path(&db->local_abspath,
|
||||
eb->anchor_abspath, path, dir_pool));
|
||||
|
||||
*child_dir_baton = db;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* */
|
||||
static svn_error_t *
|
||||
release_write_lock(struct edit_baton_t *eb,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
if (eb->lock_root_abspath)
|
||||
{
|
||||
SVN_ERR(svn_wc__release_write_lock(
|
||||
eb->ctx->wc_ctx, eb->lock_root_abspath, scratch_pool));
|
||||
eb->lock_root_abspath = NULL;
|
||||
}
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* */
|
||||
static apr_status_t
|
||||
pool_cleanup_handler(void *root_baton)
|
||||
{
|
||||
struct dir_baton_t *db = root_baton;
|
||||
struct edit_baton_t *eb = db->eb;
|
||||
|
||||
svn_error_clear(release_write_lock(eb, db->pool));
|
||||
return APR_SUCCESS;
|
||||
}
|
||||
|
||||
/* svn_delta_editor_t function */
|
||||
static svn_error_t *
|
||||
edit_open(void *edit_baton,
|
||||
svn_revnum_t base_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **root_baton)
|
||||
{
|
||||
struct edit_baton_t *eb = edit_baton;
|
||||
struct dir_baton_t *db;
|
||||
|
||||
SVN_ERR(dir_open_or_add(&db, "", NULL, eb, result_pool));
|
||||
|
||||
/* Acquire a WC write lock */
|
||||
if (eb->manage_wc_write_lock)
|
||||
{
|
||||
apr_pool_cleanup_register(db->pool, db,
|
||||
pool_cleanup_handler,
|
||||
apr_pool_cleanup_null);
|
||||
SVN_ERR(svn_wc__acquire_write_lock(&eb->lock_root_abspath,
|
||||
eb->ctx->wc_ctx,
|
||||
eb->anchor_abspath,
|
||||
FALSE /*lock_anchor*/,
|
||||
db->pool, db->pool));
|
||||
}
|
||||
|
||||
if (eb->root_dir_add)
|
||||
{
|
||||
SVN_ERR(mkdir(db->local_abspath, eb, result_pool));
|
||||
}
|
||||
|
||||
*root_baton = db;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* svn_delta_editor_t function */
|
||||
static svn_error_t *
|
||||
edit_close_or_abort(void *edit_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
SVN_ERR(release_write_lock(edit_baton, scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* */
|
||||
static svn_error_t *
|
||||
delete_entry(const char *path,
|
||||
svn_revnum_t revision,
|
||||
void *parent_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
const char *local_abspath;
|
||||
|
||||
SVN_ERR(get_path(&local_abspath,
|
||||
eb->anchor_abspath, path, scratch_pool));
|
||||
SVN_ERR(svn_wc_delete4(eb->wc_ctx, local_abspath,
|
||||
FALSE /*keep_local*/,
|
||||
TRUE /*delete_unversioned*/,
|
||||
NULL, NULL, /*cancellation*/
|
||||
eb->notify_func, eb->notify_baton, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* An svn_delta_editor_t function. */
|
||||
static svn_error_t *
|
||||
dir_open(const char *path,
|
||||
void *parent_baton,
|
||||
svn_revnum_t base_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **child_baton)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
struct dir_baton_t *db;
|
||||
|
||||
SVN_ERR(dir_open_or_add(&db, path, pb, eb, result_pool));
|
||||
|
||||
*child_baton = db;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_add(const char *path,
|
||||
void *parent_baton,
|
||||
const char *copyfrom_path,
|
||||
svn_revnum_t copyfrom_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **child_baton)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
struct dir_baton_t *db;
|
||||
/* ### Our caller should be providing a scratch pool */
|
||||
apr_pool_t *scratch_pool = svn_pool_create(result_pool);
|
||||
|
||||
SVN_ERR(dir_open_or_add(&db, path, pb, eb, result_pool));
|
||||
|
||||
if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_revision))
|
||||
{
|
||||
SVN_ERR(svn_client__repos_to_wc_copy_internal(NULL /*timestamp_sleep*/,
|
||||
svn_node_dir,
|
||||
copyfrom_path,
|
||||
copyfrom_revision,
|
||||
db->local_abspath,
|
||||
db->eb->ra_session,
|
||||
db->eb->ctx,
|
||||
scratch_pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(mkdir(db->local_abspath, eb, result_pool));
|
||||
}
|
||||
|
||||
*child_baton = db;
|
||||
svn_pool_destroy(scratch_pool);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_change_prop(void *dir_baton,
|
||||
const char *name,
|
||||
const svn_string_t *value,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct dir_baton_t *db = dir_baton;
|
||||
struct edit_baton_t *eb = db->eb;
|
||||
|
||||
if (svn_property_kind2(name) != svn_prop_regular_kind
|
||||
|| (eb->ignore_mergeinfo_changes && ! strcmp(name, SVN_PROP_MERGEINFO)))
|
||||
{
|
||||
/* We can't handle DAV, ENTRY and merge specific props here */
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
SVN_ERR(svn_wc_prop_set4(eb->wc_ctx, db->local_abspath, name, value,
|
||||
svn_depth_empty, FALSE, NULL,
|
||||
NULL, NULL, /* Cancellation */
|
||||
NULL, NULL, /* Notification */
|
||||
scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
dir_close(void *dir_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* Everything we need to know about a file that's open for edits.
|
||||
*/
|
||||
struct file_baton_t
|
||||
{
|
||||
apr_pool_t *pool;
|
||||
|
||||
struct edit_baton_t *eb;
|
||||
|
||||
const char *local_abspath;
|
||||
|
||||
/* fields for the transfer of text changes */
|
||||
const char *writing_file;
|
||||
unsigned char digest[APR_MD5_DIGESTSIZE]; /* MD5 digest of new fulltext */
|
||||
svn_stream_t *wc_file_read_stream, *tmp_file_write_stream;
|
||||
const char *tmp_path;
|
||||
};
|
||||
|
||||
/* Create a new file on disk and add it to version control.
|
||||
*
|
||||
* The file is empty and has no properties.
|
||||
*/
|
||||
static svn_error_t *
|
||||
mkfile(const char *abspath,
|
||||
struct edit_baton_t *eb,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
SVN_ERR(svn_io_file_create_empty(abspath, scratch_pool));
|
||||
SVN_ERR(svn_wc_add_from_disk3(eb->wc_ctx, abspath,
|
||||
NULL /*properties*/,
|
||||
TRUE /* skip checks */,
|
||||
eb->notify_func, eb->notify_baton,
|
||||
scratch_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
/* */
|
||||
static svn_error_t *
|
||||
file_open_or_add(const char *path,
|
||||
void *parent_baton,
|
||||
struct file_baton_t **file_baton,
|
||||
apr_pool_t *file_pool)
|
||||
{
|
||||
struct dir_baton_t *pb = parent_baton;
|
||||
struct edit_baton_t *eb = pb->eb;
|
||||
struct file_baton_t *fb = apr_pcalloc(file_pool, sizeof(*fb));
|
||||
|
||||
fb->pool = file_pool;
|
||||
fb->eb = eb;
|
||||
SVN_ERR(get_path(&fb->local_abspath,
|
||||
eb->anchor_abspath, path, fb->pool));
|
||||
|
||||
*file_baton = fb;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_open(const char *path,
|
||||
void *parent_baton,
|
||||
svn_revnum_t base_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **file_baton)
|
||||
{
|
||||
struct file_baton_t *fb;
|
||||
|
||||
SVN_ERR(file_open_or_add(path, parent_baton, &fb, result_pool));
|
||||
|
||||
*file_baton = fb;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_add(const char *path,
|
||||
void *parent_baton,
|
||||
const char *copyfrom_path,
|
||||
svn_revnum_t copyfrom_revision,
|
||||
apr_pool_t *result_pool,
|
||||
void **file_baton)
|
||||
{
|
||||
struct file_baton_t *fb;
|
||||
|
||||
SVN_ERR(file_open_or_add(path, parent_baton, &fb, result_pool));
|
||||
|
||||
if (copyfrom_path && SVN_IS_VALID_REVNUM(copyfrom_revision))
|
||||
{
|
||||
SVN_ERR(svn_client__repos_to_wc_copy_internal(NULL /*timestamp_sleep*/,
|
||||
svn_node_file,
|
||||
copyfrom_path,
|
||||
copyfrom_revision,
|
||||
fb->local_abspath,
|
||||
fb->eb->ra_session,
|
||||
fb->eb->ctx, fb->pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(mkfile(fb->local_abspath, fb->eb, result_pool));
|
||||
}
|
||||
|
||||
*file_baton = fb;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_change_prop(void *file_baton,
|
||||
const char *name,
|
||||
const svn_string_t *value,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
struct edit_baton_t *eb = fb->eb;
|
||||
|
||||
if (svn_property_kind2(name) != svn_prop_regular_kind
|
||||
|| (eb->ignore_mergeinfo_changes && ! strcmp(name, SVN_PROP_MERGEINFO)))
|
||||
{
|
||||
/* We can't handle DAV, ENTRY and merge specific props here */
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
SVN_ERR(svn_wc_prop_set4(eb->wc_ctx, fb->local_abspath, name, value,
|
||||
svn_depth_empty, FALSE, NULL,
|
||||
NULL, NULL, /* Cancellation */
|
||||
NULL, NULL, /* Notification */
|
||||
scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_textdelta(void *file_baton,
|
||||
const char *base_checksum,
|
||||
apr_pool_t *result_pool,
|
||||
svn_txdelta_window_handler_t *handler,
|
||||
void **handler_baton)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
const char *target_dir = svn_dirent_dirname(fb->local_abspath, fb->pool);
|
||||
svn_error_t *err;
|
||||
|
||||
SVN_ERR_ASSERT(! fb->writing_file);
|
||||
|
||||
err = svn_stream_open_readonly(&fb->wc_file_read_stream, fb->local_abspath,
|
||||
fb->pool, fb->pool);
|
||||
if (err && APR_STATUS_IS_ENOENT(err->apr_err))
|
||||
{
|
||||
svn_error_clear(err);
|
||||
fb->wc_file_read_stream = svn_stream_empty(fb->pool);
|
||||
}
|
||||
else
|
||||
SVN_ERR(err);
|
||||
|
||||
SVN_ERR(svn_stream_open_unique(&fb->tmp_file_write_stream, &fb->writing_file,
|
||||
target_dir, svn_io_file_del_none,
|
||||
fb->pool, fb->pool));
|
||||
|
||||
svn_txdelta_apply(fb->wc_file_read_stream,
|
||||
fb->tmp_file_write_stream,
|
||||
fb->digest,
|
||||
fb->local_abspath,
|
||||
fb->pool,
|
||||
/* Provide the handler directly */
|
||||
handler, handler_baton);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
file_close(void *file_baton,
|
||||
const char *text_checksum,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct file_baton_t *fb = file_baton;
|
||||
|
||||
/* If we have text changes, write them to disk */
|
||||
if (fb->writing_file)
|
||||
{
|
||||
SVN_ERR(svn_stream_close(fb->wc_file_read_stream));
|
||||
SVN_ERR(svn_io_file_rename2(fb->writing_file, fb->local_abspath,
|
||||
FALSE /*flush*/, scratch_pool));
|
||||
}
|
||||
|
||||
if (text_checksum)
|
||||
{
|
||||
svn_checksum_t *expected_checksum;
|
||||
svn_checksum_t *actual_checksum;
|
||||
|
||||
SVN_ERR(svn_checksum_parse_hex(&expected_checksum, svn_checksum_md5,
|
||||
text_checksum, fb->pool));
|
||||
actual_checksum = svn_checksum__from_digest_md5(fb->digest, fb->pool);
|
||||
|
||||
if (! svn_checksum_match(expected_checksum, actual_checksum))
|
||||
return svn_error_trace(
|
||||
svn_checksum_mismatch_err(expected_checksum,
|
||||
actual_checksum,
|
||||
fb->pool,
|
||||
_("Checksum mismatch for '%s'"),
|
||||
svn_dirent_local_style(
|
||||
fb->local_abspath,
|
||||
fb->pool)));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__wc_editor_internal(const svn_delta_editor_t **editor_p,
|
||||
void **edit_baton_p,
|
||||
const char *dst_abspath,
|
||||
svn_boolean_t root_dir_add,
|
||||
svn_boolean_t ignore_mergeinfo_changes,
|
||||
svn_boolean_t manage_wc_write_lock,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
svn_delta_editor_t *editor = svn_delta_default_editor(result_pool);
|
||||
struct edit_baton_t *eb = apr_pcalloc(result_pool, sizeof(*eb));
|
||||
|
||||
eb->anchor_abspath = apr_pstrdup(result_pool, dst_abspath);
|
||||
eb->manage_wc_write_lock = manage_wc_write_lock;
|
||||
eb->lock_root_abspath = NULL;
|
||||
eb->root_dir_add = root_dir_add;
|
||||
eb->ignore_mergeinfo_changes = ignore_mergeinfo_changes;
|
||||
|
||||
eb->ra_session = ra_session;
|
||||
eb->wc_ctx = ctx->wc_ctx;
|
||||
eb->ctx = ctx;
|
||||
eb->notify_func = notify_func;
|
||||
eb->notify_baton = notify_baton;
|
||||
|
||||
editor->open_root = edit_open;
|
||||
editor->close_edit = edit_close_or_abort;
|
||||
editor->abort_edit = edit_close_or_abort;
|
||||
|
||||
editor->delete_entry = delete_entry;
|
||||
|
||||
editor->open_directory = dir_open;
|
||||
editor->add_directory = dir_add;
|
||||
editor->change_dir_prop = dir_change_prop;
|
||||
editor->close_directory = dir_close;
|
||||
|
||||
editor->open_file = file_open;
|
||||
editor->add_file = file_add;
|
||||
editor->change_file_prop = file_change_prop;
|
||||
editor->apply_textdelta = file_textdelta;
|
||||
editor->close_file = file_close;
|
||||
|
||||
*editor_p = editor;
|
||||
*edit_baton_p = eb;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__wc_editor(const svn_delta_editor_t **editor_p,
|
||||
void **edit_baton_p,
|
||||
const char *dst_abspath,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_ra_session_t *ra_session,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
SVN_ERR(svn_client__wc_editor_internal(editor_p, edit_baton_p,
|
||||
dst_abspath,
|
||||
FALSE /*root_dir_add*/,
|
||||
FALSE /*ignore_mergeinfo_changes*/,
|
||||
TRUE /*manage_wc_write_lock*/,
|
||||
notify_func, notify_baton,
|
||||
ra_session,
|
||||
ctx, result_pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_client__wc_copy_mods(const char *src_wc_abspath,
|
||||
const char *dst_wc_abspath,
|
||||
svn_wc_notify_func2_t notify_func,
|
||||
void *notify_baton,
|
||||
svn_client_ctx_t *ctx,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
svn_client__pathrev_t *base;
|
||||
const char *dst_wc_url;
|
||||
svn_ra_session_t *ra_session;
|
||||
const svn_delta_editor_t *editor;
|
||||
void *edit_baton;
|
||||
apr_array_header_t *src_targets = apr_array_make(scratch_pool, 1,
|
||||
sizeof(char *));
|
||||
|
||||
/* We'll need an RA session to obtain the base of any copies */
|
||||
SVN_ERR(svn_client__wc_node_get_base(&base,
|
||||
src_wc_abspath, ctx->wc_ctx,
|
||||
scratch_pool, scratch_pool));
|
||||
dst_wc_url = base->url;
|
||||
SVN_ERR(svn_client_open_ra_session2(&ra_session,
|
||||
dst_wc_url, dst_wc_abspath,
|
||||
ctx, scratch_pool, scratch_pool));
|
||||
SVN_ERR(svn_client__wc_editor(&editor, &edit_baton,
|
||||
dst_wc_abspath,
|
||||
NULL, NULL, /*notification*/
|
||||
ra_session, ctx, scratch_pool));
|
||||
|
||||
APR_ARRAY_PUSH(src_targets, const char *) = src_wc_abspath;
|
||||
SVN_ERR(svn_client__wc_replay(src_wc_abspath,
|
||||
src_targets, svn_depth_infinity, NULL,
|
||||
editor, edit_baton,
|
||||
notify_func, notify_baton,
|
||||
ctx, scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
@ -157,7 +157,7 @@ branch_txn_delete_branch(svn_branch__txn_t *txn,
|
||||
|
||||
if (strcmp(b->bid, bid) == 0)
|
||||
{
|
||||
svn_sort__array_delete(txn->priv->branches, i, 1);
|
||||
SVN_ERR(svn_sort__array_delete2(txn->priv->branches, i, 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -875,6 +875,8 @@ drive_ev1_props(const char *repos_relpath,
|
||||
*/
|
||||
static svn_error_t *
|
||||
apply_change(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *ev1_relpath,
|
||||
@ -905,7 +907,7 @@ apply_change(void **dir_baton,
|
||||
/* Only property edits are allowed on the root. */
|
||||
SVN_ERR_ASSERT(change->action == RESTRUCTURE_NONE);
|
||||
SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
|
||||
eb->deditor, *dir_baton, scratch_pool));
|
||||
editor, *dir_baton, scratch_pool));
|
||||
|
||||
/* No further action possible for the root. */
|
||||
return SVN_NO_ERROR;
|
||||
@ -913,7 +915,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
if (change->action == RESTRUCTURE_DELETE)
|
||||
{
|
||||
SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev,
|
||||
SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev,
|
||||
parent_baton, scratch_pool));
|
||||
|
||||
/* No futher action possible for this node. */
|
||||
@ -927,10 +929,10 @@ apply_change(void **dir_baton,
|
||||
if (change->action == RESTRUCTURE_ADD_ABSENT)
|
||||
{
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->absent_directory(ev1_relpath, parent_baton,
|
||||
scratch_pool));
|
||||
else if (change->kind == svn_node_file)
|
||||
SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->absent_file(ev1_relpath, parent_baton,
|
||||
scratch_pool));
|
||||
else
|
||||
SVN_ERR_MALFUNCTION();
|
||||
@ -948,7 +950,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
/* Do we have an old node to delete first? If so, delete it. */
|
||||
if (change->deleting)
|
||||
SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting_rev,
|
||||
SVN_ERR(editor->delete_entry(ev1_relpath, change->deleting_rev,
|
||||
parent_baton, scratch_pool));
|
||||
|
||||
/* If it's a copy, determine the copy source location. */
|
||||
@ -974,11 +976,11 @@ apply_change(void **dir_baton,
|
||||
}
|
||||
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->add_directory(ev1_relpath, parent_baton,
|
||||
copyfrom_url, copyfrom_rev,
|
||||
result_pool, dir_baton));
|
||||
else if (change->kind == svn_node_file)
|
||||
SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->add_file(ev1_relpath, parent_baton,
|
||||
copyfrom_url, copyfrom_rev,
|
||||
result_pool, &file_baton));
|
||||
else
|
||||
@ -993,11 +995,11 @@ apply_change(void **dir_baton,
|
||||
when we fetch the base properties.) */
|
||||
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->open_directory(ev1_relpath, parent_baton,
|
||||
change->changing_rev,
|
||||
result_pool, dir_baton));
|
||||
else if (change->kind == svn_node_file)
|
||||
SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(editor->open_file(ev1_relpath, parent_baton,
|
||||
change->changing_rev,
|
||||
result_pool, &file_baton));
|
||||
else
|
||||
@ -1007,10 +1009,10 @@ apply_change(void **dir_baton,
|
||||
/* Apply any properties in CHANGE to the node. */
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
|
||||
eb->deditor, *dir_baton, scratch_pool));
|
||||
editor, *dir_baton, scratch_pool));
|
||||
else
|
||||
SVN_ERR(drive_ev1_props(ev1_relpath, change, base_props,
|
||||
eb->deditor, file_baton, scratch_pool));
|
||||
editor, file_baton, scratch_pool));
|
||||
|
||||
/* Send the text content delta, if new text content is provided. */
|
||||
if (change->contents_text)
|
||||
@ -1023,7 +1025,7 @@ apply_change(void **dir_baton,
|
||||
scratch_pool);
|
||||
/* ### would be nice to have a BASE_CHECKSUM, but hey: this is the
|
||||
### shim code... */
|
||||
SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool,
|
||||
SVN_ERR(editor->apply_textdelta(file_baton, NULL, scratch_pool,
|
||||
&handler, &handler_baton));
|
||||
/* ### it would be nice to send a true txdelta here, but whatever. */
|
||||
SVN_ERR(svn_txdelta_send_stream(read_stream, handler, handler_baton,
|
||||
@ -1033,7 +1035,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
if (file_baton)
|
||||
{
|
||||
SVN_ERR(eb->deditor->close_file(file_baton, NULL, scratch_pool));
|
||||
SVN_ERR(editor->close_file(file_baton, NULL, scratch_pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -1740,7 +1742,7 @@ drive_changes(svn_branch__txn_priv_t *eb,
|
||||
|
||||
/* Apply the appropriate Ev1 change to each Ev1-relative path. */
|
||||
paths = get_unsorted_paths(eb->changes, scratch_pool);
|
||||
SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton,
|
||||
SVN_ERR(svn_delta_path_driver3(eb->deditor, eb->dedit_baton,
|
||||
paths, TRUE /*sort*/,
|
||||
apply_change, (void *)eb,
|
||||
scratch_pool));
|
||||
|
@ -1577,6 +1577,8 @@ drive_ev1_props(const struct editor_baton *eb,
|
||||
/* Conforms to svn_delta_path_driver_cb_func_t */
|
||||
static svn_error_t *
|
||||
apply_change(void **dir_baton,
|
||||
const svn_delta_editor_t *deditor,
|
||||
void *dedit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *ev1_relpath,
|
||||
@ -1614,7 +1616,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
if (change->action == RESTRUCTURE_DELETE)
|
||||
{
|
||||
SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting,
|
||||
SVN_ERR(deditor->delete_entry(ev1_relpath, change->deleting,
|
||||
parent_baton, scratch_pool));
|
||||
|
||||
/* No futher action possible for this node. */
|
||||
@ -1627,10 +1629,10 @@ apply_change(void **dir_baton,
|
||||
if (change->action == RESTRUCTURE_ADD_ABSENT)
|
||||
{
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->absent_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->absent_directory(ev1_relpath, parent_baton,
|
||||
scratch_pool));
|
||||
else
|
||||
SVN_ERR(eb->deditor->absent_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->absent_file(ev1_relpath, parent_baton,
|
||||
scratch_pool));
|
||||
|
||||
/* No further action possible for this node. */
|
||||
@ -1645,7 +1647,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
/* Do we have an old node to delete first? */
|
||||
if (SVN_IS_VALID_REVNUM(change->deleting))
|
||||
SVN_ERR(eb->deditor->delete_entry(ev1_relpath, change->deleting,
|
||||
SVN_ERR(deditor->delete_entry(ev1_relpath, change->deleting,
|
||||
parent_baton, scratch_pool));
|
||||
|
||||
/* Are we copying the node from somewhere? */
|
||||
@ -1669,22 +1671,22 @@ apply_change(void **dir_baton,
|
||||
}
|
||||
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->add_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->add_directory(ev1_relpath, parent_baton,
|
||||
copyfrom_url, copyfrom_rev,
|
||||
result_pool, dir_baton));
|
||||
else
|
||||
SVN_ERR(eb->deditor->add_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->add_file(ev1_relpath, parent_baton,
|
||||
copyfrom_url, copyfrom_rev,
|
||||
result_pool, &file_baton));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (change->kind == svn_node_dir)
|
||||
SVN_ERR(eb->deditor->open_directory(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->open_directory(ev1_relpath, parent_baton,
|
||||
change->changing,
|
||||
result_pool, dir_baton));
|
||||
else
|
||||
SVN_ERR(eb->deditor->open_file(ev1_relpath, parent_baton,
|
||||
SVN_ERR(deditor->open_file(ev1_relpath, parent_baton,
|
||||
change->changing,
|
||||
result_pool, &file_baton));
|
||||
}
|
||||
@ -1703,7 +1705,7 @@ apply_change(void **dir_baton,
|
||||
|
||||
/* ### would be nice to have a BASE_CHECKSUM, but hey: this is the
|
||||
### shim code... */
|
||||
SVN_ERR(eb->deditor->apply_textdelta(file_baton, NULL, scratch_pool,
|
||||
SVN_ERR(deditor->apply_textdelta(file_baton, NULL, scratch_pool,
|
||||
&handler, &handler_baton));
|
||||
SVN_ERR(svn_stream_open_readonly(&contents, change->contents_abspath,
|
||||
scratch_pool, scratch_pool));
|
||||
@ -1718,7 +1720,7 @@ apply_change(void **dir_baton,
|
||||
const char *digest = svn_checksum_to_cstring(change->checksum,
|
||||
scratch_pool);
|
||||
|
||||
SVN_ERR(eb->deditor->close_file(file_baton, digest, scratch_pool));
|
||||
SVN_ERR(deditor->close_file(file_baton, digest, scratch_pool));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -1747,7 +1749,7 @@ drive_changes(const struct editor_baton *eb,
|
||||
|
||||
/* Get a sorted list of Ev1-relative paths. */
|
||||
paths = get_sorted_paths(eb->changes, eb->base_relpath, scratch_pool);
|
||||
SVN_ERR(svn_delta_path_driver2(eb->deditor, eb->dedit_baton, paths,
|
||||
SVN_ERR(svn_delta_path_driver3(eb->deditor, eb->dedit_baton, paths,
|
||||
FALSE, apply_change, (void *)eb,
|
||||
scratch_pool));
|
||||
|
||||
|
@ -71,9 +71,11 @@ set_target_revision(void *edit_baton,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "set_target_revision : %ld\n",
|
||||
target_revision));
|
||||
|
||||
return eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton,
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->set_target_revision(eb->wrapped_edit_baton,
|
||||
target_revision,
|
||||
pool);
|
||||
pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
@ -90,6 +92,7 @@ open_root(void *edit_baton,
|
||||
base_revision));
|
||||
eb->indent_level++;
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->open_root(eb->wrapped_edit_baton,
|
||||
base_revision,
|
||||
pool,
|
||||
@ -115,10 +118,12 @@ delete_entry(const char *path,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "delete_entry : %s:%ld\n",
|
||||
path, base_revision));
|
||||
|
||||
return eb->wrapped_editor->delete_entry(path,
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->delete_entry(path,
|
||||
base_revision,
|
||||
pb->wrapped_dir_baton,
|
||||
pool);
|
||||
pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
@ -139,6 +144,7 @@ add_directory(const char *path,
|
||||
path, copyfrom_path, copyfrom_revision));
|
||||
eb->indent_level++;
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->add_directory(path,
|
||||
pb->wrapped_dir_baton,
|
||||
copyfrom_path,
|
||||
@ -168,6 +174,7 @@ open_directory(const char *path,
|
||||
path, base_revision));
|
||||
eb->indent_level++;
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->open_directory(path,
|
||||
pb->wrapped_dir_baton,
|
||||
base_revision,
|
||||
@ -199,6 +206,7 @@ add_file(const char *path,
|
||||
|
||||
eb->indent_level++;
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->add_file(path,
|
||||
pb->wrapped_dir_baton,
|
||||
copyfrom_path,
|
||||
@ -229,6 +237,7 @@ open_file(const char *path,
|
||||
|
||||
eb->indent_level++;
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->open_file(path,
|
||||
pb->wrapped_dir_baton,
|
||||
base_revision,
|
||||
@ -255,6 +264,7 @@ apply_textdelta(void *file_baton,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "apply_textdelta : %s\n",
|
||||
base_checksum));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->apply_textdelta(fb->wrapped_file_baton,
|
||||
base_checksum,
|
||||
pool,
|
||||
@ -264,6 +274,32 @@ apply_textdelta(void *file_baton,
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
apply_textdelta_stream(const struct svn_delta_editor_t *editor,
|
||||
void *file_baton,
|
||||
const char *base_checksum,
|
||||
svn_txdelta_stream_open_func_t open_func,
|
||||
void *open_baton,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
struct file_baton *fb = file_baton;
|
||||
struct edit_baton *eb = fb->edit_baton;
|
||||
|
||||
SVN_ERR(write_indent(eb, scratch_pool));
|
||||
SVN_ERR(svn_stream_printf(eb->out, scratch_pool,
|
||||
"apply_textdelta_stream : %s\n",
|
||||
base_checksum));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->apply_textdelta_stream(eb->wrapped_editor,
|
||||
fb->wrapped_file_baton,
|
||||
base_checksum,
|
||||
open_func, open_baton,
|
||||
scratch_pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
static svn_error_t *
|
||||
close_file(void *file_baton,
|
||||
const char *text_checksum,
|
||||
@ -278,6 +314,7 @@ close_file(void *file_baton,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "close_file : %s\n",
|
||||
text_checksum));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->close_file(fb->wrapped_file_baton,
|
||||
text_checksum, pool));
|
||||
|
||||
@ -295,6 +332,7 @@ absent_file(const char *path,
|
||||
SVN_ERR(write_indent(eb, pool));
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "absent_file : %s\n", path));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->absent_file(path, fb->wrapped_file_baton,
|
||||
pool));
|
||||
|
||||
@ -312,6 +350,7 @@ close_directory(void *dir_baton,
|
||||
SVN_ERR(write_indent(eb, pool));
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "close_directory\n"));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->close_directory(db->wrapped_dir_baton,
|
||||
pool));
|
||||
|
||||
@ -330,6 +369,7 @@ absent_directory(const char *path,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "absent_directory : %s\n",
|
||||
path));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->absent_directory(path, db->wrapped_dir_baton,
|
||||
pool));
|
||||
|
||||
@ -349,6 +389,7 @@ change_file_prop(void *file_baton,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "change_file_prop : %s -> %s\n",
|
||||
name, value ? value->data : "<deleted>"));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->change_file_prop(fb->wrapped_file_baton,
|
||||
name,
|
||||
value,
|
||||
@ -370,6 +411,7 @@ change_dir_prop(void *dir_baton,
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "change_dir_prop : %s -> %s\n",
|
||||
name, value ? value->data : "<deleted>"));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->change_dir_prop(db->wrapped_dir_baton,
|
||||
name,
|
||||
value,
|
||||
@ -387,6 +429,7 @@ close_edit(void *edit_baton,
|
||||
SVN_ERR(write_indent(eb, pool));
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "close_edit\n"));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->close_edit(eb->wrapped_edit_baton, pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -401,6 +444,7 @@ abort_edit(void *edit_baton,
|
||||
SVN_ERR(write_indent(eb, pool));
|
||||
SVN_ERR(svn_stream_printf(eb->out, pool, "abort_edit\n"));
|
||||
|
||||
if (eb->wrapped_editor)
|
||||
SVN_ERR(eb->wrapped_editor->abort_edit(eb->wrapped_edit_baton, pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
@ -414,7 +458,7 @@ svn_delta__get_debug_editor(const svn_delta_editor_t **editor,
|
||||
const char *prefix,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
svn_delta_editor_t *tree_editor = apr_palloc(pool, sizeof(*tree_editor));
|
||||
svn_delta_editor_t *tree_editor = svn_delta_default_editor(pool);
|
||||
struct edit_baton *eb = apr_palloc(pool, sizeof(*eb));
|
||||
apr_file_t *errfp;
|
||||
svn_stream_t *out;
|
||||
@ -436,6 +480,7 @@ svn_delta__get_debug_editor(const svn_delta_editor_t **editor,
|
||||
tree_editor->add_file = add_file;
|
||||
tree_editor->open_file = open_file;
|
||||
tree_editor->apply_textdelta = apply_textdelta;
|
||||
tree_editor->apply_textdelta_stream = apply_textdelta_stream;
|
||||
tree_editor->change_file_prop = change_file_prop;
|
||||
tree_editor->close_file = close_file;
|
||||
tree_editor->absent_file = absent_file;
|
||||
|
@ -30,6 +30,79 @@
|
||||
#include "svn_sorts.h"
|
||||
|
||||
|
||||
struct path_driver_2_to_3_baton_t
|
||||
{
|
||||
svn_delta_path_driver_cb_func_t callback_func;
|
||||
void *callback_baton;
|
||||
svn_boolean_t slash_prefix;
|
||||
};
|
||||
|
||||
/* Convert from a newer to older callback
|
||||
*/
|
||||
static svn_error_t *
|
||||
path_driver_2_to_3_func(void **dir_baton,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
void *parent_baton,
|
||||
void *callback_baton,
|
||||
const char *path,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct path_driver_2_to_3_baton_t *b = callback_baton;
|
||||
|
||||
if (b->slash_prefix)
|
||||
path = apr_pstrcat(pool, "/", path, SVN_VA_NULL);
|
||||
|
||||
/* Just drop the 'editor' parameters */
|
||||
SVN_ERR(b->callback_func(dir_baton, parent_baton,
|
||||
b->callback_baton,
|
||||
path, pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
const apr_array_header_t *paths,
|
||||
svn_boolean_t sort_paths,
|
||||
svn_delta_path_driver_cb_func_t callback_func,
|
||||
void *callback_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
struct path_driver_2_to_3_baton_t b;
|
||||
int i;
|
||||
|
||||
b.callback_func = callback_func;
|
||||
b.callback_baton = callback_baton;
|
||||
b.slash_prefix = FALSE;
|
||||
|
||||
/* Remove any '/' prefix from incoming paths. Arrange to add a '/'
|
||||
prefix to all paths for the callback, if any incoming path had one. */
|
||||
for (i = 0; i < paths->nelts; i++)
|
||||
{
|
||||
const char *path = APR_ARRAY_IDX(paths, i, const char *);
|
||||
|
||||
if (path[0] == '/')
|
||||
{
|
||||
/* Re-allocate the array and note that we found a '/' prefix. */
|
||||
if (!b.slash_prefix)
|
||||
{
|
||||
paths = apr_array_copy(pool, paths);
|
||||
b.slash_prefix = TRUE;
|
||||
}
|
||||
|
||||
/* Modify each array element that had a '/' prefix */
|
||||
APR_ARRAY_IDX(paths, i, const char *) = path + 1;
|
||||
}
|
||||
}
|
||||
|
||||
SVN_ERR(svn_delta_path_driver3(editor, edit_baton,
|
||||
paths, sort_paths,
|
||||
path_driver_2_to_3_func, &b,
|
||||
pool));
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_delta_path_driver(const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
|
@ -375,14 +375,12 @@ svn_element__tree_get(const svn_element__tree_t *tree,
|
||||
return svn_eid__hash_get(tree->e_map, eid);
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
void
|
||||
svn_element__tree_set(svn_element__tree_t *tree,
|
||||
int eid,
|
||||
const svn_element__content_t *element)
|
||||
{
|
||||
svn_eid__hash_set(tree->e_map, eid, element);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -6,7 +6,7 @@ includedir=@includedir@
|
||||
Name: libsvn_delta
|
||||
Description: Subversion Delta Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires: apr-util-@SVN_APR_MAJOR_VERSION@, apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_delta @SVN_ZLIB_LIBS@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lsvn_delta-1 @SVN_ZLIB_LIBS@
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
@ -31,7 +31,6 @@
|
||||
#include "svn_dirent_uri.h"
|
||||
#include "svn_path.h"
|
||||
#include "svn_sorts.h"
|
||||
#include "private/svn_fspath.h"
|
||||
#include "private/svn_sorts_private.h"
|
||||
|
||||
|
||||
@ -45,6 +44,22 @@ typedef struct dir_stack_t
|
||||
} dir_stack_t;
|
||||
|
||||
|
||||
/* Push onto dir_stack a new item allocated in POOL and containing
|
||||
* DIR_BATON and POOL.
|
||||
*/
|
||||
static void
|
||||
push_dir_stack_item(apr_array_header_t *db_stack,
|
||||
void *dir_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
dir_stack_t *item = apr_pcalloc(pool, sizeof(*item));
|
||||
|
||||
item->dir_baton = dir_baton;
|
||||
item->pool = pool;
|
||||
APR_ARRAY_PUSH(db_stack, dir_stack_t *) = item;
|
||||
}
|
||||
|
||||
|
||||
/* Call EDITOR's open_directory() function with the PATH argument, then
|
||||
* add the resulting dir baton to the dir baton stack.
|
||||
*/
|
||||
@ -72,10 +87,7 @@ open_dir(apr_array_header_t *db_stack,
|
||||
&db));
|
||||
|
||||
/* Now add the dir baton to the stack. */
|
||||
item = apr_pcalloc(subpool, sizeof(*item));
|
||||
item->dir_baton = db;
|
||||
item->pool = subpool;
|
||||
APR_ARRAY_PUSH(db_stack, dir_stack_t *) = item;
|
||||
push_dir_stack_item(db_stack, db, subpool);
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
@ -131,79 +143,125 @@ count_components(const char *path)
|
||||
|
||||
/*** Public interfaces ***/
|
||||
svn_error_t *
|
||||
svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
svn_delta_path_driver3(const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
const apr_array_header_t *paths,
|
||||
const apr_array_header_t *relpaths,
|
||||
svn_boolean_t sort_paths,
|
||||
svn_delta_path_driver_cb_func_t callback_func,
|
||||
svn_delta_path_driver_cb_func2_t callback_func,
|
||||
void *callback_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
apr_array_header_t *db_stack = apr_array_make(pool, 4, sizeof(void *));
|
||||
const char *last_path = NULL;
|
||||
int i = 0;
|
||||
void *parent_db = NULL, *db = NULL;
|
||||
const char *path;
|
||||
svn_delta_path_driver_state_t *state;
|
||||
int i;
|
||||
apr_pool_t *subpool, *iterpool;
|
||||
dir_stack_t *item;
|
||||
|
||||
/* Do nothing if there are no paths. */
|
||||
if (! paths->nelts)
|
||||
if (! relpaths->nelts)
|
||||
return SVN_NO_ERROR;
|
||||
|
||||
subpool = svn_pool_create(pool);
|
||||
iterpool = svn_pool_create(pool);
|
||||
|
||||
/* sort paths if necessary */
|
||||
if (sort_paths && paths->nelts > 1)
|
||||
if (sort_paths && relpaths->nelts > 1)
|
||||
{
|
||||
apr_array_header_t *sorted = apr_array_copy(subpool, paths);
|
||||
apr_array_header_t *sorted = apr_array_copy(subpool, relpaths);
|
||||
svn_sort__array(sorted, svn_sort_compare_paths);
|
||||
paths = sorted;
|
||||
relpaths = sorted;
|
||||
}
|
||||
|
||||
item = apr_pcalloc(subpool, sizeof(*item));
|
||||
|
||||
/* If the root of the edit is also a target path, we want to call
|
||||
the callback function to let the user open the root directory and
|
||||
do what needs to be done. Otherwise, we'll do the open_root()
|
||||
ourselves. */
|
||||
path = APR_ARRAY_IDX(paths, 0, const char *);
|
||||
if (svn_path_is_empty(path))
|
||||
{
|
||||
SVN_ERR(callback_func(&db, NULL, callback_baton, path, subpool));
|
||||
last_path = path;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
{
|
||||
SVN_ERR(editor->open_root(edit_baton, SVN_INVALID_REVNUM, subpool, &db));
|
||||
}
|
||||
item->pool = subpool;
|
||||
item->dir_baton = db;
|
||||
APR_ARRAY_PUSH(db_stack, void *) = item;
|
||||
SVN_ERR(svn_delta_path_driver_start(&state,
|
||||
editor, edit_baton,
|
||||
callback_func, callback_baton,
|
||||
pool));
|
||||
|
||||
/* Now, loop over the commit items, traversing the URL tree and
|
||||
driving the editor. */
|
||||
for (; i < paths->nelts; i++)
|
||||
for (i = 0; i < relpaths->nelts; i++)
|
||||
{
|
||||
const char *pdir;
|
||||
const char *common = "";
|
||||
size_t common_len;
|
||||
const char *relpath;
|
||||
|
||||
/* Clear the iteration pool. */
|
||||
svn_pool_clear(iterpool);
|
||||
|
||||
/* Get the next path. */
|
||||
path = APR_ARRAY_IDX(paths, i, const char *);
|
||||
relpath = APR_ARRAY_IDX(relpaths, i, const char *);
|
||||
|
||||
SVN_ERR(svn_delta_path_driver_step(state, relpath, iterpool));
|
||||
}
|
||||
|
||||
/* Destroy the iteration subpool. */
|
||||
svn_pool_destroy(iterpool);
|
||||
|
||||
SVN_ERR(svn_delta_path_driver_finish(state, pool));
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
struct svn_delta_path_driver_state_t
|
||||
{
|
||||
const svn_delta_editor_t *editor;
|
||||
void *edit_baton;
|
||||
svn_delta_path_driver_cb_func2_t callback_func;
|
||||
void *callback_baton;
|
||||
apr_array_header_t *db_stack;
|
||||
const char *last_path;
|
||||
apr_pool_t *pool; /* at least the lifetime of the entire drive */
|
||||
};
|
||||
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_start(svn_delta_path_driver_state_t **state_p,
|
||||
const svn_delta_editor_t *editor,
|
||||
void *edit_baton,
|
||||
svn_delta_path_driver_cb_func2_t callback_func,
|
||||
void *callback_baton,
|
||||
apr_pool_t *pool)
|
||||
{
|
||||
svn_delta_path_driver_state_t *state = apr_pcalloc(pool, sizeof(*state));
|
||||
|
||||
state->editor = editor;
|
||||
state->edit_baton = edit_baton;
|
||||
state->callback_func = callback_func;
|
||||
state->callback_baton = callback_baton;
|
||||
state->db_stack = apr_array_make(pool, 4, sizeof(void *));
|
||||
state->last_path = NULL;
|
||||
state->pool = pool;
|
||||
|
||||
*state_p = state;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_step(svn_delta_path_driver_state_t *state,
|
||||
const char *relpath,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
const char *pdir;
|
||||
const char *common = "";
|
||||
size_t common_len;
|
||||
apr_pool_t *subpool;
|
||||
dir_stack_t *item;
|
||||
void *parent_db, *db;
|
||||
|
||||
SVN_ERR_ASSERT(svn_relpath_is_canonical(relpath));
|
||||
|
||||
/* If the first target path is not the root of the edit, we must first
|
||||
call open_root() ourselves. (If the first target path is the root of
|
||||
the edit, then we expect the user's callback to do so.) */
|
||||
if (!state->last_path && !svn_path_is_empty(relpath))
|
||||
{
|
||||
subpool = svn_pool_create(state->pool);
|
||||
SVN_ERR(state->editor->open_root(state->edit_baton, SVN_INVALID_REVNUM,
|
||||
subpool, &db));
|
||||
push_dir_stack_item(state->db_stack, db, subpool);
|
||||
}
|
||||
|
||||
/*** Step A - Find the common ancestor of the last path and the
|
||||
current one. For the first iteration, this is just the
|
||||
empty string. ***/
|
||||
if (i > 0)
|
||||
common = (last_path[0] == '/')
|
||||
? svn_fspath__get_longest_ancestor(last_path, path, iterpool)
|
||||
: svn_relpath_get_longest_ancestor(last_path, path, iterpool);
|
||||
if (state->last_path)
|
||||
common = svn_relpath_get_longest_ancestor(state->last_path, relpath,
|
||||
scratch_pool);
|
||||
common_len = strlen(common);
|
||||
|
||||
/*** Step B - Close any directories between the last path and
|
||||
@ -211,22 +269,19 @@ svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
Sometimes there is nothing to do here (like, for the first
|
||||
iteration, or when the last path was an ancestor of the
|
||||
current one). ***/
|
||||
if ((i > 0) && (strlen(last_path) > common_len))
|
||||
if ((state->last_path) && (strlen(state->last_path) > common_len))
|
||||
{
|
||||
const char *rel = last_path + (common_len ? (common_len + 1) : 0);
|
||||
const char *rel = state->last_path + (common_len ? (common_len + 1) : 0);
|
||||
int count = count_components(rel);
|
||||
while (count--)
|
||||
{
|
||||
SVN_ERR(pop_stack(db_stack, editor));
|
||||
SVN_ERR(pop_stack(state->db_stack, state->editor));
|
||||
}
|
||||
}
|
||||
|
||||
/*** Step C - Open any directories between the common ancestor
|
||||
and the parent of the current path. ***/
|
||||
if (*path == '/')
|
||||
pdir = svn_fspath__dirname(path, iterpool);
|
||||
else
|
||||
pdir = svn_relpath_dirname(path, iterpool);
|
||||
pdir = svn_relpath_dirname(relpath, scratch_pool);
|
||||
|
||||
if (strlen(pdir) > common_len)
|
||||
{
|
||||
@ -242,10 +297,10 @@ svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
/* Calculate REL as the portion of PDIR up to (but not
|
||||
including) the location to which PIECE is pointing. */
|
||||
if (piece)
|
||||
rel = apr_pstrmemdup(iterpool, pdir, piece - pdir);
|
||||
rel = apr_pstrmemdup(scratch_pool, pdir, piece - pdir);
|
||||
|
||||
/* Open the subdirectory. */
|
||||
SVN_ERR(open_dir(db_stack, editor, rel, pool));
|
||||
SVN_ERR(open_dir(state->db_stack, state->editor, rel, state->pool));
|
||||
|
||||
/* If we found a '/', advance our PIECE pointer to
|
||||
character just after that '/'. Otherwise, we're
|
||||
@ -258,16 +313,22 @@ svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
}
|
||||
|
||||
/*** Step D - Tell our caller to handle the current path. ***/
|
||||
item = APR_ARRAY_IDX(db_stack, db_stack->nelts - 1, void *);
|
||||
if (state->db_stack->nelts)
|
||||
{
|
||||
item = APR_ARRAY_IDX(state->db_stack, state->db_stack->nelts - 1, void *);
|
||||
parent_db = item->dir_baton;
|
||||
subpool = svn_pool_create(pool);
|
||||
SVN_ERR(callback_func(&db, parent_db, callback_baton, path, subpool));
|
||||
}
|
||||
else
|
||||
parent_db = NULL;
|
||||
db = NULL; /* predictable behaviour for callbacks that don't set it */
|
||||
subpool = svn_pool_create(state->pool);
|
||||
SVN_ERR(state->callback_func(&db,
|
||||
state->editor, state->edit_baton, parent_db,
|
||||
state->callback_baton,
|
||||
relpath, subpool));
|
||||
if (db)
|
||||
{
|
||||
item = apr_pcalloc(subpool, sizeof(*item));
|
||||
item->dir_baton = db;
|
||||
item->pool = subpool;
|
||||
APR_ARRAY_PUSH(db_stack, void *) = item;
|
||||
push_dir_stack_item(state->db_stack, db, subpool);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -278,21 +339,19 @@ svn_delta_path_driver2(const svn_delta_editor_t *editor,
|
||||
caller opened or added PATH as a directory, that becomes
|
||||
our LAST_PATH. Otherwise, we use PATH's parent
|
||||
directory. ***/
|
||||
state->last_path = apr_pstrdup(state->pool, db ? relpath : pdir);
|
||||
|
||||
/* NOTE: The variable LAST_PATH needs to outlive the loop. */
|
||||
if (db)
|
||||
last_path = path; /* lives in a pool outside our control. */
|
||||
else
|
||||
last_path = apr_pstrdup(pool, pdir); /* duping into POOL. */
|
||||
}
|
||||
|
||||
/* Destroy the iteration subpool. */
|
||||
svn_pool_destroy(iterpool);
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_delta_path_driver_finish(svn_delta_path_driver_state_t *state,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
/* Close down any remaining open directory batons. */
|
||||
while (db_stack->nelts)
|
||||
while (state->db_stack->nelts)
|
||||
{
|
||||
SVN_ERR(pop_stack(db_stack, editor));
|
||||
SVN_ERR(pop_stack(state->db_stack, state->editor));
|
||||
}
|
||||
|
||||
return SVN_NO_ERROR;
|
||||
|
@ -37,14 +37,6 @@
|
||||
#include "private/svn_diff_tree.h"
|
||||
#include "svn_private_config.h"
|
||||
|
||||
typedef struct tree_processor_t
|
||||
{
|
||||
svn_diff_tree_processor_t tp;
|
||||
|
||||
/* void *future_extension */
|
||||
} tree_processor_t;
|
||||
|
||||
|
||||
static svn_error_t *
|
||||
default_dir_opened(void **new_dir_baton,
|
||||
svn_boolean_t *skip,
|
||||
@ -215,33 +207,30 @@ svn_diff_tree_processor_t *
|
||||
svn_diff__tree_processor_create(void *baton,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
tree_processor_t *wrapper;
|
||||
wrapper = apr_pcalloc(result_pool, sizeof(*wrapper));
|
||||
svn_diff_tree_processor_t *tp = apr_pcalloc(result_pool, sizeof(*tp));
|
||||
|
||||
wrapper->tp.baton = baton;
|
||||
tp->baton = baton;
|
||||
|
||||
wrapper->tp.dir_opened = default_dir_opened;
|
||||
wrapper->tp.dir_added = default_dir_added;
|
||||
wrapper->tp.dir_deleted = default_dir_deleted;
|
||||
wrapper->tp.dir_changed = default_dir_changed;
|
||||
wrapper->tp.dir_closed = default_dir_closed;
|
||||
tp->dir_opened = default_dir_opened;
|
||||
tp->dir_added = default_dir_added;
|
||||
tp->dir_deleted = default_dir_deleted;
|
||||
tp->dir_changed = default_dir_changed;
|
||||
tp->dir_closed = default_dir_closed;
|
||||
|
||||
wrapper->tp.file_opened = default_file_opened;
|
||||
wrapper->tp.file_added = default_file_added;
|
||||
wrapper->tp.file_deleted = default_file_deleted;
|
||||
wrapper->tp.file_changed = default_file_changed;
|
||||
wrapper->tp.file_closed = default_file_closed;
|
||||
tp->file_opened = default_file_opened;
|
||||
tp->file_added = default_file_added;
|
||||
tp->file_deleted = default_file_deleted;
|
||||
tp->file_changed = default_file_changed;
|
||||
tp->file_closed = default_file_closed;
|
||||
|
||||
wrapper->tp.node_absent = default_node_absent;
|
||||
tp->node_absent = default_node_absent;
|
||||
|
||||
|
||||
return &wrapper->tp;
|
||||
return tp;
|
||||
}
|
||||
|
||||
struct reverse_tree_baton_t
|
||||
{
|
||||
const svn_diff_tree_processor_t *processor;
|
||||
const char *prefix_relpath;
|
||||
};
|
||||
|
||||
static svn_error_t *
|
||||
@ -259,9 +248,6 @@ reverse_dir_opened(void **new_dir_baton,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->dir_opened(new_dir_baton, skip, skip_children,
|
||||
relpath,
|
||||
right_source, left_source,
|
||||
@ -284,9 +270,6 @@ reverse_dir_added(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->dir_deleted(relpath,
|
||||
right_source,
|
||||
right_props,
|
||||
@ -307,9 +290,6 @@ reverse_dir_deleted(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->dir_added(relpath,
|
||||
NULL,
|
||||
left_source,
|
||||
@ -335,9 +315,6 @@ reverse_dir_changed(const char *relpath,
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
apr_array_header_t *reversed_prop_changes = NULL;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
if (prop_changes)
|
||||
{
|
||||
SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
|
||||
@ -367,9 +344,6 @@ reverse_dir_closed(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->dir_closed(relpath,
|
||||
right_source,
|
||||
left_source,
|
||||
@ -393,9 +367,6 @@ reverse_file_opened(void **new_file_baton,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->file_opened(new_file_baton,
|
||||
skip,
|
||||
relpath,
|
||||
@ -423,9 +394,6 @@ reverse_file_added(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->file_deleted(relpath,
|
||||
right_source,
|
||||
right_file,
|
||||
@ -447,9 +415,6 @@ reverse_file_deleted(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->file_added(relpath,
|
||||
NULL /* copyfrom src */,
|
||||
left_source,
|
||||
@ -480,9 +445,6 @@ reverse_file_changed(const char *relpath,
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
apr_array_header_t *reversed_prop_changes = NULL;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
if (prop_changes)
|
||||
{
|
||||
SVN_ERR_ASSERT(left_props != NULL && right_props != NULL);
|
||||
@ -515,9 +477,6 @@ reverse_file_closed(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->file_closed(relpath,
|
||||
right_source,
|
||||
left_source,
|
||||
@ -536,9 +495,6 @@ reverse_node_absent(const char *relpath,
|
||||
{
|
||||
struct reverse_tree_baton_t *rb = processor->baton;
|
||||
|
||||
if (rb->prefix_relpath)
|
||||
relpath = svn_relpath_join(rb->prefix_relpath, relpath, scratch_pool);
|
||||
|
||||
SVN_ERR(rb->processor->node_absent(relpath,
|
||||
dir_baton,
|
||||
rb->processor,
|
||||
@ -549,7 +505,6 @@ reverse_node_absent(const char *relpath,
|
||||
|
||||
const svn_diff_tree_processor_t *
|
||||
svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * processor,
|
||||
const char *prefix_relpath,
|
||||
apr_pool_t *result_pool)
|
||||
{
|
||||
struct reverse_tree_baton_t *rb;
|
||||
@ -557,8 +512,6 @@ svn_diff__tree_processor_reverse_create(const svn_diff_tree_processor_t * proces
|
||||
|
||||
rb = apr_pcalloc(result_pool, sizeof(*rb));
|
||||
rb->processor = processor;
|
||||
if (prefix_relpath)
|
||||
rb->prefix_relpath = apr_pstrdup(result_pool, prefix_relpath);
|
||||
|
||||
reverse = svn_diff__tree_processor_create(rb, result_pool);
|
||||
|
||||
|
@ -8,5 +8,5 @@ Description: Subversion Diff Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_diff @SVN_ZLIB_LIBS@
|
||||
Cflags: -I${includedir}
|
||||
Libs: -L${libdir} -lsvn_diff-1 @SVN_ZLIB_LIBS@
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
@ -69,6 +69,11 @@ struct svn_diff_hunk_t {
|
||||
/* APR file handle to the patch file this hunk came from. */
|
||||
apr_file_t *apr_file;
|
||||
|
||||
/* Whether the hunk was interpreted as pretty-print mergeinfo. If so,
|
||||
the hunk content is in PATCH and the rest of this hunk object is
|
||||
mostly uninitialized. */
|
||||
svn_boolean_t is_pretty_print_mergeinfo;
|
||||
|
||||
/* Ranges used to keep track of this hunk's texts positions within
|
||||
* the patch file. */
|
||||
struct svn_diff__hunk_range diff_text_range;
|
||||
@ -899,10 +904,6 @@ parse_prop_name(const char **prop_name, const char *header,
|
||||
* The hunk header has the following format:
|
||||
* ## -0,NUMBER_OF_REVERSE_MERGES +0,NUMBER_OF_FORWARD_MERGES ##
|
||||
*
|
||||
* At this point, the number of reverse merges has already been
|
||||
* parsed into HUNK->ORIGINAL_LENGTH, and the number of forward
|
||||
* merges has been parsed into HUNK->MODIFIED_LENGTH.
|
||||
*
|
||||
* The header is followed by a list of mergeinfo, one path per line.
|
||||
* This function parses such lines. Lines describing reverse merges
|
||||
* appear first, and then all lines describing forward merges appear.
|
||||
@ -914,15 +915,24 @@ parse_prop_name(const char **prop_name, const char *header,
|
||||
* ":r", which in turn is followed by a mergeinfo revision range,
|
||||
* which is terminated by whitespace or end-of-string.
|
||||
*
|
||||
* If the current line meets the above criteria and we're able
|
||||
* to parse valid mergeinfo from it, the resulting mergeinfo
|
||||
* is added to patch->mergeinfo or patch->reverse_mergeinfo,
|
||||
* and we proceed to the next line.
|
||||
* *NUMBER_OF_REVERSE_MERGES and *NUMBER_OF_FORWARD_MERGES are the
|
||||
* numbers of reverse and forward merges remaining to be read. This
|
||||
* function decrements *NUMBER_OF_REVERSE_MERGES for each LINE
|
||||
* parsed until that is zero, then *NUMBER_OF_FORWARD_MERGES for
|
||||
* each LINE parsed until that is zero. If both are zero, it parses
|
||||
* and discards LINE.
|
||||
*
|
||||
* If LINE is successfully parsed, *FOUND_MERGEINFO is set to TRUE,
|
||||
* otherwise to FALSE.
|
||||
*
|
||||
* If LINE is successfully parsed and counted, the resulting mergeinfo
|
||||
* is added to PATCH->mergeinfo or PATCH->reverse_mergeinfo.
|
||||
*/
|
||||
static svn_error_t *
|
||||
parse_mergeinfo(svn_boolean_t *found_mergeinfo,
|
||||
parse_pretty_mergeinfo_line(svn_boolean_t *found_mergeinfo,
|
||||
svn_linenum_t *number_of_reverse_merges,
|
||||
svn_linenum_t *number_of_forward_merges,
|
||||
svn_stringbuf_t *line,
|
||||
svn_diff_hunk_t *hunk,
|
||||
svn_patch_t *patch,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
@ -972,7 +982,7 @@ parse_mergeinfo(svn_boolean_t *found_mergeinfo,
|
||||
|
||||
if (mergeinfo)
|
||||
{
|
||||
if (hunk->original_length > 0) /* reverse merges */
|
||||
if (*number_of_reverse_merges > 0) /* reverse merges */
|
||||
{
|
||||
if (patch->reverse)
|
||||
{
|
||||
@ -994,9 +1004,9 @@ parse_mergeinfo(svn_boolean_t *found_mergeinfo,
|
||||
result_pool,
|
||||
scratch_pool));
|
||||
}
|
||||
hunk->original_length--;
|
||||
(*number_of_reverse_merges)--;
|
||||
}
|
||||
else if (hunk->modified_length > 0) /* forward merges */
|
||||
else if (number_of_forward_merges > 0) /* forward merges */
|
||||
{
|
||||
if (patch->reverse)
|
||||
{
|
||||
@ -1018,7 +1028,7 @@ parse_mergeinfo(svn_boolean_t *found_mergeinfo,
|
||||
result_pool,
|
||||
scratch_pool));
|
||||
}
|
||||
hunk->modified_length--;
|
||||
(*number_of_forward_merges)--;
|
||||
}
|
||||
|
||||
*found_mergeinfo = TRUE;
|
||||
@ -1165,18 +1175,48 @@ parse_next_hunk(svn_diff_hunk_t **hunk,
|
||||
if (in_hunk && *is_property && *prop_name &&
|
||||
strcmp(*prop_name, SVN_PROP_MERGEINFO) == 0)
|
||||
{
|
||||
svn_boolean_t found_mergeinfo;
|
||||
svn_boolean_t found_pretty_mergeinfo_line;
|
||||
|
||||
SVN_ERR(parse_mergeinfo(&found_mergeinfo, line, *hunk, patch,
|
||||
if (! hunk_seen)
|
||||
{
|
||||
/* We're reading the first line of the hunk, so the start
|
||||
* of the line just read is the hunk text's byte offset. */
|
||||
start = last_line;
|
||||
}
|
||||
|
||||
SVN_ERR(parse_pretty_mergeinfo_line(&found_pretty_mergeinfo_line,
|
||||
&original_lines, &modified_lines,
|
||||
line, patch,
|
||||
result_pool, iterpool));
|
||||
if (found_mergeinfo)
|
||||
if (found_pretty_mergeinfo_line)
|
||||
{
|
||||
hunk_seen = TRUE;
|
||||
(*hunk)->is_pretty_print_mergeinfo = TRUE;
|
||||
continue; /* Proceed to the next line in the svn:mergeinfo hunk. */
|
||||
}
|
||||
|
||||
if ((*hunk)->is_pretty_print_mergeinfo)
|
||||
{
|
||||
/* We have reached the end of the pretty-print-mergeinfo hunk.
|
||||
(This format uses only one hunk.) */
|
||||
if (eof)
|
||||
{
|
||||
/* The hunk ends at EOF. */
|
||||
end = pos;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Perhaps we can also use original_lines/modified_lines here */
|
||||
|
||||
in_hunk = FALSE; /* On to next property */
|
||||
/* The start of the current line marks the first byte
|
||||
* after the hunk text. */
|
||||
end = last_line;
|
||||
}
|
||||
original_end = end;
|
||||
modified_end = end;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Otherwise, this is a property diff in the
|
||||
regular format so fall through to normal processing. */
|
||||
}
|
||||
|
||||
if (in_hunk)
|
||||
@ -1971,10 +2011,10 @@ parse_hunks(svn_patch_t *patch, apr_file_t *apr_file,
|
||||
else
|
||||
last_prop_name = prop_name;
|
||||
|
||||
/* Skip svn:mergeinfo properties.
|
||||
* Mergeinfo data cannot be represented as a hunk and
|
||||
/* Skip pretty-printed svn:mergeinfo property hunks.
|
||||
* Pretty-printed mergeinfo data cannot be represented as a hunk and
|
||||
* is therefore stored in PATCH itself. */
|
||||
if (strcmp(prop_name, SVN_PROP_MERGEINFO) == 0)
|
||||
if (hunk->is_pretty_print_mergeinfo)
|
||||
continue;
|
||||
|
||||
SVN_ERR(add_property_hunk(patch, prop_name, hunk, prop_operation,
|
||||
|
@ -2221,3 +2221,42 @@ svn_fs_info_dup(const void *info_void,
|
||||
return apr_pmemdup(result_pool, info, sizeof(*info));
|
||||
}
|
||||
|
||||
svn_error_t *
|
||||
svn_fs_ioctl(svn_fs_t *fs,
|
||||
svn_fs_ioctl_code_t ctlcode,
|
||||
void *input,
|
||||
void **output_p,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool)
|
||||
{
|
||||
void *output;
|
||||
|
||||
if (fs)
|
||||
{
|
||||
if (!fs->vtable->ioctl)
|
||||
return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL);
|
||||
|
||||
SVN_ERR(fs->vtable->ioctl(fs, ctlcode, input, &output,
|
||||
cancel_func, cancel_baton,
|
||||
result_pool, scratch_pool));
|
||||
}
|
||||
else
|
||||
{
|
||||
fs_library_vtable_t *vtable;
|
||||
|
||||
SVN_ERR(get_library_vtable(&vtable, ctlcode.fs_type, scratch_pool));
|
||||
|
||||
if (!vtable->ioctl)
|
||||
return svn_error_create(SVN_ERR_FS_UNRECOGNIZED_IOCTL_CODE, NULL, NULL);
|
||||
|
||||
SVN_ERR(vtable->ioctl(ctlcode, input, &output,
|
||||
cancel_func, cancel_baton,
|
||||
result_pool, scratch_pool));
|
||||
}
|
||||
|
||||
if (output_p)
|
||||
*output_p = output;
|
||||
return SVN_NO_ERROR;
|
||||
}
|
||||
|
@ -159,6 +159,13 @@ typedef struct fs_library_vtable_t
|
||||
/* For svn_fs_info_fsfs_dup(). */
|
||||
void *(*info_fsap_dup)(const void *fsap_info,
|
||||
apr_pool_t *result_pool);
|
||||
|
||||
svn_error_t *(*ioctl)(svn_fs_ioctl_code_t ctlcode,
|
||||
void *input, void **output_p,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
} fs_library_vtable_t;
|
||||
|
||||
/* This is the type of symbol an FS module defines to fetch the
|
||||
@ -266,6 +273,12 @@ typedef struct fs_vtable_t
|
||||
svn_error_t *(*bdb_set_errcall)(svn_fs_t *fs,
|
||||
void (*handler)(const char *errpfx,
|
||||
char *msg));
|
||||
svn_error_t *(*ioctl)(svn_fs_t *fs, svn_fs_ioctl_code_t ctlcode,
|
||||
void *input, void **output_p,
|
||||
svn_cancel_func_t cancel_func,
|
||||
void *cancel_baton,
|
||||
apr_pool_t *result_pool,
|
||||
apr_pool_t *scratch_pool);
|
||||
} fs_vtable_t;
|
||||
|
||||
|
||||
|
@ -6,7 +6,7 @@ includedir=@includedir@
|
||||
Name: libsvn_fs
|
||||
Description: Subversion Repository Filesystem Library
|
||||
Version: @PACKAGE_VERSION@
|
||||
Requires: apr-util-@SVN_APR_MAJOR_VERSION@ apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_fs_util libsvn_delta libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_fs
|
||||
Cflags: -I${includedir}
|
||||
Requires: apr-util-@SVN_APR_MAJOR_VERSION@, apr-@SVN_APR_MAJOR_VERSION@
|
||||
Requires.private: libsvn_fs_util, libsvn_delta, libsvn_subr
|
||||
Libs: -L${libdir} -lsvn_fs-1
|
||||
Cflags: -I${includedir}/subversion-1
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user