Update svn-1.9.7 to 1.10.0.

This commit is contained in:
peter 2018-05-08 04:52:52 +00:00
commit dfbb866f82
434 changed files with 80538 additions and 34566 deletions

View File

@ -0,0 +1,9 @@
# top-most EditorConfig file
# See http://editorconfig.org/
root = true
[*]
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = false

View File

@ -1,3 +1,291 @@
Version 1.10.0
(?? ??? 2018, from /branches/1.10.x)
http://svn.apache.org/repos/asf/subversion/tags/1.10.0
See the 1.10 release notes for a more verbose overview of the changes since
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)
* New experimental 'svn shelve' command (issue #3625)
- Minor new features and improvements:
* svnbench: Show time taken & bytes transferred (r1703383, r1710586)
* New 'svnadmin dump' options to include/exclude paths (r1811992 et al)
* New '--normalize-props' option for 'svnadmin dump' (r1807836 et al)
* New 'svnadmin 'load-revprops', 'dump-revprops' subcommands (r1694191, -225)
* New '--no-flush-to-disk' option for 'svnadmin load' (r1736357, -7357)
* New '--file' option for several svnadmin subcommands (r1738021)
* New '--max-request-size', '--max-response-size' options for svnserve (r1714330, -333)
* New '-rN' option for 'svnadmin lstxns' (r1703699)
* New '--search' option for fast 'svn ls' searches (r1767186 et al)
* Add '--search' option support to 'svnbench null-list' (r1767202)
* New '-M' option for 'svnlook tree' (r1708222)
* New '--skip-unchanged' option for 'svnsync copy-revprops' (r1692655)
* 'svn log --search' now ignores case and diacriticals (r1731300, r1735614)
* Improved performance of server-side log processing (r1732768, r1731656)
* diff3: Reduce processing time and memory usage (r1731659)
* 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)
* '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)
* Optimize svndiff parser (r1685063)
* 'svn status' without -v: Stop showing uninteresting deletions (r1664533)
* Save a few cycles in svn_stringbuf_set() (r1759177)
* windows: Use the Unicode Windows API (r1756193)
* windows: Distinguish out-of-memory error from abort() (r1724784, -809)
* windows: Explicitly release file locks (r1702089)
* windows: Correctly check result from LoadLibrary() call (r1755983)
* Remove Windows-specific slowdown during pristine cleanup (r1701641)
* FSFS: Optionally cache node properties without full-text cache (r1723715)
* FSFS: Open transaction's proto revision in write-only mode (r1759135)
* FSFS: Avoid checksum calculations if logical addressing is used (r1756377)
* FSFS: Do not read very long change lists in block read mode (r1746012)
* FSFS: Avoid double DAG lookup (r1711582)
* FSFS: Avoid double cache lookups (r1681974, r1710370)
* FSFS: Increase default revprop pack size from 4k to 16k (r1709799)
* FSFS: Speed up revprop access (r1707986 et al)
* FSFS: Disable representation sharing for directories (r1706619)
* FSFS: Speed up transaction processing for large directories (r1706617)
* FSFS: Tune format 7 pack ordering heuristics (r1706615)
* FSFS: Reduce I/O overhead during history traversal (r1703237)
* FSFS: Use native Windows API to guarantee data is flushed (r1701053)
* FSFS: Warn if a possible rep-cache SHA1 collision is detected (r1674673)
* FSFS: Optimize revprop cache filling strategy under high load (r1795324)
* FSFS: New "verify-before-commit" fsfs.conf option (r1795351)
* FSFS: New format 8 with various performance improvements (r1801940 et al)
* FSFS/FSX: Chunked read support for changed paths lists (r1746026, -4987)
* FSFS/FSX: Improvements to cache implementation (r1694489)
* FSX: Add checksums to packed revprop manifests and files (r1713132, -9717)
* FSX: Significantly reduce size of packed revprop manifest data (r1713109)
* FSX: Improved on-disk representation of property lists (r1717427)
* FSX: New in-repository representation of directories (r1712967)
* FSX: Make 'svnadmin recover' discard all transactions (r1712937)
* FSX: Reduce number of fsync operations (r1711354 et al)
* mod_dav_svn: Improve performance and memory usage of PROPFIND (r1721732)
* mod_dav_svn: Show process-id on Windows in /svn-status page (r1718567)
* mod_dav_svn: Advertise svndiff1 support to clients (r1704891, r1791285)
* mod_dav_svn: Remove disk I/O to TMPDIR during first commit (r1716240)
* svnsync: Fix assertion failure with up-to-date repositories (r1727140)
* ra_serf: Parallel requests for text and property changes (r1716575)
* svnserve: Remove disk I/O to TMPDIR during first commit (r1716240)
* Triple performance of URI escaping (r1710099, -103)
* 'svn blame': Optimize a bit on the server side (r1711666)
* 'svn cleanup': Add --vacuum-pristines option (r1802787 et al)
* 'svn diff --git': Show diffs of symlinks like git and hg (r1706372)
* 'svn patch': Capable of handling git-like symlink changes (r1706446)
* 'svn patch': Improve detection of additions and deletions (r1706623)
* 'svn patch': Handle zero-byte files vs deleted files (r1705856)
* 'svn diff --git': Produce 'rename from/to' headers (r1706855)
* 'svn diff --git': Produce proper mode headers (r1706041)
* 'svn lock', 'svn unlock': Take the -q option (r1796288)
* 'svn help': improved wording and consistency (r1802989 et al)
* 'svn': Add a new '--accept recommended' option. (r1805623)
* 'svn': --non-interactive uses recommended tree conflict resolution (r1805620)
* Evaluate 'old mode' and 'new mode' lines from git-syle diffs (r1705391)
* svnrdump, svndumpfilter: Enable buffered stdin (r1703074)
* ra_serf: Receive svndiff1 and gzip compressed deltas (r1791282, -3, -4)
* svnadmin: 'lock', 'unlock', 'rmlocks': Take the -q option (r1796406)
* New svndiff2 binary delta format using lz4 compression (r1801938, et al)
* gpg-agent: Support gpg ≥2.1.13 and unset GPG_AGENT_INFO (r1795087)
* Add 'http-compression=auto' client config option as default (r1803899 et al)
* Speed up processing of mergeinfo (r1802470 et al)
* Check for invalid 'xt' fields in x509 certs (r1809290)
* New '--password-from-stdin' option for 'svn' (r1819093)
- Client-side bugfixes:
* svnbench: Honour the '--with-no-revprops' option (r1709593)
* ra_serf: Fix segfault when running over HTTP v1 (r1766089)
* ra_serf: Keep small svndiffs in memory during commit (r1724455)
* ra_serf: Improve error messages related to lock operations (r1716450)
* ra_serf: Work around a bug in serf bucket handling (r1714806)
* ra_serf: Fix lock token handling for file-path commits (r1815799 et al)
* Raise a malfunction instead of segfaulting with corrupt wc.db (r1749887)
* Fix check for unversioned obstructions blocking file externals (r1735932)
* 'svn patch' bugfixes:
+ Fix behaviour if a reject file can't be created (r1725948)
+ Describe adds and removes in reject file headers (r1707034)
+ Detect recorded moves that are already applied (r1706893)
+ Detect already applied patches in edge cases (r1706687)
+ Fix handling of missing trailing context (issue #4609)
+ Fix interaction of moves and property changes (r1706875)
+ Fix output for reordered hunks (issue #4533)
+ Prevent from overwriting existing reject files (r1706600)
+ Improve handling of added properties (r1706598)
+ Improve handling of rejected file deletions (r1706221)
+ Fix --dry-run with replaced files (r1706217)
+ Fix applying prop changes which should conflict (r1705733)
+ Fix duplicate notifications when adding directories (r1704883)
+ Fix duplicate notifications when patching svn:executable prop (r1706078)
+ Fix notifications when adding/removing properties (r1705698)
+ Make handle already applied property patches (r1705692)
+ Change some notifications to 'U' instead of 'G' (r1706693)
+ Don't create file if git-style patch indicates modification (r1706005)
+ Parse any properties following svn:mergeinfo (r1706825)
+ Fix potential unbounded memory usage in parser (r1705979)
+ Fix problems with --git diffs applied in reverse (r1704854, -88)
+ Fix removal of EOL if final patch context line has no EOL (#4315)
* 'svn diff --git': Fix file permission modes to match git and hg (r1695384)
* 'svn diff --git': added/deleted filenames are never /dev/null (issue #4689)
* Fix a problem with relocating some externals (r1723385)
* Fix 'svn diff URL@REV WC' wrongly looks up URL@HEAD (issue #4597)
* Fix 'svn diff --no-diff-added' shows properties as added (issue #4596)
* Properly raise text merge conflicts with file externals (r1680245)
* Fix 'svn diff' with local directories marked incomplete (r1674413 et al)
* ra_svn/ra_serf: Make negative log limits work as documented (r1665530)
* ra_svn: Eliminate unnecessary URL reparenting (r1779611, r1779611)
* ra_svn: Use svndiff2 deltas when supported on both ends (r1803269 et al)
* Handle invalid revision numbers consistently across RA layers (r1665328)
* Handle commits to revs > HEAD consistently across RA layers (r1664698)
* Eliminate one client/server roundtrip from checkouts of HEAD (r1779620)
* Expose some error messages generated by github's SVN server (r1707164)
* 'svnfsfs stats': Show average lengths of delta chains (r1705739)
* svnmucc: Fix crash during application teardown (r1795727)
* Fix assertion when exporting a working copy containing relative externals
(r1802316)
- Server-side bugfixes:
* Fix checksum validation error due to data eviction from cache (r1781694)
* FSFS pack: Use unbuffered file streams in a couple of places (r1759405)
* FSFS: Reduce excessive amount of read and seek syscalls (r1758979, -9399)
* FSFS: Reduce memory footprint of cached directories (r1725179)
* FSFS: Add various checks for integer overflows (r1714372, -32, -34)
* FSFS: Detect a very unlikely case of item index corruption (r1716973)
* FSFS: Make handling of revprop size information more resilient (r1716784)
* FSFS: Don't re-parse a directory which just got committed (r1706679)
* FSFS: Handle some known quirks in committed node revisions (r1673875)
* FSFS format 7: Verify item types more thoroughly (r1796160)
* FSFS: Fix false positive "Not a directory" error involving file moved and
replaced by dir (issue #4677)
* FSFS: Fix crash accessing revprops with --memory-cache-size=0 (r1795164)
* FSFS: Fix issue #4623 for FSFS. (r1813794 et al)
* mod_dav_svn: Omit Cache-Control HTTP header for HEAD URLs (issue #4514)
* mod_dav_svn: Reduced memory consumption for DAV merge responses (r1727790)
* mod_dav_svn: Don't set a Last-Modified header in GET responses (r1724790)
* mod_dav_svn: Actually use FSFS transaction directory cache (r1723720)
* mod_dav_svn: Do not insert newlines in base64 encoded responses (r1712223)
* Fix insertion of very large items into the membuffer cache (r1717337, -8)
* Fix capacity check of the membuffer cache's prefix pool (r1714356)
* Prevent paths containing newlines from being committed (r1662585)
* Fix for properties: Null updates break last-changed-revision (issue #4700)
* 'svnfsfs stats': Fix false positive checksum errors reading old revisions
(r1785904)
* 'svnfsfs stats': Fix support for pre-v4 FSFS repositories. (r1816966)
* svnadmin, svnfsfs: Detect invalid arguments to -M (r1787023, r1787045)
* svnlook, svnserve: Detect invalid arguments to -M (r1787023, r1787045)
* svnadmin: Output locked paths in canonical form (r1796420)
* svnadmin: Output locked paths correctly encoded (r1797122)
* svn: propdel, propset: Transcode property names on output (r1797186)
* svnserve: Make use-sasl=true a fatal error in SASL-less builds. (r1803188)
- Client-side and server-side bugfixes:
* Fix integer overflow check with >= 1G mergeinfo ranges per path (r1714380)
* Fix integer overflow checks on WoW64 platforms (r1714372)
* Fix bug with canonicalizing Window-specific drive-relative URL (r1692262)
* In file:// URLs, allow '\' directly after Windows drive letter (r1692259)
* Fix segfault with recursive configuration value definitions (issue #4543)
* FSFS: Improve error messages when DAG lookup fails (r1795120)
* Transcode command-line arguments to UTF-8 (r1797190, r1797362, et al)
* Fix segfault on x509 certificate with empty name (r1798157)
* Fix segfault with invalid URLs in svn:externals (r1803471)
* Windows: Failure to write files might remain undetected (r1806014)
- Other tool improvements and bugfixes:
* New svn-mergeinfo-normalizer tool (r1695992 et al)
* Allow configuring mailer.py to use SMTP SSL (r1777846)
* svnmucc can now delete directories with deleted children (issue #4666)
* svn-vendor.py: Minor enhancements, mostly in treating symlinks (r1732669)
* bash_completion: Better URL completion (r1701494)
* bash_completion: Complete arguments to 'svn info --show-item' (r1698276)
* fsfs-stats: New 1.8-compatible wrapper for 'svnfsfs stats' (r1802032)
* Drop support for upgrading working copies created with Subversion 1.7
(r1807584 et al)
Developer-visible changes:
- General:
* windows: Removed support for building with Visual Studio 6.0 (r1703419)
* Fix .py scripts throughout the source tree for Python 3 (r1741723 et al)
* Support memcached on Windows with APR-util 1.3 or later (r1674626 et al)
* Don't require GNU-specific sed(1) extensions during the build (r1693159)
* get-deps.sh: download Googlemock and Googletest from GitHub (r1746303)
* windows: Add autodetection for 'zlibstat.lib' (r1783704)
* windows: Compile libsvn_fs_* as DLLs (r1696758, -83)
* windows: Allow building against OpenSSL 1.1.0 (r1814724 et al)
* OS X: Silence compile-time deprecation warnings with SASL (r1739649)
* OS X: Silence ranlib warnings about disabled WIN32 code (r1809792)
* 'make check GLOBAL_SCHEDULER=1' will run many tests in parallel (r1716399)
* unix: New '--enable-apache-whitelist' configure script option (r1732294)
* OS X: Support 'configure --enable-runtime-module-search' (r1677273)
* tests: Allow tests to be run over HTTP/2 (r1710707)
* tests: httpd compile-time and run-time version may differ (r1808955 et al)
* tests: Add pre-cooked repos for all FSFS versions. (r1816402 et al)
* tests: Add FSFS_DIR_DELTIFICATION option. (r1813897)
* Add basic tests for svn_xml_parser_t API (r1765214)
* Unbreak the test suite on Python 3 (r1743034, -81, et al)
* Make the test suite work when checked out of a git repository (r1771118)
* Allow Apache HTTPD with mod_deflate in testsuite on Windows (r1758776)
* Support modern utilities for finding free TCP ports for tests (r1684649)
* The C test scheduler is more efficient in SMP environments (r1775555)
* The C tests convert paths from/to UTF-8 more efficiently (r1775642)
* Add INSTALL instructions for building with OpenSSL 1.1.0 (r1778313)
* Improved INSTALL instructions for Windows (r1703470, -2, -3, -4, et al)
* Updated INSTALL instructions (r1691712)
* windows: Support Visual Studio 2017 (r1786653, r1786669)
* gnome-keyring: Support libsecret in preference to libgnome-keyring
(r1798004)
* kwallet: Support KDE 5 in preference to KDE 4 (r1798731)
* kwallet: Fix KDE5 support with clang 3.8 (r1802536 et al)
* kwallet: Add --with-kwallet=INCDIR:LIBDIR build option (r1802646)
* Rename cxxhl bindings 'make tests' to avoid confusion with 'make test'
(r1800849)
* 'make check': Allow testing with FSFS compression (r1801936)
* svnserveautocheck.sh: Support out-of-tree builds when running a single
test file (r1802081)
* Distribution artifacts now prepared with swig 3.0.10 (r1802135)
* SQLite: Use https:// links to download amalgamation sources (r1817043)
* Create reproducible tarballs (r1804618 et al)
* Disable static builds of the apache and auth provider modules (r1802612)
* utf8proc: Update to version 2.1.0 (r1809090 et al)
* utf8proc: Build against the system library by default (r1803210 et al)
- API changes:
* New svn_client_conflict_* API functions for the new conflict resolver.
* New svn_repos_fs_get_mergeinfo2() with streamy access (r1780810 et al)
* New streamy svn_repos_get_logs5() API function (r1730389, -1163)
* New streamy svn_fs_paths_changed3() API function (r1727822, r1745055)
* New svn_client_list4() API function (r1767186)
* New svn_ra_list() API function (r1767190)
* New svn_repos_list() API function (r1765088)
* New svn_stream_contents_checksum() API function (r1755486, -6651)
* New svn_io_file_get_offset() API function (r1719269)
* New svn_base64_encode2 API function (r1711517)
* New svn_fs_create2() API function (r1710631)
* New svn_string_from_stream2() API function (r1710065)
* New svn_io_write_atomic2() API function (r1703142)
* New svn_stream_for_stdin2() API function (r1702983)
* New svn_io_file_rename2() API function (r1701017)
* New svn_error_quick_wrapf() API function (r1662668)
* New svn_repos_path_change_t type (r1802114)
* New svn_repos_log_entry_t type (r1802114)
* New svn_cstring_join2() API (r1806041)
* New svn_txdelta_to_svndiff_stream() API (r1803140 et al)
* svn_repos_parse_dumpstream3() now accepts NULL pointers (r1700180)
* Return resettable streams from svn_stream_checksummed2(). (r1804807)
* Fix svnserveautocheck&davautocheck when time is only a built-in (r1665652)
- Bindings:
* Configure the swig bindings only if swig has been enabled (r1751167)
* Error if 'configure --with-swig' is used and swig is not found (r1700844)
* Perl: Fix build with libraries in non-standard LD_LIBRARY_PATH (r1781588)
* JavaHL can now get revision properties along with log messages (r1780819)
* JavaHL: Allow access to constructors of a couple JavaHL classes (r1739704)
* JavaHL: Correct some JNIEntry method names (r1706738)
* Allow swig bindings scripts to configure the FSFS cache (r1709922)
* Disable some swig wrappers that aren't working (r1700966)
* JavaHL: Make StringArray nullable (r1785429)
* JavaHL: Add missing exception checks (r1801108)
* Ruby: Fix handling of NULL MD5 digests (r1811786)
* Ruby: Detect versions up to 2.4 (r1806570)
Version 1.9.7
(10 Aug 2017, from /branches/1.9.x)
http://svn.apache.org/repos/asf/subversion/tags/1.9.7
@ -994,6 +1282,51 @@ http://svn.apache.org/repos/asf/subversion/tags/1.9.0
* javahl: allow compiling with a C++11 compiler (r1684412)
Version 1.8.19
(10 Aug 2017, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.19
User-visible changes:
- Client-side bugfixes:
* Fix arbitrary code execution vulnerability CVE-2017-9800
See <https://subversion.apache.org/security/CVE-2017-9800-advisory.txt>
for details.
- Server-side bugfixes:
(none)
- Bindings bugfixes:
(none)
Developer-visible changes:
- General:
(none)
- API changes:
(none)
Version 1.8.18
(10 Jul 2017, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.18
User-visible changes:
- Server-side bugfixes:
* fsfs: never attempt to share directory representations (r1785053)
* fsfs: make consistency independent of hash algorithms (r1785737 et al)
This change makes Subversion resilient to collision attacks, including
SHA-1 collision attacks such as <http://shattered.io/>. See also our
documentation at <https://subversion.apache.org/faq#shattered-sha1> and
<https://subversion.apache.org/docs/release-notes/1.8#shattered-sha1>.
- Client-side and server-side bugfixes:
* work around an APR bug related to file truncation (r1759116)
Developer-visible changes:
- General:
* update serf download URI in build scripts (r1700130 et al)
Version 1.8.17
(29 Nov 2016, from /branches/1.8.x)
http://svn.apache.org/repos/asf/subversion/tags/1.8.17
@ -2666,7 +2999,7 @@ the 1.6 release: http://subversion.apache.org/docs/release-notes/1.7.html
* fixed: ra_serf doesn't support http-auth-types config (issue #3435)
* fixed: merge sets incorrect mergeinfo on skipped paths (issue #3440)
* fixed: ra_serf inconsistent handling of cached authn creds (issue #3450)
* fixed: ra_serf sefault with using NTLM or Negotiate auth (r876910)
* fixed: ra_serf segfault with using NTLM or Negotiate auth (r876910)
* fixed: excluded subtrees are not detected by svnversion (issue #3461)
* fixed: submitting a changelist while obstructed item exists (issue #3484)
* fixed: crash when changing an external's URL (issue #3530)

View File

@ -19,7 +19,7 @@ Blanket commit access:
fitz Brian W. Fitzpatrick <fitz@red-bean.com>
daniel Daniel Stenberg <daniel@haxx.se>
cmpilato C. Michael Pilato <cmpilato@collab.net>
philip Philip Martin <philip.martin@wandisco.com>
philip Philip Martin <philip@apache.org>
jerenkrantz Justin Erenkrantz <justin@erenkrantz.com>
rooneg Garrett Rooney <rooneg@electricjellyfish.net>
blair Blair Zajac <blair@orcaware.com>
@ -27,14 +27,13 @@ Blanket commit access:
dlr Daniel Rall <dlr@finemaltcoding.com>
mbk Mark Benedetto King <mbk@lowlatency.com>
jaa Jani Averbach <jaa@iki.fi>
julianfoad Julian Foad <julian.foad@wandisco.com>
julianfoad Julian Foad <julian@foad.me.uk>
jszakmeister John Szakmeister <john@szakmeister.net>
ehu Erik Hülsmann <ehuels@gmail.com>
breser Ben Reser <ben@reser.org>
maxb Max Bowsher <maxb1@ukf.net>
dberlin Daniel Berlin <dberlin@dberlin.org>
danderson David Anderson <david.anderson@natulte.net>
ivan Ivan Zhakov <chemodax@gmail.com>
djames David James <james@cs.toronto.edu>
pburba Paul Burba <pburba@collab.net>
glasser David Glasser <glasser@davidglasser.net>
@ -48,17 +47,20 @@ Blanket commit access:
kou Kouhei Sutou <kou@cozmixng.org>
danielsh Daniel Shahaf <d.s@daniel.shahaf.name>
peters Peter Samuelson <peter@p12n.org>
rhuijben Bert Huijben <rhuijben@collab.net>
rhuijben Bert Huijben <rhuijben@apache.org>
stylesen Senthil Kumaran S <stylesen@gmail.com>
steveking Stefan Küng <tortoisesvn@gmail.com>
neels Neels J. Hofmeyr <neels@elego.de>
neels Neels J. Hofmeyr <neels@hofmeyr.de>
jwhitlock Jeremy Whitlock <jcscoobyrs@gmail.com>
sbutler Stephen Butler <sbutler@elego.de>
dannas Daniel Näslund <dannas@dannas.name>
stefan2 Stefan Fuhrmann <stefan.fuhrmann@wandisco.com>
stefan2 Stefan Fuhrmann <stefan2@apache.org>
jcorvel Johan Corveleyn <jcorvel@gmail.com>
trent Trent Nelson <trent@snakebite.org>
kotkov Evgeny Kotkov <evgeny.kotkov@visualsvn.com>
astieger Andreas Stieger <andreas.stieger@gmx.de>
jamessan James McCoy <jamessan@jamessan.com>
luke1410 Stefan Hett <luke1410@posteo.de>
[[END ACTIVE FULL COMMITTERS. LEAVE THIS LINE HERE; SCRIPTS LOOK FOR IT.]]
@ -76,6 +78,7 @@ Full committers who have asked to be listed as dormant:
malcolm Malcolm Rowe <malcolm-svn-dev@farside.org.uk>
naked Nuutti Kotivuori <naked@iki.fi>
ringstrom Tobias Ringström <tobias@ringstrom.mine.nu>
ivan Ivan Zhakov <chemodax@gmail.com>
Partial committers who have asked to be listed as dormant:
@ -100,6 +103,7 @@ 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:
@ -164,14 +168,14 @@ Commit access for specific areas:
humbedooh Daniel Gruno <humbedooh@apache.org> (svnpubsub)
prabhugs Prabhu Gnana Sundar <pprabhugs@gmail.com> (verify-keep-going)
schabi Markus Schaber <schabi@apache.org> (testsuite)
gbg Gabriela Gibson <gabriela.gibson@gmail.com> (gtest)
gbg Gabriela Gibson <gabriela.gibson@gmail.com> (gtest)
lyalyakin Pavel Lyalyakin <pavel.lyalyakin@visualsvn.com> (site)
Translation of message files:
niqueco Nicolás Lichtmaier <nick@reloco.com.ar> (po: es)
luebbe Lübbe Onken <luebbe@tigris.org> (po: de)
jensseidel Jens Seidel <jensseidel@users.sf.net> (po: de)
astieger Andreas Stieger <andreas.stieger@gmx.de> (po: de)
oyvindmo Øyvind Møll <svn@moll.no> (po: nb)
sunny256 Øyvind A. Holm <sunny@sunbase.org> (po: nb)
jzgoda Jaroslaw Zgoda <jzgoda@o2.pl> (po: pl)
@ -188,8 +192,7 @@ Commit access for specific areas:
lark Wang Jian <lark@linux.net.cn> (po: zh_CN) [EMAIL
IS BOUNCING]
giorgio_valoti Giorgio Valoti <giorgio_v@mac.com> (po: it)
nebiac Federico Nebiacolombo <cint1@amsjv.it> (po: it) [EMAIL
IS BOUNCING]
nebiac Federico Nebiacolombo <cint1@amsjv.it> (po: it)
fabien Fabien Coelho <fabien@coelho.net> (po: fr)
marcelg Marcel Gosselin <marcel.gosselin@polymtl.ca> (po: fr)
mattiase Mattias Engdegård <mattiase@acm.org> (po: sv)

View File

@ -3,7 +3,7 @@
A Quick Guide
======================================
$LastChangedDate: 2015-12-12 04:00:43 +0000 (Sat, 12 Dec 2015) $
$LastChangedDate: 2017-12-25 04:00:08 +0000 (Mon, 25 Dec 2017) $
Contents:
@ -22,7 +22,7 @@ Contents:
E. Building the Latest Source under Windows
III. BUILDING A SUBVERSION SERVER
A. Setting Up Apache
A. Setting Up Apache Httpd
B. Making and Installing the Subversion Server
C. Configuring Apache for Subversion
D. Running and Testing
@ -55,7 +55,7 @@ I. INTRODUCTION
'installers' for both Windows and OS X. Visit this page for
package links:
http://subversion.apache.org/packages.html
https://subversion.apache.org/packages.html
For those of you who still wish to build from source, Subversion
follows the Unix convention of "./configure && make", but it has
@ -96,9 +96,9 @@ I. INTRODUCTION
These diff streams are used everywhere -- over the network,
in the repository, and in the client's working copy.
* libserf (OPTIONAL for client)
* Apache Serf (OPTIONAL for client)
The Serf library allows the Subversion client to send HTTP
The Apache Serf library allows the Subversion client to send HTTP
requests. This is necessary if you want your client to access
a repository served by the Apache HTTP server. There is an
alternate 'svnserve' server as well, though, and clients
@ -110,10 +110,16 @@ I. INTRODUCTION
* OpenSSL (OPTIONAL for client and server)
OpenSSL enables your client to access SSL-encrypted https://
URLs (using libserf) in addition to unencrypted http:// URLs.
URLs (using Apache Serf) in addition to unencrypted http:// URLs.
To use SSL with Subversion's WebDAV server, Apache needs to be
compiled with OpenSSL as well.
* Netwide Assembler (OPTIONAL for client and server)
The Netwide Assembler (NASM) is used to build the (optionally)
assembler modules of OpenSSL. As of OpenSSL 1.1.0 NASM is the
only supported assembler.
* Berkeley DB (OPTIONAL for client and server)
There are two different repository 'back-end'
@ -185,7 +191,7 @@ I. INTRODUCTION
Subversion's own configure script may need to be told where to find
them, if they were not installed in standard system locations.
Note: there are optional dependencies (such as openssl, swig, and httpd)
Note: there are optional dependencies (such as OpenSSL, swig, and httpd)
which get-deps.sh does not download.
Note: Because previous builds of Subversion may have installed older
@ -202,7 +208,7 @@ I. INTRODUCTION
If you do not have a pre-installed APR and APR-util, you will need
to get these yourself:
http://apr.apache.org/download.cgi
https://apr.apache.org/download.cgi
On Unix systems, if you already have the APR libraries compiled and do
not wish to regenerate them from source code, then Subversion needs to
@ -271,11 +277,11 @@ I. INTRODUCTION
newer. The autogen.sh script knows about that.
5. Serf library 1.3.4 or newer (OPTIONAL)
5. 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
serf. Though optional, we strongly recommend this.
Apache Serf. Though optional, we strongly recommend this.
In order to use ra_serf, you must install serf, and run Subversion's
./configure with the argument --with-serf. If serf is installed in a
@ -285,31 +291,31 @@ I. INTRODUCTION
instead.
Serf can be obtained via your system's package distribution
Apache Serf can be obtained via your system's package distribution
system or directly from http://code.google.com/p/serf/.
For more information on serf and Subversion's ra_serf, see the file
subversion/libsvn_ra_serf/README.
For more information on Apache Serf and Subversion's ra_serf, see the
file subversion/libsvn_ra_serf/README.
6. OpenSSL (OPTIONAL)
### needs some updates. I think serf automagically handles
### needs some updates. I think Apache Serf automagically handles
### finding OpenSSL, but we may need more docco here. and w.r.t
### zlib.
The Serf library has support for SSL encryption by relying on the
The Apache Serf library has support for SSL encryption by relying on the
OpenSSL library.
a. Using OpenSSL on the client through Serf
a. Using OpenSSL on the client through Apache Serf
On Unix systems, to build Serf with OpenSSL, you need OpenSSL
On Unix systems, to build Apache Serf with OpenSSL, you need OpenSSL
installed on your system, and you must add "--with-ssl" as a
"./configure" parameter. If your OpenSSL installation is hard
for Serf to find, you may need to use "--with-libs=/path/to/lib"
in addition. In particular, on Red Hat (but not Fedora Core) it
is necessary to specify "--with-libs=/usr/kerberos" for OpenSSL
to be found. You can also specify a path to the zlib library
using "--with-libs".
for Apache Serf to find, you may need to use
"--with-libs=/path/to/lib" in addition. In particular, on Red Hat
(but not Fedora Core) it is necessary to specify
"--with-libs=/usr/kerberos" for OpenSSL to be found. You can also
specify a path to the zlib library using "--with-libs".
Under Windows, you can specify the paths to these libraries by
passing the options --with-zlib and --with-openssl to gen-make.py.
@ -334,7 +340,7 @@ I. INTRODUCTION
including instructions for building and packaging on both Unix
systems and Windows, at:
http://www.openssl.org/
https://www.openssl.org/
7. Berkeley DB 4.X (OPTIONAL)
@ -358,7 +364,7 @@ I. INTRODUCTION
You'll need Berkeley DB installed on your system. You can
get it from:
http://www.oracle.com/technology/software/products/berkeley-db/index.html
http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/overview/index.html
If you have Berkeley DB installed in a place not searched by default
for includes and libraries, add something like this:
@ -393,7 +399,7 @@ I. INTRODUCTION
9. Apache Web Server 2.2.X or newer (OPTIONAL)
(http://httpd.apache.org/download.cgi)
(https://httpd.apache.org/download.cgi)
The Apache httpd server is one of two methods to make your Subversion
repository available over a network - the other is a custom server
@ -404,7 +410,7 @@ I. INTRODUCTION
is done: See section III for details.
10. Python 2.7 or newer (http://www.python.org/) (OPTIONAL)
10. Python 2.7 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,
@ -424,7 +430,7 @@ I. INTRODUCTION
12. SQLite (REQUIRED)
Subversion requires SQLite version 3.7.12 or above. You can meet this
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.
@ -435,7 +441,7 @@ I. INTRODUCTION
--with-sqlite configure option. This file also ships with the Subversion
dependencies distribution, or you can download it from SQLite:
http://www.sqlite.org/download.html
https://www.sqlite.org/download.html
13. pkg-config (Unix only, OPTIONAL)
@ -521,6 +527,19 @@ I. INTRODUCTION
$ ./get-dep.sh gmock
22. LZ4 (OPTIONAL)
Subversion uses LZ4 compression libary version r129 or above. Configure
will attempt to locate the system library by default using pkg-config
and known paths.
If it is installed in a non-standard location, then use:
--with-lz4=/path/to/liblz4
If configure should use the version bundled with the sources, use:
--with-lz4=internal
D. Documentation
The primary documentation for Subversion is the free book
@ -542,7 +561,7 @@ II. INSTALLATION
Download the most recent distribution tarball from:
http://subversion.apache.org/download/
https://subversion.apache.org/download/
Unpack it, and use the standard GNU procedure to compile:
@ -674,27 +693,21 @@ II. INSTALLATION
D. Installing from a Zip or Installer File under Windows
--------------------------------------------------------
-----------------------------------------------------
Of all the ways of getting a Subversion client, this is the
easiest. Download a Zip (*.zip) or self-extracting installer
(*-setup.exe) file from:
easiest. Download a Zip or self-extracting installer via:
http://subversion.apache.org/packages#windows
https://subversion.apache.org/packages.html#windows
For a Zip file, run your unzipping utility (WinZIP, ZipGenius,
UltimateZIP, FreeZIP, whatever) and extract the DLLs and EXEs to
a directory of your choice. Included in the download is the SVN
client, the SVNADMIN administration tool, and the SVNLOOK
reporting tool.
For a Zip file extract the DLLs and EXEs to a directory of your
choice. Included in the download are among other tools the SVN
client, the SVNADMIN administration tool and the SVNLOOK reporting
tool.
Note that if you need support for non-English locales you'll have
to set the APR_ICONV_PATH environment variable to the path of the
iconv directory in the folder that contains the Subversion install.
You may also want to add the bin directory in the Subversion folder
to your PATH environment variable so as to not have to use the full
path when running Subversion commands.
You may want to add the bin directory in the Subversion folder to your
PATH environment variable so as to not have to use the full path when
running Subversion commands.
To test the installation, open a DOS box (run either "cmd" or
"command" from the Start menu's "Run..." menu option), change to
@ -713,58 +726,41 @@ II. INSTALLATION
E.1 Prerequisites
* Visual Studio 6 and service pack. It can be built with later versions
of Visual Studio (Visual Studio.NET 2005-2015, Visual C++ Express
2005-2010, Visual Studio Express 2012-2013 and Visual Studio Community
2013-2015) but these instructions assume VS6.
* A recent Windows SDK. (Not needed with Visual Studio 2005 and later)
If you are using Visual Studio 6, you need the latest SDK which
is compatible with VC6, which is the one from February 2003.
You can get it from MSDN:
https://social.msdn.microsoft.com/Forums/windowsdesktop/en-US/e1147034-9b0b-4494-a5bc-6dfebb6b7eb1/download-and-install-microsoft-platform-sdk-febuary-2003-last-version-with-vc6-support?forum=windowssdk
* Python 2.7 or higher, downloaded from http://www.python.org/ which is
* Microsoft Visual Studio. Any recent (2005+) version containing the
Visual C++ component will work (E.g. Professional, Express, Community
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 http://www.activestate.com/
* Awk (from http://www.cs.princeton.edu/~bwk/btl.mirror/awk95.exe) is
needed to compile Apache or APR. Note that this is the actual awk
program, not an installer - just rename it to awk.exe and it is
ready to use.
* 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. Included in both the Subversion dependencies ZIP file
and the Apache 2 source zip. If you are building from a Subversion
1.3 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 http://www.apache.org/dist/apr/.
* SQLite 3.7.12 or higher from http://www.sqlite.org/download.html
* ZLib 1.2 or higher is required and is included in the Subversion
dependencies zip file or can be obtained from http://www.zlib.net/
* Either a Subversion client binary from http://subversion.apache.org/ to
do the initial checkout of the Subversion source or the zip file
source distribution. See the section "Bootstrapping from a Zip or
Installer File under Windows" above for more.
* A means of unpacking the files, e.g., WinZIP or similar.
from https://www.apache.org/dist/apr/.
* SQLite 3.8.2 or higher from https://www.sqlite.org/download.html
(3.8.11.1 or higher recommended)
* ZLib 1.2 or higher is required and can be obtained from
http://www.zlib.net/
* Either a Subversion client binary from
https://subversion.apache.org/packages.html to do the initial checkout
of the Subversion source or the zip file source distribution.
Additional Options
* [Optional] Apache 2 source, downloaded from
http://httpd.apache.org/download.cgi, these instructions assume
* [Optional] Apache Httpd 2 source, downloaded from
https://httpd.apache.org/download.cgi, these instructions assume
version 2.0.58. This is only needed for building the Subversion
server Apache modules. ### FIXME Apache 2.2 or greater required.
* [Optional] Apache 2 msi install file, also from
http://httpd.apache.org/download.cgi (required for running the
tests). Only needed for testing the server dso modules and if
you are using Visual Studio 6.
Note that if you are not using Visual Studio 6 (and you want to
run and test the server modules) then you must rebuild Apache
from source -- do not use the stock MSI since mixing C runtime
libraries is not supported.
* [Optional] Berkeley DB for backend support of the server
components -- versions 4.3.27 and 4.4.20 are available from
http://subversion.tigris.org/servlets/ProjectDocumentList?folderID=688
as db-4.3.27-win32.zip and db-4.4.20-win32.zip.
* [Optional] Berkeley DB for backend support of the server components
are available from
http://www.oracle.com/technetwork/database/database-technologies/berkeleydb/downloads/index-082944.html
(Version 4.4.20 or in specific cases some higher version recommended)
For more information see Section I.C.7.
* [Optional] Openssl 0.9.7f or higher can be obtained from
http://www.openssl.org/source/openssl-0.9.7f.tar.gz
* [Optional] Openssl can be obtained from https://www.openssl.org/source/
* [Optional] NASM can be obtained from http://www.nasm.us/
* [Optional] A modified version of GNU libintl, called
svn-win32-libintl.zip, can be used for displaying localized
messages. Available at:
@ -774,14 +770,11 @@ II. INSTALLATION
binaries from http://gnuwin32.sourceforge.net/. You'll need the
binaries (gettext-0.14.1-bin.zip) and dependencies
(gettext-0.14.1-dep.zip).
* [Optional] An assembler, e.g., MASM32 from http://www.masm32.com/
or nasm which is available from
http://www.nasm.us/pub/nasm/releasebuilds/?C=M;O=D
E.2 Notes
The Serf library supports secure connections with OpenSSL and
on-the-wire compression with zlib. If you want to use the
The Apache Serf library supports secure connections with OpenSSL
and on-the-wire compression with zlib. If you want to use the
secure connections feature, you should pass the option
"--with-openssl" to the gen-make.py script. See Section I.C.6 for
more details.
@ -802,35 +795,20 @@ II. INSTALLATION
installer to register environment variables or run VCVARS32.BAT
before building anything. If you are using a newer Visual Studio,
use the 'Visual Studio 20xx Command Prompt' on the Start menu.
* Install and register a recent Windows Core SDK if you are using
Visual Studio 6. This is a quote from the Microsoft February 2003
SDK documentation:
"To register the SDK bin, include, and library directories with
Microsoft Visual Studio® version 6.0 and Visual Studio .NET,
click Start, point to All Programs, point to Microsoft Platform
SDK February 2003, point to Visual Studio Registration, and then
click Register PSDK Directories with Visual Studio. This
registration process places the SDK bin, include, and library
directories at the beginning of the search paths, which ensures
that the latest headers and libraries are used when building
applications in the IDE. Note that for Visual Studio 6.0
integration to succeed, Visual Studio 6.0 must run at least once
before you select Register PSDK Directories with Visual
Studio. Also note that when this option is run, the IDEs should
not be running."
* Install Python and add it to your path
* Install Perl (it should add itself to the path)
### Subversion doesn't need perl. Only some dependencies need it
(OpenSSL and some apr scripts)
* Copy AWK (awk95.exe) to awk.exe (e.g. SVN\awk\awk.exe) and add
the directory containing it (e.g. SVN\awk) to the path.
* [Optional] Install Apache 2 using the msi file if you are going to test
the server dso modules and are using Visual Studio 6. You must build
and install it from source if you are not using Visual Studio 6 and
want to build and/or test the server modules.
### Subversion doesn't need awk. Only some dependencies need it
(some apr scripts)
* [Optional] Install NASM and add it to your path
### Subversion doesn't need NASM. Only some dependencies need it
optionally (OpenSSL)
* [Optional] If you checked out Subversion from the repository and want
to build Subversion with http/https access support then install the
serf sources into SVN\src-trunk\serf.
Apache Serf sources into SVN\src-trunk\serf.
* [Optional] If you want BDB backend support, extract the Berkeley DB
files into SVN\src-trunk\db4-win32. It's a good idea to add
SVN\src-trunk\db4-win32\bin to your PATH, so that Subversion can find
@ -846,6 +824,7 @@ II. INSTALLATION
SVN\src-trunk\db4-win32\include, and all the import libraries to
SVN\src-trunk\db4-win32\lib. Again, the DLLs should be somewhere in
your path.
### Just use --with-serf instead of the hardcoded path
* [Optional] If you want to build the server modules, extract Apache
source into SVN\httpd-2.x.x.
@ -858,22 +837,22 @@ II. INSTALLATION
- Extract the apr, apr-util and apr-iconv directories from the
srclib folder in the Apache httpd source into SVN\apr,
SVN\apr-util, and SVN\apr-iconv respectively.
### Just use --with-apr, etc. instead of the hardcoded paths
* Extract the ZLib sources into SVN\zlib if you are not using the zlib
included in the dependencies zip file.
* [Optional] If you want secure connection (https) client support, or if
you are building with enabled support for serf extract openssl into
SVN\openssl-x.x.x
### Just use --with-zlib instead of the hardcoded path
* [Optional] If you want secure connection (https) client support extract
OpenSSL into SVN\openssl
### And pass the path to both serf and gen-make.py
* [Optional] If you want localized message support, extract
svn-win32-libintl.zip into SVN\svn-win32-libintl and extract
gettext-x.x.x-bin.zip and gettext-x.x.x-dep.zip into
SVN\gettext-x.x.x-bin.
Add SVN\gettext-x.x.x-bin\bin to your path.
* [Optional] Extract MASM32 (only the ML.EXE and ML.ERR files) into
SVN\asm (or extract nasm into SVN\asm) and put it in your path.
* Download the SQLite amalgemation from
http://www.sqlite.org/download.html
and extract it into SVN\sqlite-amalgemation.
See I.C.12 for alternatives to using the amalgemation package.
Add SVN\gettext-x.x.x-bin\bin to your path.
* Download the SQLite amalgamation from
https://www.sqlite.org/download.html
and extract it into SVN\sqlite-amalgamation.
See I.C.12 for alternatives to using the amalgamation package.
E.4 Building the Binaries
@ -890,7 +869,7 @@ II. INSTALLATION
C:>set VER=trunk
C:>set DIR=trunk
C:>set BUILD_ROOT=C:\SVN
C:>set PYTHONDIR=C:\Python22
C:>set PYTHONDIR=C:\Python27
C:>set AWKDIR=C:\SVN\Awk
C:>set ASMDIR=C:\SVN\asm
C:>set SDKINC="C:\Program Files\Microsoft SDK\include"
@ -901,9 +880,9 @@ II. INSTALLATION
C:>set INCLUDE=%SDKINC%;%INCLUDE%
C:>set LIB=%SDKLIB%;%LIB%
OpenSSL
OpenSSL < 1.1.0
C:>cd openssl-0.9.7f
C:>cd openssl
C:>perl Configure VC-WIN32
[*] C:>call ms\do_masm
C:>nmake -f ms\ntdll.mak
@ -913,11 +892,23 @@ II. INSTALLATION
*Note: Use "call ms\do_nasm" if you have nasm instead of MASM, or
"call ms\do_ms" if you don't have an assembler.
Also if you are using OpenSSL >= 1.0.0 masm is no longer
supported. You will have to use do_nasm or do_ms in this case.
OpenSSL >= 1.1.0
C:>cd openssl
C:>perl Configure VC-WIN32
C:>nmake
C:>nmake test
C:>cd ..
Apache 2
This step is only required for building the server dso modules.
### FIXME Apache 2.2 or greater required. Old build instructions for VC6.
C:>set APACHEDIR=C:\Program Files\Apache Group\Apache2
C:>msdev httpd-2.0.58\apache.dsw /MAKE "BuildBin - Win32 Release"
@ -946,11 +937,11 @@ II. INSTALLATION
Note that you'd make sure to define ZLIB_WINAPI in the ZLib config
header and move the lib-file into the zlib root-directory.
Serf
Apache Serf
### Section about serf might be required/useful to add.
### scons is required too and serf needs to be configured prior to be
### able to build Subversion using:
### Section about Apache Serf might be required/useful to add.
### scons is required too and Apache Serf needs to be configured prior to
### be able to build Subversion using:
### scons APR=[PATH_TO_APR] APU=[PATH_TO_APU] OPENSSL=[PATH_TO_OPENSSL]
### ZLIB=[PATH_TO_ZLIB] PREFIX=[PATH_TO_SERF_DEST]
### scons check
@ -967,28 +958,16 @@ II. INSTALLATION
the APR libraries; the options are --with-apr, --with-apr-util and
--with-apr-iconv.
* If you would like a debug build substitute Debug for Release in
the msdev/msbuild commands.
the msbuild command.
* There have been rumors that Subversion on Win32 can be built
using the latest cygwin, you probably don't want the zip file source
distribution though. ymmv.
* The /USEENV switch to msdev makes it take notice of the INCLUDE and
LIB environment variables, it also makes it ignore its own lib and
include settings so you need to have the Windows SDK lib and include
directories in the LIB and INCLUDE environment variables. Do *not*
use this switch when starting up the msdev Visual environment. If you
wish to build in the Visual environment the SDK lib and include
directories must be in the Tools/Options/Directories settings (if you
followed the 'Register the SDK with Visual Studio 6' instructions
above this has been done for you).
* If you are using Visual Studio later than VC6 change -t dsw into
-t vcproj and add the --vsnet-version=20xx option on the gen-make.py
command.
In this case you will also have to distribute the C runtime dll with
the binaries. Also, since Apache/APR do not provide .vcproj files,
you will need to convert the Apache/APR .dsp files to .vcproj files
with Visual Studio before building -- just open the Apache .dsw file
and answer 'Yes To All' when the conversion dialog pops up, or you
can open the individual .dsp files and convert them one at a time.
* You will also have to distribute the C runtime dll with the binaries.
Also, since Apache/APR do not provide .vcproj files, you will need to
convert the Apache/APR .dsp files to .vcproj files with Visual Studio
before building -- just open the Apache .dsw file and answer 'Yes To
All' when the conversion dialog pops up, or you can open the individual
.dsp files and convert them one at a time.
The Apache/APR projects required by Subversion are:
apr-util\libaprutil.dsp, apr\libapr.dsp,
apr-iconv\libapriconv.dsp, apr-util\xml\expat\lib\xml.dsp,
@ -1003,24 +982,13 @@ II. INSTALLATION
gen-make.py will already have been run. If the source is from the zip
file, Apache 2 has not been built so gen-make.py must be run:
C:>python gen-make.py -t dsp --with-berkeley-db=db4-win32
--with-openssl=..\openssl-0.9.7f --with-zlib=..\zlib
C:>python gen-make.py --vsnet-version=20xx --with-berkeley-db=db4-win32
--with-openssl=..\openssl --with-zlib=..\zlib
--with-libintl=..\svn-win32-libintl
Then build subversion:
C:>msdev subversion_msvc.dsw /USEENV /MAKE "__ALL_TESTS__ - Win32 Release"
C:>cd ..
Or, with Visual C++.NET 2005 or C++ Express 2005:
C:>devenv subversion_vcnet.sln /build "Release" /project "__ALL_TESTS__"
C:>cd ..
Or, with Visual C++.NET 2008+, C++ Express 2008+, Studio Express 2012+ or
Studio Community 2013+:
C:>msbuild subversion_vcnet.sln /t:__ALL_TESTS__ /p:Configuration=Release
C:>msbuild subversion_vcnet.sln /t:__MORE__ /p:Configuration=Release
C:>cd ..
The binaries have now been built.
@ -1111,10 +1079,10 @@ III. BUILDING A SUBVERSION SERVER
svnserve instead, jump right to section E for a quick explanation.
A. Setting Up Apache
-----------------
A. Setting Up Apache Httpd
-----------------------
1. Obtaining and Installing Apache 2
1. Obtaining and Installing Apache Httpd 2
Subversion tries to compile against the latest released version
of Apache httpd 2.2+. The easiest thing for you to do is download
@ -1123,7 +1091,7 @@ III. BUILDING A SUBVERSION SERVER
If you have questions about the Apache httpd 2.2 build, please consult
the httpd install documentation:
http://httpd.apache.org/docs-2.2/install.html
https://httpd.apache.org/docs-2.2/install.html
At the top of the httpd tree:
@ -1206,8 +1174,8 @@ III. BUILDING A SUBVERSION SERVER
Section II.E explains how to build the server on Windows.
C. Configuring Apache for Subversion
---------------------------------
C. Configuring Apache Httpd for Subversion
---------------------------------------
The following section is an abbreviated version of the
information in the Subversion Book
@ -1221,7 +1189,7 @@ III. BUILDING A SUBVERSION SERVER
/usr/local/apache2/conf/httpd.conf to reflect your setup.
At a minimum you should look at the User, Group and ServerName
directives. Full details on setting up apache can be found at:
http://httpd.apache.org/docs-2.2/
https://httpd.apache.org/docs-2.2/
First, your httpd.conf needs to load the mod_dav_svn module.
If you pass --enable-mod-activation to Subversion's configure,
@ -1279,7 +1247,7 @@ III. BUILDING A SUBVERSION SERVER
These are only a few simple examples. For a complete tutorial
on Apache access control, please consider taking a look at the
tutorials found under "Security" on the following page:
http://httpd.apache.org/docs-2.0/misc/tutorials.html
https://httpd.apache.org/docs-2.0/misc/tutorials.html
In order for 'svn cp' to work (which is actually implemented as a
DAV COPY command), mod_dav needs to be able to determine the
@ -1302,7 +1270,7 @@ III. BUILDING A SUBVERSION SERVER
NOTE: If you are unfamiliar with an Apache directive, or not exactly
sure about what it does, don't hesitate to look it up in the
documentation: http://httpd.apache.org/docs-2.2/mod/directives.html.
documentation: https://httpd.apache.org/docs-2.2/mod/directives.html.
NOTE: Make sure that the user 'nobody' (or whatever UID the
httpd process runs as) has permission to read and write the
@ -1333,7 +1301,7 @@ III. BUILDING A SUBVERSION SERVER
To run the regression test suite for networked Subversion, see
the instructions in subversion/tests/cmdline/README.
For advice about tracing problems, see "Debugging the server" in
http://subversion.apache.org/docs/community-guide/.
https://subversion.apache.org/docs/community-guide/.
E. Alternative: 'svnserve' and ra_svn
@ -1376,11 +1344,11 @@ IV. PLATFORM-SPECIFIC ISSUES
between parent and child processes. The httpd Apache group
explains this a lot better:
http://www.apache.org/dist/httpd/binaries/win32/#xpbug
https://www.apache.org/dist/httpd/binaries/win32/#xpbug
And there's an item about this in the Subversion FAQ:
http://subversion.apache.org/faq.html#windows-xp-server
https://subversion.apache.org/faq.html#windows-xp-server
The only known workaround for now is to update to Windows XP
SP1 (or higher).

View File

@ -366,3 +366,60 @@ subversion/libsvn_subr/x509.h
* LIABILITY, WHETHER IN 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 (modified) 'linenoise' library in tools/dev/svnmover/linenoise
Copyright (c) 2010-2014, Salvatore Sanfilippo <antirez at gmail dot com>
Copyright (c) 2010-2013, Pieter Noordhuis <pcnoordhuis at gmail dot com>
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN 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 (modified) LZ4 library files in subversion/libsvn_subr/lz4
LZ4 Library
Copyright (c) 2011-2016, Yann Collet
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
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.

View File

@ -54,6 +54,8 @@ SVN_SERF_LIBS = @SVN_SERF_LIBS@
SVN_SQLITE_LIBS = @SVN_SQLITE_LIBS@
SVN_XML_LIBS = @SVN_XML_LIBS@
SVN_ZLIB_LIBS = @SVN_ZLIB_LIBS@
SVN_LZ4_LIBS = @SVN_LZ4_LIBS@
SVN_UTF8PROC_LIBS = @SVN_UTF8PROC_LIBS@
LIBS = @LIBS@
@ -130,14 +132,16 @@ INCLUDES = -I$(top_srcdir)/subversion/include -I$(top_builddir)/subversion \
@SVN_DB_INCLUDES@ @SVN_GNOME_KEYRING_INCLUDES@ \
@SVN_KWALLET_INCLUDES@ @SVN_MAGIC_INCLUDES@ \
@SVN_SASL_INCLUDES@ @SVN_SERF_INCLUDES@ @SVN_SQLITE_INCLUDES@ \
@SVN_XML_INCLUDES@ @SVN_ZLIB_INCLUDES@
@SVN_XML_INCLUDES@ @SVN_ZLIB_INCLUDES@ @SVN_LZ4_INCLUDES@ \
@SVN_UTF8PROC_INCLUDES@
APACHE_INCLUDES = @APACHE_INCLUDES@
APACHE_LIBEXECDIR = $(DESTDIR)@APACHE_LIBEXECDIR@
APACHE_LDFLAGS = @APACHE_LDFLAGS@
SVN_USE_GMOCK = @SVN_USE_GMOCK@
GMOCK_INCLUDES = -I@GMOCK_SRCDIR@
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)
SWIG = @SWIG@
SWIG_PY_INCLUDES = @SWIG_PY_INCLUDES@ -I$(SWIG_SRC_DIR)/python/libsvn_swig_py
@ -186,7 +190,10 @@ CXXMAINTAINERFLAGS = @CXXMAINTAINERFLAGS@
CPPFLAGS = @CPPFLAGS@ $(EXTRA_CPPFLAGS)
LDFLAGS = @LDFLAGS@ $(EXTRA_LDFLAGS)
SWIG_LDFLAGS = @SWIG_LDFLAGS@ $(EXTRA_SWIG_LDFLAGS)
SWIG_CPPFLAGS = @SWIG_CPPFLAGS@ $(EXTRA_CPPFLAGS)
SWIG_FEATURES = @SWIG_FEATURES@
SWIG_PY_FEATURES = @SWIG_PY_FEATURES@
SWIG_PL_FEATURES = @SWIG_PL_FEATURES@
SWIG_RB_FEATURES = @SWIG_RB_FEATURES@
COMPILE = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CMAINTAINERFLAGS) $(CFLAGS) $(INCLUDES)
COMPILE_NOWARN = $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CNOWARNFLAGS) $(CFLAGS) $(INCLUDES)
@ -199,7 +206,9 @@ LT_COMPILE_CXX_NOWARN = $(LIBTOOL) $(LTCXXFLAGS) --mode=compile $(COMPILE_CXX_NO
LT_EXECUTE = $(LIBTOOL) $(LTFLAGS) --mode=execute `for f in $(abs_builddir)/subversion/*/*.la; do echo -dlopen $$f; done`
# special compilation for files destined for mod_dav_svn
COMPILE_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CFLAGS) $(CMAINTAINERFLAGS) $(LT_CFLAGS) $(APACHE_INCLUDES) $(INCLUDES) -o $@ -c
COMPILE_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=compile $(CC) $(CMODEFLAGS) $(CPPFLAGS) $(CFLAGS) $(CMAINTAINERFLAGS) $(LT_CFLAGS) $(APACHE_INCLUDES) $(INCLUDES) -o $@ -c -shared
COMPILE_SHARED_ONLY_LIB = $(LT_COMPILE) -o $@ -c -shared
COMPILE_SHARED_ONLY_CXX_LIB = $(LT_COMPILE_CXX) -o $@ -c -shared
# special compilation for files destined for libsvn_swig_* (e.g. swigutil_*.c)
COMPILE_SWIG_PY = $(LIBTOOL) $(LTFLAGS) --mode=compile $(SWIG_PY_COMPILE) $(CPPFLAGS) $(LT_CFLAGS) -DSWIGPYTHON $(SWIG_PY_INCLUDES) $(INCLUDES) -o $@ -c
@ -252,8 +261,8 @@ TEST_SHLIB_VAR_SWIG_RB=\
# special compilation for files destined for cxxhl
COMPILE_CXXHL_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) -o $@ -c
COMPILE_GMOCK_CXX = $(LT_COMPILE_CXX_NOWARN) $(GMOCK_INCLUDES) -o $@ -c
COMPILE_CXXHL_GMOCK_CXX = $(LT_COMPILE_CXX) $(CXXHL_INCLUDES) $(GMOCK_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
LINK = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(libdir)
LINK_LIB = $(LINK) $(LT_SO_VERSION)
@ -261,11 +270,9 @@ LINK_CXX = $(LIBTOOL) $(LTCXXFLAGS) --mode=link $(CXX) $(LT_LDFLAGS) $(CXXFLAGS)
LINK_CXX_LIB = $(LINK_CXX) $(LT_SO_VERSION)
# 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)
LINK_APACHE_MOD = $(LIBTOOL) $(LTFLAGS) --mode=link $(CC) $(LT_LDFLAGS) $(CFLAGS) $(LDFLAGS) -rpath $(APACHE_LIBEXECDIR) -avoid-version -module $(APACHE_LDFLAGS) -shared
# Special LDFLAGS for some libraries
libsvn_auth_gnome_keyring_LDFLAGS = @libsvn_auth_gnome_keyring_LDFLAGS@
libsvn_auth_kwallet_LDFLAGS = @libsvn_auth_kwallet_LDFLAGS@
libsvn_client_LDFLAGS = @libsvn_client_LDFLAGS@
libsvn_delta_LDFLAGS = @libsvn_delta_LDFLAGS@
libsvn_diff_LDFLAGS = @libsvn_diff_LDFLAGS@
@ -280,6 +287,10 @@ libsvn_ra_svn_LDFLAGS = @libsvn_ra_svn_LDFLAGS@
libsvn_repos_LDFLAGS = @libsvn_repos_LDFLAGS@
libsvn_subr_LDFLAGS = @libsvn_subr_LDFLAGS@
libsvn_wc_LDFLAGS = @libsvn_wc_LDFLAGS@
shared_only_LDFLAGS = @shared_only_LDFLAGS@
LINK_SHARED_ONLY_LIB = $(LINK_LIB) $(shared_only_LDFLAGS) -shared
LINK_SHARED_ONLY_CXX_LIB = $(LINK_CXX_LIB) $(shared_only_LDFLAGS) -shared
# Compilation of SWIG-generated C source code
COMPILE_PY_WRAPPER = $(LIBTOOL) $(LTFLAGS) --mode=compile $(SWIG_PY_COMPILE) $(LT_CFLAGS) $(CPPFLAGS) $(SWIG_PY_INCLUDES) -prefer-pic -c -o $@
@ -371,6 +382,7 @@ INSTALL_EXTRA_SWIG_RB=\
APXS = @APXS@
HTTPD_VERSION = @HTTPD_VERSION@
HTTPD_WHITELIST = @HTTPD_WHITELIST@
PYTHON = @PYTHON@
PERL = @PERL@
@ -498,17 +510,17 @@ clean-javahl:
check-tigris-javahl: javahl-compat
@FIX_JAVAHL_LIB@
$(TEST_SHLIB_VAR_JAVAHL) \
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_compat_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" org.tigris.subversion.javahl.RunTests
check-apache-javahl: javahl
@FIX_JAVAHL_LIB@
$(TEST_SHLIB_VAR_JAVAHL) \
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" org.apache.subversion.javahl.RunTests
check-deprecated-authn-javahl: javahl
@FIX_JAVAHL_LIB@
$(TEST_SHLIB_VAR_JAVAHL) \
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.tests=$(JAVAHL_TESTS)" "-Dtest.authn.deprecated=true" org.apache.subversion.javahl.RunTests
$(JAVA) -Xcheck:jni "-Dtest.rootdir=$(javahl_test_rootdir)" "-Dtest.srcdir=$(javahl_test_srcdir)" "-Dtest.rooturl=$(BASE_URL)" "-Dtest.fstype=$(FS_TYPE)" "-Djava.library.path=@JAVAHL_OBJDIR@:$(libdir)" -classpath "$(javahl_tests_PATH):$(javahl_tests_CLASSPATH)" "-Dtest.cleanup=$(JAVAHL_CLEANUP)" "-Dtest.tests=$(JAVAHL_TESTS)" "-Dtest.authn.deprecated=true" org.apache.subversion.javahl.RunTests
check-javahl: check-apache-javahl
@ -540,6 +552,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@
if test "$(HTTPD_VERSION)" != ""; then \
flags="--httpd-version $(HTTPD_VERSION) $$flags"; \
fi; \
if test "$(HTTPD_WHITELIST)" != ""; then \
flags="--httpd-whitelist $(HTTPD_WHITELIST) $$flags"; \
fi; \
if test "$(SERVER_MINOR_VERSION)" != ""; then \
flags="--server-minor-version $(SERVER_MINOR_VERSION) $$flags"; \
fi; \
@ -555,6 +570,9 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@
if test "$(PARALLEL)" != ""; then \
flags="--parallel $(PARALLEL) $$flags"; \
fi; \
if test "$(GLOBAL_SCHEDULER)" != ""; then \
flags="--global-scheduler $$flags"; \
fi; \
if test "$(LOG_TO_STDOUT)" != ""; then \
flags="--log-to-stdout $$flags"; \
fi; \
@ -577,6 +595,15 @@ check: bin @TRANSFORM_LIBTOOL_SCRIPTS@ $(TEST_DEPS) @BDB_TEST_DEPS@
if test "$(MEMCACHED_SERVER)" != ""; then \
flags="--memcached-server $(MEMCACHED_SERVER) $$flags"; \
fi; \
if test "$(FSFS_COMPRESSION)" != ""; then \
flags="--fsfs-compression $(FSFS_COMPRESSION) $$flags"; \
fi; \
if test "$(FSFS_DIR_DELTIFICATION)" != ""; then \
flags="--fsfs-dir-deltification $(FSFS_DIR_DELTIFICATION) $$flags";\
fi; \
if test "$(SVN_BIN_DIR)" != ""; then \
flags="--bin $(SVN_BIN_DIR) $$flags"; \
fi; \
LD_LIBRARY_PATH='$(auth_plugin_dirs):$(LD_LIBRARY_PATH)' \
$(PYTHON) $(top_srcdir)/build/run_tests.py \
--config-file $(top_srcdir)/subversion/tests/tests.conf \
@ -656,6 +683,7 @@ check-clean: gcov-clean
rm -rf subversion/tests/libsvn_fs/test-repo-* \
subversion/tests/libsvn_fs_base/test-repo-* \
subversion/tests/libsvn_fs_fs/test-repo-* \
subversion/tests/libsvn_fs_x/test-repo-* \
subversion/tests/libsvn_ra_local/test-repo-* \
subversion/tests/libsvn_repos/test-repo-* \
subversion/tests/libsvn_subr/z \
@ -835,7 +863,7 @@ extraclean-swig-headers: clean-swig-headers
$(SWIG_PL_DIR)/native/Makefile.PL: $(SWIG_SRC_DIR)/perl/native/Makefile.PL.in
./config.status subversion/bindings/swig/perl/native/Makefile.PL
$(SWIG_PL_DIR)/native/Makefile: $(SWIG_PL_DIR)/native/Makefile.PL
$(SWIG_PL_DIR)/native/Makefile: libsvn_swig_perl $(SWIG_PL_DIR)/native/Makefile.PL
cd $(SWIG_PL_DIR)/native; $(PERL) Makefile.PL PREFIX=$(prefix)
# There is a "readlink -f" command on some systems for the same purpose,
@ -844,11 +872,13 @@ $(SWIG_PL_DIR)/native/Makefile: $(SWIG_PL_DIR)/native/Makefile.PL
READLINK_PY=$(PYTHON) -c 'import sys,os; print(os.path.realpath(sys.argv[1]))'
READLINK_PL=$(PERL) -e 'use Cwd; print Cwd::realpath(shift)'
swig-pl_DEPS = autogen-swig-pl libsvn_swig_perl \
$(SWIG_PL_DIR)/native/Makefile
swig-pl: $(swig-pl_DEPS)
swig-pl: autogen-swig-pl $(SWIG_PL_DIR)/native/Makefile
if test "`$(READLINK_PL) $(SWIG_PL_DIR)`" != "`$(READLINK_PL) $(SWIG_PL_SRC_DIR)`"; then \
ln -sf $(SWIG_PL_SRC_DIR)/native/*.c $(SWIG_PL_DIR)/native; \
for f in $(SWIG_PL_SRC_DIR)/native/*.c ; do \
if [ -e "$$f" ] ; then \
ln -sf "$$f" $(SWIG_PL_DIR)/native; \
fi; \
done; \
fi
cd $(SWIG_PL_DIR)/native; $(MAKE) OPTIMIZE="" OTHERLDFLAGS="$(SWIG_LDFLAGS)"
@ -983,4 +1013,11 @@ INSTALL_EXTRA_TOOLS=\
if test "$(DESTDIR)$(bindir)" != "$(DESTDIR)$(toolsdir)"; then \
ln -sf $(bindir)/svnmucc$(EXEEXT) $(DESTDIR)$(toolsdir)/svnmucc$(EXEEXT); \
ln -sf $(bindir)/svnbench$(EXEEXT) $(DESTDIR)$(toolsdir)/svn-bench$(EXEEXT); \
fi
fi; \
printf '\043\041/bin/sh\n%s\n' \
'exec $(bindir)/svnfsfs stats $${2:+"-M"} $${2:+"$$2"} "$$1"' \
> $(DESTDIR)$(toolsdir)/fsfs-stats$(EXEEXT) && \
chmod +x $(DESTDIR)$(toolsdir)/fsfs-stats$(EXEEXT)
# \043\041 is a "#!". It's written this way because gmake and bmake disagree on
# how to include a literal '#' in a command, and because '!' is special to some
# shells.

View File

@ -1,5 +1,5 @@
Apache Subversion
Copyright 2017 The Apache Software Foundation
Copyright 2018 The Apache Software Foundation
This product includes software developed by many people, and distributed
under Contributor License Agreements to The Apache Software Foundation
@ -26,3 +26,6 @@ under a permissive license, see LICENSE.
This software contains code derived from TropicSSL under a BSD 3-Clause
license, see LICENSE.
This product includes code derived from the software developed by Yann Collet
under a BSD 2-Clause license, see LICENSE.

View File

@ -2,7 +2,7 @@
Subversion, a version control system.
=====================================
$LastChangedDate: 2016-05-31 16:08:20 +0000 (Tue, 31 May 2016) $
$LastChangedDate: 2016-05-31 14:07:51 +0000 (Tue, 31 May 2016) $
Contents:

View File

@ -44,7 +44,10 @@ sinclude(build/ac-macros/serf.m4)
sinclude(build/ac-macros/sqlite.m4)
sinclude(build/ac-macros/swig.m4)
sinclude(build/ac-macros/zlib.m4)
sinclude(build/ac-macros/lz4.m4)
sinclude(build/ac-macros/kwallet.m4)
sinclude(build/ac-macros/libsecret.m4)
sinclude(build/ac-macros/utf8proc.m4)
sinclude(build/ac-macros/macosx.m4)
# Include the libtool macros

File diff suppressed because one or more lines are too long

View File

@ -45,7 +45,9 @@ private-includes =
subversion/bindings/cxxhl/src/private/*.hpp
subversion/bindings/javahl/native/*.hpp
subversion/bindings/javahl/native/jniwrapper/jni_*.hpp
subversion/libsvn_subr/utf8proc/utf8proc.h
tools/dev/svnmover/linenoise/linenoise.h
tools/dev/svnmover/linenoise/linenoise.c
subversion/libsvn_subr/utf8proc/utf8proc_internal.h
subversion/libsvn_subr/utf8proc/utf8proc.c
subversion/libsvn_subr/utf8proc/utf8proc_data.c
private-built-includes =
@ -96,9 +98,9 @@ test-scripts =
bdb-test-scripts =
swig-python-opts = $(SWIG_CPPFLAGS) -python -classic
swig-perl-opts = $(SWIG_CPPFLAGS) -perl -nopm -noproxy
swig-ruby-opts = $(SWIG_CPPFLAGS) -ruby
swig-python-opts = $(SWIG_FEATURES) -python $(SWIG_PY_FEATURES) -classic
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
swig-dirs =
subversion/bindings/swig/python
@ -222,7 +224,7 @@ manpages = subversion/svnmucc/svnmucc.1
# Support for GNOME Keyring
[libsvn_auth_gnome_keyring]
description = Subversion GNOME Keyring Library
type = lib
type = shared-only-lib
install = gnome-keyring-lib
path = subversion/libsvn_auth_gnome_keyring
libs = libsvn_subr apr gnome-keyring
@ -230,7 +232,7 @@ libs = libsvn_subr apr gnome-keyring
# Support for KWallet
[libsvn_auth_kwallet]
description = Subversion KWallet Library
type = lib
type = shared-only-cxx-lib
install = kwallet-lib
path = subversion/libsvn_auth_kwallet
libs = libsvn_subr apr kwallet
@ -252,7 +254,7 @@ type = lib
install = fsmod-lib
path = subversion/libsvn_delta
libs = libsvn_subr aprutil apriconv apr zlib
msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h
msvc-export = svn_delta.h private/svn_editor.h private/svn_delta_private.h private/svn_element.h private/svn_branch.h private/svn_branch_compat.h private/svn_branch_impl.h private/svn_branch_nested.h private/svn_branch_repos.h
# Routines for diffing
[libsvn_diff]
@ -282,7 +284,8 @@ path = subversion/libsvn_fs_base
sources = *.c bdb/*.c util/*.c
install = bdb-lib
libs = libsvn_delta libsvn_subr aprutil apriconv apr bdb libsvn_fs_util
msvc-static = yes
msvc-export = ../libsvn_fs_base/fs_init.h
msvc-delayload = yes
[libsvn_fs_fs]
description = Subversion FSFS Repository Filesystem Library
@ -290,7 +293,8 @@ type = fs-module
path = subversion/libsvn_fs_fs
install = fsmod-lib
libs = libsvn_delta libsvn_subr aprutil apriconv apr libsvn_fs_util
msvc-static = yes
msvc-export = private/svn_fs_fs_private.h ../libsvn_fs_fs/fs_init.h
msvc-delayload = yes
[libsvn_fs_x]
description = Subversion FSX Repository Filesystem Library
@ -298,7 +302,8 @@ type = fs-module
path = subversion/libsvn_fs_x
install = fsmod-lib
libs = libsvn_delta libsvn_subr aprutil apriconv apr libsvn_fs_util
msvc-static = yes
msvc-export = ../libsvn_fs_x/fs_init.h
msvc-delayload = yes
# Low-level grab bag of utilities
[libsvn_fs_util]
@ -308,7 +313,7 @@ install = fsmod-lib
path = subversion/libsvn_fs_util
libs = libsvn_subr aprutil apriconv apr
msvc-libs = advapi32.lib shfolder.lib
msvc-static = yes
msvc-export = private/svn_fs_util.h
# General API for accessing repositories
[libsvn_ra]
@ -321,6 +326,7 @@ add-deps = $(SVN_RA_LIB_DEPS)
add-install-deps = $(SVN_RA_LIB_INSTALL_DEPS)
install = lib
msvc-export = svn_ra.h private\svn_ra_private.h
msvc-delayload = yes
# Accessing repositories via DAV through serf
[libsvn_ra_serf]
@ -328,7 +334,7 @@ description = Subversion HTTP/WebDAV Protocol Repository Access Library
type = ra-module
path = subversion/libsvn_ra_serf
install = serf-lib
libs = libsvn_delta libsvn_subr aprutil apriconv apr serf xml zlib
libs = libsvn_delta libsvn_subr aprutil apriconv apr serf zlib
msvc-static = yes
# Accessing repositories via SVN
@ -356,7 +362,7 @@ type = lib
path = subversion/libsvn_repos
install = ramod-lib
libs = libsvn_fs libsvn_delta libsvn_subr apriconv apr
msvc-export = svn_repos.h private/svn_repos_private.h
msvc-export = svn_repos.h private/svn_repos_private.h ../libsvn_repos/authz.h
# Low-level grab bag of utilities
[libsvn_subr]
@ -364,7 +370,8 @@ description = Subversion General Utility Library
type = lib
install = fsmod-lib
path = subversion/libsvn_subr
libs = aprutil apriconv apr xml zlib apr_memcache sqlite magic intl
sources = *.c lz4/*.c
libs = aprutil apriconv apr xml zlib apr_memcache sqlite magic intl lz4 utf8proc
msvc-libs = kernel32.lib advapi32.lib shfolder.lib ole32.lib
crypt32.lib version.lib
msvc-export =
@ -385,6 +392,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
# Working copy management lib
[libsvn_wc]
@ -421,7 +429,7 @@ when = INSTALL_APACHE_MODS
type = apache-mod
path = tools/server-side/mod_dontdothat
nonlibs = mod_dav_svn apr aprutil
libs = libsvn_subr xml libhttpd
libs = libsvn_subr libhttpd
install = tools
# The Subversion FSFS repository manipulation tool
@ -431,7 +439,6 @@ type = exe
path = subversion/svnfsfs
install = bin
libs = libsvn_repos libsvn_fs libsvn_fs_fs libsvn_delta libsvn_subr apriconv apr
msvc-libs = setargv.obj
# ----------------------------------------------------------------------------
#
@ -567,6 +574,7 @@ install = swig-py-lib
compile-cmd = $(COMPILE_SWIG_PY)
msvc-static = no
msvc-export = ../bindings/swig/python/libsvn_swig_py/swigutil_py.h
description = Subversion utility library for Python bindings
# SWIG utility library for Perl modules
[libsvn_swig_perl]
@ -736,30 +744,30 @@ link-cmd = $(LINK_CXX_LIB)
[cxxhl-tests]
description = Unit tests for Subversion C++ HighLevel bindings
when = SVN_USE_GMOCK
when = SVN_USE_GOOGLEMOCK
type = exe
path = subversion/bindings/cxxhl
libs = libsvncxxhl libgmock libsvn_subr apr
libs = libsvncxxhl libgooglemock libsvn_subr apr
sources = tests/*.cpp
install = tests
compile-cmd = $(COMPILE_CXXHL_GMOCK_CXX)
install = cxxhl-tests
compile-cmd = $(COMPILE_CXXHL_GOOGLEMOCK_CXX)
link-cmd = $(LINK_CXX)
# ----------------------------------------------------------------------------
#
# Gmock targets
# Googlemock targets
#
[libgmock]
[libgooglemock]
description = Googlemock Library
when = SVN_USE_GMOCK
when = SVN_USE_GOOGLEMOCK
type = lib
path = gmock-fused
sources = gmock-gtest-all.cc
install = tests
path = googlemock
sources = googletest/src/gtest-all.cc googlemock/src/gmock-all.cc
install = cxxhl-tests
msvc-static = yes
compile-cmd = $(COMPILE_GMOCK_CXX)
compile-cmd = $(COMPILE_GOOGLEMOCK_CXX)
link-cmd = $(LINK_CXX_LIB)
# ----------------------------------------------------------------------------
@ -787,6 +795,7 @@ sources = fs-base-test.c
install = bdb-test
libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta
libsvn_fs_util libsvn_subr apriconv apr
msvc-force-static = yes
[strings-reps-test]
description = Test strings/reps in libsvn_fs_base
@ -796,6 +805,7 @@ sources = strings-reps-test.c
install = bdb-test
libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta
libsvn_subr apriconv apr
msvc-force-static = yes
[changes-test]
description = Test changes in libsvn_fs_base
@ -805,6 +815,7 @@ sources = changes-test.c
install = bdb-test
libs = libsvn_test libsvn_fs libsvn_fs_base libsvn_delta
libsvn_subr apriconv apr
msvc-force-static = yes
# ----------------------------------------------------------------------------
# Tests for libsvn_fs_fs
@ -816,6 +827,7 @@ sources = fs-fs-pack-test.c
install = test
libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta
libsvn_subr apriconv apr
msvc-force-static = yes
[fs-fs-fuzzy-test]
description = Use fuzzying to test FSFS corruption resilience
@ -825,6 +837,7 @@ sources = fs-fs-fuzzy-test.c
install = sub-test
libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta
libsvn_repos libsvn_subr apriconv apr
msvc-force-static = yes
[fs-fs-private-test]
description = Test FSSF private API
@ -834,6 +847,7 @@ sources = fs-fs-private-test.c
install = test
libs = libsvn_test libsvn_fs libsvn_fs_fs libsvn_delta
libsvn_repos libsvn_subr apriconv apr
msvc-force-static = yes
# ----------------------------------------------------------------------------
# Tests for libsvn_fs_x
@ -845,6 +859,7 @@ sources = fs-x-pack-test.c
install = test
libs = libsvn_test libsvn_fs libsvn_fs_x libsvn_delta
libsvn_subr apriconv apr
msvc-force-static = yes
[string-table-test]
description = Test fsfs string tables
@ -853,6 +868,7 @@ path = subversion/tests/libsvn_fs_x
sources = string-table-test.c
install = test
libs = libsvn_test libsvn_fs_x libsvn_subr apr
msvc-force-static = yes
# ----------------------------------------------------------------------------
# Tests for libsvn_fs
@ -867,7 +883,7 @@ libs = libsvn_test libsvn_fs libsvn_delta libsvn_subr apriconv apr
msvc-force-static = yes
[fs-test]
description = Test locks in libsvn_fs
description = Tests in libsvn_fs
type = exe
path = subversion/tests/libsvn_fs
sources = fs-test.c
@ -875,9 +891,26 @@ install = test
libs = libsvn_test libsvn_fs libsvn_delta
libsvn_fs_util libsvn_subr aprutil apriconv apr
[fs-sequential-test]
description = Tests in libsvn_fs run sequentially
type = exe
path = subversion/tests/libsvn_fs
sources = fs-sequential-test.c
install = test
libs = libsvn_test libsvn_fs libsvn_delta
libsvn_fs_util libsvn_subr aprutil apriconv apr
# ----------------------------------------------------------------------------
# Tests for libsvn_repos
[authz-test]
description = Test authz parsing in libsvn_repos
type = exe
path = subversion/tests/libsvn_repos
sources = authz-test.c
install = test
libs = libsvn_test libsvn_repos libsvn_fs libsvn_delta libsvn_subr apriconv apr
[repos-test]
description = Test delta editor in libsvn_repos
type = exe
@ -1139,6 +1172,21 @@ sources = x509-test.c
install = test
libs = libsvn_test libsvn_subr apriconv apr
[xml-test]
description = Test XML parser in libsvn_subr
type = exe
path = subversion/tests/libsvn_subr
sources = xml-test.c
install = test
libs = libsvn_test libsvn_subr apriconv apr
[compress-test]
description = Test compression functions
type = exe
path = subversion/tests/libsvn_subr
sources = compress-test.c
install = test
libs = libsvn_test libsvn_subr apr
# ----------------------------------------------------------------------------
# Tests for libsvn_delta
@ -1159,6 +1207,14 @@ sources = window-test.c
install = test
libs = libsvn_test libsvn_delta libsvn_subr apriconv apr
[svndiff-stream-test]
description = Test svndiff streams
type = exe
path = subversion/tests/libsvn_delta
sources = svndiff-stream-test.c
install = test
libs = libsvn_test libsvn_delta libsvn_subr apriconv apr
# ----------------------------------------------------------------------------
# Tests for libsvn_client
@ -1179,6 +1235,15 @@ sources = mtcc-test.c
install = test
libs = libsvn_test libsvn_client libsvn_wc libsvn_repos libsvn_ra libsvn_fs libsvn_delta libsvn_subr apriconv apr
[conflicts-test]
description = Test libsvn_client conflict resolver
type = exe
path = subversion/tests/libsvn_client
sources = conflicts-test.c ../libsvn_wc/utils.c
install = test
libs = libsvn_test libsvn_client libsvn_wc libsvn_repos libsvn_ra libsvn_fs libsvn_delta libsvn_subr apriconv apr
msvc-force-static = yes
# ----------------------------------------------------------------------------
# Tests for libsvn_diff
@ -1414,8 +1479,7 @@ external-lib = $(SVN_SASL_LIBS)
[openssl]
type = lib
external-lib = $(SVN_OPENSSL_LIBS)
msvc-libs = ssleay32.lib libeay32.lib
external-lib = $(SVN_OPENSSL_LIBS) $(SVN_LIBCRYPTO_LIBS)
[intl]
type = lib
@ -1426,6 +1490,14 @@ type = lib
external-lib = $(SVN_ZLIB_LIBS)
msvc-static = yes
[lz4]
type = lib
external-lib = $(SVN_LZ4_LIBS)
[utf8proc]
type = lib
external-lib = $(SVN_UTF8PROC_LIBS)
[apr_memcache]
type = lib
external-lib = $(SVN_APR_MEMCACHE_LIBS)
@ -1433,7 +1505,7 @@ external-lib = $(SVN_APR_MEMCACHE_LIBS)
[serf]
type = lib
external-lib = $(SVN_SERF_LIBS)
libs = apr aprutil openssl xml zlib
libs = apr aprutil openssl zlib
msvc-libs = secur32.lib
pkg-config = serf-1
pkg-config-private = yes
@ -1485,16 +1557,16 @@ libs = svn svnadmin svndumpfilter svnlook svnmucc svnserve svnrdump svnsync
svnversion
mod_authz_svn mod_dav_svn mod_dontdothat
svnauthz svnauthz-validate svnraisetreeconflict
svnfsfs svnbench
svnfsfs svnbench svnmover
[__ALL_TESTS__]
type = project
path = build/win32
libs = __ALL__
fs-test fs-base-test fs-fsfs-test fs-fs-pack-test fs-fs-fuzzy-test
fs-fs-private-test fs-x-pack-test string-table-test
fs-fs-private-test fs-x-pack-test string-table-test fs-sequential-test
skel-test strings-reps-test changes-test locks-test
repos-test dump-load-test
repos-test authz-test dump-load-test
checksum-test compat-test config-test hashdump-test mergeinfo-test
opt-test packed-data-test path-test prefix-string-test
priority-queue-test root-pools-test stream-test
@ -1511,18 +1583,20 @@ libs = __ALL__
svndiff-test vdelta-test
entries-dump atomic-ra-revprop-change wc-lock-tester wc-incomplete-tester
lock-helper
client-test mtcc-test
client-test conflicts-test mtcc-test
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
parse-diff-test x509-test xml-test afl-x509 compress-test
svndiff-stream-test
[__MORE__]
type = project
path = build/win32
libs = __ALL_TESTS__
diff diff3 diff4 fsfs-access-map svnauth
diff diff3 diff4 fsfs-access-map
svn-populate-node-origins-index x509-parser svn-wc-db-tester
svn-mergeinfo-normalizer svnconflict
[__LIBS__]
type = project
@ -1637,6 +1711,13 @@ path = tools/dev/svnraisetreeconflict
libs = libsvn_wc libsvn_subr apriconv apr
install = tools
[svn-mergeinfo-normalizer]
type = exe
path = tools/client-side/svn-mergeinfo-normalizer
install = tools
libs = libsvn_client libsvn_wc libsvn_ra libsvn_delta libsvn_diff libsvn_subr
apriconv apr
[x509-parser]
description = Tool to verify x509 certificates
type = exe
@ -1644,3 +1725,26 @@ path = tools/dev
sources = x509-parser.c
install = tools
libs = libsvn_subr apr
[svnmover]
description = Subversion Mover Command Client
type = exe
path = tools/dev/svnmover
sources = *.c
libs = libsvn_client libsvn_ra libsvn_subr libsvn_delta apriconv apr
install = tools
[svnconflict]
type = exe
path = tools/client-side/svnconflict
install = tools
libs = libsvn_client libsvn_wc libsvn_ra libsvn_subr apriconv apr
[afl-x509]
description = AFL fuzzer for x509 parser
type = exe
path = subversion/tests/afl
sources = afl-x509.c
install = test
libs = libsvn_subr apr
testing = skip

File diff suppressed because it is too large Load Diff

View File

@ -136,16 +136,27 @@ if test "$svn_lib_apr_memcache" = "yes"; then
[Defined if apr_memcache (standalone or in apr-util) is present])
fi
AC_ARG_ENABLE(apache-whitelist,
AS_HELP_STRING([--enable-apache-whitelist=VER],
[Whitelist a particular Apache version number,
typically used to enable the use of a old version
patched by a distribution.]),
[apache_whitelist_ver=$enableval],
[apache_whitelist_ver=no])
HTTPD_WHITELIST="$apache_whitelist_ver"
AC_SUBST(HTTPD_WHITELIST)
dnl Find Apache with a recent-enough magic module number
SVN_FIND_APACHE(20051115)
SVN_FIND_APACHE(20051115, $apache_whitelist_ver)
dnl Search for SQLite. If you change SQLITE_URL from a .zip to
dnl something else also update build/ac-macros/sqlite.m4 to reflect
dnl the correct command to unpack the downloaded file.
SQLITE_MINIMUM_VER="3.7.12"
SQLITE_RECOMMENDED_VER="3.7.15.1"
SQLITE_URL="http://www.sqlite.org/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip"
SQLITE_MINIMUM_VER="3.8.2"
SQLITE_RECOMMENDED_VER="3.8.11.1"
dnl Used to construct the SQLite download URL.
SQLITE_RECOMMENDED_VER_REL_YEAR="2015"
SQLITE_URL="https://www.sqlite.org/$SQLITE_RECOMMENDED_VER_REL_YEAR/sqlite-amalgamation-$(printf %d%02d%02d%02d $(echo ${SQLITE_RECOMMENDED_VER} | sed -e 's/\./ /g')).zip"
SVN_LIB_SQLITE(${SQLITE_MINIMUM_VER}, ${SQLITE_RECOMMENDED_VER},
${SQLITE_URL})
@ -546,22 +557,22 @@ AC_SUBST(SVN_HAVE_GPG_AGENT)
dnl GNOME Keyring -------------------
AC_ARG_WITH(gnome_keyring,
AS_HELP_STRING([--with-gnome-keyring],
[Enable use of GNOME Keyring for auth credentials (enabled by default if found)]),
[with_gnome_keyring="$withval"],
[with_gnome_keyring=auto])
AC_ARG_WITH(old_gnome_keyring,
AS_HELP_STRING([--with-old-gnome-keyring],
[Enable old GNOME Keyring for auth credentials (prefer --with-gnome-keyring)]),
[with_old_gnome_keyring="$withval"],
[with_old_gnome_keyring=no])
found_gnome_keyring=no
AC_MSG_CHECKING([whether to look for GNOME Keyring])
if test "$with_gnome_keyring" != "no"; then
found_old_gnome_keyring=no
AC_MSG_CHECKING([whether to look for old GNOME Keyring])
if test "$with_old_gnome_keyring" != "no"; then
AC_MSG_RESULT([yes])
case "$host" in
*-*-darwin*)
if test "$with_gnome_keyring" = "yes"; then
AC_MSG_ERROR([--with-gnome-keyring is not supported on Mac OS X.])
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([--with-old-gnome-keyring is not supported on Mac OS X.])
else
with_gnome_keyring=no
with_old_gnome_keyring=no
fi
;;
*)
@ -574,9 +585,9 @@ if test "$with_gnome_keyring" != "no"; then
old_CPPFLAGS="$CPPFLAGS"
SVN_GNOME_KEYRING_INCLUDES="`$PKG_CONFIG --cflags glib-2.0 gnome-keyring-1`"
CPPFLAGS="$CPPFLAGS $SVN_GNOME_KEYRING_INCLUDES"
AC_CHECK_HEADER(gnome-keyring.h, found_gnome_keyring=yes, found_gnome_keyring=no)
AC_CHECK_HEADER(gnome-keyring.h, found_old_gnome_keyring=yes, found_old_gnome_keyring=no)
AC_MSG_CHECKING([for GNOME Keyring])
if test "$found_gnome_keyring" = "yes"; then
if test "$found_old_gnome_keyring" = "yes"; then
AC_MSG_RESULT([yes])
AC_DEFINE([SVN_HAVE_GNOME_KEYRING], [1],
[Is GNOME Keyring support enabled?])
@ -584,37 +595,37 @@ if test "$with_gnome_keyring" != "no"; then
SVN_GNOME_KEYRING_LIBS="`$PKG_CONFIG --libs glib-2.0 gnome-keyring-1`"
else
AC_MSG_RESULT([no])
if test "$with_gnome_keyring" = "yes"; then
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([cannot find GNOME Keyring])
fi
fi
else
AC_MSG_RESULT([no])
if test "$with_gnome_keyring" = "yes"; then
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([cannot find GLib and GNOME Keyring .pc files.])
else
with_gnome_keyring=no
with_old_gnome_keyring=no
fi
fi
else
if test "$with_gnome_keyring" = "yes"; then
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([cannot find pkg-config. GNOME Keyring requires this.])
else
with_gnome_keyring=no
with_old_gnome_keyring=no
fi
fi
else
if test "$with_gnome_keyring" = "yes"; then
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([APR does not have support for DSOs. GNOME Keyring requires this.])
else
with_gnome_keyring=no
with_old_gnome_keyring=no
fi
fi
else
if test "$with_gnome_keyring" = "yes"; then
AC_MSG_ERROR([--with-gnome-keyring conflicts with --disable-shared])
if test "$with_old_gnome_keyring" = "yes"; then
AC_MSG_ERROR([--with-old-gnome-keyring conflicts with --disable-shared])
else
with_gnome_keyring=no
with_old_gnome_keyring=no
fi
fi
;;
@ -625,28 +636,31 @@ fi
AC_SUBST(SVN_GNOME_KEYRING_INCLUDES)
AC_SUBST(SVN_GNOME_KEYRING_LIBS)
dnl LibSecret -------------------
SVN_LIB_SECRET
dnl Googlemock -----------------
AC_ARG_ENABLE([gmock],
AS_HELP_STRING([--disable-gmock],
AC_ARG_ENABLE([googlemock],
AS_HELP_STRING([--disable-googlemock],
[Do not use the Googlemock testing framework]),
[],
[enable_gmock=yes])
[enable_googlemock=yes])
AC_SUBST([GMOCK_SRCDIR], [$abs_srcdir/gmock-fused])
AC_SUBST([GOOGLEMOCK_SRCDIR], [$abs_srcdir/googlemock])
AC_MSG_CHECKING([whether use Googlemock])
if test "$enable_gmock" != "no"; then
if test -d "$GMOCK_SRCDIR"; then
if test "$enable_googlemock" != "no"; then
if test -d "$GOOGLEMOCK_SRCDIR"; then
AC_MSG_RESULT([yes])
SVN_USE_GMOCK=true
SVN_USE_GOOGLEMOCK=true
else
AC_MSG_RESULT([no])
SVN_USE_GMOCK=false
SVN_USE_GOOGLEMOCK=false
fi
else
AC_MSG_RESULT([no])
SVN_USE_GMOCK_SOURCES=false
SVN_USE_GOOGLEMOCK=false
fi
AC_SUBST([SVN_USE_GMOCK])
AC_SUBST([SVN_USE_GOOGLEMOCK])
dnl Ev2 experimental features ----------------------
dnl Note: The Ev2 implementations will be built unconditionally, but by
@ -892,7 +906,7 @@ if test "$svn_lib_kwallet" = "yes"; then
INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-kwallet-lib"
fi
if test "$found_gnome_keyring" = "yes"; then
if test "$found_old_gnome_keyring" = "yes" || test "$found_gnome_keyring" = "yes"; then
BUILD_RULES="$BUILD_RULES gnome-keyring-lib"
INSTALL_RULES="`echo $INSTALL_RULES | $SED 's/install-lib/install-lib install-gnome-keyring-lib/'`"
INSTALL_STATIC_RULES="$INSTALL_STATIC_RULES install-gnome-keyring-lib"
@ -993,6 +1007,7 @@ if test "$enable_disallowing_of_undefined_references" != "no"; then
for library_dir in "$abs_srcdir/subversion/libsvn_"*; do
eval "`basename $library_dir`_LDFLAGS=-Wl,--no-undefined"
done
shared_only_LDFLAGS="-Wl,--no-undefined"
else
AC_MSG_RESULT([no])
if test "$enable_disallowing_of_undefined_references" = "yes"; then
@ -1000,8 +1015,6 @@ if test "$enable_disallowing_of_undefined_references" != "no"; then
fi
fi
fi
AC_SUBST([libsvn_auth_gnome_keyring_LDFLAGS])
AC_SUBST([libsvn_auth_kwallet_LDFLAGS])
AC_SUBST([libsvn_client_LDFLAGS])
AC_SUBST([libsvn_delta_LDFLAGS])
AC_SUBST([libsvn_diff_LDFLAGS])
@ -1016,6 +1029,7 @@ AC_SUBST([libsvn_ra_svn_LDFLAGS])
AC_SUBST([libsvn_repos_LDFLAGS])
AC_SUBST([libsvn_subr_LDFLAGS])
AC_SUBST([libsvn_wc_LDFLAGS])
AC_SUBST([shared_only_LDFLAGS])
AC_ARG_ENABLE(maintainer-mode,
@ -1052,12 +1066,13 @@ AS_HELP_STRING([--enable-maintainer-mode],
SVN_CFLAGS_ADD_IFELSE([-Wno-system-headers])
SVN_CFLAGS_ADD_IFELSE([-Wno-format-nonliteral])
SVN_CFLAGS_ADD_IFELSE([-Wmissing-variable-declarations])
SVN_CFLAGS_ADD_IFELSE([-Wno-unused-const-variable])
CMAINTAINERFLAGS="$CFLAGS"
CFLAGS="$CFLAGS_KEEP"
dnl Add flags that all versions of GCC (should) support
CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Waggregate-return -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS"
CMAINTAINERFLAGS="-Wall -Wpointer-arith -Wwrite-strings -Wshadow -Wformat=2 -Wunused -Wstrict-prototypes -Wmissing-prototypes -Wmissing-declarations -Wno-multichar -Wredundant-decls -Wnested-externs -Winline -Wno-long-long -Wbad-function-cast $CMAINTAINERFLAGS"
fi
if test "$GXX" = "yes"; then
AC_MSG_NOTICE([maintainer-mode: adding G++ warning flags])
@ -1203,6 +1218,10 @@ AS_HELP_STRING([--with-editor=PATH],
SVN_LIB_Z
SVN_LZ4
SVN_UTF8PROC
MOD_ACTIVATION=""
AC_ARG_ENABLE(mod-activation,
AS_HELP_STRING([--enable-mod-activation],
@ -1295,7 +1314,7 @@ AC_PATH_PROG(PERL, perl, none)
if test -n "$RUBY"; then
AC_PATH_PROG(RUBY, "$RUBY", none)
else
AC_PATH_PROGS(RUBY, ruby ruby1.8 ruby18 ruby1.9 ruby1 ruby1.9.3 ruby193 ruby2.0 ruby2.1, none)
AC_PATH_PROGS(RUBY, ruby ruby1 ruby1.8 ruby18 ruby1.9 ruby19 ruby1.9.3 ruby193 ruby2 ruby2.0 ruby20 ruby2.1 ruby21 ruby2.2 ruby22 ruby2.3 ruby23 ruby2.4 ruby24, none)
fi
if test "$RUBY" != "none"; then
AC_MSG_CHECKING([rb_hash_foreach])
@ -1304,7 +1323,7 @@ if test "$RUBY" != "none"; then
if test -n "$RDOC"; then
AC_PATH_PROG(RDOC, "$RDOC", none)
else
AC_PATH_PROGS(RDOC, rdoc rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2.0 rdoc2.1, none)
AC_PATH_PROGS(RUBY, rdoc rdoc1 rdoc1.8 rdoc18 rdoc1.9 rdoc19 rdoc1.9.3 rdoc193 rdoc2 rdoc2.0 rdoc20 rdoc2.1 rdoc21 rdoc2.2 rdoc22 rdoc2.3 rdoc23 rdoc2.4 rdoc24, none)
fi
AC_CACHE_CHECK([for Ruby major version], [svn_cv_ruby_major],[
svn_cv_ruby_major="`$RUBY -rrbconfig -e 'print RbConfig::CONFIG.fetch(%q(MAJOR))'`"
@ -1328,7 +1347,7 @@ if test "$RUBY" != "none"; then
# Disallow Ruby between 1.8.7 and 1.9.3
RUBY="none"
AC_MSG_WARN([The detected Ruby is between 1.9 and 1.9.3])
AC_MSG_WARN([Only 1.8.x and 1.9.3 releases are supported at this time])
AC_MSG_WARN([Only 1.8.x and 1.9.3 or later are supported at this time])
fi
else
AC_MSG_RESULT([no])
@ -1341,6 +1360,10 @@ if test "$RUBY" != "none"; then
fi
SVN_CHECK_SWIG
AC_ARG_VAR(SWIG_FEATURES, [SWIG feature flags common to all bindings])
AC_ARG_VAR(SWIG_RB_FEATURES, [SWIG feature flags specific to Ruby bindings])
AC_ARG_VAR(SWIG_PL_FEATURES, [SWIG feature flags specific to Perl bindings])
AC_ARG_VAR(SWIG_PY_FEATURES, [SWIG feature flags specific to Python bindings])
SVN_CHECK_CTYPESGEN
@ -1357,24 +1380,37 @@ AS_HELP_STRING([--enable-runtime-module-search],
fi
AC_DEFINE(SVN_USE_DSO, 1,
[Defined if svn should try to load DSOs])
dnl Mac OS X uses libname.MAJOR.SOVERSION.dylib
dnl Most other unixes use libname.MAJOR.so.SOVERSION
case "$host" in
*-*-darwin*)
AC_DEFINE(SVN_DSO_SUFFIX_FMT, ["%d.%d.dylib"],
[Shared library file name suffix format])
;;
*)
AC_DEFINE(SVN_DSO_SUFFIX_FMT, ["%d.so.%d"],
[Shared library file name suffix format])
;;
esac
fi
])
if test "$svn_enable_shared" = "no" || test "$use_dso" != "yes"; then
AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_LOCAL, 1,
[Defined if libsvn_client should link against libsvn_ra_local])
AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_LOCAL, 1,
[Defined if libsvn_ra should link against libsvn_ra_local])
svn_ra_lib_deps="\$(RA_LOCAL_DEPS)"
svn_ra_lib_install_deps="install-ramod-lib"
svn_ra_lib_link="\$(RA_LOCAL_LINK)"
AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_SVN, 1,
[Defined if libsvn_client should link against libsvn_ra_svn])
AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_SVN, 1,
[Defined if libsvn_ra should link against libsvn_ra_svn])
svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SVN_DEPS)"
svn_ra_lib_link="$svn_ra_lib_link \$(RA_SVN_LINK)"
if test "$svn_lib_serf" = "yes"; then
AC_DEFINE(SVN_LIBSVN_CLIENT_LINKS_RA_SERF, 1,
[Defined if libsvn_client should link against libsvn_ra_serf])
AC_DEFINE(SVN_LIBSVN_RA_LINKS_RA_SERF, 1,
[Defined if libsvn_ra should link against libsvn_ra_serf])
svn_ra_lib_deps="$svn_ra_lib_deps \$(RA_SERF_DEPS)"
svn_ra_lib_install_deps="$svn_ra_lib_install_deps install-serf-lib"
svn_ra_lib_link="$svn_ra_lib_link \$(RA_SERF_LINK)"
@ -1496,7 +1532,7 @@ AC_SUBST(JAVAHL_COMPAT_TESTS_TARGET)
# ==== Miscellaneous bits ====================================================
AC_CHECK_HEADERS([stdbool.h inttypes.h])
AC_CHECK_HEADERS([stdbool.h stdint.h])
# Strip '-no-cpp-precomp' from CPPFLAGS for the clang compiler
### I think we get this flag from APR, so the fix probably belongs there
@ -1504,12 +1540,6 @@ if test "$CC" = "clang"; then
SVN_STRIP_FLAG(CPPFLAGS, [-no-cpp-precomp ])
fi
# Need to strip '-no-cpp-precomp' from CPPFLAGS for SWIG as well.
SWIG_CPPFLAGS="$CPPFLAGS"
SVN_STRIP_FLAG(SWIG_CPPFLAGS, [-no-cpp-precomp ])
SVN_STRIP_FLAG(SWIG_CPPFLAGS, [-Wdate-time ])
AC_SUBST([SWIG_CPPFLAGS])
dnl Since this is used only on Unix-y systems, define the path separator as '/'
AC_DEFINE_UNQUOTED(SVN_PATH_LOCAL_SEPARATOR, '/',
[Defined to be the path separator used on your local filesystem])

View File

@ -33,6 +33,13 @@ PROJECT_NAME = Subversion
PROJECT_NUMBER =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO = doc/svn-square.jpg
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
# base path where the generated documentation will be put.
# If a relative path is entered, it will be relative to the location

View File

@ -206,9 +206,8 @@ def _usage_exit(err=None):
print(" Use static openssl")
print("")
print(" --vsnet-version=VER")
print(" generate for VS.NET version VER (2002, 2003, 2005, 2008,")
print(" 2010, 2012, 2013 or 2015)")
print(" [only valid in combination with '-t vcproj']")
print(" generate for VS.NET version VER (2005-2017 or 9.0-15.0)")
print(" [implies '-t vcproj']")
print("")
print(" -D NAME[=value]")
print(" define NAME macro during compilation")
@ -304,6 +303,8 @@ def add(self, opt, val, overwrite=True):
skip = 1
elif opt == '-t':
gentype = val
elif opt == '--vsnet-version':
gentype = 'vcproj'
else:
if opt == '--with-httpd':
rest.add('--with-apr', os.path.join(val, 'srclib', 'apr'),

View File

@ -35,8 +35,11 @@ APR_VERSION=${APR_VERSION:-"1.4.6"}
APU_VERSION=${APU_VERSION:-"1.5.1"}
SERF_VERSION=${SERF_VERSION:-"1.3.8"}
ZLIB_VERSION=${ZLIB_VERSION:-"1.2.8"}
SQLITE_VERSION=${SQLITE_VERSION:-"3.7.15.1"}
GMOCK_VERSION=${GMOCK_VERSION:-"1.6.0"}
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"}
@ -46,8 +49,10 @@ 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`
GMOCK=gmock-${GMOCK_VERSION}
GMOCK_URL=https://googlemock.googlecode.com/files/
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,7 +72,7 @@ APACHE_MIRROR=http://archive.apache.org/dist
# helpers
usage() {
echo "Usage: $0"
echo "Usage: $0 [ apr | serf | zlib | sqlite | gmock ] ..."
echo "Usage: $0 [ apr | serf | zlib | sqlite | googlemock ] ..."
exit $1
}
@ -113,7 +118,7 @@ get_sqlite() {
test -d $BASEDIR/sqlite-amalgamation && return
cd $TEMPDIR
$HTTP_FETCH http://www.sqlite.org/$SQLITE.zip
$HTTP_FETCH https://www.sqlite.org/$SQLITE_VERSION_REL_YEAR/$SQLITE.zip
cd $BASEDIR
unzip -q $TEMPDIR/$SQLITE.zip
@ -122,17 +127,22 @@ get_sqlite() {
}
get_gmock() {
test -d $BASEDIR/gmock-fused && return
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
unzip -q $TEMPDIR/$GMOCK.zip
mv $GMOCK/fused-src gmock-fused
rm -fr $GMOCK
mkdir googlemock
mv $TEMPDIR/googletest-release-${GTEST_VERSION} googlemock/googletest
mv $TEMPDIR/googlemock-release-${GMOCK_VERSION} googlemock/googlemock
}
# main()

View File

@ -27,14 +27,8 @@
#ifndef RA_SVN_SASL_H
#define RA_SVN_SASL_H
#ifdef WIN32
/* This prevents sasl.h from redefining iovec, which is always defined by APR
on win32. */
#define STRUCT_IOVEC_DEFINED
#include <sasl.h>
#else
#include <sasl/sasl.h>
#endif
/* Keep this include statement at the top of this file. */
#include "private/ra_svn_wrapped_sasl.h"
#include <apr_errno.h>
#include <apr_pools.h>

View File

@ -0,0 +1,131 @@
/*
* svn_wrapped_sasl.h : wrapped SASL API
*
* ====================================================================
* 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 RA_SVN_WRAPPED_SASL_H
#define RA_SVN_WRAPPED_SASL_H
#include <stddef.h>
#ifdef WIN32
# define APR_WANT_IOVEC
# include <apr_want.h>
/* This prevents sasl.h from redefining iovec,
which is always defined by APR on win32. */
# define STRUCT_IOVEC_DEFINED
# include <sasl.h>
#else
# include <sasl/sasl.h>
#endif
/* Apple deprecated the SASL API on Mac OS X 10.11, causing a
moderately huge number of deprecation warnings to be emitted during
compilation. Consequently, we wrap the parts of the SASL API that
we use in a set of private functions and disable the deprecation
warnings for this header and the implementation file. */
#ifdef __APPLE__
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
# pragma GCC diagnostic push
# pragma GCC diagnostic ignored "-Wdeprecated-declarations"
# endif
#endif /* __APPLE__ */
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
void
svn_sasl__set_mutex(sasl_mutex_alloc_t *, sasl_mutex_lock_t *,
sasl_mutex_unlock_t *, sasl_mutex_free_t *);
void
svn_sasl__done(void);
void
svn_sasl__dispose(sasl_conn_t **);
const char *
svn_sasl__errstring(int, const char *, const char **);
const char *
svn_sasl__errdetail(sasl_conn_t *);
int
svn_sasl__getprop(sasl_conn_t *, int, const void **);
int
svn_sasl__setprop(sasl_conn_t *, int, const void *);
int
svn_sasl__client_init(const sasl_callback_t *);
int
svn_sasl__client_new(const char *, const char *, const char *, const char *,
const sasl_callback_t *, unsigned, sasl_conn_t **);
int
svn_sasl__client_start(sasl_conn_t *, const char *, sasl_interact_t **,
const char **, unsigned *, const char **);
int
svn_sasl__client_step(sasl_conn_t *, const char *, unsigned,
sasl_interact_t **, const char **, unsigned *);
int
svn_sasl__server_init(const sasl_callback_t *, const char *);
int
svn_sasl__server_new(const char *, const char *, const char *,
const char *, const char *, const sasl_callback_t *,
unsigned, sasl_conn_t **);
int
svn_sasl__listmech(sasl_conn_t *, const char *, const char *, const char *,
const char *, const char **, unsigned *, int *);
int
svn_sasl__server_start(sasl_conn_t *, const char *, const char *, unsigned,
const char **, unsigned *);
int
svn_sasl__server_step(sasl_conn_t *, const char *, unsigned,
const char **, unsigned *);
int
svn_sasl__encode(sasl_conn_t *, const char *, unsigned,
const char **, unsigned *);
int
svn_sasl__decode(sasl_conn_t *, const char *, unsigned,
const char **, unsigned *);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#ifdef __APPLE__
# if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 2)
# pragma GCC diagnostic pop
# endif
#endif /* __APPLE__ */
#endif /* RA_SVN_WRAPPED_SASL_H */

View File

@ -75,22 +75,82 @@ extern "C" {
apr_atomic_cas32((mem), (with), (cmp))
/** @} */
/**
* @name Single-threaded atomic initialization
* @{
*/
/**
* Callback for svn_atomic__init_once().
* @return an #svn_error_t if the initialization fails.
* @since New in 1.10
*/
typedef svn_error_t *(*svn_atomic__err_init_func_t)(void *baton,
apr_pool_t *pool);
/**
* Callback for svn_atomic__init_no_error().
* @return a string containing an error message if the initialization fails.
* @since New in 1.10
*/
typedef const char *(*svn_atomic__str_init_func_t)(void *baton);
/**
* Call an initialization function in a thread-safe manner.
*
* @a global_status must be a pointer to a global, zero-initialized
* #svn_atomic_t. @a init_func is a pointer to the function that performs
* the actual initialization. @a baton and and @a pool are passed on to the
* init_func for its use.
* #svn_atomic_t. @a err_init_func is a pointer to the function that
* performs the actual initialization. @a baton and and @a pool are
* passed on to @a err_init_func for its use.
*
* @return the error returned by @a err_init_func.
*
* @since New in 1.5.
*/
svn_error_t *
svn_atomic__init_once(volatile svn_atomic_t *global_status,
svn_error_t *(*init_func)(void*,apr_pool_t*),
svn_atomic__err_init_func_t err_init_func,
void *baton,
apr_pool_t* pool);
/**
* Call an initialization function in a thread-safe manner.
*
* Unlike svn_atomic__init_once(), this function does not need a pool
* and does not create an #svn_error_t, and neither should the
* @a str_init_func implementation.
*
* @a global_status must be a pointer to a global, zero-initialized
* #svn_atomic_t. @a str_init_func is a pointer to the function that
* performs the actual initialization. @a baton is passed on to
* @a str_init_func for its use.
*
* @return the error string returned by @a str_init_func.
*
* @since New in 1.10.
*/
const char *
svn_atomic__init_once_no_error(volatile svn_atomic_t *global_status,
svn_atomic__str_init_func_t str_init_func,
void *baton);
/**
* Query and increment the global counter and set @a value to the new
* counter value.
*
* This function is thread-safe and you should call it whenever you need
* a number that is unique within the current process. The values are > 0.
*
* @return the error object in case of a synchronization failure.
*
* @since New in 1.10.
*/
svn_error_t *
svn_atomic__unique_counter(apr_uint64_t* value);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -0,0 +1,679 @@
/**
* @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_branch.h
* @brief Operating on a branched version history
*
* @since New in ???.
*/
/* Transactions
*
* A 'txn' contains a set of changes to the branches/elements.
*
* To make changes you say, for example, "for element 5: I want the parent
* element to be 3 now, and its name to be 'bar', and its content to be
* {props=... text=...}". That sets up a move and/or rename and/or
* content-change (or possibly a no-op for all three aspects) for element 5.
*
* Before or after (or at the same time, if we make a parallelizable
* implementation) we can make edits to the other elements, including
* element 3.
*
* So at the time of the edit method 'change e5: let its parent be e3'
* we might or might not have even created e3, if that happens to be an
* element that we wish to create rather than one that already existed.
*
* We allow this non-ordering because we want the changes to different
* elements to be totally independent.
*
* So at any given 'moment' in time during specifying the changes to a
* txn, the txn state is not necessarily one that maps directly to a
* flat tree (single-rooted, no cycles, no clashes of paths, etc.).
*
* Once we've finished specifying the edits, then the txn state will be
* converted to a flat tree, and that's the final result. But we can't
* query an arbitrary txn (potentially in the middle of making changes
* to it) by path, because the paths are not fully defined yet.
*
* So there are three kinds of operations:
*
* - query involving paths
* => requires a flat tree state to query, not an in-progress txn
*
* - query, not involving paths
* => accepts a txn-in-progress or a flat tree
*
* - modify (not involving paths)
* => requires a txn
*
* Currently, a txn is represented by 'svn_branch__txn_t', with
* 'svn_branch__state_t' for the individual branches in it. A flat tree is
* represented by 'svn_branch__subtree_t'. But there is currently not a
* clean separation; there is some overlap and some warts such as the
* 'svn_branch__txn_sequence_point' method.
*/
#ifndef SVN_BRANCH_H
#define SVN_BRANCH_H
#include <apr_pools.h>
#include "svn_types.h"
#include "svn_error.h"
#include "svn_io.h" /* for svn_stream_t */
#include "svn_delta.h"
#include "private/svn_element.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* ### */
#define SVN_BRANCH__ERR 123456
/** Element Identifier (EID).
*
* An element may appear in any or all branches, and its EID is the same in
* each branch in which the element appears.
*
* By definition, an element keeps the same EID for its whole lifetime, even
* if deleted from all branches and later 'resurrected'.
*
* In principle, an EID is an arbitrary token and has no intrinsic
* relationships (except equality) to other EIDs. The current implementation
* uses integers and allocates them sequentially from a central counter, but
* the implementation may be changed.
*
* ### In most places the code currently says 'int', verbatim.
*/
typedef int svn_branch__eid_t;
typedef struct svn_branch__el_rev_id_t svn_branch__el_rev_id_t;
typedef struct svn_branch__rev_bid_eid_t svn_branch__rev_bid_eid_t;
typedef struct svn_branch__rev_bid_t svn_branch__rev_bid_t;
typedef struct svn_branch__state_t svn_branch__state_t;
/* Per-repository branching info.
*/
typedef struct svn_branch__repos_t svn_branch__repos_t;
/* Methods (conceptually public, but called indirectly) for a transaction.
*/
typedef struct svn_branch__txn_vtable_t svn_branch__txn_vtable_t;
/* Private data for a transaction.
*/
typedef struct svn_branch__txn_priv_t svn_branch__txn_priv_t;
/* A container for all the branching metadata for a specific revision (or
* an uncommitted transaction).
*/
typedef struct svn_branch__txn_t
{
/* Methods (conceptually public, but called indirectly). */
svn_branch__txn_vtable_t *vtable;
/* Private data. */
svn_branch__txn_priv_t *priv;
/* Public data. */
/* The repository in which this revision exists. */
svn_branch__repos_t *repos;
/* If committed, the revision number; else SVN_INVALID_REVNUM. */
svn_revnum_t rev;
/* If committed, the previous revision number, else the revision number
on which this transaction is based. */
svn_revnum_t base_rev;
} svn_branch__txn_t;
/* Create a new branch txn object.
*/
svn_branch__txn_t *
svn_branch__txn_create(const svn_branch__txn_vtable_t *vtable,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool);
/* Return all the branches in TXN.
*
* These branches are available for reading. (Some of them may also be
* mutable.)
*
* ### Rename to 'list_branches' & return only their ids?
*
* Return an empty array if there are none.
*/
apr_array_header_t *
svn_branch__txn_get_branches(const svn_branch__txn_t *txn,
apr_pool_t *result_pool);
/* Return the branch whose id is BRANCH_ID in TXN.
*
* Return NULL if not found.
*
* Note: a branch id is, in behavioural terms, an arbitrary token. In the
* current implementation it is constructed from the hierarchy of subbranch
* root EIDs leading to the branch, but that may be changed in future.
*
* See also: svn_branch__get_id().
*/
svn_branch__state_t *
svn_branch__txn_get_branch_by_id(const svn_branch__txn_t *txn,
const char *branch_id,
apr_pool_t *scratch_pool);
svn_error_t *
svn_branch__txn_get_num_new_eids(const svn_branch__txn_t *txn,
int *num_new_eids_p,
apr_pool_t *scratch_pool);
/* Assign a new txn-scope element id in TXN.
*/
svn_error_t *
svn_branch__txn_new_eid(svn_branch__txn_t *txn,
int *new_eid_p,
apr_pool_t *scratch_pool);
/** Open for writing, either a new branch or an existing branch.
*
* When creating a new branch, declare its root element id to be ROOT_EID. Do
* not instantiate the root element, nor any other elements.
*
* TREE_REF specifies the initial tree content, by reference to a committed
* tree. It overwrites any existing tree, even if the branch was already
* mutable in the txn.
*
* If TREE_REF is null, then the initial tree is empty for a new branch
* (not already present in the txn), or the branch's current tree if the
* branch was already present (readable or mutable) in the txn.
*
* ### TODO: Take a 'history' parameter; 'none' is a valid option.
*
* We use a common 'open subbranch' method for both 'find' and 'add'
* cases, according to the principle that 'editing' a txn should dictate
* the new state without reference to the old state.
*
* This method returns a mutable 'branch state' object which is a part of
* the txn.
*
* ### When opening ('finding') an existing branch, ROOT_EID should match
* it. (Should we check, and throw an error if not?)
*/
svn_error_t *
svn_branch__txn_open_branch(svn_branch__txn_t *txn,
svn_branch__state_t **new_branch_p,
const char *branch_id,
int root_eid,
svn_branch__rev_bid_eid_t *tree_ref,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Register a sequence point.
*
* At a sequence point, elements are arranged in a tree hierarchy: each
* element has exactly one parent element, except the root, and so on.
* Translation between paths and element addressing is defined only at
* a sequence point.
*
* The other edit operations -- add, alter, delete, etc. -- result in a
* state that is not a sequence point.
*
* The new transaction begins at a sequence point. Completion of editing
* (svn_branch__txn_complete()) also creates a sequence point.
*/
svn_error_t *
svn_branch__txn_sequence_point(svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
/** Finalize this transaction.
*
* Notify that the edit has been completed successfully.
*/
svn_error_t *
svn_branch__txn_complete(svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
/** Abandon this transaction.
*
* Notify that editing this transaction was not successful.
*/
svn_error_t *
svn_branch__txn_abort(svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
/* Change txn-local EIDs (negative integers) in TXN to revision EIDs, by
* assigning a new revision-EID (positive integer) for each one.
*
* Rewrite TXN->first_eid and TXN->next_eid accordingly.
*/
svn_error_t *
svn_branch__txn_finalize_eids(svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
/* Often, branches have the same root element. For example,
* branching /trunk to /branches/br1 results in:
*
* branch 1: (root-EID=100)
* EID 100 => /trunk
* ...
* branch 2: (root-EID=100)
* EID 100 => /branches/br1
* ...
*
* However, the root element of one branch may correspond to a non-root
* element of another branch.
*
* Continuing the same example, branching from the trunk subtree
* /trunk/D (which is not itself a branch root) results in:
*
* branch 3: (root-EID=104)
* EID 100 => (nil)
* ...
* EID 104 => /branches/branch-of-trunk-subtree-D
* ...
*/
/* Methods (conceptually public, but called indirectly) for a branch state.
*/
typedef struct svn_branch__state_vtable_t svn_branch__state_vtable_t;
/* Private data for a branch state.
*/
typedef struct svn_branch__state_priv_t svn_branch__state_priv_t;
/* A branch state.
*
* A branch state object describes one version of one branch.
*/
struct svn_branch__state_t
{
/* Methods (conceptually public, but called indirectly). */
svn_branch__state_vtable_t *vtable;
/* Private data. */
svn_branch__state_priv_t *priv;
/* Public data. */
/* The branch identifier (starting with 'B') */
const char *bid;
/* The revision to which this branch state belongs */
/* ### Later we should remove this and let a single state be sharable
by multiple txns. */
svn_branch__txn_t *txn;
};
/* Create a new branch state object.
*/
svn_branch__state_t *
svn_branch__state_create(const svn_branch__state_vtable_t *vtable,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool);
/* Get the full id of branch BRANCH.
*
* Branch id format:
* B<top-level-branch-num>[.<1st-level-eid>[.<2nd-level-eid>[...]]]
*
* Note: a branch id is, in behavioural terms, an arbitrary token. In the
* current implementation it is constructed from the hierarchy of subbranch
* root EIDs leading to the branch, but that may be changed in future.
*
* See also: svn_branch__txn_get_branch_by_id().
*/
const char *
svn_branch__get_id(const svn_branch__state_t *branch,
apr_pool_t *result_pool);
/* Return the element id of the root element of BRANCH.
*/
int
svn_branch__root_eid(const svn_branch__state_t *branch);
/* Return the id of the branch nested in OUTER_BID at element OUTER_EID.
*
* For a top-level branch, OUTER_BID is null and OUTER_EID is the
* top-level branch number.
*
* (Such branches need not exist. This works purely with ids, making use
* of the fact that nested branch ids are predictable based on the nesting
* element id.)
*/
const char *
svn_branch__id_nest(const char *outer_bid,
int outer_eid,
apr_pool_t *result_pool);
/* Given a nested branch id BID, set *OUTER_BID to the outer branch's id
* and *OUTER_EID to the nesting element in the outer branch.
*
* For a top-level branch, set *OUTER_BID to NULL and *OUTER_EID to the
* top-level branch number.
*
* (Such branches need not exist. This works purely with ids, making use
* of the fact that nested branch ids are predictable based on the nesting
* element id.)
*/
void
svn_branch__id_unnest(const char **outer_bid,
int *outer_eid,
const char *bid,
apr_pool_t *result_pool);
/* Remove the branch with id BID from the list of branches in TXN.
*/
svn_error_t *
svn_branch__txn_delete_branch(svn_branch__txn_t *txn,
const char *bid,
apr_pool_t *scratch_pool);
/* Branch-Element-Revision */
struct svn_branch__el_rev_id_t
{
/* The branch state that applies to REV. */
svn_branch__state_t *branch;
/* Element. */
int eid;
/* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'.
### Do we need this if BRANCH refers to a particular branch-revision? */
svn_revnum_t rev;
};
/* Revision-branch-element id. */
struct svn_branch__rev_bid_eid_t
{
/* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */
svn_revnum_t rev;
/* The branch id in revision REV. */
const char *bid;
/* Element id. */
int eid;
};
/* Revision-branch id. */
struct svn_branch__rev_bid_t
{
/* Revision. SVN_INVALID_REVNUM means 'in this transaction', not 'head'. */
svn_revnum_t rev;
/* The branch id in revision REV. */
const char *bid;
};
/* Return a new el_rev_id object constructed with *shallow* copies of BRANCH,
* EID and REV, allocated in RESULT_POOL.
*/
svn_branch__el_rev_id_t *
svn_branch__el_rev_id_create(svn_branch__state_t *branch,
int eid,
svn_revnum_t rev,
apr_pool_t *result_pool);
/* Return a new id object constructed with a deep copy of OLD_ID,
* allocated in RESULT_POOL. */
svn_branch__el_rev_id_t *
svn_branch__el_rev_id_dup(const svn_branch__el_rev_id_t *old_id,
apr_pool_t *result_pool);
/* Return a new id object constructed with deep copies of REV, BRANCH_ID
* and EID, allocated in RESULT_POOL.
*/
svn_branch__rev_bid_eid_t *
svn_branch__rev_bid_eid_create(svn_revnum_t rev,
const char *branch_id,
int eid,
apr_pool_t *result_pool);
svn_branch__rev_bid_t *
svn_branch__rev_bid_create(svn_revnum_t rev,
const char *branch_id,
apr_pool_t *result_pool);
/* Return a new id object constructed with a deep copy of OLD_ID,
* allocated in RESULT_POOL. */
svn_branch__rev_bid_eid_t *
svn_branch__rev_bid_eid_dup(const svn_branch__rev_bid_eid_t *old_id,
apr_pool_t *result_pool);
svn_branch__rev_bid_t *
svn_branch__rev_bid_dup(const svn_branch__rev_bid_t *old_id,
apr_pool_t *result_pool);
svn_boolean_t
svn_branch__rev_bid_equal(const svn_branch__rev_bid_t *id1,
const svn_branch__rev_bid_t *id2);
typedef struct svn_branch__history_t
{
/* The immediate parents of this state in the branch/merge graph.
Hash of (BID -> svn_branch__rev_bid_t). */
apr_hash_t *parents;
} svn_branch__history_t;
svn_branch__history_t *
svn_branch__history_create_empty(apr_pool_t *result_pool);
svn_branch__history_t *
svn_branch__history_create(apr_hash_t *parents,
apr_pool_t *result_pool);
svn_branch__history_t *
svn_branch__history_dup(const svn_branch__history_t *old,
apr_pool_t *result_pool);
/* Return the mapping of elements in branch BRANCH.
*/
svn_error_t *
svn_branch__state_get_elements(const svn_branch__state_t *branch,
svn_element__tree_t **element_tree_p,
apr_pool_t *result_pool);
/* In BRANCH, get element EID (parent, name, payload).
*
* If element EID is not present, return null.
*/
svn_error_t *
svn_branch__state_get_element(const svn_branch__state_t *branch,
svn_element__content_t **element_p,
int eid,
apr_pool_t *result_pool);
/** Equivalent to
* alter_one(..., element->parent_eid, element->name, element->payload),
* or, if @a element is null, to
* delete_one(...).
*/
svn_error_t *
svn_branch__state_set_element(svn_branch__state_t *branch,
int eid,
const svn_element__content_t *element,
apr_pool_t *result_pool);
/** Specify that the element of @a branch identified by @a eid shall not
* be present.
*
* The delete is not explicitly recursive. However, as an effect of the
* final 'flattening' of a branch state into a single tree, each element
* in the final state that still has this element as its parent will also
* be deleted, recursively.
*
* The element @a eid must not be the root element of @a branch.
*
* ### Options for Out-Of-Date Checking on Rebase
*
* We may want to specify what kind of OOD check takes place. The
* following two options differ in what happens to an element that is
* added, on the other side, as a child of this deleted element.
*
* Rebase option 1: The rebase checks for changes in the whole subtree,
* excluding any portions of the subtree for which an explicit delete or
* move-away has been issued. The check includes checking that the other
* side has not added any child. In other words, the deletion is
* interpreted as an action affecting a subtree (dynamically rooted at
* this element), rather than as an action affecting a single element or
* a fixed set of elements that was explicitly or implicitly specified
* by the sender.
*
* To delete a mixed-rev subtree, the client sends an explicit delete for
* each subtree that has a different base revision from its parent.
*
* Rebase option 2: The rebase checks for changes to this element only.
* The sender can send an explicit delete for each existing child element
* that it requires to be checked as well. However, there is no way for
* the sender to specify whether a child element added by the other side
* should be considered an out-of-date error or silently deleted.
*
* It would also be possible to let the caller specify, at some suitable
* granularity, which option to use.
*/
svn_error_t *
svn_branch__state_delete_one(svn_branch__state_t *branch,
svn_branch__eid_t eid,
apr_pool_t *scratch_pool);
/** Specify the tree position and payload of the element of @a branch
* identified by @a eid.
*
* Set the element's parent EID, name and payload to @a new_parent_eid,
* @a new_name and @a new_payload respectively.
*
* This may create a new element or alter an existing element.
*
* If the element ... we can describe the effect as ...
*
* exists in the branch => altering it;
* previously existed in the branch => resurrecting it;
* only existed in other branches => branching it;
* never existed anywhere => creating or adding it.
*
* However, these are imprecise descriptions and not mutually exclusive.
* For example, if it existed previously in this branch and another, then
* we may describe the result as 'resurrecting' and/or as 'branching'.
*
* Duplicate @a new_name and @a new_payload into the branch's pool.
*/
svn_error_t *
svn_branch__state_alter_one(svn_branch__state_t *branch,
svn_branch__eid_t eid,
svn_branch__eid_t new_parent_eid,
const char *new_name,
const svn_element__payload_t *new_payload,
apr_pool_t *scratch_pool);
svn_error_t *
svn_branch__state_copy_tree(svn_branch__state_t *branch,
const svn_branch__rev_bid_eid_t *src_el_rev,
svn_branch__eid_t new_parent_eid,
const char *new_name,
apr_pool_t *scratch_pool);
/* Purge orphaned elements in BRANCH.
*/
svn_error_t *
svn_branch__state_purge(svn_branch__state_t *branch,
apr_pool_t *scratch_pool);
/* Get the merge history of BRANCH.
*/
svn_error_t *
svn_branch__state_get_history(svn_branch__state_t *branch,
svn_branch__history_t **merge_history_p,
apr_pool_t *result_pool);
/* Set the merge history of BRANCH.
*/
svn_error_t *
svn_branch__state_set_history(svn_branch__state_t *branch,
const svn_branch__history_t *merge_history,
apr_pool_t *scratch_pool);
/* Return the branch-relative path of element EID in BRANCH.
*
* If the element EID does not currently exist in BRANCH, return NULL.
*
* ### TODO: Clarify sequencing requirements.
*/
const char *
svn_branch__get_path_by_eid(const svn_branch__state_t *branch,
int eid,
apr_pool_t *result_pool);
/* Return the EID for the branch-relative path PATH in BRANCH.
*
* If no element of BRANCH is at this path, return -1.
*
* ### TODO: Clarify sequencing requirements.
*/
int
svn_branch__get_eid_by_path(const svn_branch__state_t *branch,
const char *path,
apr_pool_t *scratch_pool);
/* Get the default branching metadata for r0 of a new repository.
*/
svn_string_t *
svn_branch__get_default_r0_metadata(apr_pool_t *result_pool);
/* Create a new txn object *TXN_P, initialized with info
* parsed from STREAM, allocated in RESULT_POOL.
*/
svn_error_t *
svn_branch__txn_parse(svn_branch__txn_t **txn_p,
svn_branch__repos_t *repos,
svn_stream_t *stream,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Write to STREAM a parseable representation of TXN.
*/
svn_error_t *
svn_branch__txn_serialize(svn_branch__txn_t *txn,
svn_stream_t *stream,
apr_pool_t *scratch_pool);
/* Write to STREAM a parseable representation of BRANCH.
*/
svn_error_t *
svn_branch__state_serialize(svn_stream_t *stream,
svn_branch__state_t *branch,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_BRANCH_H */

View File

@ -0,0 +1,273 @@
/**
* @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_branch_compat.h
* @brief Compatibility with svn_delta_editor_t etc.
*
* @since New in ???.
*/
#ifndef SVN_BRANCH_COMPAT_H
#define SVN_BRANCH_COMPAT_H
#include <apr_pools.h>
#include "svn_types.h"
#include "svn_error.h"
#include "svn_delta.h"
#include "svn_ra.h"
#include "private/svn_branch.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/** Callback to retrieve a node's kind and content. This is
* needed by the various editor shims in order to effect backwards
* compatibility.
*
* Implementations should set @a *kind to the node kind of @a repos_relpath
* in @a revision.
*
* Implementations should set @a *props to the hash of properties
* associated with @a repos_relpath in @a revision, allocating that hash
* and its contents in @a result_pool. Only the 'regular' props should be
* included, not special props such as 'entry props'.
*
* Implementations should set @a *filename to the name of a file
* suitable for use as a delta base for @a repos_relpath in @a revision
* (allocating @a *filename from @a result_pool), or to @c NULL if the
* base stream is empty.
*
* Any output argument may be NULL if the output is not wanted.
*
* @a baton is an implementation-specific closure.
* @a repos_relpath is relative to the repository root.
* The implementation should ensure that @a new_content, including any
* file therein, lives at least for the life time of @a result_pool.
* @a scratch_pool is provided for temporary allocations.
*/
typedef svn_error_t *(*svn_branch__compat_fetch_func_t)(
svn_node_kind_t *kind,
apr_hash_t **props,
svn_stringbuf_t **file_text,
apr_hash_t **children_names,
void *baton,
const char *repos_relpath,
svn_revnum_t revision,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool
);
/*
*/
svn_error_t *
svn_branch__compat_fetch(svn_element__payload_t **payload_p,
svn_branch__txn_t *txn,
svn_element__branch_ref_t branch_ref,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* An object for communicating out-of-band details between an Ev1-to-Ev3
* shim and an Ev3-to-Ev1 shim. */
typedef struct svn_branch__compat_shim_connector_t svn_branch__compat_shim_connector_t;
/* Return an Ev3 editor in *EDITOR_P which will drive the Ev1 delta
* editor DEDITOR/DEDIT_BATON.
*
* This editor buffers all the changes and then drives the Ev1 when the
* returned editor's "close" method is called.
*
* This editor converts moves into copy-and-delete. It presently makes a
* one-way (lossy) conversion.
*
* TODO: Option to pass the 'move' information through as some sort of
* metadata so that it can be preserved in an Ev3-Ev1-Ev3 round-trip
* conversion.
* - Use 'entry-props'?
* - Send copy-and-delete with copy-from-rev = -1?
*
* This editor implements the "independent per-element changes" variant
* of the Ev3 commit editor interface.
*
* Use *BRANCHING_TXN as the branching state info ...
*
* SHIM_CONNECTOR can be used to enable a more exact round-trip conversion
* from an Ev1 drive to Ev3 and back to Ev1. The caller should pass the
* returned *SHIM_CONNECTOR value to svn_delta__delta_from_ev3_for_commit().
* SHIM_CONNECTOR may be null if not wanted.
*
* REPOS_ROOT_URL is the repository root URL.
*
* FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the
* original or copy-from kind/properties/text for a path being committed.
*
* CANCEL_FUNC / CANCEL_BATON: The usual cancellation callback; folded
* into the produced editor. May be NULL/NULL if not wanted.
*
* Allocate the new editor in RESULT_POOL, which may become large and must
* live for the lifetime of the edit. Use SCRATCH_POOL for temporary
* allocations.
*/
svn_error_t *
svn_branch__compat_txn_from_delta_for_commit(
svn_branch__txn_t **txn_p,
svn_branch__compat_shim_connector_t **shim_connector,
const svn_delta_editor_t *deditor,
void *dedit_baton,
svn_branch__txn_t *branching_txn,
const char *repos_root_url,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Return a delta editor in DEDITOR/DEDITOR_BATON which will drive EDITOR.
*
* REPOS_ROOT_URL is the repository root URL, and BASE_RELPATH is the
* relative path within the repository of the root directory of the edit.
* (An Ev1 edit must be rooted at a directory, not at a file.)
*
* FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the
* original or copy-from kind/properties/text for a path being committed.
*
* SHIM_CONNECTOR can be used to enable a more exact round-trip conversion
* from an Ev1 drive to Ev3 and back to Ev1. It must live for the lifetime
* of the edit. It may be null if not wanted.
*
* Allocate the new editor in RESULT_POOL, which may become large and must
* live for the lifetime of the edit. Use SCRATCH_POOL for temporary
* allocations.
*/
svn_error_t *
svn_branch__compat_delta_from_txn_for_commit(
const svn_delta_editor_t **deditor,
void **dedit_baton,
svn_branch__txn_t *edit_txn,
const char *repos_root_url,
const char *base_relpath,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
const svn_branch__compat_shim_connector_t *shim_connector,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Return in NEW_DEDITOR/NEW_DETIT_BATON a delta editor that wraps
* OLD_DEDITOR/OLD_DEDIT_BATON, inserting a pair of shims that convert
* Ev1 to Ev3 and back to Ev1.
*
* REPOS_ROOT_URL is the repository root URL, and BASE_RELPATH is the
* relative path within the repository of the root directory of the edit.
*
* FETCH_FUNC/FETCH_BATON is a callback by which the shim may retrieve the
* original or copy-from kind/properties/text for a path being committed.
*/
svn_error_t *
svn_branch__compat_insert_shims(
const svn_delta_editor_t **new_deditor,
void **new_dedit_baton,
const svn_delta_editor_t *old_deditor,
void *old_dedit_baton,
const char *repos_root,
const char *base_relpath,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* A callback for declaring the target revision of an update or switch.
*/
typedef svn_error_t *(*svn_branch__compat_set_target_revision_func_t)(
void *baton,
svn_revnum_t target_revision,
apr_pool_t *scratch_pool);
/* An update (or switch) editor.
*
* This consists of a plain Ev3 editor and the additional methods or
* resources needed for use as an update or switch editor.
*/
typedef struct svn_branch__compat_update_editor3_t {
/* The txn we're driving. */
svn_branch__txn_t *edit_txn;
/* A method to communicate the target revision of the update (or switch),
* to be called before driving the editor. It has its own baton, rather
* than using the editor's baton, so that the editor can be replaced (by
* a wrapper editor, typically) without having to wrap this callback. */
svn_branch__compat_set_target_revision_func_t set_target_revision_func;
void *set_target_revision_baton;
} svn_branch__compat_update_editor3_t;
/* Like svn_delta__ev3_from_delta_for_commit() but for an update editor.
*/
svn_error_t *
svn_branch__compat_txn_from_delta_for_update(
svn_branch__compat_update_editor3_t **editor_p,
const svn_delta_editor_t *deditor,
void *dedit_baton,
svn_branch__txn_t *branching_txn,
const char *repos_root_url,
const char *base_repos_relpath,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Like svn_delta__delta_from_ev3_for_commit() but for an update editor.
*/
svn_error_t *
svn_branch__compat_delta_from_txn_for_update(
const svn_delta_editor_t **deditor,
void **dedit_baton,
svn_branch__compat_update_editor3_t *update_editor,
const char *repos_root_url,
const char *base_repos_relpath,
svn_branch__compat_fetch_func_t fetch_func,
void *fetch_baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* An Ev1 editor that drives (heuristically) a move-tracking editor.
*/
svn_error_t *
svn_branch__compat_get_migration_editor(
const svn_delta_editor_t **old_editor,
void **old_edit_baton,
svn_branch__txn_t *edit_txn,
svn_ra_session_t *from_session,
svn_revnum_t revision,
apr_pool_t *result_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_BRANCH_COMPAT_H */

View File

@ -0,0 +1,197 @@
/**
* @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_branch_impl.h
* @brief Declarations needed by implementators of branch classes
*
* @since New in ???.
*/
#ifndef SVN_BRANCH_IMPL_H
#define SVN_BRANCH_IMPL_H
#include "private/svn_branch.h"
#ifdef __cplusplus
extern "C" {
#endif
/* Common aspects od a txn/branch 'editor' class (derived from Ev2) */
typedef struct svn_branch__vtable_priv_t
{
/* Standard cancellation function. Called before each callback. */
svn_cancel_func_t cancel_func;
void *cancel_baton;
#ifdef ENABLE_ORDERING_CHECK
svn_boolean_t within_callback;
svn_boolean_t finished;
apr_pool_t *state_pool;
#endif
} svn_branch__vtable_priv_t;
/* The methods of svn_branch__txn_t.
* See the corresponding public API functions for details.
*/
typedef apr_array_header_t *(*svn_branch__txn_v_get_branches_t)(
const svn_branch__txn_t *txn,
apr_pool_t *result_pool);
typedef svn_error_t *(*svn_branch__txn_v_delete_branch_t)(
svn_branch__txn_t *txn,
const char *bid,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_get_num_new_eids_t)(
const svn_branch__txn_t *txn,
int *num_new_eids_p,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_new_eid_t)(
svn_branch__txn_t *txn,
svn_branch__eid_t *eid_p,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_open_branch_t)(
svn_branch__txn_t *txn,
svn_branch__state_t **new_branch_p,
const char *new_branch_id,
int root_eid,
svn_branch__rev_bid_eid_t *from,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_finalize_eids_t)(
svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_serialize_t)(
svn_branch__txn_t *txn,
svn_stream_t *stream,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_sequence_point_t)(
svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_complete_t)(
svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__txn_v_abort_t)(
svn_branch__txn_t *txn,
apr_pool_t *scratch_pool);
struct svn_branch__txn_vtable_t
{
svn_branch__vtable_priv_t vpriv;
/* Methods. */
svn_branch__txn_v_get_branches_t get_branches;
svn_branch__txn_v_delete_branch_t delete_branch;
svn_branch__txn_v_get_num_new_eids_t get_num_new_eids;
svn_branch__txn_v_new_eid_t new_eid;
svn_branch__txn_v_open_branch_t open_branch;
svn_branch__txn_v_finalize_eids_t finalize_eids;
svn_branch__txn_v_serialize_t serialize;
svn_branch__txn_v_sequence_point_t sequence_point;
svn_branch__txn_v_complete_t complete;
svn_branch__txn_v_complete_t abort;
};
/* The methods of svn_branch__state_t.
* See the corresponding public API functions for details.
*/
typedef svn_error_t *(*svn_branch__state_v_get_elements_t)(
const svn_branch__state_t *branch,
svn_element__tree_t **element_tree_p,
apr_pool_t *result_pool);
typedef svn_error_t *(*svn_branch__state_v_get_element_t)(
const svn_branch__state_t *branch,
svn_element__content_t **element_p,
int eid,
apr_pool_t *result_pool);
typedef svn_error_t *(*svn_branch__state_v_set_element_t)(
svn_branch__state_t *branch,
svn_branch__eid_t eid,
const svn_element__content_t *element,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__state_v_copy_one_t)(
svn_branch__state_t *branch,
const svn_branch__rev_bid_eid_t *src_el_rev,
svn_branch__eid_t local_eid,
svn_branch__eid_t new_parent_eid,
const char *new_name,
const svn_element__payload_t *new_payload,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__state_v_copy_tree_t)(
svn_branch__state_t *branch,
const svn_branch__rev_bid_eid_t *src_el_rev,
svn_branch__eid_t new_parent_eid,
const char *new_name,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__state_v_purge_t)(
svn_branch__state_t *branch,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__state_v_get_history_t)(
svn_branch__state_t *branch,
svn_branch__history_t **history_p,
apr_pool_t *scratch_pool);
typedef svn_error_t *(*svn_branch__state_v_set_history_t)(
svn_branch__state_t *branch,
const svn_branch__history_t *history,
apr_pool_t *scratch_pool);
struct svn_branch__state_vtable_t
{
svn_branch__vtable_priv_t vpriv;
svn_branch__state_v_get_elements_t get_elements;
svn_branch__state_v_get_element_t get_element;
svn_branch__state_v_set_element_t set_element;
svn_branch__state_v_copy_one_t copy_one;
svn_branch__state_v_copy_tree_t copy_tree;
svn_branch__state_v_purge_t purge;
svn_branch__state_v_get_history_t get_history;
svn_branch__state_v_set_history_t set_history;
};
#ifdef __cplusplus
}
#endif
#endif /* SVN_BRANCH_IMPL_H */

View File

@ -0,0 +1,216 @@
/**
* @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_branch_nested.h
* @brief Nested branches and subbranch-root elements
*
* @since New in ???.
*/
#ifndef SVN_BRANCH_NESTED_H
#define SVN_BRANCH_NESTED_H
#include <apr_pools.h>
#include "svn_types.h"
#include "private/svn_branch.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
*/
void
svn_branch__get_outer_branch_and_eid(svn_branch__state_t **outer_branch_p,
int *outer_eid_p,
const svn_branch__state_t *branch,
apr_pool_t *scratch_pool);
/* Return the root repos-relpath of BRANCH.
*
* ### TODO: Clarify sequencing requirements.
*/
const char *
svn_branch__get_root_rrpath(const svn_branch__state_t *branch,
apr_pool_t *result_pool);
/* Return the repos-relpath of element EID in BRANCH.
*
* If the element EID does not currently exist in BRANCH, return NULL.
*
* ### TODO: Clarify sequencing requirements.
*/
const char *
svn_branch__get_rrpath_by_eid(const svn_branch__state_t *branch,
int eid,
apr_pool_t *result_pool);
/* Return the EID for the repos-relpath RRPATH in BRANCH.
*
* If no element of BRANCH is at this path, return -1.
*
* ### TODO: Clarify sequencing requirements.
*/
/*int*/
/*svn_branch__get_eid_by_rrpath(svn_branch__state_t *branch,*/
/* const char *rrpath,*/
/* apr_pool_t *scratch_pool);*/
/* Find the (deepest) branch of which the path RELPATH is either the root
* path or a normal, non-sub-branch path. An element need not exist at
* RELPATH.
*
* Set *BRANCH_P to the deepest branch within ROOT_BRANCH (recursively,
* including itself) that contains the path RELPATH.
*
* If EID_P is not null then set *EID_P to the element id of RELPATH in
* *BRANCH_P, or to -1 if no element exists at RELPATH in that branch.
*
* If RELPATH is not within any branch in ROOT_BRANCH, set *BRANCH_P to
* NULL and (if EID_P is not null) *EID_P to -1.
*
* ### TODO: Clarify sequencing requirements.
*/
svn_error_t *
svn_branch__find_nested_branch_element_by_relpath(
svn_branch__state_t **branch_p,
int *eid_p,
svn_branch__state_t *root_branch,
const char *relpath,
apr_pool_t *scratch_pool);
/* Set *EL_REV_P to the el-rev-id of the element at relative path RELPATH
* anywhere in or under branch BRANCH_ID in revision REVNUM in REPOS.
*
* If there is no element there, set *EL_REV_P to point to an id in which
* the BRANCH field is the nearest enclosing branch of RRPATH and the EID
* field is -1.
*
* Allocate *EL_REV_P (but not the branch object that it refers to) in
* RESULT_POOL.
*
* ### TODO: Clarify sequencing requirements.
*/
svn_error_t *
svn_branch__repos_find_el_rev_by_path_rev(svn_branch__el_rev_id_t **el_rev_p,
const svn_branch__repos_t *repos,
svn_revnum_t revnum,
const char *branch_id,
const char *relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Set *SUBBRANCHES_P an array of pointers to the branches that are immediate
* sub-branches of BRANCH.
*/
svn_error_t *
svn_branch__get_immediate_subbranches(svn_branch__state_t *branch,
apr_array_header_t **subbranches_p,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Return the subbranch rooted at BRANCH:EID, or NULL if that is
* not a subbranch root.
*/
svn_error_t *
svn_branch__get_subbranch_at_eid(svn_branch__state_t *branch,
svn_branch__state_t **subbranch_p,
int eid,
apr_pool_t *scratch_pool);
/* A subtree of a branch, including any nested branches.
*/
typedef struct svn_branch__subtree_t
{
svn_branch__rev_bid_t *predecessor;
/* EID -> svn_element__content_t mapping. */
svn_element__tree_t *tree;
/* Subbranches to be included: each subbranch-root element in E_MAP
should be mapped here.
A mapping of (int)EID -> (svn_branch__subtree_t *). */
apr_hash_t *subbranches;
} svn_branch__subtree_t;
/* Create an empty subtree (no elements populated, not even ROOT_EID).
*
* The result contains a *shallow* copy of E_MAP, or a new empty mapping
* if E_MAP is null.
*/
svn_branch__subtree_t *
svn_branch__subtree_create(apr_hash_t *e_map,
int root_eid,
apr_pool_t *result_pool);
/* Return the subtree of BRANCH rooted at EID.
* Recursive: includes subbranches.
*
* The result is limited by the lifetime of BRANCH. It includes a shallow
* copy of the element maps in BRANCH and its subbranches: the hash tables
* are duplicated but the keys and values (element content data) are not.
* It assumes that modifications on a svn_branch__state_t treat element
* map keys and values as immutable -- which they do.
*/
svn_error_t *
svn_branch__get_subtree(svn_branch__state_t *branch,
svn_branch__subtree_t **subtree_p,
int eid,
apr_pool_t *result_pool);
/* Return the subbranch rooted at SUBTREE:EID, or NULL if that is
* not a subbranch root. */
svn_branch__subtree_t *
svn_branch__subtree_get_subbranch_at_eid(svn_branch__subtree_t *subtree,
int eid,
apr_pool_t *result_pool);
/* Instantiate elements in a branch.
*
* In TO_BRANCH, instantiate (or alter, if existing) each element of
* ELEMENTS, each with its given tree structure (parent, name) and payload.
*
* Also branch the subbranches in ELEMENTS, creating corresponding new
* subbranches in TO_BRANCH, recursively.
*/
svn_error_t *
svn_branch__instantiate_elements_r(svn_branch__state_t *to_branch,
svn_branch__subtree_t elements,
apr_pool_t *scratch_pool);
/* Create a branch txn object that implements nesting, and wraps a plain
* branch txn (that doesn't support nesting) WRAPPED_TXN.
*/
svn_branch__txn_t *
svn_branch__nested_txn_create(svn_branch__txn_t *wrapped_txn,
apr_pool_t *result_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_BRANCH_NESTED_H */

View File

@ -0,0 +1,104 @@
/**
* @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_branch_repos.h
* @brief Operating on a repository
*
* @since New in ???.
*/
#ifndef SVN_BRANCH_REPOS_H
#define SVN_BRANCH_REPOS_H
#include <apr_pools.h>
#include "svn_types.h"
#include "private/svn_branch.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* Create a new branching metadata object */
svn_branch__repos_t *
svn_branch__repos_create(apr_pool_t *result_pool);
/* Add REV_ROOT as the next revision in the repository REPOS.
*
* (This does not change the REV and BASE_REV fields of REV_ROOT. The
* caller should set those, before or after this call.)
*/
svn_error_t *
svn_branch__repos_add_revision(svn_branch__repos_t *repos,
svn_branch__txn_t *rev_root);
/* Return a pointer to revision REVNUM of the repository REPOS.
*/
struct svn_branch__txn_t *
svn_branch__repos_get_revision(const svn_branch__repos_t *repos,
svn_revnum_t revnum);
/* Return the revision root that represents the base revision (or,
* potentially, txn) of the revision or txn REV_ROOT.
*/
svn_branch__txn_t *
svn_branch__repos_get_base_revision_root(svn_branch__txn_t *rev_root);
/* Set *BRANCH_P to the branch found in REPOS : REVNUM : BRANCH_ID.
*
* Return an error if REVNUM or BRANCH_ID is not found.
*/
svn_error_t *
svn_branch__repos_get_branch_by_id(svn_branch__state_t **branch_p,
const svn_branch__repos_t *repos,
svn_revnum_t revnum,
const char *branch_id,
apr_pool_t *scratch_pool);
/* Set *EL_REV_P to the el-rev-id of the element at branch id BRANCH_ID,
* element id EID, in revision REVNUM in REPOS.
*
* If there is no element there, set *EL_REV_P to point to an id in which
* the BRANCH field is the nearest enclosing branch of RRPATH and the EID
* field is -1.
*
* Allocate *EL_REV_P (but not the branch object that it refers to) in
* RESULT_POOL.
*/
svn_error_t *
svn_branch__repos_find_el_rev_by_id(svn_branch__el_rev_id_t **el_rev_p,
const svn_branch__repos_t *repos,
svn_revnum_t revnum,
const char *branch_id,
int eid,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_BRANCH_REPOS_H */

View File

@ -356,7 +356,12 @@ svn_cache__membuffer_cache_create(svn_membuffer_t **cache,
*
* If @a thread_safe is true, and APR is compiled with threads, all
* accesses to the cache will be protected with a mutex, if the shared
* @a memcache has also been created with thread_safe flag set.
* @a membuffer has also been created with thread_safe flag set.
*
* If @a short_lived is set, assume that the data stored through this
* cache will probably only be needed for a short period of time.
* Typically, some UUID is used as part of the prefix in that scenario.
* This flag is a mere hint and does not affect functionality.
*
* These caches do not support svn_cache__iter.
*/
@ -369,9 +374,23 @@ svn_cache__create_membuffer_cache(svn_cache__t **cache_p,
const char *prefix,
apr_uint32_t priority,
svn_boolean_t thread_safe,
svn_boolean_t short_lived,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Creates a null-cache instance in @a *cache_p, allocated from
* @a result_pool. The given @c id is the only data stored in it and can
* be retrieved through svn_cache__get_info().
*
* The cache object will immediately evict (reject) any data being added
* to it and will always report as empty.
*/
svn_error_t *
svn_cache__create_null(svn_cache__t **cache_p,
const char *id,
apr_pool_t *result_pool);
/**
* Sets @a handler to be @a cache's error handling routine. If any
* error is returned from a call to svn_cache__get or svn_cache__set, @a

View File

@ -63,6 +63,7 @@ svn_cmdline__print_xml_prop(svn_stringbuf_t **outstr,
* Expects a @c svn_cmdline_prompt_baton2_t to be passed as @a baton.
*
* @since New in 1.6.
* @deprecated Only used by old libgome-keyring implementation.
*/
svn_error_t *
svn_cmdline__auth_gnome_keyring_unlock_prompt(char **keyring_password,
@ -88,7 +89,7 @@ typedef struct svn_cmdline__config_argument_t
* containing svn_cmdline__config_argument_t* elements, allocating the option
* data in @a pool
*
* [Since 1.9/1.10:] If the file, section, or option value is not recognized,
* [Since 1.9:] If the file, section, or option value is not recognized,
* warn to @c stderr, using @a prefix as in svn_handle_warning2().
*
* @since New in 1.7.
@ -213,6 +214,18 @@ svn_cmdline__getopt_init(apr_getopt_t **os,
const char *argv[],
apr_pool_t *pool);
/* */
svn_boolean_t
svn_cmdline__stdin_is_a_terminal(void);
/* */
svn_boolean_t
svn_cmdline__stdout_is_a_terminal(void);
/* */
svn_boolean_t
svn_cmdline__stderr_is_a_terminal(void);
/* Determine whether interactive mode should be enabled, based on whether
* the user passed the --non-interactive or --force-interactive options.
* If neither option was passed, interactivity is enabled if standard
@ -239,6 +252,32 @@ svn_cmdline__parse_trust_options(
const char *opt_arg,
apr_pool_t *scratch_pool);
/* Setup signal handlers for signals such as SIGINT and return a
cancellation handler function. This also sets some other signals
to be ignored. */
svn_cancel_func_t
svn_cmdline__setup_cancellation_handler(void);
/* Set the handlers for signals such as SIGINT back to default. */
void
svn_cmdline__disable_cancellation_handler(void);
/* Exit this process with a status that indicates the cancellation
signal, or return without exiting if there is no signal. This
allows the shell to use WIFSIGNALED and WTERMSIG to detect the
signal. See http://www.cons.org/cracauer/sigint.html */
void
svn_cmdline__cancellation_exit(void);
/** Reads a string from stdin until a newline or EOF is found
*
* @since New in 1.10.
*/
svn_error_t *
svn_cmdline__stdin_readline(const char **result,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -0,0 +1,129 @@
/**
* @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_config_private.h
* @brief Private config file parsing API.
*/
#ifndef SVN_CONFIG_PRIVATE_H
#define SVN_CONFIG_PRIVATE_H
#include <apr_pools.h>
#include "svn_error.h"
#include "svn_io.h"
#include "svn_string.h"
#include "svn_config.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/*
* Description of a constructor for in-memory config file
* representations.
*/
typedef struct svn_config__constructor_t svn_config__constructor_t;
/*
* Constructor callback: called when the parsing of a new SECTION
* begins. If the implementation stores the value of SECTION, it
* must copy it into a permanent pool.
*
* May return SVN_ERR_CEASE_INVOCATION to stop further parsing.
*/
typedef svn_error_t *(*svn_config__open_section_fn)(
void *baton, svn_stringbuf_t *section);
/*
* Constructor callback: called when the parsing of SECTION ends. If
* the implementation stores the value of SECTION, it must copy it
* into a permanent pool.
*
* May return SVN_ERR_CEASE_INVOCATION to stop further parsing.
*/
typedef svn_error_t *(*svn_config__close_section_fn)(
void *baton, svn_stringbuf_t *section);
/*
* Constructor callback: called OPTION with VALUE in SECTION was
* parsed. If the implementation stores the values of SECTION, OPTION
* or VALUE, it must copy them into a permanent pool.
*
* May return SVN_ERR_CEASE_INVOCATION to stop further parsing.
*/
typedef svn_error_t *(*svn_config__add_value_fn)(
void *baton, svn_stringbuf_t *section,
svn_stringbuf_t *option, svn_stringbuf_t *value);
/*
* Create a new constuctor allocated from RESULT_POOL.
* Any of the callback functions may be NULL.
* The constructor implementation is responsible for implementing any
* case-insensitivity, value expansion, or other features on top of
* the basic parser.
*/
svn_config__constructor_t *
svn_config__constructor_create(
svn_config__open_section_fn open_section_callback,
svn_config__close_section_fn close_section_callback,
svn_config__add_value_fn add_value_callback,
apr_pool_t *result_pool);
/*
* Parse the configuration from STREAM, using CONSTRUCTOR to build the
* in-memory representation of the parsed configuration.
* CONSTRUCTOR_BATON is passed unchanged to the constructor
* callbacks. The parser guarantees that sections and options will be
* passed to the callback in the same order as they're defined in
* STREAM.
*
* The lifetome of section names, option names and values passed to
* the constructor does not extend past the invocation of each
* callback; see calback docs, above.
*
* The parser will use SCRATCH_POOL for its own allocations.
*/
svn_error_t *
svn_config__parse_stream(svn_stream_t *stream,
svn_config__constructor_t *constructor,
void *constructor_baton,
apr_pool_t *scratch_pool);
/*
* Write the configuration CFG to STREAM, using SCRATCH_POOL for
* temporary allocations.
*
* Note that option values will not be expanded and that the order
* of sections as well as the options within them is undefined.
*/
svn_error_t *
svn_config__write(svn_stream_t *stream,
const svn_config_t *cfg,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_CONFIG_PRIVATE_H */

View File

@ -108,6 +108,25 @@ svn_txdelta__read_raw_window_len(apr_size_t *window_len,
svn_stream_t *stream,
apr_pool_t *pool);
/* Return a debug editor that wraps @a wrapped_editor.
*
* The debug editor simply prints an indication of what callbacks are being
* called to @c stdout, and is only intended for use in debugging subversion
* editors.
*
* @a prefix, if non-null, is printed between "DBG: " and each indication.
*
* Note: Our test suite generally ignores stdout lines starting with "DBG:".
*/
svn_error_t *
svn_delta__get_debug_editor(const svn_delta_editor_t **editor,
void **edit_baton,
const svn_delta_editor_t *wrapped_editor,
void *wrapped_baton,
const char *prefix,
apr_pool_t *pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -74,6 +74,27 @@ extern "C" {
#define SVN_LOCK_IS_BUSY(x) APR_STATUS_IS_EBUSY(x)
#endif
/**
* Indicate whether we are running on a POSIX platform. This has
* implications on the way e.g. fsync() works.
*
* For details on this check, see
* http://nadeausoftware.com/articles/2012/01/c_c_tip_how_use_compiler_predefined_macros_detect_operating_system#POSIX
*
* @since New in 1.10.
*/
#ifndef SVN_ON_POSIX
#if !defined(_WIN32) \
&& ( defined(__unix__) \
|| defined(__unix) \
|| (defined(__APPLE__) && defined(__MACH__))) /* UNIX-style OS? */
# include <unistd.h>
# if defined(_POSIX_VERSION)
# define SVN_ON_POSIX
# endif
#endif
#endif
/**
* APR keeps a few interesting defines hidden away in its private
* headers apr_arch_file_io.h, so we redefined them here.
@ -93,6 +114,28 @@ extern "C" {
#endif
#endif
/**
* APR 1 has volatile qualifier bugs in some atomic prototypes that
* are fixed in APR 2:
* https://issues.apache.org/bugzilla/show_bug.cgi?id=50731
* Subversion code should put the volatile qualifier in the correct
* place when declaring variables which means that casting at the call
* site is necessary when using APR 1. No casts should be used with
* APR 2 as this allows the compiler to check that the variable has
* the correct volatile qualifier.
*/
#if APR_VERSION_AT_LEAST(2,0,0)
#define svn_atomic_casptr(mem, with, cmp) \
apr_atomic_casptr((mem), (with), (cmp))
#define svn_atomic_xchgptr(mem, val) \
apr_atomic_xchgptr((mem), (val))
#else
#define svn_atomic_casptr(mem, with, cmp) \
apr_atomic_casptr((void volatile **)(mem), (with), (cmp))
#define svn_atomic_xchgptr(mem, val) \
apr_atomic_xchgptr((void volatile **)(mem), (val))
#endif
/**
* Check at compile time if the Serf version is at least a certain
* level.

View File

@ -113,6 +113,40 @@ svn_diff__display_prop_diffs(svn_stream_t *outstream,
void *cancel_baton,
apr_pool_t *scratch_pool);
/** Create a hunk object that adds a single line without newline. Return the
* new object in @a *hunk.
*
* @a line is the added text, without a trailing newline.
*
* The hunk will be associated with @a patch.
*/
svn_error_t *
svn_diff_hunk__create_adds_single_line(svn_diff_hunk_t **hunk,
const char *line,
const svn_patch_t *patch,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Create a hunk object that deletes a single line without newline. Return
* the new object in @a *hunk.
*
* @a line is the deleted text, without a trailing newline.
*
* The hunk will be associated with @a patch.
*/
svn_error_t *
svn_diff_hunk__create_deletes_single_line(svn_diff_hunk_t **hunk,
const char *line,
const svn_patch_t *patch,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Fetches the penalty fuzz of the diff hunk. The patch file parser applies
* an additional penalty on some cases of bad patch files. These cases may
* include errors as headers that aren't consistent with bodies, etc.
*/
svn_linenum_t
svn_diff_hunk__get_fuzz_penalty(const svn_diff_hunk_t *hunk);
#ifdef __cplusplus
}

View File

@ -114,12 +114,24 @@ extern "C" {
* ### How come many users don't set the 'repos_relpath' field? */
typedef struct svn_diff_source_t
{
/* Always available */
/* Always available
In case of copyfrom: the revision copied from
*/
svn_revnum_t revision;
/* Depending on the driver available for copyfrom */
/* ### What? */
/* In case of copyfrom: the repository relative path copied from.
NULL if the node wasn't copied or moved, or when the driver doesn't
have this information */
const char *repos_relpath;
/* In case of copyfrom: the relative path of source location before the
move. This path is relative WITHIN THE DIFF. The repository path is
typically in repos_relpath
NULL if the node wasn't moved or if the driver doesn't have this
information. */
const char *moved_from_relpath;
} svn_diff_source_t;
/**

View File

@ -0,0 +1,399 @@
/**
* @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_element.h
* @brief Tree elements
*
* @since New in ???.
*/
#ifndef SVN_BRANCH_ELEMENT_H
#define SVN_BRANCH_ELEMENT_H
#include <apr_pools.h>
#include <apr_tables.h>
#include "svn_types.h"
#ifdef __cplusplus
extern "C" {
#endif /* __cplusplus */
/* ====================================================================== */
/** Like apr_hash_get() but the hash key is an integer. */
void *
svn_eid__hash_get(apr_hash_t *ht,
int key);
/** Like apr_hash_set() but the hash key is an integer. */
void
svn_eid__hash_set(apr_hash_t *ht,
int key,
const void *val);
/** Like apr_hash_this_key() but the hash key is an integer. */
int
svn_eid__hash_this_key(apr_hash_index_t *hi);
struct svn_sort__item_t;
/** A hash iterator for iterating over an array or a hash table in
* its natural order or in sorted order.
*
* For an array, the @a i and @a val members provide the index and value
* of the current item.
*/
typedef struct svn_eid__hash_iter_t
{
/* private: an array of (svn_sort__item_t) hash items for sorted iteration */
const apr_array_header_t *array;
/* current element: iteration order index */
int i;
/* current element: key */
int eid;
/* current element: value */
void *val;
} svn_eid__hash_iter_t;
svn_eid__hash_iter_t *
svn_eid__hash_sorted_first(apr_pool_t *pool,
apr_hash_t *ht,
int (*comparison_func)(const struct svn_sort__item_t *,
const struct svn_sort__item_t *));
svn_eid__hash_iter_t *
svn_eid__hash_sorted_next(svn_eid__hash_iter_t *hi);
/** A sort ordering callback function that returns an indication whether
* A sorts before or after or equal to B, by comparing their keys as EIDs.
*/
int
svn_eid__hash_sort_compare_items_by_eid(const struct svn_sort__item_t *a,
const struct svn_sort__item_t *b);
#define SVN_EID__HASH_ITER_SORTED(i, ht, comparison_func, pool) \
i = (void *)svn_eid__hash_sorted_first(pool, ht, comparison_func); \
i; \
i = (void *)svn_eid__hash_sorted_next((void *)i)
#define SVN_EID__HASH_ITER_SORTED_BY_EID(i, ht, pool) \
SVN_EID__HASH_ITER_SORTED(i, ht, svn_eid__hash_sort_compare_items_by_eid, pool)
/* ====================================================================== */
/**
*/
typedef struct svn_element__branch_ref_t
{
svn_revnum_t rev;
const char *branch_id;
int eid;
} svn_element__branch_ref_t;
/** Versioned payload of an element, excluding tree structure information.
*
* This specifies the properties and the text of a file or target of a
* symlink, directly, or by reference to an existing committed element, or
* by a delta against such a reference payload.
*
* ### An idea: If the sender and receiver agree, the payload for an element
* may be specified as "null" to designate that the payload is not
* available. For example, when a client performing a WC update has
* no read authorization for a given path, the server may send null
* payload and the client may record an 'absent' WC node. (This
* would not make sense in a commit.)
*/
typedef struct svn_element__payload_t svn_element__payload_t;
/*
* ========================================================================
* Element Payload Interface
* ========================================================================
*
* @defgroup svn_element_payload Element payload interface
* @{
*/
/** Versioned payload of a node, excluding tree structure information.
*
* Payload is described by setting fields in one of the following ways.
* Other fields SHOULD be null (or equivalent).
*
* by reference: (kind=unknown, ref)
* dir: (kind=dir, props)
* file: (kind=file, props, text)
* symlink: (kind=symlink, props, target)
*
* ### Idea for the future: Specify payload as an (optional) reference
* plus (optional) overrides or deltas against the reference?
*/
struct svn_element__payload_t
{
/* Is this a subbranch-root element, in other words a link to a nested
* branch? If so, all other fields are irrelevant. */
svn_boolean_t is_subbranch_root;
/* The node kind for this payload: dir, file, symlink, or unknown. */
svn_node_kind_t kind;
/* Reference an existing, committed payload. (Use with kind=unknown if
* there is no content in props/text/targe fields.)
* The 'null' value is (SVN_INVALID_REVNUM, NULL, *). */
svn_element__branch_ref_t branch_ref;
/* The pool in which the payload's content is allocated. Used when
* resolving (populating the props/text/target in) a payload that was
* originally defined by reference. */
apr_pool_t *pool;
/* Properties (for kind != unknown).
* Maps (const char *) name -> (svn_string_t) value.
* An empty hash means no properties. (SHOULD NOT be NULL.)
* ### Presently NULL means 'no change' in some contexts. */
apr_hash_t *props;
/* File text (for kind=file; otherwise SHOULD be NULL). */
svn_stringbuf_t *text;
/* Symlink target (for kind=symlink; otherwise SHOULD be NULL). */
const char *target;
};
/* Return true iff PAYLOAD satisfies all its invariants.
*/
svn_boolean_t
svn_element__payload_invariants(const svn_element__payload_t *payload);
/** Duplicate a node-payload @a old into @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_dup(const svn_element__payload_t *old,
apr_pool_t *result_pool);
/* Return true iff the payload of LEFT is identical to that of RIGHT.
* References are not supported. Node kind 'unknown' is not supported.
*/
svn_boolean_t
svn_element__payload_equal(const svn_element__payload_t *left,
const svn_element__payload_t *right,
apr_pool_t *scratch_pool);
/** Create a new node-payload object for a subbranch-root (link to a
* nested branch).
*
* Allocate the result in @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_create_subbranch(apr_pool_t *result_pool);
/** Create a new node-payload object by reference to an existing payload.
*
* Set the node kind to 'unknown'.
*
* Allocate the result in @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_create_ref(svn_revnum_t rev,
const char *branch_id,
int eid,
apr_pool_t *result_pool);
/** Create a new node-payload object for a directory node.
*
* Allocate the result in @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_create_dir(apr_hash_t *props,
apr_pool_t *result_pool);
/** Create a new node-payload object for a file node.
*
* Allocate the result in @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_create_file(apr_hash_t *props,
svn_stringbuf_t *text,
apr_pool_t *result_pool);
/** Create a new node-payload object for a symlink node.
*
* Allocate the result in @a result_pool.
*/
svn_element__payload_t *
svn_element__payload_create_symlink(apr_hash_t *props,
const char *target,
apr_pool_t *result_pool);
/** @} */
/*
* ========================================================================
* Element-Revision Content
* ========================================================================
*
* @defgroup svn_el_rev_content Element-Revision Content
* @{
*/
/* The content (parent, name and payload) of an element-revision.
* In other words, an el-rev node in a (mixed-rev) directory-tree.
*/
typedef struct svn_element__content_t
{
/* eid of the parent element, or -1 if this is the root element */
int parent_eid;
/* element name, or "" for root element; never null */
const char *name;
/* payload (kind, props, text, ...) */
svn_element__payload_t *payload;
} svn_element__content_t;
/* Return a new content object constructed with deep copies of PARENT_EID,
* NAME and PAYLOAD, allocated in RESULT_POOL.
*/
svn_element__content_t *
svn_element__content_create(int parent_eid,
const char *name,
const svn_element__payload_t *payload,
apr_pool_t *result_pool);
/* Return a deep copy of OLD, allocated in RESULT_POOL.
*/
svn_element__content_t *
svn_element__content_dup(const svn_element__content_t *old,
apr_pool_t *result_pool);
/* Return TRUE iff CONTENT_LEFT is the same as CONTENT_RIGHT. */
svn_boolean_t
svn_element__content_equal(const svn_element__content_t *content_left,
const svn_element__content_t *content_right,
apr_pool_t *scratch_pool);
/** @} */
/*
* ========================================================================
* Element Tree
* ========================================================================
*
* The elements in an Element Tree do not necessarily form a single,
* complete tree at all times.
*
* @defgroup svn_element_tree Element Tree
* @{
*/
/* A (sub)tree of elements.
*
* An element tree is described by the content of element ROOT_EID in E_MAP,
* and its children (as determined by their parent links) and their names
* and their content recursively. For the element ROOT_EID itself, only
* its content is relevant; its parent and name are to be ignored.
*
* E_MAP may also contain entries that are not part of the subtree. Thus,
* to select a sub-subtree, it is only necessary to change ROOT_EID.
*
* The EIDs used in here may be considered either as global EIDs (known to
* the repo), or as local stand-alone EIDs (in their own local name-space),
* according to the context.
*/
typedef struct svn_element__tree_t
{
/* EID -> svn_element__content_t mapping. */
apr_hash_t *e_map;
/* Subtree root EID. (ROOT_EID must be an existing key in E_MAP.) */
int root_eid;
} svn_element__tree_t;
/* Create an element tree object.
*
* The result contains a *shallow* copy of E_MAP, or a new empty mapping
* if E_MAP is null.
*/
svn_element__tree_t *
svn_element__tree_create(apr_hash_t *e_map,
int root_eid,
apr_pool_t *result_pool);
svn_element__content_t *
svn_element__tree_get(const svn_element__tree_t *tree,
int eid);
svn_error_t *
svn_element__tree_set(svn_element__tree_t *tree,
int eid,
const svn_element__content_t *element);
/* Purge entries from E_MAP that don't connect, via parent directory hierarchy,
* to ROOT_EID. In other words, remove elements that have been implicitly
* deleted.
*
* ROOT_EID must be present in E_MAP.
*
* ### Does not detect cycles: current implementation will not purge a cycle
* that is disconnected from ROOT_EID. This could be a problem.
*/
void
svn_element__tree_purge_orphans(apr_hash_t *e_map,
int root_eid,
apr_pool_t *scratch_pool);
/* Return the subtree-relative path of element EID in TREE.
*
* If the element EID does not currently exist in TREE, return NULL.
*
* ### TODO: Clarify sequencing requirements.
*/
const char *
svn_element__tree_get_path_by_eid(const svn_element__tree_t *tree,
int eid,
apr_pool_t *result_pool);
/* Return the subtree rooted at EID within ELEMENT_TREE.
*
* The result is limited by the lifetime of ELEMENT_TREE. It includes a
* shallow copy of the mapping in ELEMENT_TREE: the hash table is
* duplicated but the keys and values (element content data) are not.
*/
svn_element__tree_t *
svn_element__tree_get_subtree_at_eid(svn_element__tree_t *element_tree,
int eid,
apr_pool_t *result_pool);
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* SVN_BRANCH_ELEMENT_H */

View File

@ -53,7 +53,8 @@ typedef struct svn_fs_fs__large_change_info_t
/* size of the (deltified) representation */
apr_uint64_t size;
/* Revision of the representation. SVN_INVALID_REVNUM for unused entries. */
/* Revision of the representation. SVN_INVALID_REVNUM for unused entries.
*/
svn_revnum_t revision;
/* node path. "" for unused instances */
@ -151,6 +152,9 @@ typedef struct svn_fs_fs__representation_stats_t
/* sum of ref_count * expanded_size,
* i.e. total plaintext content if there was no rep sharing */
apr_uint64_t expanded_size;
/* sum of all representation delta chain lengths */
apr_uint64_t chain_len;
} svn_fs_fs__representation_stats_t;
/* Basic statistics we collect over a given set of noderevs.
@ -267,19 +271,20 @@ svn_fs_fs__get_stats(svn_fs_fs__stats_t **stats,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Node-revision IDs in FSFS consist of 3 of sub-IDs ("parts") that consist
/* 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.
*
* The parts are: node_id, copy_id and txn_id for in-txn IDs as well as
* node_id, copy_id and rev_offset for in-revision IDs. This struct the
* node_id, copy_id and rev_item for in-revision IDs. This struct is the
* data structure used for each of those parts.
*/
typedef struct svn_fs_fs__id_part_t
{
/* SVN_INVALID_REVNUM for txns -> not a txn, COUNTER must be 0.
SVN_INVALID_REVNUM for others -> not assigned to a revision, yet.
0 for others -> old-style ID or the root in rev 0. */
/* SVN_INVALID_REVNUM for txn_id part -> not a txn, NUMBER must be 0.
SVN_INVALID_REVNUM for other parts -> not assigned to a revision, yet.
0 for other parts -> old-style ID or the root in rev 0.
*/
svn_revnum_t revision;
/* sub-id value relative to REVISION. Its interpretation depends on

View File

@ -183,7 +183,7 @@ svn_fs__editor_commit(svn_revnum_t *revision,
*
* If there is no mergeinfo, set @a *mergeinfo to NULL.
*
* See svn_fs_get_mergeinfo2() but for the meanings of @a inherit and
* See svn_fs_get_mergeinfo3() but for the meanings of @a inherit and
* @a adjust_inheritable_mergeinfo and other details.
*/
svn_error_t *
@ -195,6 +195,22 @@ svn_fs__get_mergeinfo_for_path(svn_mergeinfo_t *mergeinfo,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Determine the previous location of @a path under @a root and return it
* as @a *node_path under @a *node_root. This may be called for arbitrary
* nodes but is intended for nodes that got deleted in @a root, i.e. when
* standard navigation fails. It also works if @a root is transaction root.
*
* Allocate @a *node_path and @a *node_root in @a result_pool while using
* @a scratch_pool for temporaries.
*/
svn_error_t *
svn_fs__get_deleted_node(svn_fs_root_t **node_root,
const char **node_path,
svn_fs_root_t *root,
const char *path,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** @} */

View File

@ -206,6 +206,15 @@ svn_fs__path_change_create_internal(const svn_fs_id_t *node_rev_id,
svn_fs_path_change_kind_t change_kind,
apr_pool_t *pool);
/* Allocate an svn_fs_path_change3_t structure in RESULT_POOL, initialize
and return it.
Set the change_kind to CHANGE_KIND. Set all other fields to their
_unknown, NULL or invalid value, respectively. */
svn_fs_path_change3_t *
svn_fs__path_change_create_internal2(svn_fs_path_change_kind_t change_kind,
apr_pool_t *result_pool);
/* Append REL_PATH (which may contain slashes) to each path that exists in
the mergeinfo INPUT, and return a new mergeinfo in *OUTPUT. Deep
copies the values. Perform all allocations in POOL. */

View File

@ -85,32 +85,6 @@ svn_io__file_lock_autocreate(const char *lock_file,
apr_pool_t *pool);
/** Buffer test handler function for a generic stream. @see svn_stream_t
* and svn_stream__is_buffered().
*
* @since New in 1.7.
*/
typedef svn_boolean_t (*svn_stream__is_buffered_fn_t)(void *baton);
/** Set @a stream's buffer test function to @a is_buffered_fn
*
* @since New in 1.7.
*/
void
svn_stream__set_is_buffered(svn_stream_t *stream,
svn_stream__is_buffered_fn_t is_buffered_fn);
/** Return whether this generic @a stream uses internal buffering.
* This may be used to work around subtle differences between buffered
* and non-buffered APR files. A lazy-open stream cannot report the
* true buffering state until after the lazy open: a stream that
* initially reports as non-buffered may report as buffered later.
*
* @since New in 1.7.
*/
svn_boolean_t
svn_stream__is_buffered(svn_stream_t *stream);
/** Return the underlying file, if any, associated with the stream, or
* NULL if not available. Accessing the file bypasses the stream.
*/
@ -153,6 +127,13 @@ svn_stream__install_get_info(apr_finfo_t *finfo,
apr_int32_t wanted,
apr_pool_t *scratch_pool);
/* Internal version of svn_stream_from_aprfile2() supporting the
additional TRUNCATE_ON_SEEK argument. */
svn_stream_t *
svn_stream__from_aprfile(apr_file_t *file,
svn_boolean_t disown,
svn_boolean_t truncate_on_seek,
apr_pool_t *pool);
#if defined(WIN32)

View File

@ -93,7 +93,7 @@ svn_log__get_file(const char *path, svn_revnum_t rev,
const char *
svn_log__get_dir(const char *path, svn_revnum_t rev,
svn_boolean_t want_contents, svn_boolean_t want_props,
apr_uint64_t dirent_fields,
apr_uint32_t dirent_fields,
apr_pool_t *pool);
/**
@ -253,6 +253,17 @@ const char *
svn_log__get_inherited_props(const char *path,
svn_revnum_t rev,
apr_pool_t *pool);
/**
* Return a log string for a list action.
*
* @since New in 1.10.
*/
const char *
svn_log__list(const char *path, svn_revnum_t revision,
apr_array_header_t *patterns, svn_depth_t depth,
apr_uint32_t dirent_fields, apr_pool_t *pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -52,18 +52,21 @@ svn_rangelist__set_inheritance(svn_rangelist_t *rangelist,
* Unlike svn_mergeinfo_parse(), this does not sort the ranges into order
* or combine adjacent and overlapping ranges.
*
* The compaction can be done with svn_rangelist__combine_adjacent_ranges().
* The compaction can be done with svn_rangelist__canonicalize().
*/
svn_error_t *
svn_rangelist__parse(svn_rangelist_t **rangelist,
const char *str,
apr_pool_t *result_pool);
/* In-place combines adjacent ranges in a rangelist.
SCRATCH_POOL is just used for providing error messages. */
svn_error_t *
svn_rangelist__combine_adjacent_ranges(svn_rangelist_t *rangelist,
apr_pool_t *scratch_pool);
/* Return TRUE, if all ranges in RANGELIST are in ascending order and do
* not overlap and are not adjacent.
*
* If this returns FALSE, you probaly want to call
* svn_rangelist__canonicalize().
*/
svn_boolean_t
svn_rangelist__is_canonical(const svn_rangelist_t *rangelist);
/** Canonicalize the @a rangelist: sort the ranges, and combine adjacent or
* overlapping ranges into single ranges where possible.

View File

@ -27,8 +27,6 @@
#ifndef SVN_MUTEX_H
#define SVN_MUTEX_H
#include <apr_thread_mutex.h>
#include "svn_error.h"
#ifdef __cplusplus
@ -106,6 +104,17 @@ do { \
SVN_ERR(svn_mutex__unlock(svn_mutex__m, (expr))); \
} while (0)
#if APR_HAS_THREADS
/** Return the APR mutex encapsulated in @a mutex.
*
* @note This function should only be called by APR wrapper code.
*/
apr_thread_mutex_t *
svn_mutex__get(svn_mutex__t *mutex);
#endif
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -65,80 +65,46 @@
/* The opaque object container type. */
typedef struct svn_object_pool__t svn_object_pool__t;
/* Extract the actual object from the WRAPPER using optional information
* from BATON (provided through #svn_object_pool__lookup) and return it.
* The result will be used with POOL and must remain valid throughout
* POOL's lifetime.
*
* It is legal to return a copy, allocated in POOL, of the wrapped object.
*/
typedef void * (* svn_object_pool__getter_t)(void *wrapper,
void *baton,
apr_pool_t *pool);
/* Copy the information from the SOURCE object wrapper into the already
* existing *TARGET object wrapper using POOL for allocations and BATON
* for optional context (provided through #svn_object_pool__insert).
*/
typedef svn_error_t * (* svn_object_pool__setter_t)(void **target,
void *source,
void *baton,
apr_pool_t *pool);
/* Create a new object pool in POOL and return it in *OBJECT_POOL.
* Objects will be extracted using GETTER and updated using SETTER. Either
* one (or both) may be NULL and the default implementation assumes that
* wrapper == object and updating is a no-op.
* Objects are reference-counted and stored as opaque pointers. Each
* must be allocated in a separate pool ceated by
* svn_object_pool__new_item_pool. Unused objects get destroyed at
* the object pool's discretion.
*
* If THREAD_SAFE is not set, neither the object pool nor the object
* references returned from it may be accessed from multiple threads.
*
* It is not legal to call any API on the object pool after POOL got
* cleared or destroyed. However, existing object references handed out
* from the object pool remain valid and will keep the internal pool data
* structures alive for as long as such object references exist.
* cleared or destroyed nor to use any objects from this object pool.
*/
svn_error_t *
svn_object_pool__create(svn_object_pool__t **object_pool,
svn_object_pool__getter_t getter,
svn_object_pool__setter_t setter,
svn_boolean_t thread_safe,
apr_pool_t *pool);
/* Return the root pool containing the OBJECT_POOL and all sub-structures.
/* Return a pool to allocate the new object.
*/
apr_pool_t *
svn_object_pool__new_wrapper_pool(svn_object_pool__t *object_pool);
/* Return the mutex used to serialize all OBJECT_POOL access.
*/
svn_mutex__t *
svn_object_pool__mutex(svn_object_pool__t *object_pool);
/* Return the number of object instances (used or unused) in OBJECT_POOL.
*/
unsigned
svn_object_pool__count(svn_object_pool__t *object_pool);
svn_object_pool__new_item_pool(svn_object_pool__t *object_pool);
/* In OBJECT_POOL, look for an available object by KEY and return a
* reference to it in *OBJECT. If none can be found, *OBJECT will be NULL.
* BATON will be passed to OBJECT_POOL's getter function. The reference
* will be returned when *RESULT_POOL gets cleaned up or destroyed.
*
* The reference will be returned when *RESULT_POOL and may be destroyed
* or recycled by OBJECT_POOL.
*/
svn_error_t *
svn_object_pool__lookup(void **object,
svn_object_pool__t *object_pool,
svn_membuf_t *key,
void *baton,
apr_pool_t *result_pool);
/* Store the wrapped object WRAPPER under KEY in OBJECT_POOL and return
* a reference to the object in *OBJECT (just like lookup).
/* Store the object ITEM under KEY in OBJECT_POOL and return a reference
* to the object in *OBJECT (just like lookup).
*
* The object must have been created in WRAPPER_POOL and the latter must
* be a sub-pool of OBJECT_POOL's root POOL (see #svn_object_pool__pool).
* The object must have been created in ITEM_POOL and the latter must
* have been created by svn_object_pool__new_item_pool.
*
* BATON will be passed to OBJECT_POOL's setter and getter functions.
* The reference will be returned when *RESULT_POOL gets cleaned up or
* destroyed.
*/
@ -146,9 +112,8 @@ svn_error_t *
svn_object_pool__insert(void **object,
svn_object_pool__t *object_pool,
const svn_membuf_t *key,
void *wrapper,
void *baton,
apr_pool_t *wrapper_pool,
void *item,
apr_pool_t *item_pool,
apr_pool_t *result_pool);
#endif /* SVN_OBJECT_POOL_H */

View File

@ -218,6 +218,11 @@ svn_packed__int_count(svn_packed__int_stream_t *stream);
apr_size_t
svn_packed__byte_count(svn_packed__byte_stream_t *stream);
/* Return the number of entries left to read from STREAM.
*/
apr_size_t
svn_packed__byte_block_count(svn_packed__byte_stream_t *stream);
/* Return the next number from STREAM as unsigned integer. Returns 0 when
* reading beyond the end of the stream.
*/

View File

@ -34,6 +34,104 @@
extern "C" {
#endif /* __cplusplus */
/** Memory representation of an on-the-wire data item. */
typedef struct svn_ra_svn__item_t svn_ra_svn__item_t;
/* A list of svn_ra_svn__item_t objects. */
typedef struct svn_ra_svn__list_t
{
/* List contents (array). May be NULL if NELTS is 0. */
struct svn_ra_svn__item_t *items;
/* Number of elements in ITEMS. */
int nelts;
} svn_ra_svn__list_t;
/* List element access macro. */
#define SVN_RA_SVN__LIST_ITEM(list, idx) (list)->items[idx]
/** Memory representation of an on-the-wire data item. */
struct svn_ra_svn__item_t
{
/** Variant indicator. */
svn_ra_svn_item_kind_t kind;
/** Variant data. */
union {
apr_uint64_t number;
svn_string_t string;
svn_string_t word;
svn_ra_svn__list_t list;
} u;
};
/** Command handler, used by svn_ra_svn__handle_commands(). */
typedef svn_error_t *(*svn_ra_svn__command_handler)(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
svn_ra_svn__list_t *params,
void *baton);
/** Command table, used by svn_ra_svn_handle_commands().
*/
typedef struct svn_ra_svn__cmd_entry_t
{
/** Name of the command */
const char *cmdname;
/** Handler for the command */
svn_ra_svn__command_handler handler;
/** Only set when used through a deprecated API.
* HANDLER is NULL in that case. */
svn_ra_svn_command_handler deprecated_handler;
/** Termination flag. If set, command-handling will cease after
* command is processed. */
svn_boolean_t terminate;
} svn_ra_svn__cmd_entry_t;
/* Return a deep copy of the SOURCE array containing private API
* svn_ra_svn__item_t SOURCE to public API *TARGET, allocating
* sub-structures in RESULT_POOL. */
apr_array_header_t *
svn_ra_svn__to_public_array(const svn_ra_svn__list_t *source,
apr_pool_t *result_pool);
/* Deep copy contents from private API *SOURCE to public API *TARGET,
* allocating sub-structures in RESULT_POOL. */
void
svn_ra_svn__to_public_item(svn_ra_svn_item_t *target,
const svn_ra_svn__item_t *source,
apr_pool_t *result_pool);
svn_ra_svn__list_t *
svn_ra_svn__to_private_array(const apr_array_header_t *source,
apr_pool_t *result_pool);
/* Deep copy contents from public API *SOURCE to private API *TARGET,
* allocating sub-structures in RESULT_POOL. */
void
svn_ra_svn__to_private_item(svn_ra_svn__item_t *target,
const svn_ra_svn_item_t *source,
apr_pool_t *result_pool);
/** Add the capabilities in @a list to @a conn's capabilities.
* @a list contains svn_ra_svn__item_t entries (which should be of type
* SVN_RA_SVN_WORD; a malformed data error will result if any are not).
*
* This is idempotent: if a given capability was already set for
* @a conn, it remains set.
*/
svn_error_t *
svn_ra_svn__set_capabilities(svn_ra_svn_conn_t *conn,
const svn_ra_svn__list_t *list);
/** Returns the preferred svndiff version to be used with connection @a conn.
*/
int
svn_ra_svn__svndiff_version(svn_ra_svn_conn_t *conn);
/**
* Set the shim callbacks to be used by @a conn to @a shim_callbacks.
@ -161,10 +259,10 @@ svn_ra_svn__flush(svn_ra_svn_conn_t *conn,
* to transmit an array or other unusual data. For example, to write
* a tuple containing a revision, an array of words, and a boolean:
* @code
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "r(!", rev));
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "r(!", rev));
for (i = 0; i < n; i++)
SVN_ERR(svn_ra_svn_write_word(conn, pool, words[i]));
SVN_ERR(svn_ra_svn_write_tuple(conn, pool, "!)b", flag)); @endcode
SVN_ERR(svn_ra_svn__write_word(conn, pool, words[i]));
SVN_ERR(svn_ra_svn__write_tuple(conn, pool, "!)b", flag)); @endcode
*/
svn_error_t *
svn_ra_svn__write_tuple(svn_ra_svn_conn_t *conn,
@ -175,7 +273,7 @@ svn_ra_svn__write_tuple(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__read_item(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
svn_ra_svn_item_t **item);
svn_ra_svn__item_t **item);
/** Scan data on @a conn until we find something which looks like the
* beginning of an svn server greeting (an open paren followed by a
@ -221,13 +319,12 @@ svn_ra_svn__skip_leading_garbage(svn_ra_svn_conn_t *conn,
*
* If an optional part of a tuple contains no data, 'r' values will be
* set to @c SVN_INVALID_REVNUM; 'n' and 'B' values will be set to
* #SVN_RA_SVN_UNSPECIFIED_NUMBER; 's', 'c', 'w', and 'l' values
* will be set to @c NULL; and '3' values will be set to #svn_tristate_unknown
* 'b' may not appear inside an optional tuple specification; use '3' instead.
* #SVN_RA_SVN_UNSPECIFIED_NUMBER; 's', 'c', 'w', and 'l' values will
* be set to @c NULL; '3' values will be set to #svn_tristate_unknown;
* and 'b' values will be set to @c FALSE.
*/
svn_error_t *
svn_ra_svn__parse_tuple(const apr_array_header_t *list,
apr_pool_t *pool,
svn_ra_svn__parse_tuple(const svn_ra_svn__list_t *list,
const char *fmt, ...);
/** Read a tuple from the network and parse it as a tuple, using the
@ -238,13 +335,13 @@ svn_ra_svn__read_tuple(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *fmt, ...);
/** Parse an array of @c svn_ra_svn_item_t structures as a list of
/** Parse an array of @c svn_ra_svn__item_t structures as a list of
* properties, storing the properties in a hash table.
*
* @since New in 1.5.
*/
svn_error_t *
svn_ra_svn__parse_proplist(const apr_array_header_t *list,
svn_ra_svn__parse_proplist(const svn_ra_svn__list_t *list,
apr_pool_t *pool,
apr_hash_t **props);
@ -300,7 +397,7 @@ svn_ra_svn__handle_command(svn_boolean_t *terminate,
svn_error_t *
svn_ra_svn__handle_commands2(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const svn_ra_svn_cmd_entry_t *commands,
const svn_ra_svn__cmd_entry_t *commands,
void *baton,
svn_boolean_t error_on_disconnect);
@ -347,7 +444,7 @@ svn_error_t *
svn_ra_svn__write_cmd_open_root(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
svn_revnum_t rev,
const char *token);
const svn_string_t *token);
/** Send a "delete-entry" command over connection @a conn. Delete the
* @a path at optional revision @a rev below @a parent_token.
@ -358,7 +455,7 @@ svn_ra_svn__write_cmd_delete_entry(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
svn_revnum_t rev,
const char *parent_token);
const svn_string_t *parent_token);
/** Send a "add-dir" command over connection @a conn. Add a new directory
* node named @a path under the directory identified by @a parent_token.
@ -370,8 +467,8 @@ svn_error_t *
svn_ra_svn__write_cmd_add_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token,
const char *token,
const svn_string_t *parent_token,
const svn_string_t *token,
const char *copy_path,
svn_revnum_t copy_rev);
@ -384,8 +481,8 @@ svn_error_t *
svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token,
const char *token,
const svn_string_t *parent_token,
const svn_string_t *token,
svn_revnum_t rev);
/** Send a "change-dir-prop" command over connection @a conn. Set the
@ -395,7 +492,7 @@ svn_ra_svn__write_cmd_open_dir(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token,
const svn_string_t *token,
const char *name,
const svn_string_t *value);
@ -406,7 +503,7 @@ svn_ra_svn__write_cmd_change_dir_prop(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_close_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token);
const svn_string_t *token);
/** Send a "absent-dir" command over connection @a conn. Directory node
* named @a path under the directory identified by @a parent_token is
@ -416,7 +513,7 @@ svn_error_t *
svn_ra_svn__write_cmd_absent_dir(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token);
const svn_string_t *parent_token);
/** Send a "add-file" command over connection @a conn. Add a new file
* node named @a path under the directory identified by @a parent_token.
@ -428,8 +525,8 @@ svn_error_t *
svn_ra_svn__write_cmd_add_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token,
const char *token,
const svn_string_t *parent_token,
const svn_string_t *token,
const char *copy_path,
svn_revnum_t copy_rev);
@ -442,8 +539,8 @@ svn_error_t *
svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token,
const char *token,
const svn_string_t *parent_token,
const svn_string_t *token,
svn_revnum_t rev);
/** Send a "change-file-prop" command over connection @a conn. Set the
@ -453,7 +550,7 @@ svn_ra_svn__write_cmd_open_file(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token,
const svn_string_t *token,
const char *name,
const svn_string_t *value);
@ -465,7 +562,7 @@ svn_ra_svn__write_cmd_change_file_prop(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_close_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token,
const svn_string_t *token,
const char *text_checksum);
/** Send a "absent-file" command over connection @a conn. File node
@ -476,7 +573,7 @@ svn_error_t *
svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *parent_token);
const svn_string_t *parent_token);
/** Send a "apply-textdelta" command over connection @a conn. Starts a
* series of text deltas to be applied to the file identified by @a token.
@ -486,7 +583,7 @@ svn_ra_svn__write_cmd_absent_file(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token,
const svn_string_t *token,
const char *base_checksum);
/** Send a "textdelta-chunk" command over connection @a conn. Apply
@ -496,7 +593,7 @@ svn_ra_svn__write_cmd_apply_textdelta(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token,
const svn_string_t *token,
const svn_string_t *chunk);
/** Send a "textdelta-end" command over connection @a conn. Ends the
@ -506,7 +603,7 @@ svn_ra_svn__write_cmd_textdelta_chunk(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_cmd_textdelta_end(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *token);
const svn_string_t *token);
/** Send a "close-edit" command over connection @a conn. Ends the editor
* drive (successfully). Use @a pool for allocations.
@ -790,7 +887,7 @@ svn_error_t *
svn_ra_svn__write_cmd_unlock(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const char *token,
const svn_string_t *token,
svn_boolean_t break_lock);
/** Send a "get-lock" command over connection @a conn.
@ -886,7 +983,7 @@ svn_ra_svn__write_cmd_finish_replay(svn_ra_svn_conn_t *conn,
svn_error_t *
svn_ra_svn__write_data_log_changed_path(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
const svn_string_t *path,
char action,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
@ -916,6 +1013,19 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn,
svn_boolean_t invalid_revnum,
unsigned revprop_count);
/** Send a directory entry @a dirent for @a path over connection @a conn.
* Use @a pool for allocations.
*
* Depending on the flags in @a dirent_fields, only selected elements will
* be transmitted.
*/
svn_error_t *
svn_ra_svn__write_dirent(svn_ra_svn_conn_t *conn,
apr_pool_t *pool,
const char *path,
svn_dirent_t *dirent,
apr_uint32_t dirent_fields);
/**
* @}
*/
@ -931,7 +1041,7 @@ svn_ra_svn__write_data_log_entry(svn_ra_svn_conn_t *conn,
* @see svn_log_changed_path2_t for a description of the output parameters.
*/
svn_error_t *
svn_ra_svn__read_data_log_changed_entry(const apr_array_header_t *items,
svn_ra_svn__read_data_log_changed_entry(const svn_ra_svn__list_t *items,
svn_string_t **cpath,
const char **action,
const char **copy_path,

View File

@ -34,6 +34,7 @@
#include "svn_editor.h"
#include "svn_config.h"
#include "private/svn_object_pool.h"
#include "private/svn_string_private.h"
#ifdef __cplusplus
@ -74,6 +75,30 @@ svn_repos__validate_prop(const char *name,
const svn_string_t *value,
apr_pool_t *pool);
/* Attempt to normalize a Subversion property if it "needs translation"
* (according to svn_prop_needs_translation(), currently all svn:* props).
*
* At this time, the only performed normalization is translation of
* the line endings of the property value so that it would only contain
* LF (\n) characters. "\r" characters found mid-line are replaced with "\n".
* "\r\n" sequences are replaced with "\n".
*
* 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
* unchanged and NORMALIZED_P is not NULL, then *NORMALIZED_P will be
* set to zero. SCRATCH_POOL will be used for temporary allocations.
*/
svn_error_t *
svn_repos__normalize_prop(const svn_string_t **result_p,
svn_boolean_t *normalized_p,
const char *name,
const svn_string_t *value,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Given the error @a err from svn_repos_fs_commit_txn(), return an
* string containing either or both of the svn_fs_commit_txn() error
@ -127,26 +152,27 @@ svn_repos__replay_ev2(svn_fs_root_t *root,
void *authz_read_baton,
apr_pool_t *scratch_pool);
/* Given a PATH which might be a relative repo URL (^/), an absolute
* local repo URL (file://), an absolute path outside of the repo
* or a location in the Windows registry.
/**
* Non-deprecated alias for svn_repos_get_logs4.
*
* Retrieve the configuration data that PATH points at and parse it into
* CFG_P allocated in POOL.
*
* If PATH cannot be parsed as a config file then an error is returned. The
* contents of CFG_P is then undefined. If MUST_EXIST is TRUE, a missing
* authz file is also an error. The CASE_SENSITIVE controls the lookup
* behavior for section and option names alike.
*
* REPOS_ROOT points at the root of the repos you are
* going to apply the authz against, can be NULL if you are sure that you
* don't have a repos relative URL in PATH. */
* Since the mapping of log5 to ra_get_log is would basically duplicate the
* log5->log4 adapter, we provide this log4 wrapper that does not create a
* deprecation warning.
*/
svn_error_t *
svn_repos__retrieve_config(svn_config_t **cfg_p,
const char *path,
svn_boolean_t must_exist,
svn_boolean_t case_sensitive,
svn_repos__get_logs_compat(svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
int limit,
svn_boolean_t discover_changed_paths,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
const apr_array_header_t *revprops,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
svn_log_entry_receiver_t receiver,
void *receiver_baton,
apr_pool_t *pool);
/**
@ -160,7 +186,7 @@ svn_repos__retrieve_config(svn_config_t **cfg_p,
* from multiple threads. Configuration objects no longer referenced by
* any user may linger for a while before being cleaned up.
*/
typedef struct svn_repos__config_pool_t svn_repos__config_pool_t;
typedef svn_object_pool__t svn_repos__config_pool_t;
/* Create a new configuration pool object with a lifetime determined by
* POOL and return it in *CONFIG_POOL.
@ -177,11 +203,10 @@ svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
* configuration specified by PATH. If the latter is a URL, we read the
* data from a local repository. CONFIG_POOL will store the configuration
* and make further callers use the same instance if the content matches.
* If KEY is not NULL, *KEY will be set to a unique ID - if available.
* Section and option names will be case-insensitive.
*
* If MUST_EXIST is TRUE, a missing config file is also an error, *CFG
* is otherwise simply NULL. The CASE_SENSITIVE controls the lookup
* behavior for section and option names alike.
* is otherwise simply NULL.
*
* PREFERRED_REPOS is only used if it is not NULL and PATH is a URL.
* If it matches the URL, access the repository through this object
@ -194,72 +219,14 @@ svn_repos__config_pool_create(svn_repos__config_pool_t **config_pool,
*/
svn_error_t *
svn_repos__config_pool_get(svn_config_t **cfg,
svn_membuf_t **key,
svn_repos__config_pool_t *config_pool,
const char *path,
svn_boolean_t must_exist,
svn_boolean_t case_sensitive,
svn_repos_t *preferred_repos,
apr_pool_t *pool);
/** @} */
/**
* @defgroup svn_authz_pool Authz object pool API
* @{
*/
/* Opaque thread-safe factory and container for authorization objects.
*
* Instances handed out are read-only and may be given to multiple callers
* from multiple threads. Authorization objects no longer referenced by
* any user may linger for a while before being cleaned up.
*/
typedef struct svn_repos__authz_pool_t svn_repos__authz_pool_t;
/* Create a new authorization pool object with a lifetime determined by
* POOL and return it in *AUTHZ_POOL. CONFIG_POOL will be the common
* source for the configuration data underlying the authz objects and must
* remain valid at least until POOL cleanup.
*
* The THREAD_SAFE flag indicates whether the pool actually needs to be
* thread-safe and POOL must be also be thread-safe if this flag is set.
*/
svn_error_t *
svn_repos__authz_pool_create(svn_repos__authz_pool_t **authz_pool,
svn_repos__config_pool_t *config_pool,
svn_boolean_t thread_safe,
apr_pool_t *pool);
/* Set *AUTHZ_P to a read-only reference to the current contents of the
* authorization specified by PATH and GROUPS_PATH. If these are URLs,
* we read the data from a local repository (see #svn_repos_authz_read2).
* AUTHZ_POOL will store the authz data and make further callers use the
* same instance if the content matches.
*
* If MUST_EXIST is TRUE, a missing config file is also an error, *AUTHZ_P
* is otherwise simply NULL.
*
* PREFERRED_REPOS is only used if it is not NULL and PATH is a URL.
* If it matches the URL, access the repository through this object
* instead of creating a new repo instance. Note that this might not
* return the latest content.
*
* POOL determines the minimum lifetime of *AUTHZ_P (may remain cached
* after release) but must not exceed the lifetime of the pool provided to
* svn_repos__authz_pool_create.
*/
svn_error_t *
svn_repos__authz_pool_get(svn_authz_t **authz_p,
svn_repos__authz_pool_t *authz_pool,
const char *path,
const char *groups_path,
svn_boolean_t must_exist,
svn_repos_t *preferred_repos,
apr_pool_t *pool);
/** @} */
/* Adjust mergeinfo paths and revisions in ways that are useful when loading
* a dump stream.
*

View File

@ -53,12 +53,12 @@ struct svn_sort__item_t {
/** Sort @a ht according to its keys, return an @c apr_array_header_t
* containing @c svn_sort__item_t structures holding those keys and values
* (i.e. for each @c svn_sort__item_t @a item in the returned array,
* @a item->key and @a item->size are the hash key, and @a item->value points to
* @a item.key and @a item.size are the hash key, and @a item.value points to
* the hash value).
*
* Storage is shared with the original hash, not copied.
*
* @a comparison_func should take two @c svn_sort__item_t's and return an
* @a comparison_func should take pointers to two items and return an
* integer greater than, equal to, or less than 0, according as the first item
* is greater than, equal to, or less than the second.
*

View File

@ -555,8 +555,14 @@ svn_sqlite__hotcopy(const char *src_path,
const char *dst_path,
apr_pool_t *scratch_pool);
/* Backported version of SVN_ERR_SQLITE_ROLLBACK_FAILED. */
#define SVN_SQLITE__ERR_ROLLBACK_FAILED (SVN_ERR_MISC_CATEGORY_START + 44)
/* Evaluate the expression EXPR. If any error is returned, close
* the connection in DB. */
#define SVN_SQLITE__ERR_CLOSE(expr, db) do \
{ \
svn_error_t *svn__err = (expr); \
if (svn__err) \
return svn_error_compose_create(svn__err, svn_sqlite__close(db)); \
} while (0)
#ifdef __cplusplus
}

View File

@ -131,6 +131,14 @@ svn_membuf__nzero(svn_membuf_t *membuf, apr_size_t size);
svn_string_t *
svn_stringbuf__morph_into_string(svn_stringbuf_t *strbuf);
/** Utility macro to define static svn_string_t objects. @a value must
* be a static string; the "" in the macro declaration tries to ensure this.
*
* Usage:
* static const svn_string_t my_string = SVN__STATIC_STRING("my text");
*/
#define SVN__STATIC_STRING(value) { value "", sizeof(value "") - 1 }
/** Like strtoul but with a fixed base of 10 and without overflow checks.
* This allows the compiler to generate massively faster (4x on 64bit LINUX)
* code. Overflow checks may be added on the caller side where you might

View File

@ -112,12 +112,12 @@ svn_spillbuf__get_size(const svn_spillbuf_t *buf);
svn_filesize_t
svn_spillbuf__get_memory_size(const svn_spillbuf_t *buf);
/* Retrieve the name of the spill file. The returned value can be NULL
if the file has not been created yet. */
/* Retrieve the name of the spill file. The returned value will be
NULL if the file has not been created yet. */
const char *
svn_spillbuf__get_filename(const svn_spillbuf_t *buf);
/* Retrieve the handle of the spill file. The returned value can be
/* Retrieve the handle of the spill file. The returned value will be
NULL if the file has not been created yet. */
apr_file_t *
svn_spillbuf__get_file(const svn_spillbuf_t *buf);
@ -133,8 +133,8 @@ svn_spillbuf__write(svn_spillbuf_t *buf,
/* Read a block of memory from the spill buffer. @a *data will be set to
NULL if no content remains. Otherwise, @a data and @a len will point to
data that must be fully-consumed by the caller. This data will remain
valid until another call to svn_spillbuf_write(), svn_spillbuf_read(),
or svn_spillbuf_process(), or if the spill buffer's pool is cleared. */
valid until another call to svn_spillbuf__write(), svn_spillbuf__read(),
or svn_spillbuf__process(), or if the spill buffer's pool is cleared. */
svn_error_t *
svn_spillbuf__read(const char **data,
apr_size_t *len,
@ -143,7 +143,7 @@ svn_spillbuf__read(const char **data,
/* Callback for reading content out of the spill buffer. Set @a stop if
you want to stop the processing (and will call svn_spillbuf_process
you want to stop the processing (and will call svn_spillbuf__process
again, at a later time). */
typedef svn_error_t * (*svn_spillbuf_read_t)(svn_boolean_t *stop,
void *baton,
@ -472,7 +472,7 @@ svn_version__parse_version_string(svn_version_t **version,
* @since New in 1.8.
*/
svn_boolean_t
svn_version__at_least(svn_version_t *version,
svn_version__at_least(const svn_version_t *version,
int major,
int minor,
int patch);
@ -525,6 +525,16 @@ svn_version__at_least(svn_version_t *version,
unsigned char *
svn__encode_uint(unsigned char *p, apr_uint64_t val);
/* Wrapper around svn__encode_uint using the LSB to store the sign:
*
* If VAL >= 0
* UINT_VAL = 2 * VAL
* else
* UINT_VAL = (- 2 * VAL) - 1
*/
unsigned char *
svn__encode_int(unsigned char *p, apr_int64_t val);
/* Decode an unsigned 7b/8b-encoded integer into *VAL and return a pointer
to the byte after the integer. The bytes to be decoded live in the
range [P..END-1]. If these bytes do not contain a whole encoded
@ -537,22 +547,49 @@ svn__decode_uint(apr_uint64_t *val,
const unsigned char *p,
const unsigned char *end);
/* Get the data from IN, compress it according to the specified
* COMPRESSION_METHOD and write the result to OUT.
/* Wrapper around svn__decode_uint, reversing the transformation performed
* by svn__encode_int.
*/
const unsigned char *
svn__decode_int(apr_int64_t *val,
const unsigned char *p,
const unsigned char *end);
/* Compress the data from DATA with length LEN, it according to the
* specified COMPRESSION_METHOD and write the result to OUT.
* SVN__COMPRESSION_NONE is valid for COMPRESSION_METHOD.
*/
svn_error_t *
svn__compress(svn_stringbuf_t *in,
svn_stringbuf_t *out,
int compression_method);
svn__compress_zlib(const void *data, apr_size_t len,
svn_stringbuf_t *out,
int compression_method);
/* Get the compressed data from IN, decompress it and write the result to
* OUT. Return an error if the decompressed size is larger than LIMIT.
/* Decompress the compressed data from DATA with length LEN and write the
* result to OUT. Return an error if the decompressed size is larger than
* LIMIT.
*/
svn_error_t *
svn__decompress(svn_stringbuf_t *in,
svn_stringbuf_t *out,
apr_size_t limit);
svn__decompress_zlib(const void *data, apr_size_t len,
svn_stringbuf_t *out,
apr_size_t limit);
/* Same as svn__compress_zlib(), but use LZ4 compression. Note that
* while the declaration of this function uses apr_size_t, it expects
* blocks of size not exceeding LZ4_MAX_INPUT_SIZE. The caller should
* ensure that the proper size is passed to this function.
*/
svn_error_t *
svn__compress_lz4(const void *data, apr_size_t len,
svn_stringbuf_t *out);
/* Same as svn__decompress_zlib(), but use LZ4 compression. The caller
* should ensure that the size and limit passed to this function do not
* exceed INT_MAX.
*/
svn_error_t *
svn__decompress_lz4(const void *data, apr_size_t len,
svn_stringbuf_t *out,
apr_size_t limit);
/** @} */
@ -701,6 +738,14 @@ const char *svn_zlib__compiled_version(void);
/* Return the zlib version we run against. */
const char *svn_zlib__runtime_version(void);
/* Return the lz4 version we compiled against. */
const char *svn_lz4__compiled_version(void);
/* Return the lz4 version we run against as a composed value:
* major * 100 * 100 + minor * 100 + release
*/
int svn_lz4__runtime_version(void);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -206,7 +206,7 @@ svn_temp_serializer__get(svn_temp_serializer__context_t *context);
* the pointer to resolve in @a ptr.
*/
void
svn_temp_deserializer__resolve(void *buffer, void **ptr);
svn_temp_deserializer__resolve(const void *buffer, void **ptr);
/**
* Similar to svn_temp_deserializer__resolve() but instead of modifying

View File

@ -150,6 +150,40 @@ svn_utf__normalize(const char **result,
const char *str, apr_size_t len,
svn_membuf_t *buf);
/* Transform the UTF-8 string to a shape suitable for comparison with
* strcmp(). The tranformation is defined by CASE_INSENSITIVE and
* ACCENT_INSENSITIVE arguments. If CASE_INSENSITIVE is non-zero,
* remove case distinctions from the string. If ACCENT_INSENSITIVE
* is non-zero, remove diacritical marks from the string.
*
* Use BUF as a temporary storage. If LEN is SVN_UTF__UNKNOWN_LENGTH,
* assume STR is null-terminated; otherwise, consider the string only
* up to the given length. Place the tranformed string in *RESULT, which
* shares storage with BUF and is valid only until the next time BUF is
* modified.
*
* A returned error may indicate that STRING contains invalid UTF-8 or
* invalid Unicode codepoints.
*/
svn_error_t *
svn_utf__xfrm(const char **result,
const char *str, apr_size_t len,
svn_boolean_t case_insensitive,
svn_boolean_t accent_insensitive,
svn_membuf_t *buf);
/* Return TRUE if S matches any of the const char * glob patterns in
* PATTERNS.
*
* S will internally be normalized to lower-case and accents removed
* using svn_utf__xfrm. To get a match, the PATTERNS must have been
* normalized accordingly before calling this function.
*/
svn_boolean_t
svn_utf__fuzzy_glob_match(const char *str,
const apr_array_header_t *patterns,
svn_membuf_t *buf);
/* Check if STRING is a valid, NFC-normalized UTF-8 string. Note that
* a FALSE return value may indicate that STRING is not valid UTF-8 at
* all.
@ -176,7 +210,7 @@ svn_utf__encode_ucs4_string(svn_membuf_t *buffer,
apr_size_t length,
apr_size_t *result_length);
/* Pattern matching similar to the the SQLite LIKE and GLOB
/* Pattern matching similar to the SQLite LIKE and GLOB
* operators. PATTERN, KEY and ESCAPE must all point to UTF-8
* strings. Furthermore, ESCAPE, if provided, must be a character from
* the ASCII subset.

View File

@ -82,6 +82,8 @@ svn_wc__get_file_external_editor(const svn_delta_editor_t **editor,
const char *recorded_url,
const svn_opt_revision_t *recorded_peg_rev,
const svn_opt_revision_t *recorded_rev,
svn_wc_conflict_resolver_func2_t conflict_func,
void *conflict_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
@ -346,6 +348,20 @@ 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.
*
* @a local_abspath is any path in the WC, and is used to find the WC root.
*/
SVN_EXPERIMENTAL
svn_error_t *
svn_wc__get_shelves_dir(char **dir,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* The following are temporary APIs to aid in the transition from wc-1 to
* wc-ng. Use them for new development now, but they may be disappearing
@ -1746,6 +1762,207 @@ svn_wc__resolve_conflicts(svn_wc_context_t *wc_ctx,
void *notify_baton,
apr_pool_t *scratch_pool);
/**
* Resolve the text conflict at LOCAL_ABSPATH as per CHOICE, and then
* mark the conflict resolved.
* The working copy must already be locked for resolving, e.g. by calling
* svn_wc__acquire_write_lock_for_resolve() first.
* @since New in 1.10.
*/
svn_error_t *
svn_wc__conflict_text_mark_resolved(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_wc_conflict_choice_t choice,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/**
* Resolve the conflicted property PROPNAME at LOCAL_ABSPATH as per CHOICE,
* and then mark the conflict resolved. If MERGED_VALUE is not NULL, this is
* the new merged property, used when choosing #svn_wc_conflict_choose_merged.
*
* The working copy must already be locked for resolving, e.g. by calling
* svn_wc__acquire_write_lock_for_resolve() first.
* @since New in 1.10.
*/
svn_error_t *
svn_wc__conflict_prop_mark_resolved(svn_wc_context_t *wc_ctx,
const char *local_abspath,
const char *propname,
svn_wc_conflict_choice_t choice,
const svn_string_t *merged_value,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a directory
* which was locally deleted, replaced or moved away, and which received an
* arbitrary incoming change during an update or switch operation.
*
* The conflict is resolved by accepting the current working copy state and
* breaking the 'moved-here' link for any files or directories which were
* moved out of the victim directory before the update operation.
* As a result, any such files or directories become copies (rather than moves)
* of content which the victim directory contained before it was updated.
*
* The tree conflict at LOCAL_ABSPATH must have the following properties or
* SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned:
*
* operation: svn_wc_operation_update or svn_wc_operation_switch
* local change: svn_wc_conflict_reason_deleted or
* svn_wc_conflict_reason_replaced or
* svn_wc_conflict_reason_moved_away
* incoming change: any
*
* The working copy must already be locked for resolving, e.g. by calling
* svn_wc__acquire_write_lock_for_resolve() first.
*
* @since New in 1.10.
*/
svn_error_t *
svn_wc__conflict_tree_update_break_moved_away(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a directory
* which was locally deleted or replaced, and which received an edit (some
* change inside the directory, or a change to the direcotory's properties)
* during an update or switch operation.
*
* The conflict is resolved by keeping the victim deleted, and propagating
* its tree conflict to any children which were moved out of the directory
* before the update operation.
* As a result, any such files or directories become victims of the tree
* conflict as well and must be resolved independently.
* Additionally, LOCAL_ABSPATH itself may become the victim of a different
* tree conflict as a result of resolving the existing tree conflict.
*
* The tree conflict at LOCAL_ABSPATH must have the following properties or
* SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned:
*
* operation: svn_wc_operation_update or svn_wc_operation_switch
* local change: svn_wc_conflict_reason_deleted or
* svn_wc_conflict_reason_replaced
* incoming change: svn_wc_conflict_action_edit
*
* If this conflict cannot be resolved because the conflict cannot be
* propagated to moved-away children, this function returns
* SVN_ERR_WC_OBSTRUCTED_UPDATE or SVN_ERR_WC_FOUND_CONFLICT.
* The caller should continue by resolving other conflicts and attempt to
* resolve this conflict again later.
*
* The working copy must already be locked for resolving, e.g. by calling
* svn_wc__acquire_write_lock_for_resolve() first.
*
* @since New in 1.10.
*/
svn_error_t *
svn_wc__conflict_tree_update_raise_moved_away(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Resolve a tree conflict where the victim at LOCAL_ABSPATH is a file or
* directory which was locally moved away, and which received an edit (some
* change inside the directory or file, or a change to properties) during an
* update or switch operation.
*
* The conflict is resolved by keeping the victim moved-away, and propagating
* the incoming edits to the victim's moved-to location.
*
* The tree conflict at LOCAL_ABSPATH must have the following properties or
* SVN_ERR_WC_CONFLICT_RESOLVER_FAILURE will be returned:
*
* operation: svn_wc_operation_update or svn_wc_operation_switch
* local change: svn_wc_conflict_reason_moved_away
* incoming change: svn_wc_conflict_action_edit
*
* If this conflict cannot be resolved this function returns
* SVN_ERR_WC_OBSTRUCTED_UPDATE or SVN_ERR_WC_FOUND_CONFLICT.
* The caller should continue by resolving other conflicts and attempt to
* resolve this conflict again later.
*
* The working copy must already be locked for resolving, e.g. by calling
* svn_wc__acquire_write_lock_for_resolve() first.
*
* @since New in 1.10.
*/
svn_error_t *
svn_wc__conflict_tree_update_moved_away_node(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Merge local changes from a tree conflict victim of an incoming deletion
* to the specified DEST_ABSPATH added during an update. Both LOCAL_ABSPATH
* and DEST_ABSPATH must be directories.
*
* Assuming DEST_ABSPATH is the correct move destination, this function
* allows local changes to "follow" incoming moves during updates.
*
* @since New in 1.10. */
svn_error_t *
svn_wc__conflict_tree_update_incoming_move(svn_wc_context_t *wc_ctx,
const char *local_abspath,
const char *dest_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Resolve a 'local dir add vs incoming dir add' tree conflict upon update
* by merging the locally added directory with the incoming added directory.
*
* @since New in 1.10. */
svn_error_t *
svn_wc__conflict_tree_update_local_add(svn_wc_context_t *wc_ctx,
const char *local_abspath,
svn_cancel_func_t cancel_func,
void *cancel_baton,
svn_wc_notify_func2_t notify_func,
void *notify_baton,
apr_pool_t *scratch_pool);
/* Find nodes in the working copy which corresponds to the new location
* MOVED_TO_REPOS_RELPATH of the tree conflict victim at VICTIM_ABSPATH.
* The nodes must be of the same node kind as VICTIM_NODE_KIND.
* If no such node can be found, set *POSSIBLE_TARGETS to an empty array.
*
* The nodes should be useful for conflict resolution, e.g. it should be
* possible to merge changes into these nodes to resolve an incoming-move
* tree conflict. But the exact criteria for selecting a node are left
* to the implementation of this function.
* Note that this function may not necessarily return a node which was
* actually moved. The only hard guarantee is that the node corresponds to
* the repository relpath MOVED_TO_REPOS_RELPATH specified by the caller.
* Users should perform a sanity check on the results returned from this
* function, e.g. establish whether the MOVED_TO_REPOS_RELPATH at its
* current checked-out revision shares ancestry with the conflict victim.
*/
svn_error_t *
svn_wc__guess_incoming_move_target_nodes(apr_array_header_t **possible_targets,
svn_wc_context_t *wc_ctx,
const char *victim_abspath,
svn_node_kind_t victim_node_kind,
const char *moved_to_repos_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Move @a src_abspath to @a dst_abspath, by scheduling @a dst_abspath
* for addition to the repository, remembering the history. Mark @a src_abspath
@ -1847,6 +2064,28 @@ svn_wc__diff7(const char **root_relpath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Read all conflicts at LOCAL_ABSPATH into an array containing pointers to
* svn_wc_conflict_description2_t data structures alloated in RESULT_POOL.
*/
svn_error_t *
svn_wc__read_conflict_descriptions2_t(const apr_array_header_t **conflicts,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Internal version of svn_wc_translated_stream(), accepting a working
copy context. */
svn_error_t *
svn_wc__translated_stream(svn_stream_t **stream,
svn_wc_context_t *wc_ctx,
const char *local_abspath,
const char *versioned_abspath,
apr_uint32_t flags,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */

View File

@ -1012,11 +1012,13 @@ typedef svn_error_t *(*svn_auth_gnome_keyring_unlock_prompt_func_t)(
/** @brief The pointer to function which prompts user for GNOME Keyring
* password.
* The type of this pointer should be svn_auth_gnome_keyring_unlock_prompt_func_t. */
* The type of this pointer should be svn_auth_gnome_keyring_unlock_prompt_func_t.
* @deprecated Only used by old libgnome-keyring implementation. */
#define SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC "gnome-keyring-unlock-prompt-func"
/** @brief The baton which is passed to
* @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC. */
* @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC.
* @deprecated Only used by old libgnome-keyring implementation. */
#define SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_BATON "gnome-keyring-unlock-prompt-baton"
#if (!defined(DARWIN) && !defined(WIN32)) || defined(DOXYGEN)
@ -1037,7 +1039,7 @@ svn_auth_gnome_keyring_version(void);
* This is like svn_client_get_simple_provider(), except that the
* password is stored in GNOME Keyring.
*
* If the GNOME Keyring is locked the provider calls
* If the GNOME Keyring is locked the old libgnome-keyring provider calls
* @c *SVN_AUTH_PARAM_GNOME_KEYRING_UNLOCK_PROMPT_FUNC in order to unlock
* the keyring.
*

View File

@ -46,11 +46,26 @@ extern "C" {
*/
/** Return a writable generic stream which will encode binary data in
* base64 format and write the encoded data to @a output. Be sure to
* close the stream when done writing in order to squeeze out the last
* bit of encoded data. The stream is allocated in @a pool.
* base64 format and write the encoded data to @a output. If @a break_lines
* is true, newlines will be inserted periodically; otherwise the output
* stream will only consist of base64 encoding characters. Be sure to close
* the stream when done writing in order to squeeze out the last bit of
* encoded data. The stream is allocated in @a pool.
*
* @since New in 1.10.
*/
svn_stream_t *
svn_base64_encode2(svn_stream_t *output,
svn_boolean_t break_lines,
apr_pool_t *pool);
/**
* Same as svn_base64_encode2, but with @a break_lines always TRUE.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_stream_t *
svn_base64_encode(svn_stream_t *output,
apr_pool_t *pool);

View File

@ -177,6 +177,10 @@ svn_checksum_deserialize(const svn_checksum_t **checksum,
*
* @since New in 1.6.
*/
/* ### TODO: When revving this, make it set @a *checksum to a non-NULL struct
* ### when @a hex is the all-zeroes checksum. See
* ### http://mail-archives.apache.org/mod_mbox/subversion-dev/201609.mbox/%3c00cd26ab-bdb3-67b4-ca6b-063266493874%40apache.org%3e
*/
svn_error_t *
svn_checksum_parse_hex(svn_checksum_t **checksum,
svn_checksum_kind_t kind,
@ -218,6 +222,15 @@ svn_checksum_ctx_t *
svn_checksum_ctx_create(svn_checksum_kind_t kind,
apr_pool_t *pool);
/**
* Reset an existing checksum @a ctx to initial state.
* @see svn_checksum_ctx_create()
*
* @since New in 1.10.
*/
svn_error_t *
svn_checksum_ctx_reset(svn_checksum_ctx_t *ctx);
/**
* Update the checksum represented by @a ctx, with @a len bytes starting at
* @a data.

File diff suppressed because it is too large Load Diff

View File

@ -374,6 +374,7 @@ svn_cmdline_create_auth_baton2(svn_auth_baton_t **ab,
* @deprecated Provided for backward compatibility with the 1.8 API.
* @since New in 1.6.
*/
SVN_DEPRECATED
svn_error_t *
svn_cmdline_create_auth_baton(svn_auth_baton_t **ab,
svn_boolean_t non_interactive,

View File

@ -63,6 +63,12 @@ typedef struct svn_config_t svn_config_t;
* @{
*/
/* If you add a new SVN_CONFIG_* category/section/option macro to this group,
* you have to re-run gen-make.py manually.
*
* ### This should be fixed in the build system; see issue #4581.
*/
/* This list of #defines is intentionally presented as a nested list
that matches the in-config hierarchy. */

View File

@ -386,6 +386,41 @@ extern "C" {
#define SVN_DAV_NS_DAV_SVN_REVERSE_FILE_REVS\
SVN_DAV_PROP_NS_DAV "svn/reverse-file-revs"
/** Presence of this in a DAV header in an OPTIONS response indicates
* that the transmitter (in this case, the server) knows how to handle
* svndiff1 format encoding.
*
* @since New in 1.10.
*/
#define SVN_DAV_NS_DAV_SVN_SVNDIFF1\
SVN_DAV_PROP_NS_DAV "svn/svndiff1"
/** Presence of this in a DAV header in an OPTIONS response indicates
* that the transmitter (in this case, the server) knows how to handle
* 'list' requests.
*
* @since New in 1.10.
*/
#define SVN_DAV_NS_DAV_SVN_LIST\
SVN_DAV_PROP_NS_DAV "svn/list"
/** Presence of this in a DAV header in an OPTIONS response indicates
* that the transmitter (in this case, the server) knows how to handle
* svndiff2 format encoding.
*
* @since New in 1.10.
*/
#define SVN_DAV_NS_DAV_SVN_SVNDIFF2\
SVN_DAV_PROP_NS_DAV "svn/svndiff2"
/** Presence of this in a DAV header in an OPTIONS response indicates
* that the transmitter (in this case, the server) sends the result
* checksum in the response to a successful PUT request.
*
* @since New in 1.10.
*/
#define SVN_DAV_NS_DAV_SVN_PUT_RESULT_CHECKSUM\
SVN_DAV_PROP_NS_DAV "svn/put-result-checksum"
/** @} */

View File

@ -330,6 +330,18 @@ typedef svn_error_t *
typedef const unsigned char *
(*svn_txdelta_md5_digest_fn_t)(void *baton);
/** A typedef for a function that opens an #svn_txdelta_stream_t object,
* allocated in @a result_pool. @a baton is provided by the caller.
* Any temporary allocations may be performed in @a scratch_pool.
*
* @since New in 1.10.
*/
typedef svn_error_t *
(*svn_txdelta_stream_open_func_t)(svn_txdelta_stream_t **txdelta_stream,
void *baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Create and return a generic text delta stream with @a baton, @a
* next_window and @a md5_digest. Allocate the new stream in @a
* pool.
@ -508,7 +520,9 @@ svn_txdelta_apply(svn_stream_t *source,
* version is @a svndiff_version. @a compression_level is the zlib
* compression level from 0 (no compression) and 9 (maximum compression).
*
* @since New in 1.7.
* @since New in 1.7. Since 1.10, @a svndiff_version can be 2 for the
* svndiff2 format. @a compression_level is currently ignored if
* @a svndiff_version is set to 2.
*/
void
svn_txdelta_to_svndiff3(svn_txdelta_window_handler_t *handler,
@ -544,6 +558,20 @@ svn_txdelta_to_svndiff(svn_stream_t *output,
svn_txdelta_window_handler_t *handler,
void **handler_baton);
/** Return a readable generic stream which will produce svndiff-encoded
* text delta from the delta stream @a txstream. @a svndiff_version and
* @a compression_level are same as in svn_txdelta_to_svndiff3().
*
* Allocate the stream in @a pool.
*
* @since New in 1.10.
*/
svn_stream_t *
svn_txdelta_to_svndiff_stream(svn_txdelta_stream_t *txstream,
int svndiff_version,
int compression_level,
apr_pool_t *pool);
/** Return a writable generic stream which will parse svndiff-format
* data into a text delta, invoking @a handler with @a handler_baton
* whenever a new window is ready.
@ -666,8 +694,10 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
* as it produces the delta.
*
* @note Don't try to allocate one of these yourself. Instead, always
* use svn_delta_default_editor() or some other constructor, to ensure
* that unused slots are filled in with no-op functions.
* use svn_delta_default_editor() or some other constructor, to avoid
* backwards compatibility problems if the structure is extended in
* future releases and to ensure that unused slots are filled in with
* no-op functions.
*
* <h3>Function Usage</h3>
*
@ -738,10 +768,11 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
*
* The @c add_file and @c open_file callbacks each return a baton
* for the file being created or changed. This baton can then be
* passed to @c apply_textdelta to change the file's contents, or
* @c change_file_prop to change the file's properties. When the
* producer is finished making changes to a file, it should call
* @c close_file, to let the consumer clean up and free the baton.
* passed to @c apply_textdelta or @c apply_textdelta_stream to change
* the file's contents, or @c change_file_prop to change the file's
* properties. When the producer is finished making changes to a
* file, it should call @c close_file, to let the consumer clean up
* and free the baton.
*
* The @c add_file and @c add_directory functions each take arguments
* @a copyfrom_path and @a copyfrom_revision. If @a copyfrom_path is
@ -783,15 +814,16 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
* 5. When the producer calls @c open_file or @c add_file, either:
*
* (a) The producer must follow with any changes to the file
* (@c change_file_prop and/or @c apply_textdelta, as applicable),
* followed by a @c close_file call, before issuing any other file
* or directory calls, or
* (@c change_file_prop and/or @c apply_textdelta /
* @c apply_textdelta_stream, as applicable), followed by
* a @c close_file call, before issuing any other file or
* directory calls, or
*
* (b) The producer must follow with a @c change_file_prop call if
* it is applicable, before issuing any other file or directory
* calls; later, after all directory batons including the root
* have been closed, the producer must issue @c apply_textdelta
* and @c close_file calls.
* have been closed, the producer must issue @c apply_textdelta /
* @c apply_textdelta_stream and @c close_file calls.
*
* 6. When the producer calls @c apply_textdelta, it must make all of
* the window handler calls (including the @c NULL window at the
@ -800,7 +832,7 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
* So, the producer needs to use directory and file batons as if it
* is doing a single depth-first traversal of the tree, with the
* exception that the producer may keep file batons open in order to
* make @c apply_textdelta calls at the end.
* make @c apply_textdelta / @c apply_textdelta_stream calls at the end.
*
*
* <h3>Pool Usage</h3>
@ -824,12 +856,13 @@ svn_txdelta_skip_svndiff_window(apr_file_t *file,
* Note that close_directory can be called *before* a file in that
* directory has been closed. That is, the directory's baton is
* closed before the file's baton. The implication is that
* @c apply_textdelta 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 @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.
* @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
* @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.
*
*
* <h3>Errors</h3>
@ -977,7 +1010,8 @@ typedef struct svn_delta_editor_t
/** We are going to add a new file at @a path, a child of the
* directory represented by @a parent_baton. The callback can
* store a baton for this new file in @a **file_baton; whatever value
* it stores there should be passed through to @c apply_textdelta.
* it stores there should be passed through to @c apply_textdelta or
* @c apply_textdelta_stream.
*
* If @a copyfrom_path is non-@c NULL, this add has history (i.e., is a
* copy), and the origin of the copy may be recorded as
@ -1009,8 +1043,8 @@ typedef struct svn_delta_editor_t
*
* The callback can store a baton for this new file in @a **file_baton;
* whatever value it stores there should be passed through to
* @c apply_textdelta. If a valid revnum, @a base_revision is the
* current revision of the file.
* @c apply_textdelta or @c apply_textdelta_stream. If a valid revnum,
* @a base_revision is the current revision of the file.
*
* Allocations for the returned @a file_baton should be performed in
* @a result_pool. It is also typical to save this pool for later usage
@ -1075,11 +1109,11 @@ typedef struct svn_delta_editor_t
* more, so whatever resources it refers to may now be freed.
*
* @a text_checksum is the hex MD5 digest for the fulltext that
* resulted from a delta application, see @c apply_textdelta. The
* checksum is ignored if NULL. If not null, it is compared to the
* checksum of the new fulltext, and the error
* SVN_ERR_CHECKSUM_MISMATCH is returned if they do not match. If
* there is no new fulltext, @a text_checksum is ignored.
* resulted from a delta application, see @c apply_textdelta and
* @c apply_textdelta_stream. The checksum is ignored if NULL.
* If not null, it is compared to the checksum of the new fulltext,
* and the error SVN_ERR_CHECKSUM_MISMATCH is returned if they do
* not match. If there is no new fulltext, @a text_checksum is ignored.
*
* Any temporary allocations may be performed in @a scratch_pool.
*/
@ -1115,6 +1149,38 @@ typedef struct svn_delta_editor_t
svn_error_t *(*abort_edit)(void *edit_baton,
apr_pool_t *scratch_pool);
/** Apply a text delta stream, yielding the new revision of a file.
* This callback operates on the passed-in @a editor instance.
*
* @a file_baton indicates the file we're creating or updating, and the
* ancestor file on which it is based; it is the baton set by some
* prior @c add_file or @c open_file callback.
*
* @a open_func is a function that opens a #svn_txdelta_stream_t object.
* @a open_baton is provided by the caller.
*
* @a base_checksum is the hex MD5 digest for the base text against
* which the delta is being applied; it is ignored if NULL, and may
* be ignored even if not NULL. If it is not ignored, it must match
* the checksum of the base text against which svndiff data is being
* applied; if it does not, @c apply_textdelta_stream call which detects
* the mismatch will return the error #SVN_ERR_CHECKSUM_MISMATCH
* (if there is no base text, there may still be an error if
* @a base_checksum is neither NULL nor the hex MD5 checksum of the
* empty string).
*
* Any temporary allocations may be performed in @a scratch_pool.
*
* @since New in 1.10.
*/
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);
/* Be sure to update svn_delta_get_cancellation_editor() and
* svn_delta_default_editor() if you add a new callback here. */
} svn_delta_editor_t;

View File

@ -1211,8 +1211,44 @@ typedef struct svn_prop_patch_t {
apr_array_header_t *hunks;
} svn_prop_patch_t;
/**
* A binary patch representation. This basically describes replacing one
* exact binary representation with another one.
*
* @since New in 1.10. */
typedef struct svn_diff_binary_patch_t svn_diff_binary_patch_t;
/**
* Creates a stream allocated in @a result_pool from which the original
* (pre-patch-application) version of the binary patched file can be read.
*
* @note Like many svn_diff_get functions over patches, this is implemented
* as reading from the backing patch file. Therefore it is recommended to
* read the whole stream before using other functions on the same patch file.
*
* @since New in 1.10 */
svn_stream_t *
svn_diff_get_binary_diff_original_stream(const svn_diff_binary_patch_t *bpatch,
apr_pool_t *result_pool);
/**
* Creates a stream allocated in @a result_pool from which the resulting
* (post-patch-application) version of the binary patched file can be read.
*
* @note Like many svn_diff_get functions over patches, this is implemented
* as reading from the backing patch file. Therefore it is recommended to
* read the whole stream before using other functions on the same patch file.
*
* @since New in 1.10 */
svn_stream_t *
svn_diff_get_binary_diff_result_stream(const svn_diff_binary_patch_t *bpatch,
apr_pool_t *result_pool);
/**
* Data type to manage parsing of patches.
*
* Represents a patch to one target file.
*
* API users should not allocate structures of this type directly.
*
* @since New in 1.7. */
@ -1239,7 +1275,9 @@ typedef struct svn_patch_t {
svn_diff_operation_kind_t operation;
/**
* Indicates whether the patch is being interpreted in reverse. */
* Indicates whether the patch is being interpreted in reverse.
* ### If so, how does this affect the interpretation of other fields?
*/
svn_boolean_t reverse;
/**
@ -1249,6 +1287,45 @@ typedef struct svn_patch_t {
* @since New in 1.9. */
svn_mergeinfo_t mergeinfo;
svn_mergeinfo_t reverse_mergeinfo;
/**
* Declares that there is a binary conflict and contains the information
* to apply it as parsed from the file.
* @since New in 1.10. */
svn_diff_binary_patch_t *binary_patch;
/** The old and new executability bits, as retrieved from the patch file, from
* the git-like mode headers.
*
* A patch may specify an executability change via @a old_executable_bit and
* @a new_executable_bit, via a #SVN_PROP_EXECUTABLE propchange hunk, or both
* ways. It is upto caller how to decide how conflicting information is
* handled.
*
* #svn_tristate_unknown indicates the patch does not specify the
* corresponding bit.
*
* @since New in 1.10.
*/
svn_tristate_t old_executable_bit;
svn_tristate_t new_executable_bit;
/** The old and new symlink bits, as retrieved from the patch file, from
* the git-like mode headers.
*
* A patch may specify a symlink change via @a old_symlink_bit and
* @a new_symlink_bit, via a #SVN_PROP_SPECIAL propchange hunk, or both
* ways. It is upto caller how to decide how conflicting information is
* handled. Most implementations will currently just describe a replacement
* of the file though.
*
* #svn_tristate_unknown indicates the patch does not specify the
* corresponding bit.
*
* @since New in 1.10.
*/
svn_tristate_t old_symlink_bit;
svn_tristate_t new_symlink_bit;
} svn_patch_t;
/** An opaque type representing an open patch file.

View File

@ -165,18 +165,16 @@ svn_error_wrap_apr(apr_status_t status,
...)
__attribute__((format(printf, 2, 3)));
/** A quick n' easy way to create a wrapped exception with your own
* message, before throwing it up the stack. (It uses all of the
* @a child's fields.)
/** If @a child is SVN_NO_ERROR, return SVN_NO_ERROR.
* Else, prepend a new error to the error chain of @a child. The new error
* uses @a new_msg as error message but all other error attributes (such
* as the error code) are copied from @a child.
*/
svn_error_t *
svn_error_quick_wrap(svn_error_t *child,
const char *new_msg);
/** A quick n' easy way to create a wrapped exception with your own
* printf-style error message produced by passing @a fmt, using
* apr_psprintf(), before throwing it up the stack. (It uses all of the
* @a child's fields.)
/** Like svn_error_quick_wrap(), but with format string support.
*
* @since New in 1.9.
*/

View File

@ -240,6 +240,11 @@ SVN_ERROR_START
SVN_ERR_BAD_CATEGORY_START + 16,
"Invalid compression method")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_BAD_PROPERTY_VALUE_EOL,
SVN_ERR_BAD_CATEGORY_START + 17,
"Unexpected line ending in the property value")
/* xml errors */
SVN_ERRDEF(SVN_ERR_XML_ATTRIB_NOT_FOUND,
@ -868,6 +873,21 @@ SVN_ERROR_START
SVN_ERR_FS_CATEGORY_START + 63,
"Invalid generation number data.")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_FS_CORRUPT_REVPROP_MANIFEST,
SVN_ERR_FS_CATEGORY_START + 64,
"Revprop manifest corrupt.")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_FS_CORRUPT_PROPLIST,
SVN_ERR_FS_CATEGORY_START + 65,
"Property list is corrupt.")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_FS_AMBIGUOUS_CHECKSUM_REP,
SVN_ERR_FS_CATEGORY_START + 67,
"Content checksums supposedly match but content does not.")
/* repos errors */
SVN_ERRDEF(SVN_ERR_REPOS_LOCKED,
@ -1236,6 +1256,11 @@ SVN_ERROR_START
SVN_ERR_CLIENT_CATEGORY_START + 23,
"The operation is forbidden by the server")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_CLIENT_CONFLICT_OPTION_NOT_APPLICABLE,
SVN_ERR_CLIENT_CATEGORY_START + 24,
"The conflict resolution option is not applicable")
/* misc errors */
SVN_ERRDEF(SVN_ERR_BASE,
@ -1442,6 +1467,21 @@ SVN_ERROR_START
SVN_ERR_MISC_CATEGORY_START + 43,
"Parser error: invalid input")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_SQLITE_ROLLBACK_FAILED,
SVN_ERR_MISC_CATEGORY_START + 44,
"SQLite transaction rollback failed")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_LZ4_COMPRESSION_FAILED,
SVN_ERR_MISC_CATEGORY_START + 45,
"LZ4 compression failed")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_LZ4_DECOMPRESSION_FAILED,
SVN_ERR_MISC_CATEGORY_START + 46,
"LZ4 decompression failed")
/* command-line client errors */
SVN_ERRDEF(SVN_ERR_CL_ARG_PARSING_ERROR,
@ -1537,6 +1577,16 @@ SVN_ERROR_START
SVN_ERR_RA_SVN_CATEGORY_START + 8,
"Editor drive was aborted")
/** @since New in 1.10 */
SVN_ERRDEF(SVN_ERR_RA_SVN_REQUEST_SIZE,
SVN_ERR_RA_SVN_CATEGORY_START + 9,
"Client request too long")
/** @since New in 1.10 */
SVN_ERRDEF(SVN_ERR_RA_SVN_RESPONSE_SIZE,
SVN_ERR_RA_SVN_CATEGORY_START + 10,
"Server response too long")
/* libsvn_auth errors */
/* this error can be used when an auth provider doesn't have
@ -1594,6 +1644,11 @@ SVN_ERROR_START
SVN_ERR_DIFF_CATEGORY_START + 0,
"Diff data source modified unexpectedly")
/** @since New in 1.10 */
SVN_ERRDEF(SVN_ERR_DIFF_UNEXPECTED_DATA,
SVN_ERR_DIFF_CATEGORY_START + 1,
"Diff data unexpected")
/* libsvn_ra_serf errors */
/** @since New in 1.5.
@deprecated SSPI now handled by serf rather than libsvn_ra_serf. */
@ -1617,6 +1672,11 @@ SVN_ERROR_START
SVN_ERR_RA_SERF_CATEGORY_START + 3,
"While handling serf response:")
/** @since New in 1.10. */
SVN_ERRDEF(SVN_ERR_RA_SERF_STREAM_BUCKET_READ_ERROR,
SVN_ERR_RA_SERF_CATEGORY_START + 4,
"Can't read from stream")
/* malfunctions such as assertion failures */
SVN_ERRDEF(SVN_ERR_ASSERTION_FAIL,

View File

@ -113,7 +113,7 @@ typedef struct svn_fs_t svn_fs_t;
*
* "2" is allowed, too and means "enable if efficient",
* i.e. this will not create warning at runtime if there
* if no efficient support for revprop caching.
* is no efficient support for revprop caching.
*
* @since New in 1.8.
*/
@ -134,6 +134,12 @@ typedef struct svn_fs_t svn_fs_t;
*/
#define SVN_FS_CONFIG_FSFS_CACHE_NS "fsfs-cache-namespace"
/** Enable / disable caching of node properties for a FSFS repository.
*
* @since New in 1.10.
*/
#define SVN_FS_CONFIG_FSFS_CACHE_NODEPROPS "fsfs-cache-nodeprops"
/** Enable / disable the FSFS format 7 "block read" feature.
*
* @since New in 1.9.
@ -207,6 +213,20 @@ typedef struct svn_fs_t svn_fs_t;
* @since New in 1.9.
*/
#define SVN_FS_CONFIG_COMPATIBLE_VERSION "compatible-version"
/** Specifies whether the filesystem should be forcing a physical write of
* the data to disk. Enabling the option allows the filesystem to return
* from the API calls without forcing the write to disk. If this option
* is disabled, the changes are always written to disk.
*
* @note Avoiding the forced write to disk usually is more efficient, but
* doesn't guarantee data integrity after a system crash or power failure
* and should be used with caution.
*
* @since New in 1.10.
*/
#define SVN_FS_CONFIG_NO_FLUSH_TO_DISK "no-flush-to-disk"
/** @} */
@ -269,11 +289,13 @@ svn_fs_set_warning_func(svn_fs_t *fs,
* @c NULL, the options it contains modify the behavior of the
* filesystem. The interpretation of @a fs_config is specific to the
* filesystem back-end. The new filesystem may be closed by
* destroying @a pool.
* destroying @a result_pool.
*
* Use @a scratch_pool for temporary allocations.
*
* @note The lifetime of @a fs_config must not be shorter than @a
* pool's. It's a good idea to allocate @a fs_config from @a pool or
* one of its ancestors.
* result_pool's. It's a good idea to allocate @a fs_config from
* @a result_pool or one of its ancestors.
*
* If @a fs_config contains a value for #SVN_FS_CONFIG_FS_TYPE, that
* value determines the filesystem type for the new filesystem.
@ -289,8 +311,22 @@ svn_fs_set_warning_func(svn_fs_t *fs,
* though the caller should not rely upon any particular default if they
* wish to ensure that a filesystem of a specific type is created.
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_create2(svn_fs_t **fs_p,
const char *path,
apr_hash_t *fs_config,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Like svn_fs_create2(), but without @a scratch_pool.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
* @since New in 1.1.
*/
SVN_DEPRECATED
svn_error_t *
svn_fs_create(svn_fs_t **fs_p,
const char *path,
@ -1060,15 +1096,12 @@ svn_fs_unparse_id(const svn_fs_id_t *id,
* set.
*
* The Subversion filesystem will make a best effort to not reuse
* transaction names. The Berkeley DB backend generates transaction
* names using a sequence, or a counter, which is stored in the BDB
* transaction names. The BDB and FSFS backends generate transaction
* names using a sequence, or a counter, which is stored in the
* database. Each new transaction increments the counter. The
* current value of the counter is not serialized into a filesystem
* dump file, so dumping and restoring the repository will reset the
* sequence and reuse transaction names. The FSFS backend generates a
* transaction name using the hostname, process ID and current time in
* microseconds since 00:00:00 January 1, 1970 UTC. So it is
* extremely unlikely that a transaction name will be reused.
* sequence and so may reuse transaction names.
*
* @defgroup svn_fs_txns Filesystem transactions
* @{
@ -1425,7 +1458,7 @@ svn_fs_revision_root_revision(svn_fs_root_t *root);
* Unicode canonical decomposition and ordering. No directory entry
* may be named '.', '..', or the empty string. Given a directory
* entry name which fails to meet these requirements, a filesystem
* function returns an SVN_ERR_FS_PATH_SYNTAX error.
* function returns an #SVN_ERR_FS_PATH_SYNTAX error.
*
* A directory path is a sequence of zero or more directory entry
* names, separated by slash characters (U+002f), and possibly ending
@ -1433,7 +1466,7 @@ svn_fs_revision_root_revision(svn_fs_root_t *root);
* characters are treated as if they were a single slash. If a path
* ends with a slash, it refers to the same node it would without the
* slash, but that node must be a directory, or else the function
* returns an SVN_ERR_FS_NOT_DIRECTORY error.
* may return an #SVN_ERR_FS_NOT_DIRECTORY error.
*
* A path consisting of the empty string, or a string containing only
* slashes, refers to the root directory.
@ -1474,7 +1507,75 @@ typedef enum svn_fs_path_change_kind_t
* by the commit API; this does not mean the new value is different from
* the old value.
*
* @since New in 1.6. */
* @since New in 1.10. */
typedef struct svn_fs_path_change3_t
{
/** path of the node that got changed. */
svn_string_t path;
/** kind of change */
svn_fs_path_change_kind_t change_kind;
/** what node kind is the path?
(Note: it is legal for this to be #svn_node_unknown.) */
svn_node_kind_t node_kind;
/** was the text touched?
* For node_kind=dir: always false. For node_kind=file:
* modify: true iff text touched.
* add (copy): true iff text touched.
* add (plain): always true.
* delete: always false.
* replace: as for the add/copy part of the replacement.
*/
svn_boolean_t text_mod;
/** were the properties touched?
* modify: true iff props touched.
* add (copy): true iff props touched.
* add (plain): true iff props touched.
* delete: always false.
* replace: as for the add/copy part of the replacement.
*/
svn_boolean_t prop_mod;
/** was the mergeinfo property touched?
* modify: } true iff svn:mergeinfo property add/del/mod
* add (copy): } and fs format supports this flag.
* add (plain): }
* delete: always false.
* replace: as for the add/copy part of the replacement.
* (Note: Pre-1.9 repositories will report #svn_tristate_unknown.)
*/
svn_tristate_t mergeinfo_mod;
/** Copyfrom revision and path; this is only valid if copyfrom_known
* is true. */
svn_boolean_t copyfrom_known;
svn_revnum_t copyfrom_rev;
const char *copyfrom_path;
/* NOTE! Please update svn_fs_path_change3_create() when adding new
fields here. */
} svn_fs_path_change3_t;
/** Similar to #svn_fs_path_change3_t, but with @a node_rev_id and without
* path information.
*
* @note Fields may be added to the end of this structure in future
* versions. Therefore, to preserve binary compatibility, users
* should not directly allocate structures of this type.
*
* @note The @c text_mod, @c prop_mod and @c mergeinfo_mod flags mean the
* text, properties and mergeinfo property (respectively) were "touched"
* by the commit API; this does not mean the new value is different from
* the old value.
*
* @since New in 1.6.
*
* @deprecated Provided for backwards compatibility with the 1.9 API.
*/
typedef struct svn_fs_path_change2_t
{
/** node revision id of changed path */
@ -1563,22 +1664,94 @@ svn_fs_path_change2_create(const svn_fs_id_t *node_rev_id,
svn_fs_path_change_kind_t change_kind,
apr_pool_t *pool);
/**
* Allocate an #svn_fs_path_change3_t structure in @a result_pool,
* initialize and return it.
*
* Set the @c change_kind field to @a change_kind. Set all other fields
* to their @c _unknown, @c NULL or invalid value, respectively.
*
* @since New in 1.10.
*/
svn_fs_path_change3_t *
svn_fs_path_change3_create(svn_fs_path_change_kind_t change_kind,
apr_pool_t *result_pool);
/**
* Return a deep copy of @a *change, allocated in @a result_pool.
*
* @since New in 1.10.
*/
svn_fs_path_change3_t *
svn_fs_path_change3_dup(svn_fs_path_change3_t *change,
apr_pool_t *result_pool);
/**
* Opaque iterator object type for a changed paths list.
*
* @since New in 1.10.
*/
typedef struct svn_fs_path_change_iterator_t svn_fs_path_change_iterator_t;
/**
* Set @a *change to the path change that @a iterator currently points to
* and advance the @a iterator. If the change list has been exhausted,
* @a change will be set to @c NULL.
*
* You may modify @a **change but its content becomes invalid as soon as
* either @a iterator becomes invalid or you call this function again.
*
* @note The @c node_kind field in @a change may be #svn_node_unknown and
* the @c copyfrom_known fields may be FALSE.
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_path_change_get(svn_fs_path_change3_t **change,
svn_fs_path_change_iterator_t *iterator);
/** Determine what has changed under a @a root.
*
* Set @a *iterator to an iterator object, allocated in @a result_pool,
* which will give access to the full list of changed paths under @a root.
* Each call to @a svn_fs_path_change_get will return a new unique path
* change and has amortized O(1) runtime. The iteration order is undefined
* and may change even for the same @a root.
*
* If @a root becomes invalid, @a *iterator becomes invalid, too.
*
* Use @a scratch_pool for temporary allocations.
*
* @note The @a *iterator may be a large object and bind limited system
* resources such as file handles. Be sure to clear the owning
* pool once you don't need that iterator anymore.
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_paths_changed3(svn_fs_path_change_iterator_t **iterator,
svn_fs_root_t *root,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Same as svn_fs_paths_changed3() but returning all changes in a single,
* large data structure and using a single pool for all allocations.
*
* Allocate and return a hash @a *changed_paths2_p containing descriptions
* of the paths changed under @a root. The hash is keyed with
* <tt>const char *</tt> paths, and has #svn_fs_path_change2_t * values.
*
* Callers can assume that this function takes time proportional to
* the amount of data output, and does not need to do tree crawls;
* however, it is possible that some of the @c node_kind fields in the
* #svn_fs_path_change2_t * values will be #svn_node_unknown or
* that and some of the @c copyfrom_known fields will be FALSE.
*
* 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
* be expensive in some FS backends.
*
* @since New in 1.6.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_fs_paths_changed2(apr_hash_t **changed_paths2_p,
svn_fs_root_t *root,
@ -1989,11 +2162,23 @@ svn_fs_closest_copy(svn_fs_root_t **root_p,
const char *path,
apr_pool_t *pool);
/** Receives parsed @a mergeinfo for the file system path @a path.
*
* The user-provided @a baton is being passed through by the retrieval
* function and @a scratch_pool will be cleared between invocations.
*
* @since New in 1.10.
*/
typedef svn_error_t *
(*svn_fs_mergeinfo_receiver_t)(const char *path,
svn_mergeinfo_t mergeinfo,
void *baton,
apr_pool_t *scratch_pool);
/** Retrieve mergeinfo for multiple nodes.
*
* @a *catalog is a catalog for @a paths. It will never be @c NULL,
* but may be empty.
* For each node found with mergeinfo on it, invoke @a receiver with
* the provided @a baton.
*
* @a root is revision root to use when looking up paths.
*
@ -2003,7 +2188,7 @@ svn_fs_closest_copy(svn_fs_root_t **root_p,
* explicit-or-inherited, or only inherited mergeinfo.
*
* If @a adjust_inherited_mergeinfo is @c TRUE, then any inherited
* mergeinfo returned in @a *catalog is normalized to represent the
* mergeinfo reported to @a *receiver is normalized to represent the
* inherited mergeinfo on the path which inherits it. This adjusted
* mergeinfo is keyed by the path which inherits it. If
* @a adjust_inherited_mergeinfo is @c FALSE, then any inherited
@ -2018,13 +2203,31 @@ svn_fs_closest_copy(svn_fs_root_t **root_p,
* the #SVN_PROP_MERGEINFO property explicitly set on it. (Note
* that inheritance is only taken into account for the elements in @a
* paths; descendants of the elements in @a paths which get their
* mergeinfo via inheritance are not included in @a *catalog.)
* mergeinfo via inheritance are not reported to @a receiver.)
*
* Allocate @a *catalog in result_pool. Do any necessary temporary
* allocations in @a scratch_pool.
* Do any necessary temporary allocations in @a scratch_pool.
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_get_mergeinfo3(svn_fs_root_t *root,
const apr_array_header_t *paths,
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_descendants,
svn_boolean_t adjust_inherited_mergeinfo,
svn_fs_mergeinfo_receiver_t receiver,
void *baton,
apr_pool_t *scratch_pool);
/**
* Same as svn_fs_get_mergeinfo3(), but all mergeinfo is being collected
* and returned in @a *catalog. It will never be @c NULL, but may be empty.
*
* @since New in 1.8.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_fs_get_mergeinfo2(svn_mergeinfo_catalog_t *catalog,
svn_fs_root_t *root,
@ -2545,12 +2748,71 @@ svn_fs_deltify_revision(svn_fs_t *fs,
svn_revnum_t revision,
apr_pool_t *pool);
/** Make sure that all completed revision property changes to the filesystem
* underlying @a fs are actually visible through @a fs. Use @a scratch_pool
* for temporary allocations.
*
* This is an explicit synchronization barrier for revprop changes made
* through different #svn_fs_t for the same underlying filesystem. Any
* revprop change through @a fs acts as an implicit barrier, i.e. that
* object will see all completed revprop changes up to an including its own.
* Only #svn_fs_revision_prop2 and #svn_fs_revision_proplist2 have an option
* to not synchronize with on-disk data and potentially return outdated data
* as old as the last barrier.
*
* The intended use of this is implementing efficient queries in upper layers
* where the result only needs to include all changes up to the start of
* that query but does not need to pick up on changes while the query is
* running:
*
* @code
SVN_ERR(svn_fs_deltify_revision(fs, pool);
for (i = 0; i < n; i++)
SVN_ERR(svn_fs_revision_prop2(&authors[i], fs, revs[i], "svn:author",
FALSE, pool, pool)); @endcode
*
* @see svn_fs_revision_prop2, svn_fs_revision_proplist2
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_refresh_revision_props(svn_fs_t *fs,
apr_pool_t *scratch_pool);
/** Set @a *value_p to the value of the property named @a propname on
* revision @a rev in the filesystem @a fs. If @a rev has no property by
* that name, set @a *value_p to zero. Allocate the result in @a pool.
* that name, set @a *value_p to zero.
*
* If @a refresh is set, this call acts as a read barrier and is guaranteed
* to return the latest value. Otherwise, it may return data as old as the
* last synchronization point but can be much faster to access - in
* particular for packed repositories.
*
* Allocate the result in @a result_pool and use @a scratch_pool for
* temporary allocations.
*
* @see svn_fs_refresh_revision_props
*
* @since New in 1.10.
*/
svn_error_t *
svn_fs_revision_prop2(svn_string_t **value_p,
svn_fs_t *fs,
svn_revnum_t rev,
const char *propname,
svn_boolean_t refresh,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Like #svn_fs_revision_prop2 but using @a pool for @a scratch_pool as
* well as @a result_pool and setting @a refresh to #TRUE.
*
* @see svn_fs_refresh_revision_props
*
* @deprecated For backward compatibility with 1.9.
*/
SVN_DEPRECATED
svn_error_t *
svn_fs_revision_prop(svn_string_t **value_p,
svn_fs_t *fs,
svn_revnum_t rev,
@ -2561,15 +2823,41 @@ svn_fs_revision_prop(svn_string_t **value_p,
/** Set @a *table_p to the entire property list of revision @a rev in
* filesystem @a fs, as an APR hash table allocated in @a pool. The table
* maps <tt>char *</tt> property names to #svn_string_t * values; the names
* and values are allocated in @a pool.
* and values are allocated in @a result_pool. Use @a scratch_pool for
* temporary allocations.
*
* If @a refresh is set, this call acts as a read barrier and is guaranteed
* to return the latest value. Otherwise, it may return data as old as the
* last synchronization point but can be much faster to access - in
* particular for packed repositories.
*
* @see svn_fs_refresh_revision_props
*
* @since New in 1.10.
*
*/
svn_error_t *
svn_fs_revision_proplist2(apr_hash_t **table_p,
svn_fs_t *fs,
svn_revnum_t rev,
svn_boolean_t refresh,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Like svn_fs_revision_proplist2 but using @a pool for @a scratch_pool as
* well as @a result_pool and setting @a refresh to #TRUE.
*
* @see svn_fs_refresh_revision_props
*
* @deprecated For backward compatibility with 1.9.
*/
SVN_DEPRECATED
svn_error_t *
svn_fs_revision_proplist(apr_hash_t **table_p,
svn_fs_t *fs,
svn_revnum_t rev,
apr_pool_t *pool);
/** Change a revision's property's value, or add/delete a property.
*
* - @a fs is a filesystem, and @a rev is the revision in that filesystem
@ -2992,7 +3280,13 @@ typedef enum svn_fs_pack_notify_action_t
/** packing of the shard revprops has completed
@since New in 1.7. */
svn_fs_pack_notify_end_revprop
svn_fs_pack_notify_end_revprop,
/** pack has been a no-op for this repository. The next / future packable
shard will be given. If the shard is -1, then the repository does not
support packing at all.
@since New in 1.10. */
svn_fs_pack_notify_noop
} svn_fs_pack_notify_action_t;

View File

@ -239,19 +239,44 @@ svn_hash_from_cstring_keys(apr_hash_t **hash,
const apr_array_header_t *keys,
apr_pool_t *pool);
/* For the Subversion developers, this #define makes the svn_hash_gets and
* svn_hash_sets macros forward their parameters through functions in order to
* gain type checking for the 'key' parameter which the basic apr_hash_* APIs
* declare only as 'void *'.
*/
#ifdef SVN_DEBUG
#define SVN_HASH__GETS_SETS
#endif
#ifdef SVN_HASH__GETS_SETS
void *
svn_hash__gets_debug(apr_hash_t *ht, const char *key);
#define svn_hash_gets(ht, key) \
svn_hash__gets_debug(ht, key)
#else
/** Shortcut for apr_hash_get() with a const char * key.
*
* @since New in 1.8.
*/
#define svn_hash_gets(ht, key) \
apr_hash_get(ht, key, APR_HASH_KEY_STRING)
#endif
#ifdef SVN_HASH__GETS_SETS
void
svn_hash__sets_debug(apr_hash_t *ht, const char *key, const void *value);
#define svn_hash_sets(ht, key, val) \
svn_hash__sets_debug(ht, key, val)
#else
/** Shortcut for apr_hash_set() with a const char * key.
*
* @since New in 1.8.
*/
#define svn_hash_sets(ht, key, val) \
apr_hash_set(ht, key, APR_HASH_KEY_STRING, val)
#endif
/** @} */

View File

@ -918,6 +918,17 @@ typedef svn_error_t *(*svn_stream_seek_fn_t)(void *baton,
typedef svn_error_t *(*svn_stream_data_available_fn_t)(void *baton,
svn_boolean_t *data_available);
/** Readline handler function for a generic stream. @see svn_stream_t and
* svn_stream_readline().
*
* @since New in 1.10.
*/
typedef svn_error_t *(*svn_stream_readline_fn_t)(void *baton,
svn_stringbuf_t **stringbuf,
const char *eol,
svn_boolean_t *eof,
apr_pool_t *pool);
/** Create a generic stream. @see svn_stream_t. */
svn_stream_t *
svn_stream_create(void *baton,
@ -992,6 +1003,14 @@ void
svn_stream_set_data_available(svn_stream_t *stream,
svn_stream_data_available_fn_t data_available);
/** Set @a stream's readline function to @a readline_fn
*
* @since New in 1.10.
*/
void
svn_stream_set_readline(svn_stream_t *stream,
svn_stream_readline_fn_t readline_fn);
/** Create a stream that is empty for reading and infinite for writing. */
svn_stream_t *
svn_stream_empty(apr_pool_t *pool);
@ -1102,11 +1121,29 @@ svn_stream_from_aprfile(apr_file_t *file,
apr_pool_t *pool);
/** Set @a *in to a generic stream connected to stdin, allocated in
* @a pool. The stream and its underlying APR handle will be closed
* when @a pool is cleared or destroyed.
* @a pool. If @a buffered is set, APR buffering will be enabled.
* The stream and its underlying APR handle will be closed when @a pool
* is cleared or destroyed.
*
* @note APR buffering will try to fill the whole internal buffer before
* serving read requests. This may be inappropriate for interactive
* applications where stdin will not deliver any more data unless
* the application processed the data already received.
*
* @since New in 1.10.
*/
svn_error_t *
svn_stream_for_stdin2(svn_stream_t **in,
svn_boolean_t buffered,
apr_pool_t *pool);
/** Similar to svn_stream_for_stdin2(), but with buffering being disabled.
*
* @since New in 1.7.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_stream_for_stdin(svn_stream_t **in,
apr_pool_t *pool);
@ -1129,16 +1166,27 @@ svn_error_t *
svn_stream_for_stdout(svn_stream_t **out,
apr_pool_t *pool);
/** Set @a *str to a string buffer allocated in @a result_pool that contains
* all data from the current position in @a stream to its end. @a len_hint
* specifies the initial capacity of the string buffer and may be 0. The
* buffer gets automatically resized to fit the actual amount of data being
* read from @a stream.
/** Read the contents of @a stream into memory, from its current position
* to its end, returning the data in @a *result. This function does not
* close the @a stream upon completion.
*
* @a len_hint gives a hint about the expected length, in bytes, of the
* actual data that will be read from the stream. It may be 0, meaning no
* hint is being provided. Efficiency in time and/or in space may be
* better (and in general will not be worse) when the actual data length
* is equal or approximately equal to the length hint.
*
* The returned memory is allocated in @a result_pool.
*
* @note The present implementation is efficient when @a len_hint is big
* enough (but not vastly bigger than necessary), and also for actual
* lengths up to 64 bytes when @a len_hint is 0. Otherwise it can incur
* significant time and space overheads. See source code for details.
*
* @since New in 1.9.
*/
svn_error_t *
svn_stringbuf_from_stream(svn_stringbuf_t **str,
svn_stringbuf_from_stream(svn_stringbuf_t **result,
svn_stream_t *stream,
apr_size_t len_hint,
apr_pool_t *result_pool);
@ -1200,7 +1248,8 @@ svn_stream_compressed(svn_stream_t *stream,
* The @a stream passed into this function is closed when the created
* stream is closed.
*
* @since New in 1.6.
* @since New in 1.6. Since 1.10, the resulting stream supports reset
* via stream_stream_reset().
*/
svn_stream_t *
svn_stream_checksummed2(svn_stream_t *stream,
@ -1225,6 +1274,24 @@ svn_stream_checksummed(svn_stream_t *stream,
svn_boolean_t read_all,
apr_pool_t *pool);
/** Read the contents of the readable stream @a stream and return its
* checksum of type @a kind in @a *checksum.
*
* The stream will be closed before this function returns (regardless
* of the result, or any possible error).
*
* Use @a scratch_pool for temporary allocations and @a result_pool
* to allocate @a *checksum.
*
* @since New in 1.10.
*/
svn_error_t *
svn_stream_contents_checksum(svn_checksum_t **checksum,
svn_stream_t *stream,
svn_checksum_kind_t kind,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** Read from a generic stream until @a buffer is filled upto @a *len or
* until EOF is reached. @see svn_stream_t
*
@ -1318,6 +1385,14 @@ svn_stream_reset(svn_stream_t *stream);
svn_boolean_t
svn_stream_supports_mark(svn_stream_t *stream);
/** Returns @c TRUE if the generic @a stream supports svn_stream_reset().
*
* @see svn_stream_reset()
* @since New in 1.10.
*/
svn_boolean_t
svn_stream_supports_reset(svn_stream_t *stream);
/** Set a @a mark at the current position of a generic @a stream,
* which can later be sought back to using svn_stream_seek().
* The @a mark is allocated in @a pool.
@ -1502,25 +1577,44 @@ svn_stream_contents_same(svn_boolean_t *same,
apr_pool_t *pool);
/** Read the contents of @a stream into memory, returning the data in
* @a result. The stream will be closed when it has been successfully and
* completely read.
/** Read the contents of @a stream into memory, from its current position
* to its end, returning the data in @a *result. The stream will be closed
* when it has been successfully and completely read.
*
* @a len_hint gives a hint about the expected length, in bytes, of the
* actual data that will be read from the stream. It may be 0, meaning no
* hint is being provided. Efficiency in time and/or in space may be
* better (and in general will not be worse) when the actual data length
* is equal or approximately equal to the length hint.
*
* The returned memory is allocated in @a result_pool, and any temporary
* allocations are performed in @a scratch_pool.
* allocations may be performed in @a scratch_pool.
*
* @note due to memory pseudo-reallocation behavior (due to pools), this
* can be a memory-intensive operation for large files.
* @note The present implementation is efficient when @a len_hint is big
* enough (but not vastly bigger than necessary), and also for actual
* lengths up to 64 bytes when @a len_hint is 0. Otherwise it can incur
* significant time and space overheads. See source code for details.
*
* @since New in 1.6
* @since New in 1.10
*/
svn_error_t *
svn_string_from_stream2(svn_string_t **result,
svn_stream_t *stream,
apr_size_t len_hint,
apr_pool_t *result_pool);
/** Similar to svn_string_from_stream2(), but always passes 0 for
* @a len_hint.
*
* @deprecated Provided for backwards compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_string_from_stream(svn_string_t **result,
svn_stream_t *stream,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/** A function type provided for use as a callback from
* @c svn_stream_lazyopen_create().
*
@ -2175,6 +2269,28 @@ svn_io_file_info_get(apr_finfo_t *finfo,
apr_pool_t *pool);
/** Set @a *filesize_p to the size of @a file. Use @a pool for temporary
* allocations.
*
* @note Use svn_io_file_info_get() to get more information about
* apr_file_t.
*
* @since New in 1.10
*/
svn_error_t *
svn_io_file_size_get(svn_filesize_t *filesize_p, apr_file_t *file,
apr_pool_t *pool);
/** Fetch the current offset of @a file into @a *offset_p. Use @a pool for
* temporary allocations.
*
* @since New in 1.10
*/
svn_error_t *
svn_io_file_get_offset(apr_off_t *offset_p,
apr_file_t *file,
apr_pool_t *pool);
/** Wrapper for apr_file_read(). */
svn_error_t *
svn_io_file_read(apr_file_t *file,
@ -2276,13 +2392,31 @@ svn_io_file_write_full(apr_file_t *file,
* If @a copy_perms_path is not NULL, copy the permissions applied on @a
* @a copy_perms_path on the temporary file before renaming.
*
* @note This function uses advanced file control operations to flush buffers
* to disk that aren't always accessible and can be very expensive. Avoid
* using this function in cases where the file should just work on any
* network filesystem.
* If @a flush_to_disk is non-zero, do not return until the node has
* actually been written on the disk.
*
* @note The flush to disk operation can be very expensive on systems
* that implement flushing on all IO layers, like Windows. Please use
* @a flush_to_disk flag only for critical data.
*
* @since New in 1.10.
*/
svn_error_t *
svn_io_write_atomic2(const char *final_path,
const void *buf,
apr_size_t nbytes,
const char *copy_perms_path,
svn_boolean_t flush_to_disk,
apr_pool_t *scratch_pool);
/** Similar to svn_io_write_atomic2(), but with @a flush_to_disk set
* to @c TRUE.
*
* @since New in 1.9.
*
* @deprecated Provided for backward compatibility with the 1.9 API
*/
SVN_DEPRECATED
svn_error_t *
svn_io_write_atomic(const char *final_path,
const void *buf,
@ -2332,10 +2466,27 @@ svn_io_stat(apr_finfo_t *finfo,
* @a from_path to a new path @a to_path within the same filesystem.
* In some cases, an existing node at @a to_path will be overwritten.
*
* A wrapper for apr_file_rename(). @a from_path and @a to_path are
* utf8-encoded.
* @a from_path and @a to_path are utf8-encoded. If @a flush_to_disk
* is non-zero, do not return until the node has actually been moved on
* the disk.
*
* @note The flush to disk operation can be very expensive on systems
* that implement flushing on all IO layers, like Windows. Please use
* @a flush_to_disk flag only for critical data.
*
* @since New in 1.10.
*/
svn_error_t *
svn_io_file_rename2(const char *from_path, const char *to_path,
svn_boolean_t flush_to_disk, apr_pool_t *pool);
/** Similar to svn_io_file_rename2(), but with @a flush_to_disk set
* to @c FALSE.
*
* @deprecated Provided for backward compatibility with the 1.9 API
*/
SVN_DEPRECATED
svn_error_t *
svn_io_file_rename(const char *from_path,
const char *to_path,
apr_pool_t *pool);

View File

@ -475,22 +475,42 @@ svn_prop_name_is_valid(const char *prop_name);
/** The files' last modification time.
* This is stored as string in the form @c "2008-08-07T07:38:51.008782Z", to
* be converted by the functions @c svn_time_to_cstring() and
* @c svn_time_from_cstring(). */
* @c svn_time_from_cstring().
*
* @note This property name is reserved for future usage, but currently unused.
*
* @since New in 1.6.
*/
#define SVN_PROP_TEXT_TIME SVN_PROP_PREFIX "text-time"
/** The files' owner.
* Stored as numeric ID, optionally followed by whitespace and the string:
* @c "1000 pmarek". Parsers @b should accept any number of whitespace,
* and writers @b should put exactly a single space. */
* and writers @b should put exactly a single space.
*
* @note This property name is reserved for future usage, but currently unused.
*
* @since New in 1.6.
*/
#define SVN_PROP_OWNER SVN_PROP_PREFIX "owner"
/** The files' group.
* The same format as for @c SVN_PROP_OWNER, the owner-property. */
* The same format as for @c SVN_PROP_OWNER, the owner-property.
*
* @note This property name is reserved for future usage, but currently unused.
*
* @since New in 1.6.
*/
#define SVN_PROP_GROUP SVN_PROP_PREFIX "group"
/** The files' unix-mode.
* Stored in octal, with a leading @c 0; may have 5 digits if any of @c setuid,
* @c setgid or @c sticky are set; an example is @c "0644". */
* @c setgid or @c sticky are set; an example is @c "0644".
*
* @note This property name is reserved for future usage, but currently unused.
*
* @since New in 1.6.
*/
#define SVN_PROP_UNIX_MODE SVN_PROP_PREFIX "unix-mode"
/** @} */ /* Meta-data properties */

View File

@ -1089,7 +1089,7 @@ svn_ra_get_file(svn_ra_session_t *session,
* @a path is interpreted relative to the URL in @a session.
*
* If @a revision is @c SVN_INVALID_REVNUM (meaning 'head') and
* @a *fetched_rev is not @c NULL, then this function will set
* @a fetched_rev is not @c NULL, then this function will set
* @a *fetched_rev to the actual revision that was retrieved. (Some
* callers want to know, and some don't.)
*
@ -1129,6 +1129,63 @@ svn_ra_get_dir(svn_ra_session_t *session,
apr_hash_t **props,
apr_pool_t *pool);
/**
* Callback type to be used with svn_ra_list(). It will be invoked for
* every directory entry found.
*
* The full path of the entry is given in @a rel_path and @a dirent contains
* various additional information. Only the elements of @a dirent specified
* by the @a dirent_fields argument to svn_ra_list() will be valid.
*
* @a baton is the user-provided receiver baton. @a scratch_pool may be
* used for temporary allocations.
*
* @since New in 1.10.
*/
typedef svn_error_t *(* svn_ra_dirent_receiver_t)(const char *rel_path,
svn_dirent_t *dirent,
void *baton,
apr_pool_t *scratch_pool);
/**
* Efficiently list everything within a sub-tree. Specify a glob pattern
* to search for specific files and folders.
*
* In @a session, walk the sub-tree starting at @a path at @a revision down
* to the given @a depth. For each directory entry found, @a receiver will
* be called with @a receiver_baton. The starting @a path will be reported
* as well. Because retrieving elements of a #svn_dirent_t can be
* expensive, you need to select them individually via flags set in
* @a dirent_fields.
*
* @a patterns is an optional array of <tt>const char *</tt>. If it is
* not @c NULL, only those directory entries will be reported whose last
* path segment matches at least one of these patterns. This feature uses
* apr_fnmatch() for glob matching and requiring '.' to matched by dots
* in the path.
*
* @a path must point to a directory and @a depth must be at least
* #svn_depth_empty.
*
* If the server doesn't support the 'list' command, return
* #SVN_ERR_UNSUPPORTED_FEATURE in preference to any other error that
* might otherwise be returned.
*
* Use @a scratch_pool for temporary memory allocation.
*
* @since New in 1.10.
*/
svn_error_t *
svn_ra_list(svn_ra_session_t *session,
const char *path,
svn_revnum_t revision,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_ra_dirent_receiver_t receiver,
void *receiver_baton,
apr_pool_t *scratch_pool);
/**
* Set @a *catalog to a mergeinfo catalog for the paths in @a paths.
* If no mergeinfo is available, set @a *catalog to @c NULL. The
@ -1550,7 +1607,7 @@ svn_ra_do_diff(svn_ra_session_t *session,
* revisions in which at least one of @a paths was changed (i.e., if
* file, text or props changed; if dir, props changed or an entry
* was added or deleted). Each path is an <tt>const char *</tt>, relative
* to the @a session's common parent.
* to the repository root of @a session.
*
* If @a limit is greater than zero only invoke @a receiver on the first
* @a limit logs.
@ -1717,9 +1774,10 @@ svn_ra_get_repos_root(svn_ra_session_t *session,
/**
* Set @a *locations to the locations (at the repository revisions
* @a location_revisions) of the file identified by @a path in
* @a peg_revision. @a path is relative to the URL to which
* @a session was opened. @a location_revisions is an array of
* @c svn_revnum_t's. @a *locations will be a mapping from the revisions to
* @a peg_revision (passing @c SVN_INVALID_REVNUM is an error).
* @a path is relative to the URL to which @a session was opened.
* @a location_revisions is an array of @c svn_revnum_t's.
* @a *locations will be a mapping from the revisions to
* their appropriate absolute paths. If the file doesn't exist in a
* location_revision, that revision will be ignored.
*
@ -1966,7 +2024,7 @@ svn_ra_get_locks(svn_ra_session_t *session,
/**
* Replay the changes from a range of revisions between @a start_revision
* and @a end_revision.
* and @a end_revision (inclusive).
*
* When receiving information for one revision, a callback @a revstart_func is
* called; this callback will provide an editor and baton through which the
@ -2174,6 +2232,13 @@ svn_ra_has_capability(svn_ra_session_t *session,
*/
#define SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE "get-file-revs-reversed"
/**
* The capability of a server to understand the list command.
*
* @since New in 1.10.
*/
#define SVN_RA_CAPABILITY_LIST "list"
/* *** PLEASE READ THIS IF YOU ADD A NEW CAPABILITY ***
*

View File

@ -49,6 +49,7 @@ extern "C" {
/** Currently-defined capabilities. */
#define SVN_RA_SVN_CAP_EDIT_PIPELINE "edit-pipeline"
#define SVN_RA_SVN_CAP_SVNDIFF1 "svndiff1"
#define SVN_RA_SVN_CAP_SVNDIFF2_ACCEPTED "accepts-svndiff2"
#define SVN_RA_SVN_CAP_ABSENT_ENTRIES "absent-entries"
/* maps to SVN_RA_CAPABILITY_COMMIT_REVPROPS: */
#define SVN_RA_SVN_CAP_COMMIT_REVPROPS "commit-revprops"
@ -68,6 +69,8 @@ extern "C" {
#define SVN_RA_SVN_CAP_EPHEMERAL_TXNPROPS "ephemeral-txnprops"
/* maps to SVN_RA_CAPABILITY_GET_FILE_REVS_REVERSE */
#define SVN_RA_SVN_CAP_GET_FILE_REVS_REVERSE "file-revs-reverse"
/* maps to SVN_RA_CAPABILITY_LIST */
#define SVN_RA_SVN_CAP_LIST "list"
/** ra_svn passes @c svn_dirent_t fields over the wire as a list of
@ -141,16 +144,23 @@ typedef struct svn_ra_svn_cmd_entry_t
svn_boolean_t terminate;
} svn_ra_svn_cmd_entry_t;
/** Data types defined by the svn:// protocol.
*
* @since The typedef name is new in 1.10; the enumerators are not. */
typedef enum
{
SVN_RA_SVN_NUMBER,
SVN_RA_SVN_STRING,
SVN_RA_SVN_WORD,
SVN_RA_SVN_LIST
} svn_ra_svn_item_kind_t;
/** Memory representation of an on-the-wire data item. */
typedef struct svn_ra_svn_item_t
{
/** Variant indicator. */
enum {
SVN_RA_SVN_NUMBER,
SVN_RA_SVN_STRING,
SVN_RA_SVN_WORD,
SVN_RA_SVN_LIST
} kind;
svn_ra_svn_item_kind_t kind;
/** Variant data. */
union {
apr_uint64_t number;
@ -169,7 +179,9 @@ typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton);
*
* Either @a sock or @a in_stream/@a out_stream must be set, not both.
* @a compression_level specifies the desired network data compression
* level (zlib) from 0 (no compression) to 9 (best but slowest).
* level from 0 (no compression) to 9 (best but slowest). The effect
* of the parameter depends on the compression algorithm; for example,
* it is used verbatim by zlib/deflate but ignored by LZ4.
*
* If @a zero_copy_limit is not 0, cached file contents smaller than the
* given limit may be sent directly to the network socket. Otherwise,
@ -184,13 +196,38 @@ typedef svn_error_t *(*svn_ra_svn_edit_callback)(void *baton);
* It defines the number of bytes that must have been sent since the last
* check before the next check will be made.
*
* If @a max_in is not 0, error out and close the connection whenever more
* than @a max_in bytes are received for a command (e.g. a client request).
* If @a max_out is not 0, error out and close the connection whenever more
* than @a max_out bytes have been send as response to some command.
*
* @note The limits enforced may vary slightly by +/- the I/O buffer size.
*
* @note If @a out_stream is an wrapped apr_file_t* the backing file will be
* used for some operations.
*
* Allocate the result in @a pool.
*
* @since New in 1.9
* @since New in 1.10
*/
svn_ra_svn_conn_t *svn_ra_svn_create_conn5(apr_socket_t *sock,
svn_stream_t *in_stream,
svn_stream_t *out_stream,
int compression_level,
apr_size_t zero_copy_limit,
apr_size_t error_check_interval,
apr_uint64_t max_in,
apr_uint64_t max_out,
apr_pool_t *result_pool);
/** Similar to svn_ra_svn_create_conn5() but with @a max_in and @a max_out
* set to 0.
*
* @since New in 1.9
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_ra_svn_conn_t *svn_ra_svn_create_conn4(apr_socket_t *sock,
svn_stream_t *in_stream,
svn_stream_t *out_stream,

View File

@ -244,7 +244,13 @@ typedef enum svn_repos_notify_action_t
svn_repos_notify_format_bumped,
/** A revision range was copied. @since New in 1.9. */
svn_repos_notify_hotcopy_rev_range
svn_repos_notify_hotcopy_rev_range,
/** The repository pack did not do anything. @since New in 1.10. */
svn_repos_notify_pack_noop,
/** The revision properties got set. @since New in 1.10. */
svn_repos_notify_load_revprop_set
} svn_repos_notify_action_t;
/** The type of warning occurring.
@ -369,6 +375,24 @@ typedef void (*svn_repos_notify_func_t)(void *baton,
const svn_repos_notify_t *notify,
apr_pool_t *scratch_pool);
/** Callback for filtering repository contents during dump.
*
* Set @a *include to TRUE to indicate that node, identified by path
* @a path in @a root should be included in dump, or set it to @c FALSE
* to indicate that node should be excluded (presumably according to state
* stored in @a baton).
*
* Do not assume @a scratch_pool has any lifetime beyond this call.
*
* @since New in 1.10.
*/
typedef svn_error_t * (*svn_repos_dump_filter_func_t)(
svn_boolean_t *include,
svn_fs_root_t *root,
const char *path,
void *baton,
apr_pool_t *scratch_pool);
/**
* Allocate an #svn_repos_notify_t structure in @a result_pool, initialize
* and return it.
@ -1701,6 +1725,68 @@ svn_repos_stat(svn_dirent_t **dirent,
const char *path,
apr_pool_t *pool);
/**
* Callback type to be used with svn_repos_list(). It will be invoked for
* every directory entry found.
*
* The full path of the entry is given in @a path and @a dirent contains
* various additional information. If svn_repos_list() has been called
* with @a path_info_only set, only the @a kind element of this struct
* will be valid.
*
* @a baton is the user-provided receiver baton. @a scratch_pool may be
* used for temporary allocations.
*
* @since New in 1.10.
*/
typedef svn_error_t *(* svn_repos_dirent_receiver_t)(const char *path,
svn_dirent_t *dirent,
void *baton,
apr_pool_t *scratch_pool);
/**
* Efficiently list everything within a sub-tree. Specify glob patterns
* to search for specific files and folders.
*
* Walk the sub-tree starting at @a path under @a root up to the given
* @a depth. For each directory entry found, @a receiver will be called
* with @a receiver_baton. The starting @a path will be reported as well.
* Because retrieving all elements of a #svn_dirent_t can be expensive,
* you may set @a path_info_only to receive only the path name and the node
* kind. The entries will be reported ordered by their path.
*
* @a patterns is an optional array of <tt>const char *</tt>. If it is
* not @c NULL, only those directory entries will be reported whose last
* path segment matches at least one of these patterns. This feature uses
* apr_fnmatch() for glob matching and requiring '.' to matched by dots
* in the path.
*
* If @a authz_read_func is not @c NULL, this function will neither report
* entries nor recurse into directories that the user has no access to.
*
* Cancellation support is provided in the usual way through the optional
* @a cancel_func and @a cancel_baton.
*
* @a path must point to a directory and @a depth must be at least
* #svn_depth_empty.
*
* Use @a scratch_pool for temporary memory allocation.
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_list(svn_fs_root_t *root,
const char *path,
const apr_array_header_t *patterns,
svn_depth_t depth,
svn_boolean_t path_info_only,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
svn_repos_dirent_receiver_t receiver,
void *receiver_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool);
/**
* Given @a path which exists at revision @a start in @a fs, set
@ -1864,13 +1950,181 @@ svn_repos_node_location_segments(svn_repos_t *repos,
/* Retrieving log messages. */
/** Path change descriptor.
*
* @note Identical to #svn_fs_path_change3_t but with all information
* known, i.e. @a node_kind is never #svn_node_unknown and
* @a copyfrom_known is always @c TRUE.
*
* @note To allow for extending this structure in future releases,
* always use svn_repos_path_change_create() to allocate the stucture.
*
* @see svn_fs_path_change3_t
*
* @since New in 1.10.
*/
typedef svn_fs_path_change3_t svn_repos_path_change_t;
/**
* Invoke @a receiver with @a receiver_baton on each log message from
* @a start to @a end in @a repos's filesystem. @a start may be greater
* or less than @a end; this just controls whether the log messages are
* Return an #svn_repos_path_change_t structure, allocated in @a result_pool,
* with all fields initialized to their respective null/none/empty/invalid
* values.
*
* @note To allow for extending the #svn_repos_path_change_t structure in
* future releases, this function should always be used to allocate it.
*
* @since New in 1.10.
*/
svn_repos_path_change_t *
svn_repos_path_change_create(apr_pool_t *result_pool);
/**
* Return a deep copy of @a change, allocated in @a result_pool.
*
* @since New in 1.10.
*/
svn_repos_path_change_t *
svn_repos_path_change_dup(svn_repos_path_change_t *change,
apr_pool_t *result_pool);
/** The callback invoked by log message loopers, such as
* svn_repos_get_logs5().
*
* This function is invoked once on each changed path, in a potentially
* random order that may even change between invocations for the same
* revisions.
*
* @a baton is what you think it is, and @a change contains relevant
* information for the changed path. Please note that @a change may be
* modified within this callback but it will become invalid as soon as
* the callback returns.
*
* Use @a scratch_pool for temporary allocation. The caller may clear it
* between or after invocations.
*
* @since New in 1.10.
*/
typedef svn_error_t *(*svn_repos_path_change_receiver_t)(
void *baton,
svn_repos_path_change_t *change,
apr_pool_t *scratch_pool);
/**
* A structure to represent all the information about a particular log entry.
*
* @note To allow for extending this structure in future releases,
* always use svn_repos_log_entry_create() to allocate the stucture.
*
* @since New in 1.10.
*/
typedef struct svn_repos_log_entry_t
{
/** The revision of the commit. */
svn_revnum_t revision;
/** The hash of requested revision properties, which may be NULL if it
* would contain no revprops. Maps (const char *) property name to
* (svn_string_t *) property value. */
apr_hash_t *revprops;
/**
* Whether or not this message has children.
*
* When a log operation requests additional merge information, extra log
* entries may be returned as a result of this entry. The new entries, are
* considered children of the original entry, and will follow it. When
* the HAS_CHILDREN flag is set, the receiver should increment its stack
* depth, and wait until an entry is provided with SVN_INVALID_REVNUM which
* indicates the end of the children.
*
* For log operations which do not request additional merge information, the
* HAS_CHILDREN flag is always FALSE.
*
* For more information see:
* https://svn.apache.org/repos/asf/subversion/trunk/notes/merge-tracking/design.html#commutative-reporting
*/
svn_boolean_t has_children;
/**
* Whether @a revision should be interpreted as non-inheritable in the
* same sense of #svn_merge_range_t.
*
* Currently always FALSE.
*/
svn_boolean_t non_inheritable;
/**
* Whether @a revision is a merged revision resulting from a reverse merge.
*/
svn_boolean_t subtractive_merge;
/* NOTE: Add new fields at the end to preserve binary compatibility. */
} svn_repos_log_entry_t;
/**
* Return an #svn_repos_log_entry_t, allocated in @a result_pool,
* with all fields initialized to their respective null/none/empty/invalid
* values.
*
* @note To allow for extending the #svn_repos_log_entry_t structure in
* future releases, this function should always be used to allocate it.
*
* @since New in 1.10.
*/
svn_repos_log_entry_t *
svn_repos_log_entry_create(apr_pool_t *result_pool);
/** Return a deep copy of @a log_entry, allocated in @a result_pool.
*
* @since New in 1.10.
*/
svn_repos_log_entry_t *
svn_repos_log_entry_dup(const svn_repos_log_entry_t *log_entry,
apr_pool_t *result_pool);
/** The callback invoked by log message loopers, such as
* svn_repos_get_logs5().
*
* This function is invoked once on each log message, in the order
* determined by the caller (see above-mentioned functions).
*
* @a baton is what you think it is, and @a log_entry contains relevant
* information for the log message.
*
* If @a log_entry->has_children is @c TRUE, the message will be followed
* immediately by any number of merged revisions (child messages), which are
* terminated by an invocation with SVN_INVALID_REVNUM. This usage may
* be recursive.
*
* Use @a scratch_pool for temporary allocation. The caller may clear it
* between or after invocations.
*
* @since New in 1.10.
*/
typedef svn_error_t *(*svn_repos_log_entry_receiver_t)(
void *baton,
svn_repos_log_entry_t *log_entry,
apr_pool_t *scratch_pool);
/**
* Invoke @a revision_receiver with @a revision_receiver_baton on each
* revision from @a start to @a end in @a repos's filesystem. @a start may
* be greater or less than @a end; this just controls whether the log is
* processed in descending or ascending revision number order.
*
* If not @c NULL, @a path_change_receiver will be invoked with
* @a path_change_receiver_baton for each changed path in the respective
* revision. These changes will be reported before the @a revision_receiver
* is invoked for that revision. So, for each revision in the log, there
* is a number of calls to @a path_change_receiver followed by a single
* invocation of @a revision_receiver, implicitly marking the end of the
* changes list for that revision. If a revision does not contain any
* changes (or if none are visible due to @a authz_read_func),
* @a path_change_receiver will not be called for that revision.
*
* If @a start or @a end is #SVN_INVALID_REVNUM, it defaults to youngest.
*
* If @a paths is non-NULL and has one or more elements, then only show
@ -1881,13 +2135,8 @@ svn_repos_node_location_segments(svn_repos_t *repos,
* show all revisions regardless of what paths were changed in those
* revisions.
*
* If @a limit is greater than zero then only invoke @a receiver on the first
* @a limit logs.
*
* If @a discover_changed_paths, then each call to @a receiver passes a
* hash mapping paths committed in that revision to information about them
* as the receiver's @a changed_paths argument.
* Otherwise, each call to @a receiver passes NULL for @a changed_paths.
* If @a limit is greater than zero then only invoke @a revision_receiver
* on the first @a limit logs.
*
* If @a strict_node_history is set, copy history (if any exists) will
* not be traversed while harvesting revision logs for each path.
@ -1902,28 +2151,64 @@ svn_repos_node_location_segments(svn_repos_t *repos,
* only the revision properties named by the (const char *) array elements
* (i.e. retrieve none if the array is empty).
*
* If any invocation of @a receiver returns error, return that error
* immediately and without wrapping it.
* If any invocation of @a revision_receiver or @a path_change_receiver
* returnn an error, return that error immediately and without wrapping it.
*
* If @a start or @a end is a non-existent revision, return the error
* #SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a receiver.
* #SVN_ERR_FS_NO_SUCH_REVISION, without ever invoking @a revision_receiver.
*
* If optional @a authz_read_func is non-NULL, then use this function
* (along with optional @a authz_read_baton) to check the readability
* of each changed-path in each revision about to be "pushed" at
* @a receiver. If a revision has some changed-paths readable and
* others unreadable, unreadable paths are omitted from the
* changed_paths field and only svn:author and svn:date will be
* available in the revprops field. If a revision has no
* changed-paths readable at all, then all paths are omitted and no
* revprops are available.
* @a path_change_receiver. If a revision has some changed-paths readable
* and others unreadable, unreadable paths are omitted from the
* @a path_change_receiver invocations and only svn:author and svn:date
* will be available in the revprops field in the @a revision_receiver
* callback. If a revision has no changed-paths readable at all, then all
* paths are omitted and no revprops are available. If
* @a path_change_receiver is @c NULL, the same filtering is performed
* just without reporting any path changes.
*
* See also the documentation for #svn_log_entry_receiver_t.
* Use @a scratch_pool for temporary allocations.
*
* Use @a pool for temporary allocations.
* @see svn_repos_path_change_receiver_t, svn_repos_log_entry_receiver_t
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_get_logs5(svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t start,
svn_revnum_t end,
int limit,
svn_boolean_t strict_node_history,
svn_boolean_t include_merged_revisions,
const apr_array_header_t *revprops,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
svn_repos_path_change_receiver_t path_change_receiver,
void *path_change_receiver_baton,
svn_repos_log_entry_receiver_t revision_receiver,
void *revision_receiver_baton,
apr_pool_t *scratch_pool);
/**
* Similar to svn_repos_get_logs5 but using a #svn_log_entry_receiver_t
* @a receiver to receive revision properties and changed paths through a
* single callback and the @a discover_changed_paths flag to control it.
*
* If @a discover_changed_paths, then each call to @a receiver passes a
* hash mapping paths committed in that revision to information about them
* as the receiver's @a changed_paths argument.
* Otherwise, each call to @a receiver passes NULL for @a changed_paths.
*
* @see svn_log_entry_receiver_t
*
* @since New in 1.5.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_get_logs4(svn_repos_t *repos,
const apr_array_header_t *paths,
@ -2009,12 +2294,20 @@ svn_repos_get_logs(svn_repos_t *repos,
/* Retrieving mergeinfo. */
/**
* Fetch the mergeinfo for @a paths at @a revision in @a repos, and
* set @a *catalog to a catalog of this mergeinfo. @a *catalog will
* never be @c NULL but may be empty.
/** Receives parsed @a mergeinfo for the file system path @a path.
*
* The paths in @a paths, and the keys of @a catalog, start with '/'.
* The user-provided @a baton is being passed through by the retrieval
* function and @a scratch_pool will be cleared between invocations.
*
* @since New in 1.10.
*/
typedef svn_fs_mergeinfo_receiver_t svn_repos_mergeinfo_receiver_t;
/**
* For each node found with mergeinfo on it, invoke @a receiver with
* the provided @a receiver_baton.
*
* The paths in @a paths start with '/'.
*
* @a inherit indicates whether explicit, explicit or inherited, or
* only inherited mergeinfo for @a paths is fetched.
@ -2026,17 +2319,38 @@ svn_repos_get_logs(svn_repos_t *repos,
* the #SVN_PROP_MERGEINFO property explicitly set on it. (Note
* that inheritance is only taken into account for the elements in @a
* paths; descendants of the elements in @a paths which get their
* mergeinfo via inheritance are not included in @a *catalog.)
* mergeinfo via inheritance are not reported to @a receiver.)
*
* If optional @a authz_read_func is non-NULL, then use this function
* (along with optional @a authz_read_baton) to check the readability
* of each path which mergeinfo was requested for (from @a paths).
* Silently omit unreadable paths from the request for mergeinfo.
*
* Use @a pool for all allocations.
* Use @a scratch_pool for temporary allocations.
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_fs_get_mergeinfo2(svn_repos_t *repos,
const apr_array_header_t *paths,
svn_revnum_t revision,
svn_mergeinfo_inheritance_t inherit,
svn_boolean_t include_descendants,
svn_repos_authz_func_t authz_read_func,
void *authz_read_baton,
svn_repos_mergeinfo_receiver_t receiver,
void *receiver_baton,
apr_pool_t *scratch_pool);
/**
* Same as svn_repos_fs_get_mergeinfo2(), but all mergeinfo is being collected
* and returned in @a *catalog. It will never be @c NULL, but may be empty.
*
* @since New in 1.5.
*
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_fs_get_mergeinfo(svn_mergeinfo_catalog_t *catalog,
svn_repos_t *repos,
@ -2983,6 +3297,12 @@ svn_repos_verify_fs(svn_repos_t *repos,
* be done with full plain text. A dump with @a use_deltas set cannot
* be loaded by Subversion 1.0.x.
*
* If @a include_revprops is @c TRUE, output the revision properties as
* well, otherwise omit them.
*
* If @a include_changes is @c TRUE, output the revision contents, i.e.
* tree and node changes.
*
* If @a notify_func is not null, then call it with @a notify_baton and
* with a notification structure in which the fields are set as follows.
* (For a warning or error notification that does not apply to a specific
@ -3008,15 +3328,44 @@ svn_repos_verify_fs(svn_repos_t *repos,
* reiterating the existence of previous warnings
* ### This is a presentation issue. Caller could do this itself.
*
* If @a filter_func is not @c NULL, it is called for each node being
* dumped, allowing the caller to exclude it from dump.
*
* If @a cancel_func is not @c NULL, it is called periodically with
* @a cancel_baton as argument to see if the client wishes to cancel
* the dump.
*
* Use @a scratch_pool for temporary allocation.
*
* @since New in 1.7.
* @since New in 1.10.
*/
svn_error_t *
svn_repos_dump_fs4(svn_repos_t *repos,
svn_stream_t *stream,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t incremental,
svn_boolean_t use_deltas,
svn_boolean_t include_revprops,
svn_boolean_t include_changes,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_repos_dump_filter_func_t filter_func,
void *filter_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool);
/**
* Similar to svn_repos_dump_fs4(), but with @a include_revprops and
* @a include_changes both set to @c TRUE and @a filter_func and
* @a filter_baton set to @c NULL.
*
* @since New in 1.7.
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_dump_fs3(svn_repos_t *repos,
svn_stream_t *dumpstream,
svn_revnum_t start_rev,
@ -3111,6 +3460,15 @@ svn_repos_dump_fs(svn_repos_t *repos,
* to be stamped as if they were newly created via the normal commit
* process.
*
* If @a normalize_props is set, attempt to normalize invalid Subversion
* revision and node properties (those in the svn: namespace) so that
* their values would follow the established rules for them. For example,
* for such properties, typically the value must be in UTF-8 with LF
* line endings.
*
* @note The details or the performed normalizations are deliberately
* left unspecified and may change in the future.
*
* If non-NULL, use @a notify_func and @a notify_baton to send notification
* of events to the caller.
*
@ -3118,9 +3476,35 @@ svn_repos_dump_fs(svn_repos_t *repos,
* @a cancel_baton as argument to see if the client wishes to cancel
* the load.
*
* @since New in 1.9.
* @since New in 1.10.
*/
svn_error_t *
svn_repos_load_fs6(svn_repos_t *repos,
svn_stream_t *dumpstream,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
svn_boolean_t use_pre_commit_hook,
svn_boolean_t use_post_commit_hook,
svn_boolean_t validate_props,
svn_boolean_t ignore_dates,
svn_boolean_t normalize_props,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *pool);
/**
* Similar to svn_repos_load_fs6(), but with the @a normalize_props
* parameter always set to @c FALSE.
*
* @since New in 1.9.
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_load_fs5(svn_repos_t *repos,
svn_stream_t *dumpstream,
svn_revnum_t start_rev,
@ -3219,6 +3603,62 @@ svn_repos_load_fs(svn_repos_t *repos,
void *cancel_baton,
apr_pool_t *pool);
/**
* Read and parse dumpfile-formatted @a dumpstream, extracting the
* revision properties from it and apply them to the already-open
* @a repos. Use @a scratch_pool for temporary allocations.
*
* If, after filtering by the @a start_rev and @a end_rev, the dumpstream
* contains revisions missing in @a repos, an error will be thrown.
*
* @a start_rev and @a end_rev act as filters, the lower and upper
* (inclusive) range values of revisions in @a dumpstream which will
* be loaded. Either both of these values are #SVN_INVALID_REVNUM (in
* which case no revision-based filtering occurs at all), or both are
* valid revisions (where @a start_rev is older than or equivalent to
* @a end_rev).
*
* If @a validate_props is set, then validate Subversion revision
* properties (those in the svn: namespace) against established
* rules for those things.
*
* If @a ignore_dates is set, ignore any revision datestamps found in
* @a dumpstream, keeping whatever timestamps the revisions currently
* have.
*
* If @a normalize_props is set, attempt to normalize invalid Subversion
* revision and node properties (those in the svn: namespace) so that
* their values would follow the established rules for them. For example,
* for such properties, typically the value must be in UTF-8 with LF
* line endings.
*
* @note The details or the performed normalizations are deliberately
* left unspecified and may change in the future.
*
* If non-NULL, use @a notify_func and @a notify_baton to send notification
* of events to the caller.
*
* If @a cancel_func is not @c NULL, it is called periodically with
* @a cancel_baton as argument to see if the client wishes to cancel
* the load.
*
* @remark No repository hooks will be triggered.
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_load_fs_revprops(svn_repos_t *repos,
svn_stream_t *dumpstream,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t validate_props,
svn_boolean_t ignore_dates,
svn_boolean_t normalize_props,
svn_repos_notify_func_t notify_func,
void *notify_baton,
svn_cancel_func_t cancel_func,
void *cancel_baton,
apr_pool_t *scratch_pool);
/**
* A vtable that is driven by svn_repos_parse_dumpstream3().
@ -3362,6 +3802,9 @@ typedef struct svn_repos_parse_fns3_t
* could stop reading entirely after the youngest required rev.
*
* @since New in 1.8.
* @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 *
svn_repos_parse_dumpstream3(svn_stream_t *stream,
@ -3414,13 +3857,48 @@ svn_repos_parse_dumpstream3(svn_stream_t *stream,
* to be stamped as if they were newly created via the normal commit
* process.
*
* If @a normalize_props is set, attempt to normalize invalid Subversion
* revision and node properties (those in the svn: namespace) so that
* their values would follow the established rules for them. For example,
* for such properties, typically the value must be in UTF-8 with LF
* line endings.
*
* @note The details or the performed normalizations are deliberately
* left unspecified and may change in the future.
*
* If @a parent_dir is not NULL, then the parser will reparent all the
* loaded nodes, from root to @a parent_dir. The directory @a parent_dir
* must be an existing directory in the repository.
*
* @since New in 1.9.
* @since New in 1.10.
*/
svn_error_t *
svn_repos_get_fs_build_parser6(const svn_repos_parse_fns3_t **parser,
void **parse_baton,
svn_repos_t *repos,
svn_revnum_t start_rev,
svn_revnum_t end_rev,
svn_boolean_t use_history,
svn_boolean_t validate_props,
enum svn_repos_load_uuid uuid_action,
const char *parent_dir,
svn_boolean_t use_pre_commit_hook,
svn_boolean_t use_post_commit_hook,
svn_boolean_t ignore_dates,
svn_boolean_t normalize_props,
svn_repos_notify_func_t notify_func,
void *notify_baton,
apr_pool_t *pool);
/**
* Similar to svn_repos_get_fs_build_parser6(), but with the
* @a normalize_props parameter always set to @c FALSE.
*
* @since New in 1.9.
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_get_fs_build_parser5(const svn_repos_parse_fns3_t **parser,
void **parse_baton,
svn_repos_t *repos,
@ -3654,6 +4132,17 @@ svn_repos_get_fs_build_parser(const svn_repos_parser_fns_t **parser,
*/
typedef struct svn_authz_t svn_authz_t;
/**
* This should be called before any other authz function.
*
* @a pool must support multi-threaded access if the application will use
* authz from multiple threads.
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_authz_initialize(apr_pool_t *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.
@ -3667,9 +4156,30 @@ typedef struct svn_authz_t svn_authz_t;
* is also an error other than #SVN_ERR_AUTHZ_INVALID_CONFIG (exact error
* depends on the access type).
*
* @since New in 1.8.
* For efficient access of in-repository authz, you may provide @a repos_hint
* which will be tried first and may remove the need to open a temporary
* repository instance. Otherwise, set it to NULL and the repositories will
* be opened as needed.
*
* @since New in 1.10.
*/
svn_error_t *
svn_repos_authz_read3(svn_authz_t **authz_p,
const char *path,
const char *groups_path,
svn_boolean_t must_exist,
svn_repos_t *repos_hint,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/**
* Similar to svn_repos_authz_read3(), but with @a repos_hint set to @c NULL.
*
* @since New in 1.8.
* @deprecated Provided for backward compatibility with the 1.9 API.
*/
SVN_DEPRECATED
svn_error_t *
svn_repos_authz_read2(svn_authz_t **authz_p,
const char *path,
const char *groups_path,

View File

@ -294,6 +294,14 @@ svn_stringbuf_isempty(const svn_stringbuf_t *str);
void
svn_stringbuf_chop(svn_stringbuf_t *str, apr_size_t nbytes);
/**
* Chop @a nbytes bytes off the start of @a str, but not more than @a str->len.
*
* @since New in 1.10.
*/
void
svn_stringbuf_leftchop(svn_stringbuf_t *str, apr_size_t nbytes);
/** Fill @a str with character @a c. */
void
svn_stringbuf_fillchar(svn_stringbuf_t *str, unsigned char c);
@ -404,6 +412,16 @@ svn_stringbuf_replace(svn_stringbuf_t *str,
const char *bytes,
apr_size_t new_count);
/** Replace all occurrences of @a to_find in @a str with @a replacement.
* Return the number of replacements made.
*
* @since New in 1.10.
*/
apr_size_t
svn_stringbuf_replace_all(svn_stringbuf_t *str,
const char *to_find,
const char *replacement);
/** Return a duplicate of @a original_string. */
svn_stringbuf_t *
svn_stringbuf_dup(const svn_stringbuf_t *original_string, apr_pool_t *pool);
@ -512,12 +530,27 @@ svn_cstring_count_newlines(const char *msg);
/**
* Return a cstring which is the concatenation of @a strings (an array
* of char *) each followed by @a separator (that is, @a separator
* will also end the resulting string). Allocate the result in @a pool.
* of char *) joined by @a separator. Allocate the result in @a pool.
* If @a strings is empty, then return the empty string.
* If @a trailing_separator is non-zero, also append the separator
* after the last joined element.
*
* @since New in 1.10.
*/
char *
svn_cstring_join2(const apr_array_header_t *strings,
const char *separator,
svn_boolean_t trailing_separator,
apr_pool_t *pool);
/**
* Similar to svn_cstring_join2(), but always includes the trailing
* separator.
*
* @since New in 1.2.
* @deprecated Provided for backwards compatibility with the 1.9 API.
*/
SVN_DEPRECATED
char *
svn_cstring_join(const apr_array_header_t *strings,
const char *separator,
@ -541,7 +574,17 @@ svn_cstring_casecmp(const char *str1, const char *str2);
* Assume that the number is represented in base @a base.
* Raise an error if conversion fails (e.g. due to overflow), or if the
* converted number is smaller than @a minval or larger than @a maxval.
*
* Leading whitespace in @a str is skipped in a locale-dependent way.
* After that, the string may contain an optional '+' (positive, default)
* or '-' (negative) character, followed by an optional '0x' prefix if
* @a base is 0 or 16, followed by numeric digits appropriate for the base.
* If there are any more characters after the numeric digits, an error is
* returned.
*
* If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal,
* else a leading '0' means octal (implemented, though not documented, in
* apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten.
*
* @since New in 1.7.
*/
@ -554,7 +597,8 @@ svn_cstring_strtoi64(apr_int64_t *n, const char *str,
* Parse the C string @a str into a 64 bit number, and return it in @a *n.
* Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
* Leading whitespace in @a str is skipped in a locale-dependent way.
*
* The behaviour otherwise is as described for svn_cstring_strtoi64().
*
* @since New in 1.7.
*/
@ -565,7 +609,8 @@ svn_cstring_atoi64(apr_int64_t *n, const char *str);
* Parse the C string @a str into a 32 bit number, and return it in @a *n.
* Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
* Leading whitespace in @a str is skipped in a locale-dependent way.
*
* The behaviour otherwise is as described for svn_cstring_strtoi64().
*
* @since New in 1.7.
*/
@ -577,7 +622,21 @@ svn_cstring_atoi(int *n, const char *str);
* it in @a *n. Assume that the number is represented in base @a base.
* Raise an error if conversion fails (e.g. due to overflow), or if the
* converted number is smaller than @a minval or larger than @a maxval.
*
* Leading whitespace in @a str is skipped in a locale-dependent way.
* After that, the string may contain an optional '+' (positive, default)
* or '-' (negative) character, followed by an optional '0x' prefix if
* @a base is 0 or 16, followed by numeric digits appropriate for the base.
* If there are any more characters after the numeric digits, an error is
* returned.
*
* If @a base is zero, then a leading '0x' or '0X' prefix means hexadecimal,
* else a leading '0' means octal (implemented, though not documented, in
* apr_strtoi64() in APR 0.9.0 through 1.5.0), else use base ten.
*
* @warning The implementation used since version 1.7 returns an error
* if the parsed number is greater than APR_INT64_MAX, even if it is not
* greater than @a maxval.
*
* @since New in 1.7.
*/
@ -590,7 +649,9 @@ svn_cstring_strtoui64(apr_uint64_t *n, const char *str,
* Parse the C string @a str into an unsigned 64 bit number, and return
* it in @a *n. Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
* Leading whitespace in @a str is skipped in a locale-dependent way.
*
* The behaviour otherwise is as described for svn_cstring_strtoui64(),
* including the upper limit of APR_INT64_MAX.
*
* @since New in 1.7.
*/
@ -601,7 +662,9 @@ svn_cstring_atoui64(apr_uint64_t *n, const char *str);
* Parse the C string @a str into an unsigned 32 bit number, and return
* it in @a *n. Assume that the number is represented in base 10.
* Raise an error if conversion fails (e.g. due to overflow).
* Leading whitespace in @a str is skipped in a locale-dependent way.
*
* The behaviour otherwise is as described for svn_cstring_strtoui64(),
* including the upper limit of APR_INT64_MAX.
*
* @since New in 1.7.
*/

View File

@ -416,7 +416,7 @@ svn_tristate__from_word(const char * word);
* 2. Creating a new textual name similar to
* SVN_SUBST__SPECIAL_LINK_STR in libsvn_subr/subst.c.
* 3. Handling the translation/detranslation case for the new type in
* create_special_file and detranslate_special_file, using the
* create_special_file_from_stream and detranslate_special_file, using the
* routines from 1.
*/
@ -652,7 +652,7 @@ typedef struct svn_dirent_t
/** node kind */
svn_node_kind_t kind;
/** length of file text, or 0 for directories */
/** length of file text, otherwise SVN_INVALID_FILESIZE */
svn_filesize_t size;
/** does the node have props? */
@ -1078,6 +1078,11 @@ typedef svn_error_t *(*svn_log_message_receiver_t)(
* @a commit_info, along with the @a baton closure.
* @a pool can be used for temporary allocations.
*
* @note Implementers of this callback that pass this callback to
* svn_ra_get_commit_editor3() should be careful with returning errors
* as these might be returned as commit errors. See the documentation
* of svn_ra_get_commit_editor3() for more details.
*
* @since New in 1.4.
*/
typedef svn_error_t *(*svn_commit_callback2_t)(

View File

@ -45,6 +45,9 @@ svn_user_get_name(apr_pool_t *pool);
* any necessary allocation, returning NULL on error.
*
* @since New in 1.4.
* @since 1.10 returns a canonical path. Earlier versions returned a
* non-canonical path if the operating system reported a non-canonical
* path such as "/home/user/" or "//home/user".
*/
const char *
svn_user_get_homedir(apr_pool_t *pool);

View File

@ -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 9
#define SVN_VER_MINOR 10
/**
* Patch number.
@ -70,7 +70,7 @@ extern "C" {
*
* @since New in 1.1.
*/
#define SVN_VER_PATCH 7
#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 " (r1800392)"
#define SVN_VER_TAG " (r1827917)"
/** 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 1800392
#define SVN_VER_REVISION 1827917
/* Version strings composed from the above definitions. */

View File

@ -998,7 +998,10 @@ typedef enum svn_wc_notify_action_t
/** A revert operation has failed. */
svn_wc_notify_failed_revert,
/** Resolving a conflict. */
/** All conflicts on a path were marked as resolved.
* @note As of 1.10, separate notifications are sent for individually
* resolved text, property, and tree conflicts. This notification is used
* only if all conflicts on a path were marked resolved at once. */
svn_wc_notify_resolved,
/** Skipping a path. */
@ -1274,7 +1277,34 @@ typedef enum svn_wc_notify_action_t
/** Finalizing commit.
* @since New in 1.9. */
svn_wc_notify_commit_finalizing
svn_wc_notify_commit_finalizing,
/** All text conflicts in a file were marked as resolved.
* @since New in 1.10. */
svn_wc_notify_resolved_text,
/** A property conflict on a path was marked as resolved.
* The name of the property is specified in #svn_wc_notify_t.prop_name.
* @since New in 1.10. */
svn_wc_notify_resolved_prop,
/** A tree conflict on a path was marked as resolved.
* @since New in 1.10. */
svn_wc_notify_resolved_tree,
/** Starting to search the repository for details about a tree conflict.
* @since New in 1.10. */
svn_wc_notify_begin_search_tree_conflict_details,
/** Progressing in search of repository for details about a tree conflict.
* The revision being searched is specified in #svn_wc_notify_t.revision.
* @since New in 1.10. */
svn_wc_notify_tree_conflict_details_progress,
/** Done searching the repository for details about a conflict.
* @since New in 1.10. */
svn_wc_notify_end_search_tree_conflict_details
} svn_wc_notify_action_t;
@ -1911,8 +1941,9 @@ typedef struct svn_wc_conflict_description_t
/** The path that is in conflict (for a tree conflict, it is the victim) */
const char *path;
/** The node type of the path being operated on (for a tree conflict,
* ### which version?) */
/** The local node type of the path being operated on (for a tree conflict,
* this specifies the local node kind, which may be (and typically is)
* different than the left and right kind) */
svn_node_kind_t node_kind;
/** What sort of conflict are we describing? */
@ -2063,7 +2094,7 @@ svn_wc_conflict_description_create_prop(const char *path,
*
* Set the @c local_abspath field of the created struct to @a local_abspath
* (which must be an absolute path), the @c kind field to
* #svn_wc_conflict_kind_tree, the @c local_node_kind to @a local_node_kind,
* #svn_wc_conflict_kind_tree, the @c node_kind to @a node_kind,
* the @c operation to @a operation, the @c src_left_version field to
* @a src_left_version, and the @c src_right_version field to
* @a src_right_version.
@ -2131,8 +2162,11 @@ svn_wc__conflict_description2_dup(
*/
typedef enum svn_wc_conflict_choice_t
{
/** Undefined; for internal use only.
This value is never returned in svn_wc_conflict_result_t.
/** Undefined; for private use only.
This value must never be returned in svn_wc_conflict_result_t,
but a separate value, unequal to all other pre-defined values may
be useful in conflict resolver implementations to signal that no
choice is made yet.
* @since New in 1.9
*/
svn_wc_conflict_choose_undefined = -1,
@ -4544,7 +4578,7 @@ svn_wc_move(svn_wc_context_t *wc_ctx,
* and everything below @a local_abspath.
*
* If @a keep_local is FALSE, this function immediately deletes all files,
* modified and unmodified, versioned and of @a delete_unversioned is TRUE,
* modified and unmodified, versioned and if @a delete_unversioned is TRUE,
* unversioned from the working copy.
* It also immediately deletes unversioned directories and directories that
* are scheduled to be added below @a local_abspath. Only versioned may
@ -5050,7 +5084,11 @@ svn_wc_remove_from_revision_control(svn_wc_adm_access_t *adm_access,
* Temporary allocations will be performed in @a scratch_pool.
*
* @since New in 1.7.
* @deprecated Provided for backward compatibility with the 1.9 API.
* Use svn_client_conflict_text_resolve(), svn_client_conflict_prop_resolve(),
* and svn_client_conflict_tree_resolve() instead.
*/
SVN_DEPRECATED
svn_error_t *
svn_wc_resolved_conflict5(svn_wc_context_t *wc_ctx,
const char *local_abspath,

View File

@ -166,7 +166,7 @@ svn_x509_certinfo_get_valid_from(const svn_x509_certinfo_t *certinfo);
*
* @since New in 1.9.
*/
const apr_time_t
apr_time_t
svn_x509_certinfo_get_valid_to(const svn_x509_certinfo_t *certinfo);
/**
@ -188,7 +188,7 @@ svn_x509_certinfo_get_hostnames(const svn_x509_certinfo_t *certinfo);
* Given an @a oid return a null-terminated C string representation.
* For example an OID with the bytes "\x2A\x86\x48\x86\xF7\x0D\x01\x09\x01"
* would be converted to the string "1.2.840.113549.1.9.1". Returns
* NULL if the @oid can't be represented as a string.
* NULL if the @a oid can't be represented as a string.
*
* @since New in 1.9. */
const char *

View File

@ -169,7 +169,15 @@ typedef void (*svn_xml_char_data)(void *baton,
apr_size_t len);
/** Create a general Subversion XML parser */
/** Create a general Subversion XML parser.
*
* The @c svn_xml_parser_t object itself will be allocated from @a pool,
* but some internal structures may be allocated out of pool. Use
* svn_xml_free_parser() to free all memory used by the parser.
*
* @since Since Subversion 1.10 parser will be freed automatically on pool
* cleanup or by svn_xml_free_parser() call.
*/
svn_xml_parser_t *
svn_xml_make_parser(void *baton,
svn_xml_start_elem start_handler,

View File

@ -23,31 +23,169 @@
/* ==================================================================== */
/*** Includes. ***/
#include <apr_pools.h>
#include <apr_strings.h>
#include <glib.h>
#include <gnome-keyring.h>
#include "svn_auth.h"
#include "svn_config.h"
#include "svn_error.h"
#include "svn_hash.h"
#include "svn_pools.h"
#include "svn_version.h"
#include "private/svn_auth_private.h"
#include "svn_private_config.h"
#ifdef SVN_HAVE_LIBSECRET
/*-----------------------------------------------------------------------*/
/* GNOME Keyring simple provider, puts passwords in GNOME Keyring */
/*-----------------------------------------------------------------------*/
#include <libsecret/secret.h>
/* Return TRUE if the default collection is available and FALSE
otherwise. In interactive mode the collection only has to exist to
be available, it can be locked or unlocked. The default collection
will be created if necessary.
In non-interactive mode the collection is only available if it
already exists and is unlocked. Such an available collection can
be used without prompting. Strictly this is racy: nothing ensures
the collection remains unlocked. A similar issue affects the
KWallet and original GNOME Keyring providers.
As a non-racy alternative one could override prompt_async in the
_SecretServiceClass vtable, the get/set would still fail but there
would be no prompt and no race. This "works" but it is not clear
to me whether it is legitimate since the SecretService is a
singleton and the effect would be application-wide.
*/
static svn_boolean_t
available_collection(svn_boolean_t non_interactive,
apr_pool_t *pool)
{
GError *gerror = NULL;
SecretService *service = NULL;
SecretCollection *collection = NULL;
service = secret_service_get_sync(SECRET_SERVICE_NONE, NULL, &gerror);
if (gerror || !service)
goto error_return;
collection = secret_collection_for_alias_sync(service,
SECRET_COLLECTION_DEFAULT,
SECRET_COLLECTION_NONE,
NULL, &gerror);
if (gerror)
goto error_return;
if (!collection)
{
if (non_interactive)
goto error_return;
/* "Default" is the label used by the old libgnome-keyring. */
collection = secret_collection_create_sync(service, "Default",
SECRET_COLLECTION_DEFAULT,
0, NULL, &gerror);
if (gerror || !collection)
goto error_return;
}
if (non_interactive && secret_collection_get_locked(collection))
goto error_return;
g_object_unref(collection);
g_object_unref(service);
return TRUE;
error_return:
if (gerror)
g_error_free(gerror);
if (collection)
g_object_unref(collection);
if (service)
g_object_unref(service);
return FALSE;
}
/* Implementation of svn_auth__password_get_t that retrieves the password
using libsecret. */
static svn_error_t *
password_get_gnome_keyring(svn_boolean_t *done,
const char **password,
apr_hash_t *creds,
const char *realmstring,
const char *username,
apr_hash_t *parameters,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
GError *gerror = NULL;
gchar *gpassword;
if (!available_collection(non_interactive, pool))
return SVN_NO_ERROR;
gpassword = secret_password_lookup_sync(SECRET_SCHEMA_COMPAT_NETWORK, NULL,
&gerror,
"domain", realmstring,
"user", username,
NULL);
if (gerror)
{
g_error_free(gerror);
}
else if (gpassword)
{
*password = apr_pstrdup(pool, gpassword);
g_free(gpassword);
*done = TRUE;
}
return SVN_NO_ERROR;
}
/* Implementation of svn_auth__password_set_t that stores the password
using libsecret. */
static svn_error_t *
password_set_gnome_keyring(svn_boolean_t *done,
apr_hash_t *creds,
const char *realmstring,
const char *username,
const char *password,
apr_hash_t *parameters,
svn_boolean_t non_interactive,
apr_pool_t *pool)
{
GError *gerror = NULL;
gboolean gstatus;
if (!available_collection(non_interactive, pool))
return SVN_NO_ERROR;
/* "network password" is the label used by the old libgnome-keyring. */
gstatus = secret_password_store_sync(SECRET_SCHEMA_COMPAT_NETWORK,
SECRET_COLLECTION_DEFAULT,
"network password",
password,
NULL, &gerror,
"domain", realmstring,
"user", username,
NULL);
if (gerror)
{
g_error_free(gerror);
}
else if (gstatus)
{
*done = TRUE;
}
return SVN_NO_ERROR;
}
#endif /* SVN_HAVE_LIBSECRET */
#ifdef SVN_HAVE_GNOME_KEYRING
#include <glib.h>
#include <gnome-keyring.h>
/* Returns the default keyring name, allocated in RESULT_POOL. */
static char*
@ -252,6 +390,41 @@ password_set_gnome_keyring(svn_boolean_t *done,
return SVN_NO_ERROR;
}
#if GLIB_CHECK_VERSION(2,6,0)
static void
log_noop(const gchar *log_domain, GLogLevelFlags log_level,
const gchar *message, gpointer user_data)
{
/* do nothing */
}
#endif
static void
init_gnome_keyring(void)
{
const char *application_name = NULL;
application_name = g_get_application_name();
if (!application_name)
g_set_application_name("Subversion");
/* Ideally we call g_log_set_handler() with a log_domain specific to
libgnome-keyring. Unfortunately, at least as of gnome-keyring
2.22.3, it doesn't have its own log_domain. As a result, we
suppress stderr spam for not only libgnome-keyring, but for
anything else the app is linked to that uses glib logging and
doesn't specify a log_domain. */
#if GLIB_CHECK_VERSION(2,6,0)
g_log_set_default_handler(log_noop, NULL);
#endif
}
#endif /* SVN_HAVE_GNOME_KEYRING */
/*-----------------------------------------------------------------------*/
/* GNOME Keyring simple provider, puts passwords in GNOME Keyring */
/*-----------------------------------------------------------------------*/
/* Get cached encrypted credentials from the simple provider's cache. */
static svn_error_t *
simple_gnome_keyring_first_creds(void **credentials,
@ -286,34 +459,6 @@ simple_gnome_keyring_save_creds(svn_boolean_t *saved,
pool);
}
#if GLIB_CHECK_VERSION(2,6,0)
static void
log_noop(const gchar *log_domain, GLogLevelFlags log_level,
const gchar *message, gpointer user_data)
{
/* do nothing */
}
#endif
static void
init_gnome_keyring(void)
{
const char *application_name = NULL;
application_name = g_get_application_name();
if (!application_name)
g_set_application_name("Subversion");
/* Ideally we call g_log_set_handler() with a log_domain specific to
libgnome-keyring. Unfortunately, at least as of gnome-keyring
2.22.3, it doesn't have its own log_domain. As a result, we
suppress stderr spam for not only libgnome-keyring, but for
anything else the app is linked to that uses glib logging and
doesn't specify a log_domain. */
#if GLIB_CHECK_VERSION(2,6,0)
g_log_set_default_handler(log_noop, NULL);
#endif
}
static const svn_auth_provider_t gnome_keyring_simple_provider = {
SVN_AUTH_CRED_SIMPLE,
simple_gnome_keyring_first_creds,
@ -332,9 +477,12 @@ svn_auth_get_gnome_keyring_simple_provider
po->vtable = &gnome_keyring_simple_provider;
*provider = po;
#ifdef SVN_HAVE_GNOME_KEYRING
init_gnome_keyring();
#endif
}
/*-----------------------------------------------------------------------*/
/* GNOME Keyring SSL client certificate passphrase provider, */
@ -391,5 +539,7 @@ svn_auth_get_gnome_keyring_ssl_client_cert_pw_provider
po->vtable = &gnome_keyring_ssl_client_cert_pw_provider;
*provider = po;
#ifdef SVN_HAVE_GNOME_KEYRING
init_gnome_keyring();
#endif
}

View File

@ -39,8 +39,6 @@
#include <QtCore/QString>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kcomponentdata.h>
#include <klocalizedstring.h>
#include <kwallet.h>
@ -57,6 +55,10 @@
#include "svn_private_config.h"
#ifndef SVN_HAVE_KF5
#include <kcmdlineargs.h>
#include <kcomponentdata.h>
#endif
/*-----------------------------------------------------------------------*/
/* KWallet simple provider, puts passwords in KWallet */
@ -221,6 +223,16 @@ kwallet_password_get(svn_boolean_t *done,
app = new QCoreApplication(argc, q_argv);
}
#if SVN_HAVE_KF5
KLocalizedString::setApplicationDomain("subversion"); /* translation domain */
/* componentName appears in KDE GUI prompts */
KAboutData aboutData(QStringLiteral("subversion"), /* componentName */
i18n(get_application_name(parameters,
pool)), /* displayName */
QStringLiteral(SVN_VER_NUMBER));
KAboutData::setApplicationData(aboutData);
#else
KCmdLineArgs::init(q_argc, q_argv,
get_application_name(parameters, pool),
"subversion",
@ -229,6 +241,8 @@ kwallet_password_get(svn_boolean_t *done,
ki18n("Version control system"),
KCmdLineArgs::CmdLineArgKDE);
KComponentData component_data(KCmdLineArgs::aboutData());
#endif
QString folder = QString::fromUtf8("Subversion");
QString key =
QString::fromUtf8(username) + "@" + QString::fromUtf8(realmstring);
@ -291,6 +305,16 @@ kwallet_password_set(svn_boolean_t *done,
app = new QCoreApplication(argc, q_argv);
}
#if SVN_HAVE_KF5
KLocalizedString::setApplicationDomain("subversion"); /* translation domain */
/* componentName appears in KDE GUI prompts */
KAboutData aboutData(QStringLiteral("subversion"), /* componentName */
i18n(get_application_name(parameters,
pool)), /* displayName */
QStringLiteral(SVN_VER_NUMBER));
KAboutData::setApplicationData(aboutData);
#else
KCmdLineArgs::init(q_argc, q_argv,
get_application_name(parameters, pool),
"subversion",
@ -299,6 +323,8 @@ kwallet_password_set(svn_boolean_t *done,
ki18n("Version control system"),
KCmdLineArgs::CmdLineArgKDE);
KComponentData component_data(KCmdLineArgs::aboutData());
#endif
QString q_password = QString::fromUtf8(password);
QString folder = QString::fromUtf8("Subversion");
KWallet::Wallet *wallet = get_wallet(wallet_name, parameters);

View File

@ -81,6 +81,7 @@ svn_client__checkout_internal(svn_revnum_t *result_rev,
{
svn_node_kind_t kind;
svn_client__pathrev_t *pathrev;
svn_opt_revision_t resolved_rev = { svn_opt_revision_number };
/* Sanity check. Without these, the checkout is meaningless. */
SVN_ERR_ASSERT(local_abspath != NULL);
@ -125,6 +126,7 @@ svn_client__checkout_internal(svn_revnum_t *result_rev,
}
SVN_ERR(svn_ra_check_path(ra_session, "", pathrev->rev, &kind, scratch_pool));
resolved_rev.value.number = pathrev->rev;
if (kind == svn_node_none)
return svn_error_createf(SVN_ERR_RA_ILLEGAL_URL, NULL,
@ -185,8 +187,8 @@ svn_client__checkout_internal(svn_revnum_t *result_rev,
/* Have update fix the incompleteness. */
SVN_ERR(svn_client__update_internal(result_rev, timestamp_sleep,
local_abspath, revision, depth, TRUE,
ignore_externals,
local_abspath, &resolved_rev, depth,
TRUE, ignore_externals,
allow_unver_obstructions,
TRUE /* adds_as_modification */,
FALSE, FALSE, ra_session,

View File

@ -1072,9 +1072,13 @@ svn_client__ensure_revprop_table(apr_hash_t **revprop_table_out,
EXPAND_KEYWORDS operates as per the EXPAND argument to
svn_subst_stream_translated, which see. If NORMALIZE_EOLS is TRUE and
LOCAL_ABSPATH requires translation, then normalize the line endings in
*NORMAL_STREAM.
*NORMAL_STREAM to "\n" if the stream has svn:eol-style set.
Uses SCRATCH_POOL for temporary allocations. */
Note that this IS NOT the repository normal form of the stream as that
would use "\r\n" if set to CRLF and "\r" if set to CR.
The stream is allocated in RESULT_POOL and temporary SCRATCH_POOL is
used for temporary allocations. */
svn_error_t *
svn_client__get_normalized_stream(svn_stream_t **normal_stream,
svn_wc_context_t *wc_ctx,
@ -1181,6 +1185,88 @@ svn_client__remote_propget(apr_hash_t *props,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* */
typedef struct merge_source_t
{
/* "left" side URL and revision (inclusive iff youngest) */
const svn_client__pathrev_t *loc1;
/* "right" side URL and revision (inclusive iff youngest) */
const svn_client__pathrev_t *loc2;
/* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */
svn_boolean_t ancestral;
} merge_source_t;
/* Description of the merge target root node (a WC working node) */
typedef struct merge_target_t
{
/* Absolute path to the WC node */
const char *abspath;
/* The repository location of the base node of the target WC. If the node
* is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM.
* REPOS_ROOT_URL and REPOS_UUID are always valid. */
svn_client__pathrev_t loc;
} merge_target_t;
/*
* Similar API to svn_client_merge_peg5().
*/
svn_error_t *
svn_client__merge_elements(svn_boolean_t *use_sleep,
apr_array_header_t *merge_sources,
merge_target_t *target,
svn_ra_session_t *ra_session,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t dry_run,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
/* Data for reporting when a merge aborted because of raising conflicts.
*
* ### TODO: More info, including the ranges (or other parameters) the user
* needs to complete the merge.
*/
typedef struct svn_client__conflict_report_t
{
const char *target_abspath;
/* The revision range during which conflicts were raised */
const merge_source_t *conflicted_range;
/* Was the conflicted range the last range in the whole requested merge? */
svn_boolean_t was_last_range;
} svn_client__conflict_report_t;
/* Create and return an error structure appropriate for the unmerged
revisions range(s). */
svn_error_t *
svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report,
apr_pool_t *scratch_pool);
/* The body of svn_client_merge5(), which see for details. */
svn_error_t *
svn_client__merge_locked(svn_client__conflict_report_t **conflict_report,
const char *source1,
const svn_opt_revision_t *revision1,
const char *source2,
const svn_opt_revision_t *revision2,
const char *target_abspath,
svn_depth_t depth,
svn_boolean_t ignore_mergeinfo,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t record_only,
svn_boolean_t dry_run,
svn_boolean_t allow_mixed_rev,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool);
#ifdef __cplusplus
}
#endif /* __cplusplus */

File diff suppressed because it is too large Load Diff

View File

@ -1711,13 +1711,9 @@ repos_to_repos_copy(const apr_array_header_t *copy_pairs,
SVN_ERR(svn_ra_check_path(ra_session, dst_rel, SVN_INVALID_REVNUM,
&dst_kind, pool));
if (dst_kind != svn_node_none)
{
const char *path = svn_uri_skip_ancestor(repos_root,
pair->dst_abspath_or_url,
pool);
return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
_("Path '/%s' already exists"), path);
}
return svn_error_createf(SVN_ERR_FS_ALREADY_EXISTS, NULL,
_("Path '%s' already exists"),
pair->dst_abspath_or_url);
/* More info for our INFO structure. */
info->src_path = src_rel; /* May be NULL, if outside RA session scope */
@ -2433,10 +2429,10 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
*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. */
/* 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,
@ -2451,7 +2447,7 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
pool));
/* Move the temporary disk tree into place. */
SVN_ERR(svn_io_file_rename(tmp_abspath, dst_abspath, pool));
SVN_ERR(svn_io_file_rename2(tmp_abspath, dst_abspath, FALSE, pool));
}
else
{
@ -2580,7 +2576,7 @@ repos_to_wc_copy_single(svn_boolean_t *timestamp_sleep,
static svn_error_t *
repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
const apr_array_header_t *copy_pairs,
const char *top_dst_path,
const char *top_dst_abspath,
svn_boolean_t ignore_externals,
svn_boolean_t pin_externals,
const apr_hash_t *externals_to_pin,
@ -2600,39 +2596,25 @@ repos_to_wc_copy_locked(svn_boolean_t *timestamp_sleep,
/* Decide whether the two repositories are the same or not. */
{
svn_error_t *src_err, *dst_err;
const char *parent;
const char *parent_abspath;
const char *src_uuid, *dst_uuid;
/* Get the repository uuid of SRC_URL */
src_err = svn_ra_get_uuid2(ra_session, &src_uuid, iterpool);
if (src_err && src_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
return svn_error_trace(src_err);
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 = svn_dirent_dirname(top_dst_path, scratch_pool);
parent_abspath = svn_dirent_dirname(top_dst_abspath, scratch_pool);
else
parent = top_dst_path;
parent_abspath = top_dst_abspath;
SVN_ERR(svn_dirent_get_absolute(&parent_abspath, parent, scratch_pool));
dst_err = svn_client_get_repos_root(NULL /* root_url */, &dst_uuid,
parent_abspath, ctx,
iterpool, iterpool);
if (dst_err && dst_err->apr_err != SVN_ERR_RA_NO_REPOS_UUID)
return dst_err;
/* If either of the UUIDs are nonexistent, then at least one of
the repositories must be very old. Rather than punish the
user, just assume the repositories are different, so no
copy-history is attempted. */
if (src_err || dst_err || (! src_uuid) || (! dst_uuid))
same_repositories = FALSE;
else
same_repositories = (strcmp(src_uuid, dst_uuid) == 0);
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. */
@ -2668,7 +2650,7 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
apr_pool_t *pool)
{
svn_ra_session_t *ra_session;
const char *top_src_url, *top_dst_path;
const char *top_src_url, *top_dst_abspath;
apr_pool_t *iterpool = svn_pool_create(pool);
const char *lock_abspath;
int i;
@ -2693,13 +2675,13 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
pair->src_abspath_or_url = apr_pstrdup(pool, src);
}
SVN_ERR(get_copy_pair_ancestors(copy_pairs, &top_src_url, &top_dst_path,
SVN_ERR(get_copy_pair_ancestors(copy_pairs, &top_src_url, &top_dst_abspath,
NULL, pool));
lock_abspath = top_dst_path;
lock_abspath = top_dst_abspath;
if (copy_pairs->nelts == 1)
{
top_src_url = svn_uri_dirname(top_src_url, pool);
lock_abspath = svn_dirent_dirname(top_dst_path, pool);
lock_abspath = svn_dirent_dirname(top_dst_abspath, pool);
}
/* Open a repository session to the longest common src ancestor. We do not
@ -2771,7 +2753,7 @@ repos_to_wc_copy(svn_boolean_t *timestamp_sleep,
SVN_WC__CALL_WITH_WRITE_LOCK(
repos_to_wc_copy_locked(timestamp_sleep,
copy_pairs, top_dst_path, ignore_externals,
copy_pairs, top_dst_abspath, ignore_externals,
pin_externals, externals_to_pin,
ra_session, ctx, pool),
ctx->wc_ctx, lock_abspath, FALSE, pool);

View File

@ -1330,6 +1330,26 @@ svn_client_export(svn_revnum_t *result_rev,
/*** From list.c ***/
svn_error_t *
svn_client_list3(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
svn_boolean_t include_externals,
svn_client_list_func2_t list_func,
void *baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
{
return svn_error_trace(svn_client_list4(path_or_url, peg_revision,
revision, NULL, depth,
dirent_fields, fetch_locks,
include_externals,
list_func, baton, ctx, pool));
}
/* Baton for use with wrap_list_func */
struct list_func_wrapper_baton {
void *list_func1_baton;

View File

@ -230,113 +230,158 @@ adjust_paths_for_diff_labels(const char **index_path,
/* Generate a label for the diff output for file PATH at revision REVNUM.
If REVNUM is invalid then it is assumed to be the current working
copy. Assumes the paths are already in the desired style (local
vs internal). Allocate the label in POOL. */
vs internal). Allocate the label in RESULT-POOL. */
static const char *
diff_label(const char *path,
svn_revnum_t revnum,
apr_pool_t *pool)
apr_pool_t *result_pool)
{
const char *label;
if (revnum >= 0)
label = apr_psprintf(pool, _("%s\t(revision %ld)"), path, revnum);
label = apr_psprintf(result_pool, _("%s\t(revision %ld)"), path, revnum);
else if (revnum == DIFF_REVNUM_NONEXISTENT)
label = apr_psprintf(pool, _("%s\t(nonexistent)"), path);
label = apr_psprintf(result_pool, _("%s\t(nonexistent)"), path);
else /* SVN_INVALID_REVNUM */
label = apr_psprintf(pool, _("%s\t(working copy)"), path);
label = apr_psprintf(result_pool, _("%s\t(working copy)"), path);
return label;
}
/* Standard modes produced in git style diffs */
static const int exec_mode = 0755;
static const int noexec_mode = 0644;
static const int kind_file_mode = 0100000;
/*static const kind_dir_mode = 0040000;*/
static const int kind_symlink_mode = 0120000;
/* Print a git diff header for an addition within a diff between PATH1 and
* PATH2 to the stream OS using HEADER_ENCODING.
* All allocations are done in RESULT_POOL. */
* PATH2 to the stream OS using HEADER_ENCODING. */
static svn_error_t *
print_git_diff_header_added(svn_stream_t *os, const char *header_encoding,
const char *path1, const char *path2,
apr_pool_t *result_pool)
svn_boolean_t exec_bit,
svn_boolean_t symlink_bit,
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
int new_mode = (exec_bit ? exec_mode : noexec_mode)
| (symlink_bit ? kind_symlink_mode : kind_file_mode);
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"diff --git a/%s b/%s%s",
path1, path2, APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
"new file mode 10644" APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"new file mode %06o" APR_EOL_STR,
new_mode));
return SVN_NO_ERROR;
}
/* Print a git diff header for a deletion within a diff between PATH1 and
* PATH2 to the stream OS using HEADER_ENCODING.
* All allocations are done in RESULT_POOL. */
* PATH2 to the stream OS using HEADER_ENCODING. */
static svn_error_t *
print_git_diff_header_deleted(svn_stream_t *os, const char *header_encoding,
const char *path1, const char *path2,
apr_pool_t *result_pool)
svn_boolean_t exec_bit,
svn_boolean_t symlink_bit,
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
int old_mode = (exec_bit ? exec_mode : noexec_mode)
| (symlink_bit ? kind_symlink_mode : kind_file_mode);
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"diff --git a/%s b/%s%s",
path1, path2, APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
"deleted file mode 10644"
APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"deleted file mode %06o" APR_EOL_STR,
old_mode));
return SVN_NO_ERROR;
}
/* Print a git diff header for a copy from COPYFROM_PATH to PATH to the stream
* OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */
* OS using HEADER_ENCODING. */
static svn_error_t *
print_git_diff_header_copied(svn_stream_t *os, const char *header_encoding,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
const char *path,
apr_pool_t *result_pool)
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"diff --git a/%s b/%s%s",
copyfrom_path, path, APR_EOL_STR));
if (copyfrom_rev != SVN_INVALID_REVNUM)
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"copy from %s@%ld%s", copyfrom_path,
copyfrom_rev, APR_EOL_STR));
else
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"copy from %s%s", copyfrom_path,
APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"copy to %s%s", path, APR_EOL_STR));
return SVN_NO_ERROR;
}
/* Print a git diff header for a rename from COPYFROM_PATH to PATH to the
* stream OS using HEADER_ENCODING. All allocations are done in RESULT_POOL. */
* stream OS using HEADER_ENCODING. */
static svn_error_t *
print_git_diff_header_renamed(svn_stream_t *os, const char *header_encoding,
const char *copyfrom_path, const char *path,
apr_pool_t *result_pool)
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"diff --git a/%s b/%s%s",
copyfrom_path, path, APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"rename from %s%s", copyfrom_path,
APR_EOL_STR));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"rename to %s%s", path, APR_EOL_STR));
return SVN_NO_ERROR;
}
/* Print a git diff header for a modification within a diff between PATH1 and
* PATH2 to the stream OS using HEADER_ENCODING.
* All allocations are done in RESULT_POOL. */
* PATH2 to the stream OS using HEADER_ENCODING. */
static svn_error_t *
print_git_diff_header_modified(svn_stream_t *os, const char *header_encoding,
const char *path1, const char *path2,
apr_pool_t *result_pool)
apr_pool_t *scratch_pool)
{
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, result_pool,
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"diff --git a/%s b/%s%s",
path1, path2, APR_EOL_STR));
return SVN_NO_ERROR;
}
/* Helper function for print_git_diff_header */
static svn_error_t *
maybe_print_mode_change(svn_stream_t *os,
const char *header_encoding,
svn_boolean_t exec_bit1,
svn_boolean_t exec_bit2,
svn_boolean_t symlink_bit1,
svn_boolean_t symlink_bit2,
const char *git_index_shas,
apr_pool_t *scratch_pool)
{
int old_mode = (exec_bit1 ? exec_mode : noexec_mode)
| (symlink_bit1 ? kind_symlink_mode : kind_file_mode);
int new_mode = (exec_bit2 ? exec_mode : noexec_mode)
| (symlink_bit2 ? kind_symlink_mode : kind_file_mode);
if (old_mode == new_mode)
{
if (git_index_shas)
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"index %s %06o" APR_EOL_STR,
git_index_shas, old_mode));
return SVN_NO_ERROR;
}
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"old mode %06o" APR_EOL_STR, old_mode));
SVN_ERR(svn_stream_printf_from_utf8(os, header_encoding, scratch_pool,
"new mode %06o" APR_EOL_STR, new_mode));
return SVN_NO_ERROR;
}
/* Print a git diff header showing the OPERATION to the stream OS using
* HEADER_ENCODING. Return suitable diff labels for the git diff in *LABEL1
* and *LABEL2. REPOS_RELPATH1 and REPOS_RELPATH2 are relative to reposroot.
@ -354,17 +399,31 @@ print_git_diff_header(svn_stream_t *os,
svn_revnum_t rev2,
const char *copyfrom_path,
svn_revnum_t copyfrom_rev,
apr_hash_t *left_props,
apr_hash_t *right_props,
const char *git_index_shas,
const char *header_encoding,
apr_pool_t *scratch_pool)
{
svn_boolean_t exec_bit1 = (svn_prop_get_value(left_props,
SVN_PROP_EXECUTABLE) != NULL);
svn_boolean_t exec_bit2 = (svn_prop_get_value(right_props,
SVN_PROP_EXECUTABLE) != NULL);
svn_boolean_t symlink_bit1 = (svn_prop_get_value(left_props,
SVN_PROP_SPECIAL) != NULL);
svn_boolean_t symlink_bit2 = (svn_prop_get_value(right_props,
SVN_PROP_SPECIAL) != NULL);
if (operation == svn_diff_op_deleted)
{
SVN_ERR(print_git_diff_header_deleted(os, header_encoding,
repos_relpath1, repos_relpath2,
exec_bit1, symlink_bit1,
scratch_pool));
*label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", repos_relpath1),
rev1, scratch_pool);
*label2 = diff_label("/dev/null", rev2, scratch_pool);
*label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
rev2, scratch_pool);
}
else if (operation == svn_diff_op_copied)
@ -377,13 +436,20 @@ print_git_diff_header(svn_stream_t *os,
rev1, scratch_pool);
*label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
rev2, scratch_pool);
SVN_ERR(maybe_print_mode_change(os, header_encoding,
exec_bit1, exec_bit2,
symlink_bit1, symlink_bit2,
git_index_shas,
scratch_pool));
}
else if (operation == svn_diff_op_added)
{
SVN_ERR(print_git_diff_header_added(os, header_encoding,
repos_relpath1, repos_relpath2,
exec_bit2, symlink_bit2,
scratch_pool));
*label1 = diff_label("/dev/null", rev1, scratch_pool);
*label1 = diff_label(apr_psprintf(scratch_pool, "a/%s", repos_relpath1),
rev1, scratch_pool);
*label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
rev2, scratch_pool);
}
@ -396,6 +462,11 @@ print_git_diff_header(svn_stream_t *os,
rev1, scratch_pool);
*label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
rev2, scratch_pool);
SVN_ERR(maybe_print_mode_change(os, header_encoding,
exec_bit1, exec_bit2,
symlink_bit1, symlink_bit2,
git_index_shas,
scratch_pool));
}
else if (operation == svn_diff_op_moved)
{
@ -406,6 +477,11 @@ print_git_diff_header(svn_stream_t *os,
rev1, scratch_pool);
*label2 = diff_label(apr_psprintf(scratch_pool, "b/%s", repos_relpath2),
rev2, scratch_pool);
SVN_ERR(maybe_print_mode_change(os, header_encoding,
exec_bit1, exec_bit2,
symlink_bit1, symlink_bit2,
git_index_shas,
scratch_pool));
}
return SVN_NO_ERROR;
@ -425,7 +501,8 @@ print_git_diff_header(svn_stream_t *os,
ANCHOR is the local path where the diff editor is anchored. */
static svn_error_t *
display_prop_diffs(const apr_array_header_t *propchanges,
apr_hash_t *original_props,
apr_hash_t *left_props,
apr_hash_t *right_props,
const char *diff_relpath,
const char *anchor,
const char *orig_path1,
@ -487,6 +564,9 @@ display_prop_diffs(const apr_array_header_t *propchanges,
repos_relpath1, repos_relpath2,
rev1, rev2, NULL,
SVN_INVALID_REVNUM,
left_props,
right_props,
NULL,
encoding, scratch_pool));
/* --- label1
@ -496,18 +576,18 @@ display_prop_diffs(const apr_array_header_t *propchanges,
}
SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, scratch_pool,
_("%sProperty changes on: %s%s"),
APR_EOL_STR
"Property changes on: %s"
APR_EOL_STR,
use_git_diff_format
? repos_relpath1
: index_path,
APR_EOL_STR));
: index_path));
SVN_ERR(svn_stream_printf_from_utf8(outstream, encoding, scratch_pool,
SVN_DIFF__UNDER_STRING APR_EOL_STR));
SVN_ERR(svn_diff__display_prop_diffs(
outstream, encoding, propchanges, original_props,
outstream, encoding, propchanges, left_props,
TRUE /* pretty_print_mergeinfo */,
-1 /* context_size */,
cancel_func, cancel_baton, scratch_pool));
@ -606,7 +686,8 @@ diff_props_changed(const char *diff_relpath,
svn_revnum_t rev1,
svn_revnum_t rev2,
const apr_array_header_t *propchanges,
apr_hash_t *original_props,
apr_hash_t *left_props,
apr_hash_t *right_props,
svn_boolean_t show_diff_header,
diff_writer_info_t *dwi,
apr_pool_t *scratch_pool)
@ -625,7 +706,7 @@ diff_props_changed(const char *diff_relpath,
/* We're using the revnums from the dwi since there's
* no revision argument to the svn_wc_diff_callback_t
* dir_props_changed(). */
SVN_ERR(display_prop_diffs(props, original_props,
SVN_ERR(display_prop_diffs(props, left_props, right_props,
diff_relpath,
dwi->ddi.anchor,
dwi->ddi.orig_path_1,
@ -647,6 +728,62 @@ diff_props_changed(const char *diff_relpath,
return SVN_NO_ERROR;
}
/* Given a file ORIG_TMPFILE, return a path to a temporary file that lives at
* least as long as RESULT_POOL, containing the git-like represention of
* ORIG_TMPFILE */
static svn_error_t *
transform_link_to_git(const char **new_tmpfile,
const char **git_sha1,
const char *orig_tmpfile,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_file_t *orig;
apr_file_t *gitlike;
svn_stringbuf_t *line;
*git_sha1 = NULL;
SVN_ERR(svn_io_file_open(&orig, orig_tmpfile, APR_READ, APR_OS_DEFAULT,
scratch_pool));
SVN_ERR(svn_io_open_unique_file3(&gitlike, new_tmpfile, NULL,
svn_io_file_del_on_pool_cleanup,
result_pool, scratch_pool));
SVN_ERR(svn_io_file_readline(orig, &line, NULL, NULL, 2 * APR_PATH_MAX + 2,
scratch_pool, scratch_pool));
if (line->len > 5 && !strncmp(line->data, "link ", 5))
{
const char *sz_str;
svn_checksum_t *checksum;
svn_stringbuf_remove(line, 0, 5);
SVN_ERR(svn_io_file_write_full(gitlike, line->data, line->len,
NULL, scratch_pool));
/* git calculates the sha over "blob X\0" + the actual data,
where X is the decimal size of the blob. */
sz_str = apr_psprintf(scratch_pool, "blob %u", (unsigned int)line->len);
svn_stringbuf_insert(line, 0, sz_str, strlen(sz_str) + 1);
SVN_ERR(svn_checksum(&checksum, svn_checksum_sha1,
line->data, line->len, scratch_pool));
*git_sha1 = svn_checksum_to_cstring(checksum, result_pool);
}
else
{
/* Not a link... so can't convert */
*new_tmpfile = apr_pstrdup(result_pool, orig_tmpfile);
}
SVN_ERR(svn_io_file_close(orig, scratch_pool));
SVN_ERR(svn_io_file_close(gitlike, scratch_pool));
return SVN_NO_ERROR;
}
/* Show differences between TMPFILE1 and TMPFILE2. DIFF_RELPATH, REV1, and
REV2 are used in the headers to indicate the file and revisions. If either
MIMETYPE1 or MIMETYPE2 indicate binary content, don't show a diff,
@ -662,8 +799,8 @@ diff_content_changed(svn_boolean_t *wrote_header,
const char *tmpfile2,
svn_revnum_t rev1,
svn_revnum_t rev2,
const char *mimetype1,
const char *mimetype2,
apr_hash_t *left_props,
apr_hash_t *right_props,
svn_diff_operation_kind_t operation,
svn_boolean_t force_diff,
const char *copyfrom_path,
@ -678,6 +815,9 @@ diff_content_changed(svn_boolean_t *wrote_header,
const char *index_path = diff_relpath;
const char *path1 = dwi->ddi.orig_path_1;
const char *path2 = dwi->ddi.orig_path_2;
const char *mimetype1 = svn_prop_get_value(left_props, SVN_PROP_MIME_TYPE);
const char *mimetype2 = svn_prop_get_value(right_props, SVN_PROP_MIME_TYPE);
const char *index_shas = NULL;
/* If only property differences are shown, there's nothing to do. */
if (dwi->properties_only)
@ -699,6 +839,33 @@ diff_content_changed(svn_boolean_t *wrote_header,
if (mimetype2)
mt2_binary = svn_mime_type_is_binary(mimetype2);
if (dwi->use_git_diff_format)
{
const char *l_hash = NULL;
const char *r_hash = NULL;
/* Change symlinks to their 'git like' plain format */
if (svn_prop_get_value(left_props, SVN_PROP_SPECIAL))
SVN_ERR(transform_link_to_git(&tmpfile1, &l_hash, tmpfile1,
scratch_pool, scratch_pool));
if (svn_prop_get_value(right_props, SVN_PROP_SPECIAL))
SVN_ERR(transform_link_to_git(&tmpfile2, &r_hash, tmpfile2,
scratch_pool, scratch_pool));
if (l_hash && r_hash)
{
/* The symlink has changed. But we can't tell the user of the
diff whether we are writing git diffs or svn diffs of the
symlink... except when we add a git-like index line */
l_hash = apr_pstrndup(scratch_pool, l_hash, 8);
r_hash = apr_pstrndup(scratch_pool, r_hash, 8);
index_shas = apr_psprintf(scratch_pool, "%8s..%8s",
l_hash, r_hash);
}
}
if (! dwi->force_binary && (mt1_binary || mt2_binary))
{
/* Print out the diff header. */
@ -708,6 +875,8 @@ diff_content_changed(svn_boolean_t *wrote_header,
SVN_DIFF__EQUAL_STRING APR_EOL_STR,
index_path));
*wrote_header = TRUE;
/* ### Print git diff headers. */
if (dwi->use_git_diff_format)
@ -716,6 +885,7 @@ diff_content_changed(svn_boolean_t *wrote_header,
svn_stream_t *right_stream;
const char *repos_relpath1;
const char *repos_relpath2;
const char *copyfrom_repos_relpath = NULL;
SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath,
dwi->ddi.orig_path_1,
@ -729,12 +899,22 @@ diff_content_changed(svn_boolean_t *wrote_header,
dwi->wc_ctx,
dwi->ddi.anchor,
scratch_pool, scratch_pool));
if (copyfrom_path)
SVN_ERR(make_repos_relpath(&copyfrom_repos_relpath, copyfrom_path,
dwi->ddi.orig_path_2,
dwi->ddi.session_relpath,
dwi->wc_ctx,
dwi->ddi.anchor,
scratch_pool, scratch_pool));
SVN_ERR(print_git_diff_header(outstream, &label1, &label2,
operation,
repos_relpath1, repos_relpath2,
rev1, rev2,
copyfrom_path,
copyfrom_repos_relpath,
copyfrom_rev,
left_props,
right_props,
index_shas,
dwi->header_encoding,
scratch_pool));
@ -878,6 +1058,8 @@ diff_content_changed(svn_boolean_t *wrote_header,
{
const char *repos_relpath1;
const char *repos_relpath2;
const char *copyfrom_repos_relpath = NULL;
SVN_ERR(make_repos_relpath(&repos_relpath1, diff_relpath,
dwi->ddi.orig_path_1,
dwi->ddi.session_relpath,
@ -890,12 +1072,23 @@ diff_content_changed(svn_boolean_t *wrote_header,
dwi->wc_ctx,
dwi->ddi.anchor,
scratch_pool, scratch_pool));
if (copyfrom_path)
SVN_ERR(make_repos_relpath(&copyfrom_repos_relpath,
copyfrom_path,
dwi->ddi.orig_path_2,
dwi->ddi.session_relpath,
dwi->wc_ctx,
dwi->ddi.anchor,
scratch_pool, scratch_pool));
SVN_ERR(print_git_diff_header(outstream, &label1, &label2,
operation,
repos_relpath1, repos_relpath2,
rev1, rev2,
copyfrom_path,
copyfrom_repos_relpath,
copyfrom_rev,
left_props,
right_props,
index_shas,
dwi->header_encoding,
scratch_pool));
}
@ -916,10 +1109,6 @@ diff_content_changed(svn_boolean_t *wrote_header,
}
}
/* ### todo: someday we'll need to worry about whether we're going
to need to write a diff plug-in mechanism that makes use of the
two paths, instead of just blindly running SVN_CLIENT_DIFF. */
return SVN_NO_ERROR;
}
@ -946,10 +1135,7 @@ diff_file_changed(const char *relpath,
left_file, right_file,
left_source->revision,
right_source->revision,
svn_prop_get_value(left_props,
SVN_PROP_MIME_TYPE),
svn_prop_get_value(right_props,
SVN_PROP_MIME_TYPE),
left_props, right_props,
svn_diff_op_modified, FALSE,
NULL,
SVN_INVALID_REVNUM, dwi,
@ -958,7 +1144,7 @@ diff_file_changed(const char *relpath,
SVN_ERR(diff_props_changed(relpath,
left_source->revision,
right_source->revision, prop_changes,
left_props, !wrote_header,
left_props, right_props, !wrote_header,
dwi, scratch_pool));
return SVN_NO_ERROR;
}
@ -986,6 +1172,23 @@ diff_file_added(const char *relpath,
apr_hash_t *left_props;
apr_array_header_t *prop_changes;
if (dwi->no_diff_added)
{
const char *index_path = relpath;
if (dwi->ddi.anchor)
index_path = svn_dirent_join(dwi->ddi.anchor, relpath,
scratch_pool);
SVN_ERR(svn_stream_printf_from_utf8(dwi->outstream,
dwi->header_encoding, scratch_pool,
"Index: %s (added)" APR_EOL_STR
SVN_DIFF__EQUAL_STRING APR_EOL_STR,
index_path));
wrote_header = TRUE;
return SVN_NO_ERROR;
}
/* During repos->wc diff of a copy revision numbers obtained
* from the working copy are always SVN_INVALID_REVNUM. */
if (copyfrom_source && !dwi->show_copies_as_adds)
@ -1009,33 +1212,19 @@ diff_file_added(const char *relpath,
SVN_ERR(svn_prop_diffs(&prop_changes, right_props, left_props, scratch_pool));
if (dwi->no_diff_added)
{
const char *index_path = relpath;
if (dwi->ddi.anchor)
index_path = svn_dirent_join(dwi->ddi.anchor, relpath,
scratch_pool);
SVN_ERR(svn_stream_printf_from_utf8(dwi->outstream,
dwi->header_encoding, scratch_pool,
"Index: %s (added)" APR_EOL_STR
SVN_DIFF__EQUAL_STRING APR_EOL_STR,
index_path));
wrote_header = TRUE;
}
else if (copyfrom_source && right_file)
if (copyfrom_source && right_file)
SVN_ERR(diff_content_changed(&wrote_header, relpath,
left_file, right_file,
copyfrom_source->revision,
right_source->revision,
svn_prop_get_value(left_props,
SVN_PROP_MIME_TYPE),
svn_prop_get_value(right_props,
SVN_PROP_MIME_TYPE),
svn_diff_op_copied,
left_props, right_props,
copyfrom_source->moved_from_relpath
? svn_diff_op_moved
: svn_diff_op_copied,
TRUE /* force diff output */,
copyfrom_source->repos_relpath,
copyfrom_source->moved_from_relpath
? copyfrom_source->moved_from_relpath
: copyfrom_source->repos_relpath,
copyfrom_source->revision,
dwi, scratch_pool));
else if (right_file)
@ -1043,10 +1232,7 @@ diff_file_added(const char *relpath,
left_file, right_file,
DIFF_REVNUM_NONEXISTENT,
right_source->revision,
svn_prop_get_value(left_props,
SVN_PROP_MIME_TYPE),
svn_prop_get_value(right_props,
SVN_PROP_MIME_TYPE),
left_props, right_props,
svn_diff_op_added,
TRUE /* force diff output */,
NULL, SVN_INVALID_REVNUM,
@ -1058,8 +1244,8 @@ diff_file_added(const char *relpath,
: DIFF_REVNUM_NONEXISTENT,
right_source->revision,
prop_changes,
left_props, ! wrote_header,
dwi, scratch_pool));
left_props, right_props,
! wrote_header, dwi, scratch_pool));
return SVN_NO_ERROR;
}
@ -1104,8 +1290,7 @@ diff_file_deleted(const char *relpath,
left_file, dwi->empty_file,
left_source->revision,
DIFF_REVNUM_NONEXISTENT,
svn_prop_get_value(left_props,
SVN_PROP_MIME_TYPE),
left_props,
NULL,
svn_diff_op_deleted, FALSE,
NULL, SVN_INVALID_REVNUM,
@ -1123,8 +1308,8 @@ diff_file_deleted(const char *relpath,
left_source->revision,
DIFF_REVNUM_NONEXISTENT,
prop_changes,
left_props, ! wrote_header,
dwi, scratch_pool));
left_props, NULL,
! wrote_header, dwi, scratch_pool));
}
}
@ -1149,7 +1334,7 @@ diff_dir_changed(const char *relpath,
left_source->revision,
right_source->revision,
prop_changes,
left_props,
left_props, right_props,
TRUE /* show_diff_header */,
dwi,
scratch_pool));
@ -1194,7 +1379,7 @@ diff_dir_added(const char *relpath,
: DIFF_REVNUM_NONEXISTENT,
right_source->revision,
prop_changes,
left_props,
left_props, right_props,
TRUE /* show_diff_header */,
dwi,
scratch_pool));
@ -1211,19 +1396,20 @@ diff_dir_deleted(const char *relpath,
{
diff_writer_info_t *dwi = processor->baton;
apr_array_header_t *prop_changes;
apr_hash_t *right_props;
if (dwi->no_diff_deleted)
return SVN_NO_ERROR;
SVN_ERR(svn_prop_diffs(&prop_changes, apr_hash_make(scratch_pool),
right_props = apr_hash_make(scratch_pool);
SVN_ERR(svn_prop_diffs(&prop_changes, right_props,
left_props, scratch_pool));
SVN_ERR(diff_props_changed(relpath,
left_source->revision,
DIFF_REVNUM_NONEXISTENT,
prop_changes,
left_props,
left_props, right_props,
TRUE /* show_diff_header */,
dwi,
scratch_pool));
@ -1852,11 +2038,15 @@ diff_repos_repos(const char **root_relpath,
/* Perform a diff between a repository path and a working-copy path.
PATH_OR_URL1 may be either a URL or a working copy path. PATH2 is a
working copy path. REVISION1 and REVISION2 are their respective
revisions. If REVERSE is TRUE, the diff will be done in reverse.
If PEG_REVISION is specified, then PATH_OR_URL1 is the path in the peg
revision, and the actual repository path to be compared is
determined by following copy history.
working copy path. REVISION1 is the revision of URL1. If PEG_REVISION1
is specified, then PATH_OR_URL1 is the path in the peg revision, and the
actual repository path to be compared is determined by following copy
history.
REVISION_KIND2 specifies which revision should be reported from the
working copy (BASE or WORKING)
If REVERSE is TRUE, the diff will be reported in reverse.
All other options are the same as those passed to svn_client_diff6(). */
static svn_error_t *
@ -1865,9 +2055,9 @@ diff_repos_wc(const char **root_relpath,
struct diff_driver_info_t *ddi,
const char *path_or_url1,
const svn_opt_revision_t *revision1,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *peg_revision1,
const char *path2,
const svn_opt_revision_t *revision2,
enum svn_opt_revision_kind revision2_kind,
svn_boolean_t reverse,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
@ -1884,7 +2074,7 @@ diff_repos_wc(const char **root_relpath,
void *reporter_baton;
const svn_delta_editor_t *diff_editor;
void *diff_edit_baton;
svn_boolean_t rev2_is_base = (revision2->kind == svn_opt_revision_base);
svn_boolean_t rev2_is_base = (revision2_kind == svn_opt_revision_base);
svn_boolean_t server_supports_depth;
const char *abspath_or_url1;
const char *abspath2;
@ -1924,10 +2114,10 @@ diff_repos_wc(const char **root_relpath,
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc1,
path_or_url1, abspath2,
peg_revision, revision1,
peg_revision1, revision1,
ctx, scratch_pool));
if (revision2->kind == svn_opt_revision_base || !is_copy)
if (revision2_kind == svn_opt_revision_base || !is_copy)
{
/* Convert path_or_url1 to a URL to feed to do_diff. */
SVN_ERR(svn_wc_get_actual_target2(&anchor, &target, ctx->wc_ctx, path2,
@ -2069,22 +2259,20 @@ diff_repos_wc(const char **root_relpath,
else
diff_depth = svn_depth_unknown;
/* Tell the RA layer we want a delta to change our txn to URL1 */
SVN_ERR(svn_ra_do_diff3(ra_session,
&reporter, &reporter_baton,
loc1->rev,
target,
diff_depth,
ignore_ancestry,
TRUE, /* text_deltas */
loc1->url,
diff_editor, diff_edit_baton,
scratch_pool));
if (is_copy && revision2->kind != svn_opt_revision_base)
if (is_copy && revision2_kind != svn_opt_revision_base)
{
/* Tell the RA layer we want a delta to change our txn to URL1 */
SVN_ERR(svn_ra_do_diff3(ra_session,
&reporter, &reporter_baton,
loc1->rev,
target,
diff_depth,
ignore_ancestry,
TRUE, /* text_deltas */
loc1->url,
diff_editor, diff_edit_baton,
scratch_pool));
/* Report the copy source. */
if (cf_depth == svn_depth_unknown)
cf_depth = svn_depth_infinity;
@ -2108,18 +2296,6 @@ diff_repos_wc(const char **root_relpath,
}
else
{
/* Tell the RA layer we want a delta to change our txn to URL1 */
SVN_ERR(svn_ra_do_diff3(ra_session,
&reporter, &reporter_baton,
loc1->rev,
target,
diff_depth,
ignore_ancestry,
TRUE, /* text_deltas */
loc1->url,
diff_editor, diff_edit_baton,
scratch_pool));
/* Create a txn mirror of path2; the diff editor will print
diffs in reverse. :-) */
SVN_ERR(svn_wc_crawl_revisions5(ctx->wc_ctx, abspath2,
@ -2146,6 +2322,7 @@ do_diff(const char **root_relpath,
const svn_opt_revision_t *revision1,
const svn_opt_revision_t *revision2,
const svn_opt_revision_t *peg_revision,
svn_boolean_t no_peg_revision,
svn_depth_t depth,
svn_boolean_t ignore_ancestry,
const apr_array_header_t *changelists,
@ -2166,7 +2343,7 @@ do_diff(const char **root_relpath,
{
if (is_repos2)
{
/* ### Ignores 'show_copies_as_adds'. */
/* Ignores changelists. */
SVN_ERR(diff_repos_repos(root_relpath, root_is_dir,
ddi,
path_or_url1, path_or_url2,
@ -2179,8 +2356,11 @@ do_diff(const char **root_relpath,
else /* path_or_url2 is a working copy path */
{
SVN_ERR(diff_repos_wc(root_relpath, root_is_dir, ddi,
path_or_url1, revision1, peg_revision,
path_or_url2, revision2, FALSE, depth,
path_or_url1, revision1,
no_peg_revision ? revision1
: peg_revision,
path_or_url2, revision2->kind,
FALSE, depth,
ignore_ancestry, changelists,
diff_processor, ctx,
result_pool, scratch_pool));
@ -2191,8 +2371,12 @@ do_diff(const char **root_relpath,
if (is_repos2)
{
SVN_ERR(diff_repos_wc(root_relpath, root_is_dir, ddi,
path_or_url2, revision2, peg_revision,
path_or_url1, revision1, TRUE, depth,
path_or_url2, revision2,
no_peg_revision ? revision2
: peg_revision,
path_or_url1,
revision1->kind,
TRUE, depth,
ignore_ancestry, changelists,
diff_processor, ctx,
result_pool, scratch_pool));
@ -2211,7 +2395,7 @@ do_diff(const char **root_relpath,
scratch_pool));
/* ### What about ddi? */
/* Ignores changelists, ignore_ancestry */
SVN_ERR(svn_client__arbitrary_nodes_diff(root_relpath, root_is_dir,
abspath1, abspath2,
depth,
@ -2415,7 +2599,8 @@ svn_client_diff6(const apr_array_header_t *options,
return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi,
path_or_url1, path_or_url2,
revision1, revision2, &peg_revision,
revision1, revision2,
&peg_revision, TRUE /* no_peg_revision */,
depth, ignore_ancestry, changelists,
TRUE /* text_deltas */,
diff_processor, ctx, pool, pool));
@ -2498,7 +2683,8 @@ svn_client_diff_peg6(const apr_array_header_t *options,
return svn_error_trace(do_diff(NULL, NULL, &dwi.ddi,
path_or_url, path_or_url,
start_revision, end_revision, peg_revision,
start_revision, end_revision,
peg_revision, FALSE /* no_peg_revision */,
depth, ignore_ancestry, changelists,
TRUE /* text_deltas */,
diff_processor, ctx, pool, pool));
@ -2531,7 +2717,8 @@ svn_client_diff_summarize2(const char *path_or_url1,
return svn_error_trace(do_diff(p_root_relpath, NULL, NULL,
path_or_url1, path_or_url2,
revision1, revision2, &peg_revision,
revision1, revision2,
&peg_revision, TRUE /* no_peg_revision */,
depth, ignore_ancestry, changelists,
FALSE /* text_deltas */,
diff_processor, ctx, pool, pool));
@ -2560,7 +2747,8 @@ svn_client_diff_summarize_peg2(const char *path_or_url,
return svn_error_trace(do_diff(p_root_relpath, NULL, NULL,
path_or_url, path_or_url,
start_revision, end_revision, peg_revision,
start_revision, end_revision,
peg_revision, FALSE /* no_peg_revision */,
depth, ignore_ancestry, changelists,
FALSE /* text_deltas */,
diff_processor, ctx, pool, pool));

View File

@ -179,7 +179,7 @@ inner_dir_diff(const char *left_abspath,
{
svn_error_clear(err);
right_dirents = apr_hash_make(scratch_pool);
right_only = TRUE;
left_only = TRUE;
}
else
SVN_ERR(err);
@ -669,9 +669,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 (depth == svn_depth_unknown)
depth = svn_depth_infinity;
if (left_kind == svn_node_dir && right_kind == svn_node_dir)
{
left_root_abspath = left_abspath;

View File

@ -432,7 +432,7 @@ export_node(void *baton,
scratch_pool));
/* Now that dst_tmp contains the translated data, do the atomic rename. */
SVN_ERR(svn_io_file_rename(dst_tmp, to_abspath, scratch_pool));
SVN_ERR(svn_io_file_rename2(dst_tmp, to_abspath, FALSE, scratch_pool));
if (eib->notify_func)
{
@ -816,7 +816,7 @@ close_file(void *file_baton,
if ((! fb->eol_style_val) && (! fb->keywords_val) && (! fb->special))
{
SVN_ERR(svn_io_file_rename(fb->tmppath, fb->path, pool));
SVN_ERR(svn_io_file_rename2(fb->tmppath, fb->path, FALSE, pool));
}
else
{
@ -1035,7 +1035,7 @@ add_file_ev2(void *baton,
eb->cancel_baton, scratch_pool));
/* Move the file into place. */
SVN_ERR(svn_io_file_rename(tmppath, full_path, scratch_pool));
SVN_ERR(svn_io_file_rename2(tmppath, full_path, FALSE, scratch_pool));
}
if (executable_val)
@ -1148,7 +1148,7 @@ get_editor_ev2(const svn_delta_editor_t **export_editor,
}
static svn_error_t *
export_file_ev2(const char *from_path_or_url,
export_file_ev2(const char *from_url,
const char *to_path,
struct edit_baton *eb,
svn_client__pathrev_t *loc,
@ -1156,23 +1156,21 @@ export_file_ev2(const char *from_path_or_url,
svn_boolean_t overwrite,
apr_pool_t *scratch_pool)
{
svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
apr_hash_t *props;
svn_stream_t *tmp_stream;
svn_node_kind_t to_kind;
SVN_ERR_ASSERT(svn_path_is_url(from_url));
if (svn_path_is_empty(to_path))
{
if (from_is_url)
to_path = svn_uri_basename(from_path_or_url, scratch_pool);
else
to_path = svn_dirent_basename(from_path_or_url, NULL);
to_path = svn_uri_basename(from_url, scratch_pool);
eb->root_path = to_path;
}
else
{
SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url,
from_is_url, scratch_pool));
SVN_ERR(append_basename_if_dir(&to_path, from_url,
TRUE, scratch_pool));
eb->root_path = to_path;
}
@ -1204,7 +1202,7 @@ export_file_ev2(const char *from_path_or_url,
}
static svn_error_t *
export_file(const char *from_path_or_url,
export_file(const char *from_url,
const char *to_path,
struct edit_baton *eb,
svn_client__pathrev_t *loc,
@ -1216,20 +1214,18 @@ export_file(const char *from_path_or_url,
apr_hash_index_t *hi;
struct file_baton *fb = apr_pcalloc(scratch_pool, sizeof(*fb));
svn_node_kind_t to_kind;
svn_boolean_t from_is_url = svn_path_is_url(from_path_or_url);
SVN_ERR_ASSERT(svn_path_is_url(from_url));
if (svn_path_is_empty(to_path))
{
if (from_is_url)
to_path = svn_uri_basename(from_path_or_url, scratch_pool);
else
to_path = svn_dirent_basename(from_path_or_url, NULL);
to_path = svn_uri_basename(from_url, scratch_pool);
eb->root_path = to_path;
}
else
{
SVN_ERR(append_basename_if_dir(&to_path, from_path_or_url,
from_is_url, scratch_pool));
SVN_ERR(append_basename_if_dir(&to_path, from_url,
TRUE, scratch_pool));
eb->root_path = to_path;
}
@ -1288,7 +1284,7 @@ export_file(const char *from_path_or_url,
}
static svn_error_t *
export_directory(const char *from_path_or_url,
export_directory(const char *from_url,
const char *to_path,
struct edit_baton *eb,
svn_client__pathrev_t *loc,
@ -1307,6 +1303,8 @@ export_directory(const char *from_path_or_url,
void *report_baton;
svn_node_kind_t kind;
SVN_ERR_ASSERT(svn_path_is_url(from_url));
if (!ENABLE_EV2_IMPL)
SVN_ERR(get_editor_ev1(&export_editor, &edit_baton, eb, ctx,
scratch_pool, scratch_pool));
@ -1355,7 +1353,7 @@ export_directory(const char *from_path_or_url,
SVN_ERR(svn_dirent_get_absolute(&to_abspath, to_path, scratch_pool));
SVN_ERR(svn_client__export_externals(eb->externals,
from_path_or_url,
from_url,
to_abspath, eb->repos_root_url,
depth, native_eol,
ignore_keywords,
@ -1402,8 +1400,12 @@ svn_client_export5(svn_revnum_t *result_rev,
svn_client__pathrev_t *loc;
svn_ra_session_t *ra_session;
svn_node_kind_t kind;
const char *from_url;
struct edit_baton *eb = apr_pcalloc(pool, sizeof(*eb));
SVN_ERR(svn_client_url_from_path2(&from_url, from_path_or_url,
ctx, pool, pool));
/* Get the RA connection. */
SVN_ERR(svn_client__ra_session_from_path2(&ra_session, &loc,
from_path_or_url, NULL,
@ -1428,15 +1430,15 @@ svn_client_export5(svn_revnum_t *result_rev,
if (kind == svn_node_file)
{
if (!ENABLE_EV2_IMPL)
SVN_ERR(export_file(from_path_or_url, to_path, eb, loc, ra_session,
SVN_ERR(export_file(from_url, to_path, eb, loc, ra_session,
overwrite, pool));
else
SVN_ERR(export_file_ev2(from_path_or_url, to_path, eb, loc,
SVN_ERR(export_file_ev2(from_url, to_path, eb, loc,
ra_session, overwrite, pool));
}
else if (kind == svn_node_dir)
{
SVN_ERR(export_directory(from_path_or_url, to_path,
SVN_ERR(export_directory(from_url, to_path,
eb, loc, ra_session, overwrite,
ignore_externals, ignore_keywords, depth,
native_eol, ctx, pool));
@ -1508,7 +1510,7 @@ svn_client_export5(svn_revnum_t *result_rev,
eib.ignore_keywords = ignore_keywords;
eib.wc_ctx = ctx->wc_ctx;
eib.native_eol = native_eol;
eib.notify_func = ctx->notify_func2;;
eib.notify_func = ctx->notify_func2;
eib.notify_baton = ctx->notify_baton2;
eib.origin_abspath = from_path_or_url;
eib.exported = FALSE;

View File

@ -120,7 +120,7 @@ relegate_dir_external(svn_wc_context_t *wc_ctx,
/* And if it is no longer a working copy, we should just rename
it */
err = svn_io_file_rename(local_abspath, new_path, scratch_pool);
err = svn_io_file_rename2(local_abspath, new_path, FALSE, scratch_pool);
}
/* ### TODO: We should notify the user about the rename */
@ -534,7 +534,7 @@ switch_file_external(const char *local_abspath,
SVN_ERR(svn_io_check_path(local_abspath, &disk_kind, scratch_pool));
if (kind == svn_node_file || kind == svn_node_dir)
if (disk_kind == svn_node_file || disk_kind == svn_node_dir)
return svn_error_createf(SVN_ERR_WC_PATH_FOUND, NULL,
_("The file external '%s' can not be "
"created because the node exists."),
@ -574,6 +574,8 @@ switch_file_external(const char *local_abspath,
record_url,
record_peg_revision,
record_revision,
ctx->conflict_func2,
ctx->conflict_baton2,
ctx->cancel_func,
ctx->cancel_baton,
ctx->notify_func2,

View File

@ -73,32 +73,59 @@ typedef struct import_ctx_t
apr_hash_t *autoprops;
} import_ctx_t;
typedef struct open_txdelta_stream_baton_t
{
svn_boolean_t need_reset;
svn_stream_t *stream;
} open_txdelta_stream_baton_t;
/* Implements svn_txdelta_stream_open_func_t */
static svn_error_t *
open_txdelta_stream(svn_txdelta_stream_t **txdelta_stream_p,
void *baton,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
open_txdelta_stream_baton_t *b = baton;
if (b->need_reset)
{
/* Under rare circumstances, we can be restarted and would need to
* supply the delta stream again. In this case, reset the base
* stream. */
SVN_ERR(svn_stream_reset(b->stream));
}
/* Get the delta stream (delta against the empty string). */
svn_txdelta2(txdelta_stream_p, svn_stream_empty(result_pool),
b->stream, FALSE, result_pool);
b->need_reset = TRUE;
return SVN_NO_ERROR;
}
/* Apply LOCAL_ABSPATH's contents (as a delta against the empty string) to
FILE_BATON in EDITOR. Use POOL for any temporary allocation.
PROPERTIES is the set of node properties set on this file.
Fill DIGEST with the md5 checksum of the sent file; DIGEST must be
at least APR_MD5_DIGESTSIZE bytes long. */
Return the resulting checksum in *RESULT_MD5_CHECKSUM_P. */
/* ### how does this compare against svn_wc_transmit_text_deltas2() ??? */
static svn_error_t *
send_file_contents(const char *local_abspath,
send_file_contents(svn_checksum_t **result_md5_checksum_p,
const char *local_abspath,
void *file_baton,
const svn_delta_editor_t *editor,
apr_hash_t *properties,
unsigned char *digest,
apr_pool_t *pool)
{
svn_stream_t *contents;
svn_txdelta_window_handler_t handler;
void *handler_baton;
const svn_string_t *eol_style_val = NULL, *keywords_val = NULL;
svn_boolean_t special = FALSE;
svn_subst_eol_style_t eol_style;
const char *eol;
apr_hash_t *keywords;
open_txdelta_stream_baton_t baton = { 0 };
/* If there are properties, look for EOL-style and keywords ones. */
if (properties)
@ -111,10 +138,6 @@ send_file_contents(const char *local_abspath,
special = TRUE;
}
/* Get an editor func that wants to consume the delta stream. */
SVN_ERR(editor->apply_textdelta(file_baton, NULL, pool,
&handler, &handler_baton));
if (eol_style_val)
svn_subst_eol_style_from_value(&eol_style, &eol, eol_style_val->data);
else
@ -168,10 +191,17 @@ send_file_contents(const char *local_abspath,
}
}
/* Send the file's contents to the delta-window handler. */
return svn_error_trace(svn_txdelta_send_stream(contents, handler,
handler_baton, digest,
pool));
/* Arrange the stream to calculate the resulting MD5. */
contents = svn_stream_checksummed2(contents, result_md5_checksum_p, NULL,
svn_checksum_md5, TRUE, pool);
/* Send the contents. */
baton.need_reset = FALSE;
baton.stream = svn_stream_disown(contents, pool);
SVN_ERR(editor->apply_textdelta_stream(editor, file_baton, NULL,
open_txdelta_stream, &baton, pool));
SVN_ERR(svn_stream_close(contents));
return SVN_NO_ERROR;
}
@ -198,7 +228,7 @@ import_file(const svn_delta_editor_t *editor,
{
void *file_baton;
const char *mimetype = NULL;
unsigned char digest[APR_MD5_DIGESTSIZE];
svn_checksum_t *result_md5_checksum;
const char *text_checksum;
apr_hash_t* properties;
apr_hash_index_t *hi;
@ -262,13 +292,11 @@ import_file(const svn_delta_editor_t *editor,
}
/* Now, transmit the file contents. */
SVN_ERR(send_file_contents(local_abspath, file_baton, editor,
properties, digest, pool));
SVN_ERR(send_file_contents(&result_md5_checksum, local_abspath,
file_baton, editor, properties, pool));
/* Finally, close the file. */
text_checksum =
svn_checksum_to_cstring(svn_checksum__from_digest_md5(digest, pool), pool);
text_checksum = svn_checksum_to_cstring(result_md5_checksum, pool);
return svn_error_trace(editor->close_file(file_baton, text_checksum, pool));
}
@ -577,26 +605,26 @@ import_dir(const svn_delta_editor_t *editor,
}
/* Recursively import PATH to a repository using EDITOR and
* EDIT_BATON. PATH can be a file or directory.
/* Recursively import LOCAL_ABSPATH to a repository using EDITOR and
* EDIT_BATON. LOCAL_ABSPATH can be a file or directory.
*
* Sets *UPDATED_REPOSITORY to TRUE when the repository was modified by
* a successfull commit, otherwise to FALSE.
*
* DEPTH is the depth at which to import PATH; it behaves as for
* svn_client_import4().
* DEPTH is the depth at which to import LOCAL_ABSPATH; it behaves as for
* svn_client_import5().
*
* BASE_REV is the revision to use for the root of the commit. We
* checked the preconditions against this revision.
*
* NEW_ENTRIES is an ordered array of path components that must be
* created in the repository (where the ordering direction is
* parent-to-child). If PATH is a directory, NEW_ENTRIES may be empty
* parent-to-child). If LOCAL_ABSPATH is a directory, NEW_ENTRIES may be empty
* -- the result is an import which creates as many new entries in the
* top repository target directory as there are importable entries in
* the top of PATH; but if NEW_ENTRIES is not empty, its last item is
* the top of LOCAL_ABSPATH; but if NEW_ENTRIES is not empty, its last item is
* the name of a new subdirectory in the repository to hold the
* import. If PATH is a file, NEW_ENTRIES may not be empty, and its
* import. If LOCAL_ABSPATH is a file, NEW_ENTRIES may not be empty, and its
* last item is the name used for the file in the repository. If
* NEW_ENTRIES contains more than one item, all but the last item are
* the names of intermediate directories that are created before the
@ -624,6 +652,8 @@ import_dir(const svn_delta_editor_t *editor,
* If CTX->NOTIFY_FUNC is non-null, invoke it with CTX->NOTIFY_BATON for
* each imported path, passing actions svn_wc_notify_commit_added.
*
* URL is used only in the 'commit_finalizing' notification.
*
* Use POOL for any temporary allocation.
*
* Note: the repository directory receiving the import was specified

View File

@ -253,17 +253,17 @@ same_resource_in_head(svn_boolean_t *same_p,
apr_pool_t *pool)
{
svn_error_t *err;
svn_opt_revision_t start_rev, peg_rev;
svn_opt_revision_t operative_rev, peg_rev;
const char *head_url;
start_rev.kind = svn_opt_revision_head;
peg_rev.kind = svn_opt_revision_number;
peg_rev.value.number = rev;
peg_rev.kind = svn_opt_revision_head;
operative_rev.kind = svn_opt_revision_number;
operative_rev.value.number = rev;
err = svn_client__repos_locations(&head_url, NULL, NULL, NULL,
ra_session,
url, &peg_rev,
&start_rev, NULL,
&operative_rev, NULL,
ctx, pool);
if (err &&
((err->apr_err == SVN_ERR_CLIENT_UNRELATED_RESOURCES) ||

View File

@ -21,6 +21,8 @@
* ====================================================================
*/
#include <apr_fnmatch.h>
#include "svn_client.h"
#include "svn_dirent_uri.h"
#include "svn_hash.h"
@ -35,12 +37,14 @@
#include "private/svn_fspath.h"
#include "private/svn_ra_private.h"
#include "private/svn_sorts_private.h"
#include "private/svn_utf_private.h"
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
/* Prototypes for referencing before declaration */
static svn_error_t *
list_externals(apr_hash_t *externals,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -53,6 +57,7 @@ static svn_error_t *
list_internal(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -64,6 +69,18 @@ list_internal(const char *path_or_url,
svn_client_ctx_t *ctx,
apr_pool_t *pool);
/* Return TRUE if S matches any of the const char * in PATTERNS.
* Note that any S will match if PATTERNS is empty.
* Use SCRATCH_BUFFER for temporary string contents. */
static svn_boolean_t
match_patterns(const char *s,
const apr_array_header_t *patterns,
svn_membuf_t *scratch_buffer)
{
return patterns
? svn_utf__fuzzy_glob_match(s, patterns, scratch_buffer)
: TRUE;
}
/* Get the directory entries of DIR at REV (relative to the root of
RA_SESSION), getting at least the fields specified by DIRENT_FIELDS.
@ -75,6 +92,10 @@ list_internal(const char *path_or_url,
if svn_depth_infinity, invoke it on file and directory entries and
recurse into the directory entries with the same depth.
If PATTERNS is not empty, the last path segments must match at least
one of const char * patterns in it or the respective dirent will not
be reported.
LOCKS, if non-NULL, is a hash mapping const char * paths to svn_lock_t
objects and FS_PATH is the absolute filesystem path of the RA session.
Use SCRATCH_POOL for temporary allocations.
@ -86,6 +107,8 @@ list_internal(const char *path_or_url,
EXTERNAL_PARENT_URL and EXTERNAL_TARGET are set when external items
are listed, otherwise both are set to NULL by the caller.
Use SCRATCH_BUFFER for temporary string contents.
*/
static svn_error_t *
get_dir_contents(apr_uint32_t dirent_fields,
@ -94,6 +117,7 @@ get_dir_contents(apr_uint32_t dirent_fields,
svn_ra_session_t *ra_session,
apr_hash_t *locks,
const char *fs_path,
const apr_array_header_t *patterns,
svn_depth_t depth,
svn_client_ctx_t *ctx,
apr_hash_t *externals,
@ -101,6 +125,7 @@ get_dir_contents(apr_uint32_t dirent_fields,
const char *external_target,
svn_client_list_func2_t list_func,
void *baton,
svn_membuf_t *scratch_buffer,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
@ -175,23 +200,71 @@ get_dir_contents(apr_uint32_t dirent_fields,
if (the_ent->kind == svn_node_file
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity)
SVN_ERR(list_func(baton, path, the_ent, lock, fs_path,
external_parent_url, external_target, iterpool));
if (match_patterns(item->key, patterns, scratch_buffer))
SVN_ERR(list_func(baton, path, the_ent, lock, fs_path,
external_parent_url, external_target, iterpool));
/* If externals is non-NULL, populate the externals hash table
recursively for all directory entries. */
if (depth == svn_depth_infinity && the_ent->kind == svn_node_dir)
SVN_ERR(get_dir_contents(dirent_fields, path, rev,
ra_session, locks, fs_path, depth, ctx,
SVN_ERR(get_dir_contents(dirent_fields, path, rev, ra_session,
locks, fs_path, patterns, depth, ctx,
externals, external_parent_url,
external_target, list_func, baton,
result_pool, iterpool));
scratch_buffer, result_pool, iterpool));
}
svn_pool_destroy(iterpool);
return SVN_NO_ERROR;
}
/* Baton type to be used with list_receiver. */
typedef struct receiver_baton_t
{
/* Wrapped callback function to invoke. */
svn_client_list_func2_t list_func;
/* Baton to be used with LIST_FUNC. */
void *list_baton;
/* Client context providing cancellation support. */
svn_client_ctx_t *ctx;
/* All locks found for the whole tree; pick yours. */
apr_hash_t *locks;
/* Start path of the operation. */
const char *fs_base_path;
} receiver_baton_t;
/* Implement svn_ra_dirent_receiver_t.
The BATON type must be a receiver_baton_t. */
static svn_error_t *
list_receiver(const char *rel_path,
svn_dirent_t *dirent,
void *baton,
apr_pool_t *pool)
{
receiver_baton_t *b = baton;
const svn_lock_t *lock = NULL;
/* We only report the path relative to the start path. */
rel_path = svn_dirent_skip_ancestor(b->fs_base_path, rel_path);
if (b->locks)
{
const char *abs_path = svn_dirent_join(b->fs_base_path, rel_path, pool);
lock = svn_hash_gets(b->locks, abs_path);
}
if (b->ctx->cancel_func)
SVN_ERR(b->ctx->cancel_func(b->ctx->cancel_baton));
SVN_ERR(b->list_func(b->list_baton, rel_path, dirent, lock,
b->fs_base_path, NULL, NULL, pool));
return SVN_NO_ERROR;
}
/* List the file/directory entries for PATH_OR_URL at REVISION.
The actual node revision selected is determined by the path as
@ -204,6 +277,10 @@ get_dir_contents(apr_uint32_t dirent_fields,
subdirectories (at svn_depth_empty). Else if DEPTH is
svn_depth_empty, just list PATH_OR_URL with none of its entries.
If PATTERNS is not NULL, the last path segments must match at least
one of const char * patterns in it or the respective dirent will not
be reported.
DIRENT_FIELDS controls which fields in the svn_dirent_t's are
filled in. To have them totally filled in use SVN_DIRENT_ALL,
otherwise simply bitwise OR together the combination of SVN_DIRENT_*
@ -230,6 +307,7 @@ static svn_error_t *
list_internal(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -248,6 +326,7 @@ list_internal(const char *path_or_url,
svn_error_t *err;
apr_hash_t *locks;
apr_hash_t *externals;
svn_membuf_t scratch_buffer;
if (include_externals)
externals = apr_hash_make(pool);
@ -266,12 +345,6 @@ list_internal(const char *path_or_url,
fs_path = svn_client__pathrev_fspath(loc, pool);
SVN_ERR(svn_ra_stat(ra_session, "", loc->rev, &dirent, pool));
if (! dirent)
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
_("URL '%s' non-existent in revision %ld"),
loc->url, loc->rev);
/* Maybe get all locks under url. */
if (fetch_locks)
{
@ -290,20 +363,52 @@ list_internal(const char *path_or_url,
else
locks = NULL;
/* Try to use the efficient and fully authz-filtered code path. */
if (!include_externals)
{
receiver_baton_t receiver_baton;
receiver_baton.list_baton = baton;
receiver_baton.ctx = ctx;
receiver_baton.list_func = list_func;
receiver_baton.locks = locks;
receiver_baton.fs_base_path = fs_path;
err = svn_ra_list(ra_session, "", loc->rev, patterns, depth,
dirent_fields, list_receiver, &receiver_baton, pool);
if (svn_error_find_cause(err, SVN_ERR_UNSUPPORTED_FEATURE))
svn_error_clear(err);
else
return svn_error_trace(err);
}
/* Stat for the file / directory node itself. */
SVN_ERR(svn_ra_stat(ra_session, "", loc->rev, &dirent, pool));
if (! dirent)
return svn_error_createf(SVN_ERR_FS_NOT_FOUND, NULL,
_("URL '%s' non-existent in revision %ld"),
loc->url, loc->rev);
/* We need a scratch buffer for temporary string data.
* Create one with a reasonable initial size. */
svn_membuf__create(&scratch_buffer, 256, pool);
/* Report the dirent for the target. */
SVN_ERR(list_func(baton, "", dirent, locks
? (svn_hash_gets(locks, fs_path))
: NULL, fs_path, external_parent_url,
external_target, pool));
if (match_patterns(svn_dirent_dirname(fs_path, pool), patterns,
&scratch_buffer))
SVN_ERR(list_func(baton, "", dirent, locks
? (svn_hash_gets(locks, fs_path))
: NULL, fs_path, external_parent_url,
external_target, pool));
if (dirent->kind == svn_node_dir
&& (depth == svn_depth_files
|| depth == svn_depth_immediates
|| depth == svn_depth_infinity))
SVN_ERR(get_dir_contents(dirent_fields, "", loc->rev, ra_session, locks,
fs_path, depth, ctx, externals,
fs_path, patterns, depth, ctx, externals,
external_parent_url, external_target, list_func,
baton, pool, pool));
baton, &scratch_buffer, pool, pool));
/* We handle externals after listing entries under path_or_url, so that
handling external items (and any errors therefrom) doesn't delay
@ -312,7 +417,7 @@ list_internal(const char *path_or_url,
{
/* The 'externals' hash populated by get_dir_contents() is processed
here. */
SVN_ERR(list_externals(externals, depth, dirent_fields,
SVN_ERR(list_externals(externals, patterns, depth, dirent_fields,
fetch_locks, list_func, baton,
ctx, pool));
}
@ -349,6 +454,7 @@ wrap_list_error(const svn_client_ctx_t *ctx,
static svn_error_t *
list_external_items(apr_array_header_t *external_items,
const char *externals_parent_url,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -389,6 +495,7 @@ list_external_items(apr_array_header_t *external_items,
list_internal(resolved_url,
&item->peg_revision,
&item->revision,
patterns,
depth, dirent_fields,
fetch_locks,
TRUE,
@ -411,6 +518,7 @@ list_external_items(apr_array_header_t *external_items,
passed to svn_client_list(). */
static svn_error_t *
list_externals(apr_hash_t *externals,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -440,9 +548,10 @@ list_externals(apr_hash_t *externals,
if (! external_items->nelts)
continue;
SVN_ERR(list_external_items(external_items, externals_parent_url, depth,
dirent_fields, fetch_locks, list_func,
baton, ctx, iterpool));
SVN_ERR(list_external_items(external_items, externals_parent_url,
patterns, depth, dirent_fields,
fetch_locks, list_func, baton, ctx,
iterpool));
}
svn_pool_destroy(iterpool);
@ -452,9 +561,10 @@ list_externals(apr_hash_t *externals,
svn_error_t *
svn_client_list3(const char *path_or_url,
svn_client_list4(const char *path_or_url,
const svn_opt_revision_t *peg_revision,
const svn_opt_revision_t *revision,
const apr_array_header_t *patterns,
svn_depth_t depth,
apr_uint32_t dirent_fields,
svn_boolean_t fetch_locks,
@ -462,14 +572,14 @@ svn_client_list3(const char *path_or_url,
svn_client_list_func2_t list_func,
void *baton,
svn_client_ctx_t *ctx,
apr_pool_t *pool)
apr_pool_t *scratch_pool)
{
return svn_error_trace(list_internal(path_or_url, peg_revision,
revision,
revision, patterns,
depth, dirent_fields,
fetch_locks,
include_externals,
NULL, NULL, list_func,
baton, ctx, pool));
baton, ctx, scratch_pool));
}

View File

@ -215,32 +215,6 @@
/*** Repos-Diff Editor Callbacks ***/
/* */
typedef struct merge_source_t
{
/* "left" side URL and revision (inclusive iff youngest) */
const svn_client__pathrev_t *loc1;
/* "right" side URL and revision (inclusive iff youngest) */
const svn_client__pathrev_t *loc2;
/* True iff LOC1 is an ancestor of LOC2 or vice-versa (history-wise). */
svn_boolean_t ancestral;
} merge_source_t;
/* Description of the merge target root node (a WC working node) */
typedef struct merge_target_t
{
/* Absolute path to the WC node */
const char *abspath;
/* The repository location of the base node of the target WC. If the node
* is locally added, then URL & REV are NULL & SVN_INVALID_REVNUM.
* REPOS_ROOT_URL and REPOS_UUID are always valid. */
svn_client__pathrev_t loc;
} merge_target_t;
typedef struct merge_cmd_baton_t {
svn_boolean_t force_delete; /* Delete a file/dir even if modified */
svn_boolean_t dry_run;
@ -1236,7 +1210,7 @@ struct merge_file_baton_t
/* If a tree conflict will be installed once edited, it's reason. If a skip
should be produced its reason. Some special values are defined. See the
merge_tree_baton_t for an explanation. */
merge_dir_baton_t for an explanation. */
svn_wc_conflict_reason_t tree_conflict_reason;
svn_wc_conflict_action_t tree_conflict_action;
svn_node_kind_t tree_conflict_local_node_kind;
@ -2266,13 +2240,9 @@ merge_file_added(const char *relpath,
Otherwise, we'll use a pure add. */
if (merge_b->same_repos)
{
const char *child =
svn_dirent_skip_ancestor(merge_b->target->abspath,
local_abspath);
SVN_ERR_ASSERT(child != NULL);
copyfrom_url = svn_path_url_add_component2(
merge_b->merge_source.loc2->url,
child, scratch_pool);
relpath, scratch_pool);
copyfrom_rev = right_source->revision;
SVN_ERR(check_repos_match(merge_b->target, local_abspath,
copyfrom_url, scratch_pool));
@ -5524,29 +5494,16 @@ single_range_conflict_report_create(const merge_source_t *conflicted_range,
return report;
}
/* Data for reporting when a merge aborted because of raising conflicts.
*
* ### TODO: More info, including the ranges (or other parameters) the user
* needs to complete the merge.
*/
typedef struct conflict_report_t
{
const char *target_abspath;
/* The revision range during which conflicts were raised */
const merge_source_t *conflicted_range;
/* Was the conflicted range the last range in the whole requested merge? */
svn_boolean_t was_last_range;
} conflict_report_t;
/* Return a new conflict_report_t containing deep copies of the parameters,
* allocated in RESULT_POOL. */
static conflict_report_t *
/* Return a new svn_client__conflict_report_t containing deep copies of the
* parameters, allocated in RESULT_POOL. */
static svn_client__conflict_report_t *
conflict_report_create(const char *target_abspath,
const merge_source_t *conflicted_range,
svn_boolean_t was_last_range,
apr_pool_t *result_pool)
{
conflict_report_t *report = apr_palloc(result_pool, sizeof(*report));
svn_client__conflict_report_t *report = apr_palloc(result_pool,
sizeof(*report));
report->target_abspath = apr_pstrdup(result_pool, target_abspath);
report->conflicted_range = merge_source_dup(conflicted_range, result_pool);
@ -5555,11 +5512,12 @@ conflict_report_create(const char *target_abspath,
}
/* Return a deep copy of REPORT, allocated in RESULT_POOL. */
static conflict_report_t *
conflict_report_dup(const conflict_report_t *report,
static svn_client__conflict_report_t *
conflict_report_dup(const svn_client__conflict_report_t *report,
apr_pool_t *result_pool)
{
conflict_report_t *new = apr_pmemdup(result_pool, report, sizeof(*new));
svn_client__conflict_report_t *new = apr_pmemdup(result_pool, report,
sizeof(*new));
new->target_abspath = apr_pstrdup(result_pool, report->target_abspath);
new->conflicted_range = merge_source_dup(report->conflicted_range,
@ -5567,11 +5525,9 @@ conflict_report_dup(const conflict_report_t *report,
return new;
}
/* Create and return an error structure appropriate for the unmerged
revisions range(s). */
static APR_INLINE svn_error_t *
make_merge_conflict_error(conflict_report_t *report,
apr_pool_t *scratch_pool)
svn_error_t *
svn_client__make_merge_conflict_error(svn_client__conflict_report_t *report,
apr_pool_t *scratch_pool)
{
assert(!report || svn_dirent_is_absolute(report->target_abspath));
@ -6512,10 +6468,7 @@ get_mergeinfo_paths(apr_array_header_t *children_with_mergeinfo,
/* Sort CHILDREN_WITH_MERGEINFO by each child's path (i.e. as per
compare_merge_path_t_as_paths). Any subsequent insertions of new
children with insert_child_to_merge() require this ordering. */
qsort(children_with_mergeinfo->elts,
children_with_mergeinfo->nelts,
children_with_mergeinfo->elt_size,
compare_merge_path_t_as_paths);
svn_sort__array(children_with_mergeinfo, compare_merge_path_t_as_paths);
}
svn_pool_destroy(swmi_pool);
@ -7125,8 +7078,7 @@ combine_range_with_segments(apr_array_header_t **merge_source_ts_p,
/* If this was a subtractive merge, and we created more than one
merge source, we need to reverse the sort ordering of our sources. */
if (subtractive && (merge_source_ts->nelts > 1))
qsort(merge_source_ts->elts, merge_source_ts->nelts,
merge_source_ts->elt_size, compare_merge_source_ts);
svn_sort__array(merge_source_ts, compare_merge_source_ts);
*merge_source_ts_p = merge_source_ts;
return SVN_NO_ERROR;
@ -9814,7 +9766,7 @@ ensure_ra_session_url(svn_ra_session_t **ra_session,
static svn_error_t *
do_merge(apr_hash_t **modified_subtrees,
svn_mergeinfo_catalog_t result_catalog,
conflict_report_t **conflict_report,
svn_client__conflict_report_t **conflict_report,
svn_boolean_t *use_sleep,
const apr_array_header_t *merge_sources,
const merge_target_t *target,
@ -10137,23 +10089,24 @@ do_merge(apr_hash_t **modified_subtrees,
SCRATCH_POOL is used for all temporary allocations.
*/
static svn_error_t *
merge_cousins_and_supplement_mergeinfo(conflict_report_t **conflict_report,
svn_boolean_t *use_sleep,
const merge_target_t *target,
svn_ra_session_t *URL1_ra_session,
svn_ra_session_t *URL2_ra_session,
const merge_source_t *source,
const svn_client__pathrev_t *yca,
svn_boolean_t same_repos,
svn_depth_t depth,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t record_only,
svn_boolean_t dry_run,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
merge_cousins_and_supplement_mergeinfo(
svn_client__conflict_report_t **conflict_report,
svn_boolean_t *use_sleep,
const merge_target_t *target,
svn_ra_session_t *URL1_ra_session,
svn_ra_session_t *URL2_ra_session,
const merge_source_t *source,
const svn_client__pathrev_t *yca,
svn_boolean_t same_repos,
svn_depth_t depth,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t record_only,
svn_boolean_t dry_run,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
apr_array_header_t *remove_sources, *add_sources;
apr_hash_t *modified_subtrees = NULL;
@ -10477,24 +10430,24 @@ open_target_wc(merge_target_t **target_p,
*
* IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
*/
static svn_error_t *
merge_locked(conflict_report_t **conflict_report,
const char *source1,
const svn_opt_revision_t *revision1,
const char *source2,
const svn_opt_revision_t *revision2,
const char *target_abspath,
svn_depth_t depth,
svn_boolean_t ignore_mergeinfo,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t record_only,
svn_boolean_t dry_run,
svn_boolean_t allow_mixed_rev,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
svn_error_t *
svn_client__merge_locked(svn_client__conflict_report_t **conflict_report,
const char *source1,
const svn_opt_revision_t *revision1,
const char *source2,
const svn_opt_revision_t *revision2,
const char *target_abspath,
svn_depth_t depth,
svn_boolean_t ignore_mergeinfo,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t record_only,
svn_boolean_t dry_run,
svn_boolean_t allow_mixed_rev,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
merge_target_t *target;
svn_client__pathrev_t *source1_loc, *source2_loc;
@ -10691,7 +10644,7 @@ svn_client_merge5(const char *source1,
apr_pool_t *pool)
{
const char *target_abspath, *lock_abspath;
conflict_report_t *conflict_report;
svn_client__conflict_report_t *conflict_report;
/* Sanity check our input -- we require specified revisions,
* and either 2 paths or 2 URLs. */
@ -10714,22 +10667,23 @@ svn_client_merge5(const char *source1,
if (!dry_run)
SVN_WC__CALL_WITH_WRITE_LOCK(
merge_locked(&conflict_report,
source1, revision1, source2, revision2,
target_abspath, depth, ignore_mergeinfo,
diff_ignore_ancestry,
force_delete, record_only, dry_run,
allow_mixed_rev, merge_options, ctx, pool, pool),
svn_client__merge_locked(&conflict_report,
source1, revision1, source2, revision2,
target_abspath, depth, ignore_mergeinfo,
diff_ignore_ancestry,
force_delete, record_only, dry_run,
allow_mixed_rev, merge_options, ctx, pool, pool),
ctx->wc_ctx, lock_abspath, FALSE /* lock_anchor */, pool);
else
SVN_ERR(merge_locked(&conflict_report,
source1, revision1, source2, revision2,
target_abspath, depth, ignore_mergeinfo,
diff_ignore_ancestry,
force_delete, record_only, dry_run,
allow_mixed_rev, merge_options, ctx, pool, pool));
SVN_ERR(svn_client__merge_locked(&conflict_report,
source1, revision1, source2, revision2,
target_abspath, depth, ignore_mergeinfo,
diff_ignore_ancestry,
force_delete, record_only, dry_run,
allow_mixed_rev, merge_options, ctx, pool,
pool));
SVN_ERR(make_merge_conflict_error(conflict_report, pool));
SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool));
return SVN_NO_ERROR;
}
@ -11756,7 +11710,7 @@ open_reintegrate_source_and_target(svn_ra_session_t **source_ra_session_p,
/* The body of svn_client_merge_reintegrate(), which see for details. */
static svn_error_t *
merge_reintegrate_locked(conflict_report_t **conflict_report,
merge_reintegrate_locked(svn_client__conflict_report_t **conflict_report,
const char *source_path_or_url,
const svn_opt_revision_t *source_peg_revision,
const char *target_abspath,
@ -11831,7 +11785,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url,
apr_pool_t *pool)
{
const char *target_abspath, *lock_abspath;
conflict_report_t *conflict_report;
svn_client__conflict_report_t *conflict_report;
SVN_ERR(get_target_and_lock_abspath(&target_abspath, &lock_abspath,
target_wcpath, ctx, pool));
@ -11851,7 +11805,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url,
FALSE /*diff_ignore_ancestry*/,
dry_run, merge_options, ctx, pool, pool));
SVN_ERR(make_merge_conflict_error(conflict_report, pool));
SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool));
return SVN_NO_ERROR;
}
@ -11861,7 +11815,7 @@ svn_client_merge_reintegrate(const char *source_path_or_url,
* IGNORE_MERGEINFO and DIFF_IGNORE_ANCESTRY are as in do_merge().
*/
static svn_error_t *
merge_peg_locked(conflict_report_t **conflict_report,
merge_peg_locked(svn_client__conflict_report_t **conflict_report,
const char *source_path_or_url,
const svn_opt_revision_t *source_peg_revision,
const svn_rangelist_t *ranges_to_merge,
@ -11913,6 +11867,21 @@ merge_peg_locked(conflict_report_t **conflict_report,
/* Do the real merge! (We say with confidence that our merge
sources are both ancestral and related.) */
if (getenv("SVN_ELEMENT_MERGE")
&& same_repos
&& (depth == svn_depth_infinity || depth == svn_depth_unknown)
&& ignore_mergeinfo
&& !record_only)
{
err = svn_client__merge_elements(&use_sleep,
merge_sources, target, ra_session,
diff_ignore_ancestry, force_delete,
dry_run, merge_options,
ctx, result_pool, scratch_pool);
/* ### Currently this merge just errors out on any conflicts */
*conflict_report = NULL;
}
else
err = do_merge(NULL, NULL, conflict_report, &use_sleep,
merge_sources, target, ra_session,
TRUE /*sources_related*/, same_repos, ignore_mergeinfo,
@ -11951,7 +11920,7 @@ client_find_automatic_merge(automatic_merge_t **merge_p,
apr_pool_t *scratch_pool);
static svn_error_t *
do_automatic_merge_locked(conflict_report_t **conflict_report,
do_automatic_merge_locked(svn_client__conflict_report_t **conflict_report,
const automatic_merge_t *merge,
const char *target_abspath,
svn_depth_t depth,
@ -11981,7 +11950,7 @@ svn_client_merge_peg5(const char *source_path_or_url,
apr_pool_t *pool)
{
const char *target_abspath, *lock_abspath;
conflict_report_t *conflict_report;
svn_client__conflict_report_t *conflict_report;
/* No ranges to merge? No problem. */
if (ranges_to_merge != NULL && ranges_to_merge->nelts == 0)
@ -12046,7 +12015,7 @@ svn_client_merge_peg5(const char *source_path_or_url,
force_delete, record_only, dry_run,
allow_mixed_rev, merge_options, ctx, pool, pool));
SVN_ERR(make_merge_conflict_error(conflict_report, pool));
SVN_ERR(svn_client__make_merge_conflict_error(conflict_report, pool));
return SVN_NO_ERROR;
}
@ -12731,7 +12700,7 @@ client_find_automatic_merge(automatic_merge_t **merge_p,
* eliminate already-cherry-picked revisions from the source.
*/
static svn_error_t *
do_automatic_merge_locked(conflict_report_t **conflict_report,
do_automatic_merge_locked(svn_client__conflict_report_t **conflict_report,
const automatic_merge_t *merge,
const char *target_abspath,
svn_depth_t depth,

View File

@ -0,0 +1,248 @@
/*
* merge_elements.c: element-based merging
*
* ====================================================================
* 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.
* ====================================================================
*/
#include <assert.h>
#include <apr_strings.h>
#include <apr_tables.h>
#include <apr_hash.h>
#include "svn_types.h"
#include "svn_error.h"
#include "svn_pools.h"
#include "svn_hash.h"
#include "svn_wc.h"
#include "svn_client.h"
#include "svn_dirent_uri.h"
#include "client.h"
#include "private/svn_element.h"
#include "svn_private_config.h"
/* Print a notification.
* ### TODO: Send notifications through ctx->notify_func2().
* ### TODO: Only when 'verbose' output is requested.
*/
static
__attribute__((format(printf, 1, 2)))
void
verbose_notify(const char *fmt,
...)
{
va_list ap;
va_start(ap, fmt);
vprintf(fmt, ap);
if (fmt[strlen(fmt) - 1] != '\n')
printf("\n");
va_end(ap);
}
/* Return a string representation of PATHREV. */
static const char *
pathrev_str(const svn_client__pathrev_t *pathrev,
apr_pool_t *pool)
{
const char *rrpath
= svn_uri_skip_ancestor(pathrev->repos_root_url, pathrev->url, pool);
return apr_psprintf(pool, "^/%s@%ld", rrpath, pathrev->rev);
}
/* Element matching info.
*/
typedef struct element_matching_info_t
{
void *info;
} element_matching_info_t;
/* Return a string representation of INFO. */
static const char *
element_matching_info_str(const element_matching_info_t *info,
apr_pool_t *result_pool)
{
/* ### */
const char *str = "{...}";
return str;
}
/* Assign EIDs (in memory) to the source-left, source-right and target
* trees.
*/
static svn_error_t *
assign_eids_to_trees(svn_element__tree_t **tree_left_p,
svn_element__tree_t **tree_right_p,
svn_element__tree_t **tree_target_p,
const svn_client__pathrev_t *src_left,
const svn_client__pathrev_t *src_right,
merge_target_t *target,
svn_ra_session_t *ra_session,
element_matching_info_t *element_matching_info,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
verbose_notify("--- Assigning EIDs to trees");
/* ### */
return SVN_NO_ERROR;
}
/* Perform a three-way tree merge. Write the result to *MERGE_RESULT_P.
*
* Set *CONFLICTS_P to describe any conflicts, or set *CONFLICTS_P to
* null if there are none.
*/
static svn_error_t *
merge_trees(svn_element__tree_t **merge_result_p,
void **conflicts_p,
svn_element__tree_t *tree_left,
svn_element__tree_t *tree_right,
svn_element__tree_t *tree_target,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
verbose_notify("--- Merging trees");
/* ### */
*merge_result_p = NULL;
*conflicts_p = NULL;
return SVN_NO_ERROR;
}
/* Convert the MERGE_RESULT to a series of WC edits and apply those to
* the WC described in TARGET.
*/
static svn_error_t *
apply_merge_result_to_wc(merge_target_t *target,
svn_element__tree_t *merge_result,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
verbose_notify("--- Writing merge result to WC");
return SVN_NO_ERROR;
}
/* Do a three-way element-based merge for one merge source range,
* SRC_LEFT:SRC_RIGHT. If there are no conflicts, write the result to the
* WC described in TARGET.
*/
static svn_error_t *
merge_elements_one_source(svn_boolean_t *use_sleep,
const svn_client__pathrev_t *src_left,
const svn_client__pathrev_t *src_right,
merge_target_t *target,
svn_ra_session_t *ra_session,
element_matching_info_t *element_matching_info,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t dry_run,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *scratch_pool)
{
svn_element__tree_t *tree_left, *tree_right, *tree_target;
svn_element__tree_t *merge_result;
void *conflicts;
verbose_notify("--- Merging by elements: "
"left=%s, right=%s, matching=%s",
pathrev_str(src_left, scratch_pool),
pathrev_str(src_right, scratch_pool),
element_matching_info_str(element_matching_info,
scratch_pool));
/* assign EIDs (in memory) to the source-left, source-right and target
trees */
SVN_ERR(assign_eids_to_trees(&tree_left, &tree_right, &tree_target,
src_left, src_right, target, ra_session,
element_matching_info,
ctx, scratch_pool, scratch_pool));
/* perform a tree merge, creating a temporary result (in memory) */
SVN_ERR(merge_trees(&merge_result, &conflicts,
tree_left, tree_right, tree_target,
scratch_pool, scratch_pool));
/* check for (new style) conflicts in the result; if any, bail out */
if (conflicts)
{
return svn_error_create(SVN_ERR_UNSUPPORTED_FEATURE, NULL,
_("Merge had conflicts; "
"this is not yet supported"));
}
/* convert the result to a series of WC edits and apply those to the WC */
if (dry_run)
{
verbose_notify("--- Dry run; not writing merge result to WC");
}
else
{
SVN_ERR(apply_merge_result_to_wc(target, merge_result,
ctx, scratch_pool));
*use_sleep = TRUE;
}
/* forget all the EID metadata */
return SVN_NO_ERROR;
}
svn_error_t *
svn_client__merge_elements(svn_boolean_t *use_sleep,
apr_array_header_t *merge_sources,
merge_target_t *target,
svn_ra_session_t *ra_session,
svn_boolean_t diff_ignore_ancestry,
svn_boolean_t force_delete,
svn_boolean_t dry_run,
const apr_array_header_t *merge_options,
svn_client_ctx_t *ctx,
apr_pool_t *result_pool,
apr_pool_t *scratch_pool)
{
int i;
/* Merge each source range in turn */
for (i = 0; i < merge_sources->nelts; i++)
{
merge_source_t *source
= APR_ARRAY_IDX(merge_sources, i, void *);
element_matching_info_t *element_matching_info;
/* ### TODO: get element matching info from the user */
element_matching_info = NULL;
SVN_ERR(merge_elements_one_source(use_sleep,
source->loc1, source->loc2,
target, ra_session,
element_matching_info,
diff_ignore_ancestry,
force_delete, dry_run, merge_options,
ctx, scratch_pool));
}
return SVN_NO_ERROR;
}

View File

@ -1946,12 +1946,12 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(
&subtree_source_history, source_history,
subtree_rel_path, scratch_pool, scratch_pool));
subtree_rel_path, scratch_pool, iterpool));
if (!finding_merged)
SVN_ERR(svn_mergeinfo__add_suffix_to_mergeinfo(
&subtree_history, target_history,
subtree_rel_path, scratch_pool, scratch_pool));
subtree_rel_path, scratch_pool, iterpool));
}
else
{
@ -1969,7 +1969,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
scratch_pool, iterpool));
SVN_ERR(svn_mergeinfo_merge2(subtree_mergeinfo,
merged_via_history,
scratch_pool, scratch_pool));
scratch_pool, iterpool));
}
SVN_ERR(svn_mergeinfo_inheritable2(&subtree_inheritable_mergeinfo,
@ -1995,7 +1995,7 @@ svn_client__mergeinfo_log(svn_boolean_t finding_merged,
subtree_source_history, FALSE,
scratch_pool, iterpool));
svn_mergeinfo__set_inheritance(merged_noninheritable, FALSE,
scratch_pool);
iterpool);
/* Keep track of all ranges partially merged to any and all
subtrees. */

View File

@ -568,10 +568,44 @@ svn_client__mtcc_add_copy(const char *src_relpath,
return SVN_NO_ERROR;
}
svn_error_t *
svn_client__mtcc_add_delete(const char *relpath,
svn_client__mtcc_t *mtcc,
apr_pool_t *scratch_pool)
/* Check if this operation contains at least one change that is not a
plain delete */
static svn_boolean_t
mtcc_op_contains_non_delete(const mtcc_op_t *op)
{
if (op->kind != OP_OPEN_DIR && op->kind != OP_OPEN_FILE
&& op->kind != OP_DELETE)
{
return TRUE;
}
if (op->prop_mods && op->prop_mods->nelts)
return TRUE;
if (op->src_stream)
return TRUE;
if (op->children)
{
int i;
for (i = 0; i < op->children->nelts; i++)
{
const mtcc_op_t *c_op = APR_ARRAY_IDX(op->children, i,
const mtcc_op_t *);
if (mtcc_op_contains_non_delete(c_op))
return TRUE;
}
}
return FALSE;
}
static svn_error_t *
mtcc_add_delete(const char *relpath,
svn_boolean_t for_move,
svn_client__mtcc_t *mtcc,
apr_pool_t *scratch_pool)
{
mtcc_op_t *op;
svn_boolean_t created;
@ -598,6 +632,20 @@ svn_client__mtcc_add_delete(const char *relpath,
SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, FALSE, TRUE,
TRUE, mtcc->pool, scratch_pool));
if (!for_move && !op && !created)
{
/* Allow deleting directories, that are unmodified except for
one or more deleted descendants */
SVN_ERR(mtcc_op_find(&op, &created, relpath, mtcc->root_op, TRUE,
FALSE, FALSE, mtcc->pool, scratch_pool));
if (op && mtcc_op_contains_non_delete(op))
op = NULL;
else
created = TRUE;
}
if (!op || !created)
{
return svn_error_createf(SVN_ERR_ILLEGAL_TARGET, NULL,
@ -613,6 +661,14 @@ svn_client__mtcc_add_delete(const char *relpath,
return SVN_NO_ERROR;
}
svn_error_t *
svn_client__mtcc_add_delete(const char *relpath,
svn_client__mtcc_t *mtcc,
apr_pool_t *scratch_pool)
{
return svn_error_trace(mtcc_add_delete(relpath, FALSE, mtcc, scratch_pool));
}
svn_error_t *
svn_client__mtcc_add_mkdir(const char *relpath,
svn_client__mtcc_t *mtcc,
@ -662,7 +718,7 @@ svn_client__mtcc_add_move(const char *src_relpath,
SVN_ERR(svn_client__mtcc_add_copy(src_relpath, mtcc->base_revision,
dst_relpath, mtcc, scratch_pool));
SVN_ERR(svn_client__mtcc_add_delete(src_relpath, mtcc, scratch_pool));
SVN_ERR(mtcc_add_delete(src_relpath, TRUE, mtcc, scratch_pool));
return SVN_NO_ERROR;
}
@ -712,6 +768,7 @@ mtcc_prop_getter(const svn_string_t **mime_type,
{
*mime_type = svn_string_dup(mod->value, pool);
mime_type = NULL;
break;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -727,7 +727,7 @@ repos_locations(const char **start_url,
/* We'd better have all the paths we were looking for! */
if (start_url)
{
start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(svn_revnum_t));
start_path = apr_hash_get(rev_locs, &start_revnum, sizeof(start_revnum));
if (! start_path)
return svn_error_createf
(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,
@ -739,7 +739,7 @@ repos_locations(const char **start_url,
if (end_url)
{
end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(svn_revnum_t));
end_path = apr_hash_get(rev_locs, &end_revnum, sizeof(end_revnum));
if (! end_path)
return svn_error_createf
(SVN_ERR_CLIENT_UNRELATED_RESOURCES, NULL,

View File

@ -141,6 +141,8 @@ svn_client_relocate2(const char *wcroot_dir,
apr_hash_index_t *hi;
apr_pool_t *iterpool = NULL;
const char *old_repos_root_url, *new_repos_root_url;
char *sig_from_prefix, *sig_to_prefix;
apr_size_t index_from, index_to;
/* Populate our validator callback baton, and call the relocate code. */
vb.ctx = ctx;
@ -183,6 +185,21 @@ svn_client_relocate2(const char *wcroot_dir,
if (! apr_hash_count(externals_hash))
return SVN_NO_ERROR;
/* A valid prefix for the main working copy may be too long to be
valid for an external. Trim any common trailing characters to
leave the significant part that changes. */
sig_from_prefix = apr_pstrdup(pool, from_prefix);
sig_to_prefix = apr_pstrdup(pool, to_prefix);
index_from = strlen(sig_from_prefix);
index_to = strlen(sig_to_prefix);
while (index_from && index_to
&& sig_from_prefix[index_from] == sig_to_prefix[index_to])
{
sig_from_prefix[index_from] = sig_to_prefix[index_to] = '\0';
--index_from;
--index_to;
}
iterpool = svn_pool_create(pool);
for (hi = apr_hash_first(pool, externals_hash);
@ -218,7 +235,8 @@ svn_client_relocate2(const char *wcroot_dir,
SVN_ERR(err);
if (strcmp(old_repos_root_url, this_repos_root_url) == 0)
SVN_ERR(svn_client_relocate2(this_abspath, from_prefix, to_prefix,
SVN_ERR(svn_client_relocate2(this_abspath,
sig_from_prefix, sig_to_prefix,
FALSE /* ignore_externals */,
ctx, iterpool));
}

View File

@ -1,5 +1,5 @@
/*
* resolved.c: wrapper around wc resolved functionality.
* resolved.c: wrapper around Subversion <=1.9 wc resolved functionality
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
@ -41,6 +41,7 @@
#include "private/svn_wc_private.h"
#include "svn_private_config.h"
/*** Code. ***/

View File

@ -89,7 +89,9 @@ svn_client__get_revision_number(svn_revnum_t *revnum,
/* The BASE, COMMITTED, and PREV revision keywords do not
apply to URLs. */
if (svn_path_is_url(local_abspath))
goto invalid_rev_arg;
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("PREV, BASE, or COMMITTED revision "
"keywords are invalid for URL"));
err = svn_wc__node_get_origin(NULL, revnum, NULL, NULL, NULL, NULL,
NULL,
@ -129,7 +131,9 @@ svn_client__get_revision_number(svn_revnum_t *revnum,
/* The BASE, COMMITTED, and PREV revision keywords do not
apply to URLs. */
if (svn_path_is_url(local_abspath))
goto invalid_rev_arg;
return svn_error_create(SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("PREV, BASE, or COMMITTED revision "
"keywords are invalid for URL"));
SVN_ERR(svn_wc__node_get_changed_info(revnum, NULL, NULL,
wc_ctx, local_abspath,
@ -183,10 +187,4 @@ svn_client__get_revision_number(svn_revnum_t *revnum,
*revnum = *youngest_rev;
return SVN_NO_ERROR;
invalid_rev_arg:
return svn_error_create(
SVN_ERR_CLIENT_BAD_REVISION, NULL,
_("PREV, BASE, or COMMITTED revision keywords are invalid for URL"));
}

View File

@ -0,0 +1,552 @@
/*
* 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;
}

View File

@ -179,6 +179,122 @@ svn_client_upgrade(const char *path,
return SVN_NO_ERROR;
}
/* Helper for upgrade_externals_from_properties: upgrades one external ITEM
in EXTERNALS_PARENT. Uses SCRATCH_POOL for temporary allocations. */
static svn_error_t *
upgrade_external_item(svn_client_ctx_t *ctx,
const char *externals_parent_abspath,
const char *externals_parent_url,
const char *externals_parent_repos_root_url,
svn_wc_external_item2_t *item,
struct repos_info_baton *info_baton,
apr_pool_t *scratch_pool)
{
const char *resolved_url;
const char *external_abspath;
const char *repos_relpath;
const char *repos_root_url;
const char *repos_uuid;
svn_node_kind_t external_kind;
svn_revnum_t peg_revision;
svn_revnum_t revision;
svn_error_t *err;
external_abspath = svn_dirent_join(externals_parent_abspath,
item->target_dir,
scratch_pool);
SVN_ERR(svn_wc__resolve_relative_external_url(
&resolved_url,
item,
externals_parent_repos_root_url,
externals_parent_url,
scratch_pool, scratch_pool));
/* This is a hack. We only need to call svn_wc_upgrade() on external
* dirs, as file externals are upgraded along with their defining
* WC. Reading the kind will throw an exception on an external dir,
* saying that the wc must be upgraded. If it's a file, the lookup
* is done in an adm_dir belonging to the defining wc (which has
* already been upgraded) and no error is returned. If it doesn't
* exist (external that isn't checked out yet), we'll just get
* svn_node_none. */
err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
external_abspath, TRUE, FALSE, scratch_pool);
if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
{
svn_error_clear(err);
SVN_ERR(svn_client_upgrade(external_abspath, ctx, scratch_pool));
}
else if (err)
return svn_error_trace(err);
/* The upgrade of any dir should be done now, get the now reliable
* kind. */
SVN_ERR(svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
TRUE, FALSE, scratch_pool));
/* Update the EXTERNALS table according to the root URL,
* relpath and uuid known in the upgraded external WC. */
/* We should probably have a function that provides all three
* of root URL, repos relpath and uuid at once, but here goes... */
/* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
* when the node is not present in the file system.
* svn_wc__node_get_repos_info() would try to derive the URL. */
SVN_ERR(svn_wc__node_get_repos_info(NULL,
&repos_relpath,
&repos_root_url,
&repos_uuid,
ctx->wc_ctx,
external_abspath,
scratch_pool, scratch_pool));
/* If we haven't got any information from the checked out external,
* or if the URL information mismatches the external's definition,
* ask fetch_repos_info() to find out the repos root. */
if (0 != strcmp(resolved_url,
svn_path_url_add_component2(repos_root_url,
repos_relpath,
scratch_pool)))
{
SVN_ERR(fetch_repos_info(&repos_root_url, &repos_uuid, info_baton,
resolved_url, scratch_pool, scratch_pool));
repos_relpath = svn_uri_skip_ancestor(repos_root_url,
resolved_url,
scratch_pool);
/* There's just the URL, no idea what kind the external is.
* That's fine, as the external isn't even checked out yet.
* The kind will be set during the next 'update'. */
external_kind = svn_node_unknown;
}
peg_revision = (item->peg_revision.kind == svn_opt_revision_number
? item->peg_revision.value.number
: SVN_INVALID_REVNUM);
revision = (item->revision.kind == svn_opt_revision_number
? item->revision.value.number
: SVN_INVALID_REVNUM);
SVN_ERR(svn_wc__upgrade_add_external_info(ctx->wc_ctx,
external_abspath,
external_kind,
externals_parent_abspath,
repos_relpath,
repos_root_url,
repos_uuid,
peg_revision,
revision,
scratch_pool));
return SVN_NO_ERROR;
}
static svn_error_t *
upgrade_externals_from_properties(svn_client_ctx_t *ctx,
const char *local_abspath,
@ -207,34 +323,32 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
hi = apr_hash_next(hi))
{
int i;
const char *externals_parent_abspath;
const char *externals_parent_url;
const char *externals_parent_repos_root_url;
const char *externals_parent_repos_relpath;
const char *externals_parent = apr_hash_this_key(hi);
const char *externals_parent_abspath = apr_hash_this_key(hi);
svn_string_t *external_desc = apr_hash_this_val(hi);
apr_array_header_t *externals_p;
svn_error_t *err;
svn_pool_clear(iterpool);
/* svn_client_propget5() has API promise to return absolute paths. */
SVN_ERR_ASSERT(svn_dirent_is_absolute(externals_parent_abspath));
externals_p = apr_array_make(iterpool, 1,
sizeof(svn_wc_external_item2_t*));
/* In this loop, an error causes the respective externals definition, or
* the external (inner loop), to be skipped, so that upgrade carries on
* with the other externals. */
err = svn_dirent_get_absolute(&externals_parent_abspath,
externals_parent, iterpool);
if (!err)
err = svn_wc__node_get_repos_info(NULL,
&externals_parent_repos_relpath,
&externals_parent_repos_root_url,
NULL,
ctx->wc_ctx,
externals_parent_abspath,
iterpool, iterpool);
err = svn_wc__node_get_repos_info(NULL,
&externals_parent_repos_relpath,
&externals_parent_repos_root_url,
NULL,
ctx->wc_ctx,
externals_parent_abspath,
iterpool, iterpool);
if (!err)
externals_parent_url = svn_path_url_add_component2(
@ -248,7 +362,7 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
if (err)
{
svn_wc_notify_t *notify =
svn_wc_create_notify(externals_parent,
svn_wc_create_notify(externals_parent_abspath,
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;
@ -265,130 +379,21 @@ upgrade_externals_from_properties(svn_client_ctx_t *ctx,
for (i = 0; i < externals_p->nelts; i++)
{
svn_wc_external_item2_t *item;
const char *resolved_url;
const char *external_abspath;
const char *repos_relpath;
const char *repos_root_url;
const char *repos_uuid;
svn_node_kind_t external_kind;
svn_revnum_t peg_revision;
svn_revnum_t revision;
item = APR_ARRAY_IDX(externals_p, i, svn_wc_external_item2_t*);
svn_pool_clear(iterpool2);
external_abspath = svn_dirent_join(externals_parent_abspath,
item->target_dir,
iterpool2);
err = upgrade_external_item(ctx, externals_parent_abspath,
externals_parent_url,
externals_parent_repos_root_url,
item, info_baton, iterpool2);
err = svn_wc__resolve_relative_external_url(
&resolved_url,
item,
externals_parent_repos_root_url,
externals_parent_url,
scratch_pool, scratch_pool);
if (err)
goto handle_error;
/* This is a hack. We only need to call svn_wc_upgrade() on external
* dirs, as file externals are upgraded along with their defining
* WC. Reading the kind will throw an exception on an external dir,
* saying that the wc must be upgraded. If it's a file, the lookup
* is done in an adm_dir belonging to the defining wc (which has
* already been upgraded) and no error is returned. If it doesn't
* exist (external that isn't checked out yet), we'll just get
* svn_node_none. */
err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx,
external_abspath, TRUE, FALSE, iterpool2);
if (err && err->apr_err == SVN_ERR_WC_UPGRADE_REQUIRED)
{
svn_error_clear(err);
err = svn_client_upgrade(external_abspath, ctx, iterpool2);
if (err)
goto handle_error;
}
else if (err)
goto handle_error;
/* The upgrade of any dir should be done now, get the now reliable
* kind. */
err = svn_wc_read_kind2(&external_kind, ctx->wc_ctx, external_abspath,
TRUE, FALSE, iterpool2);
if (err)
goto handle_error;
/* Update the EXTERNALS table according to the root URL,
* relpath and uuid known in the upgraded external WC. */
/* We should probably have a function that provides all three
* of root URL, repos relpath and uuid at once, but here goes... */
/* First get the relpath, as that returns SVN_ERR_WC_PATH_NOT_FOUND
* when the node is not present in the file system.
* svn_wc__node_get_repos_info() would try to derive the URL. */
err = svn_wc__node_get_repos_info(NULL,
&repos_relpath,
&repos_root_url,
&repos_uuid,
ctx->wc_ctx,
external_abspath,
iterpool2, iterpool2);
if (err)
goto handle_error;
/* If we haven't got any information from the checked out external,
* or if the URL information mismatches the external's definition,
* ask fetch_repos_info() to find out the repos root. */
if (0 != strcmp(resolved_url,
svn_path_url_add_component2(repos_root_url,
repos_relpath,
scratch_pool)))
{
err = fetch_repos_info(&repos_root_url,
&repos_uuid,
info_baton,
resolved_url,
scratch_pool, scratch_pool);
if (err)
goto handle_error;
repos_relpath = svn_uri_skip_ancestor(repos_root_url,
resolved_url,
iterpool2);
/* There's just the URL, no idea what kind the external is.
* That's fine, as the external isn't even checked out yet.
* The kind will be set during the next 'update'. */
external_kind = svn_node_unknown;
}
if (err)
goto handle_error;
peg_revision = (item->peg_revision.kind == svn_opt_revision_number
? item->peg_revision.value.number
: SVN_INVALID_REVNUM);
revision = (item->revision.kind == svn_opt_revision_number
? item->revision.value.number
: SVN_INVALID_REVNUM);
err = svn_wc__upgrade_add_external_info(ctx->wc_ctx,
external_abspath,
external_kind,
externals_parent,
repos_relpath,
repos_root_url,
repos_uuid,
peg_revision,
revision,
iterpool2);
handle_error:
if (err)
{
svn_wc_notify_t *notify =
svn_wc_create_notify(external_abspath,
svn_wc_create_notify(svn_dirent_join(externals_parent_abspath,
item->target_dir,
iterpool2),
svn_wc_notify_failed_external,
scratch_pool);
notify->err = err;

Some files were not shown because too many files have changed in this diff Show More