| <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" | 
 | "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> | 
 | <html xmlns="http://www.w3.org/1999/xhtml"> | 
 | <head> | 
 | <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> | 
 | <style type="text/css"> /* <![CDATA[ */ | 
 |   @import "branding/css/tigris.css"; | 
 |   @import "branding/css/inst.css"; | 
 |   /* ]]> */</style> | 
 | <link rel="stylesheet" type="text/css" media="print" | 
 |   href="branding/css/print.css" /> | 
 | <script type="text/javascript" src="branding/scripts/tigris.js"></script> | 
 | <title>Hacker's Guide to Subversion</title> | 
 | </head> | 
 |  | 
 | <body> | 
 | <div class="app"> | 
 |  | 
 | <h1 style="text-align: center;">Hacker's Guide to Subversion</h1> | 
 |  | 
 | <p>If you are contributing code to the Subversion project, please read | 
 | this first.</p> | 
 |  | 
 | <pre> | 
 | $LastChangedDate$ | 
 | </pre> | 
 |  | 
 |  | 
 | <!-- Other pages seem to use "h2" for ToC, but I think "h1" works | 
 |      better, because the ToC is fundamentally different from other | 
 |      sections and therefore it's confusing when it looks the same as | 
 |      the others. --> | 
 | <div class="h1"><!-- no 'id' or 'title' attribute for ToC --> | 
 | <h1>Table of Contents</h1> | 
 |  | 
 | <ul> | 
 | <li><a href="#participating">Participating in the community</a></li> | 
 | <li><a href="#docs">Theory and documentation</a></li> | 
 | <li><a href="#code-to-read">Code to read</a></li> | 
 | <li><a href="#directory-layout">Directory layout</a></li> | 
 | <li><a href="#coding-style">Coding style</a></li> | 
 | <li><a href="#secure-coding">Secure coding guidelines</a></li> | 
 | <li><a href="#destruction-of-stacked-resources">Destruction of stacked resources</a></li> | 
 | <li><a href="#documenting">Documentation</a></li> | 
 | <li><a href="#use-page-breaks">Using page breaks</a></li> | 
 | <li><a href="#error-messages">Error message conventions</a></li> | 
 | <li><a href="#other-conventions">Other conventions</a></li> | 
 | <li><a href="#apr-pools">APR pool usage conventions</a></li> | 
 | <li><a href="#apr-status-codes">APR status codes</a></li> | 
 | <li><a href="#exception-handling">Exception handling</a></li> | 
 | <li><a href="#automated-tests">Automated tests</a></li> | 
 | <li><a href="#write-test-cases-first">Writing test cases before code</a></li> | 
 | <li><a href="#server-debugging">Debugging the server</a></li> | 
 | <li><a href="#net-trace">Tracing network traffic</a></li> | 
 | <li><a href="#tracing-memory-leaks">Tracking down memory leaks</a></li> | 
 | <li><a href="#log-messages">Writing log messages</a></li> | 
 | <li><a href="#crediting">Crediting</a></li> | 
 | <li><a href="#patches">Patch submission guidelines</a></li> | 
 | <li><a href="#filing-issues">Filing bugs / issues</a></li> | 
 | <li><a href="#issue-triage">Issue triage</a></li> | 
 | <li><a href="#commit-access">Commit access</a></li> | 
 | <li><a href="#lightweight-branches">Use lightweight branches</a></li> | 
 | <li><a href="#configury">The configuration/build system under unix</a></li> | 
 | <li><a href="#releasing">How to release a distribution tarball</a></li> | 
 | <li><a href="#release-numbering">Release numbering, compatibility, and deprecation</a></li> | 
 | <li><a href="#release-stabilization">Stabilizing and maintaining releases</a></li> | 
 | <li><a href="#tarball-signing">Signing source distribution packages</a></li> | 
 | <li><a href="#custom-releases">Custom releases</a></li> | 
 | <li><a href="#l10n">Localization (l10n)</a></li> | 
 | </ul> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="participating" title="participating"> | 
 | <h2>Participating in the community</h2> | 
 |  | 
 | <p>Although Subversion is originally sponsored and hosted by CollabNet | 
 | (<a href="http://www.collab.net">http://www.collab.net</a>), it's a | 
 | true open-source project under a BSD-style license.  A number of | 
 | developers work for CollabNet, some work for other large companies | 
 | (such as RedHat), and many others are simply excellent volunteers who | 
 | are interested in building a better version control system.</p> | 
 |  | 
 | <p>The community exists mainly through mailing lists and a Subversion | 
 | repository.  To participate:</p> | 
 |  | 
 | <p>Go to <a href="http://subversion.tigris.org/" | 
 | >http://subversion.tigris.org/</a> and</p> | 
 |  | 
 | <ul> | 
 | <li><p>Join the "dev", "svn", and "announce" mailing lists. | 
 |        The dev list, dev@subversion.tigris.org, is where almost all | 
 |        discussion takes place.  All development questions should go | 
 |        there, though you might want to check the list archives first. | 
 |        The "svn" list receives automated commit emails.</p></li> | 
 |  | 
 | <li><p>Get a copy of the latest development sources from | 
 |        <a href="http://svn.collab.net/repos/svn/trunk/" | 
 |                >http://svn.collab.net/repos/svn/trunk/</a>. | 
 |        <br /> | 
 |        New development always takes place on trunk.  Bugfixes, | 
 |        enhancements, and new features are backported from there to the | 
 |        various release branches.</p></li>  | 
 | </ul> | 
 |  | 
 | <p>There are many ways to join the project, either by writing code, or | 
 | by testing and/or helping to manage the bug database.  If you'd like | 
 | to contribute, then look at:</p> | 
 |  | 
 | <ul> | 
 | <li><p>The bugs/issues database | 
 |        <a href="http://subversion.tigris.org/issue-tracker.html" | 
 |                >http://subversion.tigris.org/issue-tracker.html</a></p></li> | 
 |  | 
 | <li><p>The bite-sized tasks page | 
 |        <a href="http://subversion.tigris.org/project_tasks.html" | 
 |                >http://subversion.tigris.org/project_tasks.html</a></p></li> | 
 | </ul> | 
 |  | 
 | <p>To submit code, simply send your patches to | 
 | dev@subversion.tigris.org.  No, wait, first read the rest of this | 
 | file, <i>then</i> start sending patches to | 
 | dev@subversion.tigris.org. :-)</p> | 
 |  | 
 | <p>To help manage the issues database, read over the issue summaries, | 
 | looking and testing for issues that are either invalid, or are | 
 | duplicates of other issues.  Both kinds are very common, the first | 
 | because bugs often get unknowingly fixed as side effects of other | 
 | changes in the code, and the second because people sometimes file an | 
 | issue without noticing that it has already been reported.  If you are | 
 | not sure about an issue, post a question to dev@subversion.tigris.org. | 
 | ("Subversion: We're here to help you help us!")</p> | 
 |  | 
 | <p>Another way to help is to set up automated builds and test suite | 
 | runs of Subversion on some platform, and have the output sent to the | 
 | svn-breakage@subversion.tigris.org mailing list.  See more details at | 
 | <a href="http://subversion.tigris.org/servlets/ProjectMailingListList" | 
 |         >http://subversion.tigris.org/servlets/ProjectMailingListList</a> | 
 | in the description for the svn-breakage list.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="docs" title="docs"> | 
 | <h2>Theory and documentation</h2> | 
 |  | 
 | <ol> | 
 | <li><p>Design</p> | 
 |  | 
 |      <p>A <a href="design.html">design spec</a> was written in June 2000, | 
 |      and is a bit out of date.  But it still gives a good theoretical | 
 |      introduction to the inner workings of the repository, and to | 
 |      Subversion's various layers.</p> | 
 | </li> | 
 |  | 
 | <li><p>API Documentation</p> | 
 |      <p>See the section on the <a href="#doxygen-docs">public API | 
 |      documentation</a> for more information.</p> | 
 | </li> | 
 |  | 
 | <li><p>Delta Editors</p> | 
 |      <p>Karl Fogel wrote a chapter for O'Reilly's 2007 book | 
 |      <a href="http://beautifulcode.oreillynet.com/"> | 
 |      Beautiful Code: Leading Programmers Explain How They Think</a> | 
 |      covering the design and use of | 
 |      <a href="http://www.red-bean.com/kfogel/beautiful-code/bc-chapter-02.html"> | 
 |      Subversion's delta editor interface</a>.</p> | 
 | </li> | 
 |  | 
 | <li> <p>Network Protocols</p> | 
 |  | 
 |      <p>The <a href="webdav-usage.html">WebDAV Usage</a> document is | 
 |      an introduction to Subversion's DAV network protocol, which is | 
 |      an extended dialect of HTTP and uses URLs beginning with | 
 |      "http://" or "https://".</p> | 
 |  | 
 |      <p>The <a | 
 | href="http://svn.collab.net/repos/svn/trunk/subversion/libsvn_ra_svn/protocol" | 
 |      >SVN Protocol</a> document contains a formal description of | 
 |      Subversion ra_svn network protocol, which is a custom protocol | 
 |      on port 3690 (by default), whose URLs begin with "svn://" or | 
 |      "svn+ssh://".</p> | 
 | </li> | 
 |  | 
 | <li><p>User Manual</p> | 
 |  | 
 |      <p>Version Control with Subversion is a book published by | 
 |      O'Reilly that shows in detail how to effectively use Subversion. | 
 |      The text of the book is free, and is actively being revised. | 
 |      On-line versions are available | 
 |      at <a href="http://svnbook.red-bean.com" | 
 |      >http://svnbook.red-bean.com</a>.  The XML source and | 
 |      translations to other languages are maintained in their own | 
 |      repository at <a href="http://svn.red-bean.com/svnbook" | 
 |      >http://svn.red-bean.com/svnbook</a>.</p> | 
 | </li> | 
 |  | 
 | <li><p>System notes</p> | 
 |  | 
 |      <p>A lot of the design ideas for particular aspects of the system | 
 |      have been documented in individual files in the  | 
 |      <a href="http://svn.collab.net/repos/svn/trunk/notes/">notes/</a> | 
 |      directory.</p> | 
 | </li> | 
 |  | 
 | </ol> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="code-to-read" title="code-to-read"> | 
 | <h2>Code to read</h2> | 
 |  | 
 | <p>Before you can contribute code, you'll need to familiarize yourself | 
 | with the existing code base and interfaces.</p> | 
 |  | 
 | <p>Check out a copy of Subversion (anonymously, if you don't yet have | 
 | an account with commit access) — so you can look at | 
 | the code.</p> | 
 |  | 
 | <p>Within 'subversion/include/' are a bunch of header files with huge | 
 | doc comments.  If you read through these, you'll have a pretty good | 
 | understanding of the implementation details.  Here's a suggested | 
 | perusal order:</p> | 
 |  | 
 | <ol> | 
 | <li><p>the basic building blocks:  svn_string.h, svn_error.h, svn_types.h</p> | 
 | </li> | 
 | <li><p>useful utilities:  svn_io.h, svn_path.h, svn_hash.h, svn_xml.h</p> | 
 | </li> | 
 | <li><p>the critical interface:  svn_delta.h</p> | 
 | </li> | 
 | <li><p>client-side interfaces:  svn_ra.h, svn_wc.h, svn_client.h</p> | 
 | </li> | 
 | <li><p>the repository and versioned filesystem:  svn_repos.h, svn_fs.h</p> | 
 | </li> | 
 | </ol> | 
 |  | 
 | <p>Subversion tries to stay portable by using only ANSI/ISO C and by | 
 | using the Apache Portable Runtime (APR) library.  APR is the | 
 | portability layer used by the Apache httpd server, and more | 
 | information can be found at <a href="http://apr.apache.org/" | 
 | >http://apr.apache.org/</a>.</p> | 
 |  | 
 | <p>Because Subversion depends so heavily on APR, it may be hard to | 
 | understand Subversion without first glancing over certain header files | 
 | in APR (look in 'apr/include/'):</p> | 
 |  | 
 | <ul> | 
 | <li><p>memory pools:  apr_pools.h</p></li> | 
 | <li><p>filesystem access:  apr_file_io.h</p></li> | 
 | <li><p>hashes and arrays:  apr_hash.h, apr_tables.h</p></li> | 
 | </ul> | 
 |  | 
 | <p>Subversion also tries to deliver reliable and secure software. This | 
 | can only be achieved by developers who understand secure programming | 
 | in the C programming language. Please see 'notes/assurance.txt' for | 
 | the full rationale behind this.  Specifically, you should make it a | 
 | point to carefully read David Wheeler's Secure Programming (as | 
 | mentioned in 'notes/assurance.txt'). If at any point you have | 
 | questions about the security implications of a change, you are urged | 
 | to ask for review on the developer mailing list.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="directory-layout" title="directory-layout"> | 
 | <h2>Directory layout</h2> | 
 |  | 
 | <p>A rough guide to the source tree:</p> | 
 |  | 
 | <ul> | 
 | <li><p><tt>doc/</tt><br /> | 
 |     User and Developer documentation.</p> | 
 | </li> | 
 | <li><p><tt>www/</tt><br /> | 
 |     Subversion web pages (live content at | 
 |       <a href="http://subversion.tigris.org/" | 
 |       >http://subversion.tigris.org/</a>).</p> | 
 | </li> | 
 | <li><p><tt>tools/</tt><br /> | 
 |     Stuff that works with Subversion, but that Subversion doesn't | 
 |     depend on.  Code in tools/ is maintained collectively by the | 
 |     Subversion project, and is under the same open source copyright as | 
 |     Subversion itself.</p> | 
 | </li> | 
 | <li><p><tt>contrib/</tt><br /> | 
 |     Stuff that works with Subversion, but that Subversion doesn't | 
 |     depend on, and that is maintained by individuals who may or may | 
 |     not participate in Subversion development.  Code in contrib/ is | 
 |     open source, but may have a different license or copyright holder | 
 |     than Subversion itself.</p> | 
 | </li> | 
 | <li><p><tt>packages/</tt><br /> | 
 |     Stuff to help packaging systems, like rpm and dpkg.</p> | 
 | </li> | 
 | <li><p><tt>subversion/</tt><br /> | 
 |     Source code to Subversion itself (as opposed to external | 
 |     libraries).</p> | 
 | </li> | 
 | <li><p><tt>subversion/include/</tt><br /> | 
 |     Public header files for users of Subversion libraries.</p> | 
 | </li> | 
 | <li><p><tt>subversion/include/private/</tt><br /> | 
 |     Private header files shared internally by Subversion libraries.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_fs/</tt><br /> | 
 |     The versioning "filesystem" API.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_repos/</tt><br /> | 
 |     Repository functionality built around the `libsvn_fs' core.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_delta/</tt><br /> | 
 |     Common code for tree deltas, text deltas, and property deltas.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_wc/</tt><br /> | 
 |     Common code for working copies.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_ra/</tt><br /> | 
 |     Common code for repository access.</p> | 
 | </li> | 
 | <li><p><tt>subversion/libsvn_client/</tt><br /> | 
 |     Common code for client operations.</p> | 
 | </li> | 
 | <li><p><tt>subversion/svn/</tt><br /> | 
 |     The command line client.</p> | 
 | </li> | 
 | <li><p><tt>subversion/tests/</tt><br /> | 
 |     Automated test suite.</p> | 
 | </li> | 
 | <li><p><tt>apr/</tt><br /> | 
 |     Apache Portable Runtime library.  (Note: This is not in the same | 
 |     repository as Subversion.  Read INSTALL for instructions on how to | 
 |     get it if you don't already have it.)</p> | 
 | </li> | 
 | <li><p><tt>neon/</tt><br /> | 
 |     Neon library from Joe Orton.  (Note: This is not in the same | 
 |     repository as Subversion.  Read INSTALL for instructions on how to | 
 |     get it if you don't already have it.)</p> | 
 | </li> | 
 | </ul> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="coding-style" title="coding-style"> | 
 | <h2>Coding style</h2> | 
 |  | 
 | <p>Subversion uses ANSI C, and follows the GNU coding standards, | 
 | except that we do not put a space between the name of a function and | 
 | the opening parenthesis of its parameter list.  Emacs users can just | 
 | load svn-dev.el to get the right indentation behavior (most source | 
 | files here will load it automatically, if `enable-local-eval' is set | 
 | appropriately).</p> | 
 |  | 
 | <p>Read <a href="http://www.gnu.org/prep/standards.html" | 
 | >http://www.gnu.org/prep/standards.html</a> for a full description of | 
 | the GNU coding standards.  Below is a short example demonstrating the | 
 | most important formatting guidelines, including our | 
 | no-space-before-param-list-paren exception:</p> | 
 |  | 
 | <pre> | 
 |    char *                                     /* func type on own line */ | 
 |    argblarg(char *arg1, int arg2)             /* func name on own line */ | 
 |    {                                          /* first brace on own line */ | 
 |      if ((some_very_long_condition && arg2)   /* indent 2 cols */ | 
 |          || remaining_condition)              /* new line before operator */ | 
 |        {                                      /* brace on own line, indent 2 */ | 
 |          arg1 = some_func(arg1, arg2);        /* NO SPACE BEFORE PAREN */ | 
 |        }                                      /* close brace on own line */ | 
 |      else | 
 |        { | 
 |          do                                   /* format do-while like this */ | 
 |            { | 
 |              arg1 = another_func(arg1); | 
 |            } | 
 |          while (*arg1); | 
 |        } | 
 |    } | 
 | </pre> | 
 |  | 
 | <p>In general, be generous with parentheses even when you're sure | 
 | about the operator precedence, and be willing to add spaces and | 
 | newlines to avoid "code crunch".  Don't worry too much about vertical | 
 | density; it's more important to make code readable than to fit that | 
 | extra line on the screen.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="secure-coding" title="secure-coding"> | 
 | <h2>Secure coding guidelines</h2> | 
 |  | 
 | <p>Just like almost any other programming language, C has undesirable | 
 | features which enables an attacker to make your program fail in | 
 | predictable ways, often to the attacker's benefit. The goal of these | 
 | guidelines is to make you aware of the pitfalls of C as they apply to | 
 | the Subversion project.  You are encouraged to keep these pitfalls in | 
 | mind when reviewing code of your peers, as even the most skilled and | 
 | paranoid programmers make occasional mistakes.</p> | 
 |  | 
 | <p>Input validation is the act of defining legal input and rejecting | 
 | everything else. The code must perform input validation on all | 
 | untrusted input. </p> | 
 |  | 
 | <p>Security boundaries:</p> | 
 |  | 
 | <p>A security boundary in the Subversion server code must be | 
 | identified as such as this enables auditors to quickly determine the | 
 | quality of the boundary.  Security boundaries exist where the running | 
 | code has access to information the user does not or where the code | 
 | runs with privileges above those of the user making the | 
 | request. Typical examples of such is code that does access control or | 
 | an application with the SUID bit set.</p> | 
 |  | 
 | <p>Functions which make calls to a security boundary must include | 
 | validation checks of the arguments passed. Functions which themselves | 
 | are security boundaries should audit the input received and alarm when | 
 | invoked with improper values. </p> | 
 |  | 
 | <p>[### todo: need some examples from Subversion here...]</p> | 
 |  | 
 | <p>String operations:</p> | 
 |  | 
 | <p>Use the string functions provided in apr_strings.h instead of | 
 | standard C library functions that write to strings.  The APR functions | 
 | are safer because they do bounds-checking and dest allocation | 
 | automatically.  Although there may be circumstances where it's | 
 | theoretically safe to use plain C string functions (such as when you | 
 | already know the lengths of the source and dest), please use the APR | 
 | functions anyway, so the code is less brittle and more reviewable.</p> | 
 |  | 
 | <p>Password storage:</p> | 
 |  | 
 | <p>Help users keep their passwords secret: When the client reads or | 
 | writes password locally, it should ensure that the file is mode | 
 | 0600. If the file is readable by other users, the client should exit | 
 | with a message that tells the user to change the filemode due to the | 
 | risk of exposure.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="destruction-of-stacked-resources" | 
 |      title="destruction-of-stacked-resources"> | 
 | <h2>Destruction of stacked resources</h2> | 
 |  | 
 | <p>Some resources need destruction to ensure correct functioning of the | 
 | application.  Such resources include files, especially since open | 
 | files cannot be deleted on Windows.</p> | 
 |  | 
 | <p>When writing an API which creates and returns a stream, in the | 
 | background this stream may be stacked on a file or other stream.  To | 
 | ensure correct destruction of the resources the stream is built upon, | 
 | it must correctly call the destructors of the stream(s) it is built | 
 | upon (owns).</p> | 
 |  | 
 | <p>At first in <a href="http://svn.haxx.se/dev/archive-2005-12/0487.shtml"> | 
 | http://svn.haxx.se/dev/archive-2005-12/0487.shtml</a> | 
 | and later in <a href="http://svn.haxx.se/dev/archive-2005-12/0633.shtml"> | 
 | http://svn.haxx.se/dev/archive-2005-12/0633.shtml</a> this | 
 | was discussed in more general terms for files, streams, editors and | 
 | window handlers.</p> | 
 |  | 
 | <p>As Greg Hudson put it:</p> | 
 |  | 
 | <blockquote> | 
 | <p>On consideration, here is where I would like us to be:</p> | 
 |  | 
 | <ul><li>Streams which read from or write to an underlying object own that | 
 | object, i.e. closing the stream closes the underlying object, if | 
 | applicable.</li> | 
 |  | 
 | <li>The layer (function or data type) which created a stream is | 
 | responsible for closing it, except when the above rule applies.</li> | 
 |  | 
 | <li>Window handlers are thought of as an odd kind of stream, and passing | 
 | the final NULL window is considered closing the stream.</li> | 
 | </ul> | 
 |  | 
 | <p>If you think of apply_textdelta as creating a window handler, then I | 
 | don't think we're too far off.  svn_stream_from_aprfile isn't owning its | 
 | subsidiary file, svn_txdelta_apply is erroneously taking responsibility | 
 | for closing the window stream it is passed, and there may be some other | 
 | deviations.</p> | 
 | </blockquote> | 
 |  | 
 | <p>There is one exception to the rules above though.  When a stream is passed | 
 | to a function as an argument (for example: the 'out' parameter of | 
 | svn_client_cat2()), that routine can't call the streams destructor, since | 
 | it did not create that resource.</p> | 
 |  | 
 | <p>If svn_client_cat2() creates a stream, it must also call the destructor | 
 | for that stream.  By the above model, that stream will call the destructor | 
 | for the 'out' parameter.  This is however wrong, because the responsibility | 
 | to destruct the 'out' parameter lies elsewhere.</p> | 
 |  | 
 | <p>To solve this problem, at least in the stream case, svn_stream_disown() | 
 | has been introduced.  This function wraps a stream, making sure it's | 
 | <em>not</em> destroyed, even though any streams stacked upon it may try | 
 | to do so.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="documenting" title="documenting"> | 
 | <h2>Documentation</h2> | 
 |  | 
 | <div class="h3" id="document-everything" title="document-everything"> | 
 | <h3>Document Everything</h3> | 
 | <p>Every function, whether public or internal, must start out with a | 
 | documentation comment that describes what the function does.  The | 
 | documentation should mention every parameter received by the function, | 
 | every possible return value, and (if not obvious) the conditions under | 
 | which the function could return an error.</p> | 
 |  | 
 | <p>For internal documentation put the parameter names in upper case | 
 | in the doc string, even when they are not upper case in the actual | 
 | declaration, so that they stand out to human readers.</p> | 
 |  | 
 | <p>For public or semi-public API functions, the doc string should go | 
 | above the function in the .h file where it is declared; otherwise, it | 
 | goes above the function definition in the .c file.</p> | 
 |  | 
 | <p>For structure types, document each individual member of the structure as | 
 | well as the structure itself.</p> | 
 |  | 
 | <p>For actual source code, internally document chunks of each function, so | 
 | that an someone familiar with Subversion can understand the algorithm being | 
 | implemented.  Do not include obvious or overly verbose documentation; the | 
 | comments should help understanding of the code, not hinder it.</p> | 
 |  | 
 | <p>For example:</p> | 
 | <pre> | 
 |   <span style="color: red;">/*** How not to document.  Don't do this. ***/</span> | 
 |  | 
 |   /* Make a foo object. */ | 
 |   static foo_t * | 
 |   make_foo_object(arg1, arg2, apr_pool_t *pool) | 
 |   { | 
 |      /* Create a subpool. */ | 
 |      apr_pool_t *subpool = svn_pool_create(pool); | 
 |  | 
 |      /* Allocate a foo object from the main pool */ | 
 |      foo_t *foo = apr_palloc(pool, sizeof(*foo)); | 
 |      ... | 
 |   } | 
 | </pre> | 
 |  | 
 | <p>Instead, document decent sized chunks of code, like this:</p> | 
 | <pre> | 
 |       /* Transmit the segment (if its within the scope of our concern). */ | 
 |       SVN_ERR(maybe_crop_and_send_segment(segment, start_rev, end_rev, | 
 |                                           receiver, receiver_baton, subpool)); | 
 |  | 
 |       /* If we've set CURRENT_REV to SVN_INVALID_REVNUM, we're done | 
 |          (and didn't ever reach END_REV).  */ | 
 |       if (! SVN_IS_VALID_REVNUM(current_rev)) | 
 |         break; | 
 |  | 
 |       /* If there's a gap in the history, we need to report as much | 
 |          (if the gap is within the scope of our concern). */ | 
 |       if (segment->range_start - current_rev < 1) | 
 |         { | 
 |           svn_location_segment_t *gap_segment; | 
 |           gap_segment = apr_pcalloc(subpool, sizeof(*gap_segment)); | 
 |           gap_segment->range_end = segment->range_start - 1; | 
 |           gap_segment->range_start = current_rev + 1; | 
 |           gap_segment->path = NULL; | 
 |           SVN_ERR(maybe_crop_and_send_segment(gap_segment, start_rev, end_rev, | 
 |                                               receiver, receiver_baton, | 
 |                                               subpool)); | 
 |         } | 
 | </pre> | 
 |  | 
 | <p>Read over the Subversion code to get an overview of how documentation looks | 
 | in practice; in particular, see  | 
 | <a href="http://svn.collab.net/repos/svn/trunk/subversion/include/"> | 
 | subversion/include/*.h</a> for doxygen examples. | 
 | </p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="doxygen-docs" title="doxygen-docs"> | 
 | <h3>Public API Documentation</h3> | 
 | <p>We use the <a href="http://www.doxygen.org/">Doxygen</a> format for | 
 | public interface documentation.  This means anything that goes in a | 
 | public header file.  <a href="http://svn.collab.net/svn-doxygen/">Snapshots | 
 | </a> of the public API documentation are generated nightly from the latest | 
 | Subversion sources.</p> | 
 |  | 
 | <p>We use only a small portion of the available | 
 | <a href="http://www.stack.nl/~dimitri/doxygen/commands.html">doxygen | 
 | commands</a> to markup our source.  When writing doxygen documentation, the | 
 | following conventions apply:</p> | 
 | <ul> | 
 |   <li>Use complete sentences and prose descriptions of the function, preceding | 
 |   parameter names with <code>@a</code>, and type and macro names with | 
 |   <code>@c</code>.</li> | 
 |  | 
 |   <li>Use <code><tt>...</tt></code> to display multiple words | 
 |   and <code>@p</code> to display only one word in typewriter font.</li> | 
 |  | 
 |   <li>Constant values, such as <code>TRUE</code>, <code>FALSE</code> and  | 
 |   <code>NULL</code> should be in all caps.</li> | 
 |  | 
 |   <li>When several functions are related, define a group name, and group them | 
 |   together using <code>@defgroup</code> and <code>@{...@}</code>.</li> | 
 | </ul> | 
 |  | 
 | <p>See the <a href="http://www.stack.nl/~dimitri/doxygen/manual.html">Doxygen | 
 | manual</a> for a complete list of commands.</p> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="use-page-breaks" title="use-page-breaks"> | 
 | <h2>Using page breaks</h2> | 
 |  | 
 | <p>We're using page breaks (the Ctrl-L character, ASCII 12) for | 
 | section boundaries in both code and plaintext prose files.  Each | 
 | section starts with a page break, and immediately after the page break | 
 | comes the title of the section.</p> | 
 |  | 
 | <p>This helps out people who use the Emacs page commands, such as | 
 | `pages-directory' and `narrow-to-page'.  Such people are not as scarce | 
 | as you might think, and if you'd like to become one of them, then add | 
 | (require 'page-ext) to your .emacs and type C-x C-p C-h sometime.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="error-messages" title="error-messages"> | 
 | <h2>Error message conventions</h2> | 
 |  | 
 | <p>For error messages the following conventions apply:</p> | 
 |  | 
 | <ul> | 
 |  | 
 | <li><p>Provide specific error messages only when there is information  | 
 |      to add to the general error message found in  | 
 |      subversion/include/svn_error_codes.h.</p></li> | 
 |  | 
 | <li><p>Messages start with a capital letter.</p></li> | 
 |  | 
 | <li><p>Try keeping messages below 70 characters.</p></li> | 
 |  | 
 | <li><p>Don't end the error message with a period (".").</p></li> | 
 |  | 
 | <li><p>Don't include newline characters in error messages.</p></li> | 
 |  | 
 | <li><p>Quoting information is done using single quotes (e.g. "'some info'").</p></li> | 
 |  | 
 | <li><p>Don't include the name of the function where the error occurs | 
 |      in the error message. If Subversion is compiled using the | 
 |      '--enable-maintainer-mode' configure-flag, it will provide this | 
 |      information by itself.</p></li> | 
 |  | 
 | <li><p>When including path or filenames in the error string, be sure | 
 |      to quote them (e.g. "Can't find '/path/to/repos/userfile'").</p></li> | 
 |  | 
 | <li><p>When including path or filenames in the error string, be sure | 
 |      to convert them using <a | 
 |      href="http://svn.collab.net/svn-doxygen/svn__path_8h.html#a1" | 
 |      ><tt>svn_path_local_style()</tt></a> before inclusion (since | 
 |      paths passed to and from Subversion APIs are assumed to be | 
 |      in <a href="http://svn.collab.net/svn-doxygen/svn__path_8h.html#a0" | 
 |      >canonical form</a>).</p></li> | 
 |  | 
 | <li><p>Don't use Subversion-specific abbreviations (e.g. use "repository" | 
 |      instead of "repo", "working copy" instead of "wc").</p></li> | 
 |  | 
 | <li><p>If you want to add an explanation to the error, report it | 
 |      followed by a colon and the explanation like this:</p> | 
 |      <pre> | 
 |        "Invalid " SVN_PROP_EXTERNALS " property on '%s': " | 
 |        "target involves '.' or '..'". | 
 |      </pre></li> | 
 |  | 
 | <li><p>Suggestions or other additions can be added after a semi-colon,  | 
 |      like this:</p> | 
 |      <pre> | 
 |        "Can't write to '%s': object of same name already exists; remove " | 
 |        "before retrying". | 
 |      </pre></li> | 
 |  | 
 | <li><p>Try to stay within the boundaries of these conventions, so please avoid | 
 |      separating different parts of error messages by other separators such  | 
 |      as '--' and others.</p></li> | 
 |  | 
 | </ul> | 
 |  | 
 | <p>Also read about <a href="#l10n">Localization</a>.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="other-conventions" title="other-conventions"> | 
 | <h2>Other conventions</h2> | 
 |  | 
 | <p>In addition to the GNU standards, Subversion uses these | 
 | conventions:</p> | 
 |  | 
 | <ul> | 
 | <li><p>When using a path or file name as input to most <a | 
 |      href="http://svn.collab.net/svn-doxygen/">Subversion APIs</a>, be | 
 |      sure to convert them to Subversion's internal/canonical form | 
 |      using the <a href="http://svn.collab.net/svn-doxygen/svn__path_8h.html#a0" | 
 |      ><tt>svn_path_internal_style()</tt></a> API.  Alternately, when | 
 |      receiving a path or file name as output from a Subversion API, | 
 |      convert them into the expected form for your platform using the  | 
 |      <a href="http://svn.collab.net/svn-doxygen/svn__path_8h.html#a1" | 
 |      ><tt>svn_path_local_style()</tt></a> API.</p></li> | 
 |  | 
 | <li><p>Use only spaces for indenting code, never tabs.  Tab display | 
 |       width is not standardized enough, and anyway it's easier to | 
 |       manually adjust indentation that uses spaces.</p> | 
 | </li> | 
 |  | 
 | <li><p>Restrict lines to 79 columns, so that code will display well in a | 
 |       minimal standard display window.  (There can be exceptions, such | 
 |       as when declaring a block of 80-column text with a few extra | 
 |       columns taken up by indentation, quotes, etc., if splitting each | 
 |       line in two would be unreasonably messy.)</p> | 
 | </li> | 
 |  | 
 | <li><p>All published functions, variables, and structures must be signified | 
 |       with the corresponding library name - such as libsvn_wc's | 
 |       svn_wc_adm_open.  All library-internal declarations made in a | 
 |       library-private header file (such as libsvn_wc/wc.h) must be signified | 
 |       by two underscores after the library prefix (such as | 
 |       svn_wc__ensure_directory).  All declarations private to a single file | 
 |       (such as the static function get_entry_url inside of | 
 |       <tt>libsvn_wc/update_editor.c</tt>) do not require any | 
 |       additional namespace decorations.  Symbols that need to be used | 
 |       outside a library, but still are not public are put in a shared | 
 |       header file in the <tt>include/private/</tt> directory, and use | 
 |       the double underscore notation.  Such symbols may be used by | 
 |       Subversion core code only.</p> | 
 |        | 
 |       <p>To recap:</p> | 
 |       <pre> | 
 |          /* Part of published API: subversion/include/svn_wc.h */ | 
 |          svn_wc_adm_open()             | 
 |          #define SVN_WC_ADM_DIR_NAME ... | 
 |          typedef enum svn_wc_schedule_t ... | 
 |  | 
 |          /* For use within one library only: subversion/libsvn_wc/wc.h */ | 
 |          svn_wc__ensure_directory()    | 
 |          #define SVN_WC__BASE_EXT ...  | 
 |          typedef struct svn_wc__compat_notify_baton_t ... | 
 |  | 
 |          /* For use within one file: subversion/libsvn_wc/update_editor.c */  | 
 |          get_entry_url() | 
 |          struct handler_baton { | 
 |  | 
 |          /* For internal use in svn core code only: | 
 |             subversion/include/private/svn_wc_private.h */ | 
 |          svn_wc__entry_versioned() | 
 |       </pre> | 
 |  | 
 |      <p>Pre-Subversion 1.5, private symbols which needed to be used | 
 |        outside of a library were put into public header files, | 
 |        using the double underscore notation.  This practice has been | 
 |        abandoned, and any such symbols are legacy, maintained for <a | 
 |        href="#release-numbering">backwards compatibility</a>.</p> | 
 | </li> | 
 |  | 
 | <li><p>In text strings that might be printed out (or otherwise made | 
 |       available) to users, use only forward quotes around paths and | 
 |       other quotable things.  For example:</p> | 
 |       <pre> | 
 |          $ svn revert foo | 
 |          svn: warning: svn_wc_is_wc_root: 'foo' is not a versioned resource | 
 |          $ | 
 |       </pre> | 
 |  | 
 |       <p>There used to be a lot of strings that used a backtick for | 
 |       the first quote (`foo' instead of 'foo'), but that looked bad in | 
 |       some fonts, and also messed up some people's auto-highlighting, | 
 |       so we settled on the convention of always using forward | 
 |       quotes.</p> | 
 | </li> | 
 |  | 
 | <li><p>If you use Emacs, put something like this in your .emacs file, | 
 |       so you get svn-dev.el and svnbook.el when needed:</p> | 
 |       <pre> | 
 |          ;;; Begin Subversion development section | 
 |          (defun my-find-file-hook () | 
 |            (let ((svn-tree-path (expand-file-name "~/projects/subversion")) | 
 |                  (book-tree-path (expand-file-name "~/projects/svnbook"))) | 
 |              (cond | 
 |               ((string-match svn-tree-path buffer-file-name) | 
 |                (load (concat svn-tree-path "/tools/dev/svn-dev"))) | 
 |               ((string-match book-tree-path buffer-file-name) | 
 |                ;; Handle load exception for svnbook.el, because it tries to | 
 |                ;; load psgml, and not everyone has that available. | 
 |                (condition-case nil | 
 |                    (load (concat book-tree-path "/src/tools/svnbook")) | 
 |                  (error | 
 |                   (message "(Ignored problem loading svnbook.el.)"))))))) | 
 |  | 
 |          (add-hook 'find-file-hooks 'my-find-file-hook) | 
 |          ;;; End Subversion development section | 
 |       </pre> | 
 |  | 
 |       <p>You'll need to customize the path for your setup, of course. | 
 |       You can also make the regexp to string-match more selective; for | 
 |       example, one developer says:</p> | 
 |       <pre> | 
 |       > Here's the regexp I'm using: | 
 |       >  | 
 |       >     "src/svn/[^/]*/\\(subversion\\|tools\\|build\\)/" | 
 |       > | 
 |       > Two things to notice there: (1) I sometimes have several | 
 |       > working copies checked out under ...src/svn, and I want the | 
 |       > regexp to match all of them; (2) I want the hook to catch only | 
 |       > in "our" directories within the working copy, so I match | 
 |       > "subversion", "tools" and "build" explicitly; I don't want to | 
 |       > use GNU style in the APR that's checked out into my repo. :-) | 
 |       </pre> | 
 | </li> | 
 |  | 
 | <li><p>We have a tradition of not marking files with the names of | 
 |       individual authors (i.e., we don't put lines like | 
 |       "Author: foo" or "@author foo" in a special position | 
 |       at the top of a source file).  This is to discourage | 
 |       territoriality — even when a file has only one | 
 |       author, we want to make sure others feel free to make changes. | 
 |       People might be unnecessarily hesitant if someone appears to | 
 |       have staked a personal claim to the file.</p> | 
 | </li> | 
 |  | 
 | <li><p>Put two spaces between the end of one sentence and the start of | 
 |       the next.  This helps readability, and allows people to use | 
 |       their editors' sentence-motion and -manipulation commands.</p> | 
 | </li> | 
 |  | 
 | <li><p>There are many other unspoken conventions maintained throughout | 
 |       the code, that are only noticed when someone unintentionally | 
 |       fails to follow them.  Just try to have a sensitive eye for the | 
 |       way things are done, and when in doubt, ask.</p> | 
 | </li> | 
 | </ul> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="apr-pools" title="apr-pools"> | 
 | <h2>APR pool usage conventions</h2> | 
 |  | 
 | <p>(This assumes you already basically understand how APR pools work; | 
 | see apr_pools.h for details.)</p> | 
 |  | 
 | <p>Applications using the Subversion libraries must call | 
 | apr_initialize() before calling any Subversion functions.</p> | 
 |  | 
 | <p>Subversion's general pool usage strategy can be summed up in two | 
 | principles:</p> | 
 |  | 
 | <ol> | 
 | <li><p>The call level that created a pool is the only place to clear or | 
 |        destroy that pool.</p> | 
 | </li> | 
 | <li><p>When iterating an unbounded number of times, create a subpool | 
 |        before entering the iteration, use it inside the loop and clear  | 
 |        it at the start of each iteration, then destroy it after the loop  | 
 |        is done, like so:</p> | 
 |        <pre> | 
 |          apr_pool_t *subpool = svn_pool_create(pool); | 
 |  | 
 |          for (i = 0; i < n; ++i) | 
 |          { | 
 |            svn_pool_clear(subpool); | 
 |            do_operation(..., subpool); | 
 |          } | 
 |  | 
 |          svn_pool_destroy(subpool); | 
 |        </pre> | 
 | </li> | 
 | </ol> | 
 |  | 
 | <p>By using a loop subpool for loop-bounded data, you ensure O(1) instead | 
 | of O(N) memory leakage should the function return abruptly from | 
 | within the loop (say, due to error).  That's why you shouldn't make a | 
 | subpool for data which persists throughout a function, but instead | 
 | should use the pool passed in by the caller.  That memory will be | 
 | reclaimed when the caller's pool is cleared or destroyed.  If the | 
 | caller is invoking the callee in a loop, then trust the caller to take | 
 | care of clearing the pool on each iteration.  The same logic | 
 | propagates all the way up the call stack.</p> | 
 |  | 
 | <p>The pool you use also helps readers of the code understand object | 
 | lifetimes.  Is a given object used only during one iteration of the | 
 | loop, or will it need to last beyond the end of the loop?  For | 
 | example, pool choices indicate a lot about what's going on in this | 
 | code:</p> | 
 |  | 
 | <pre> | 
 |       apr_hash_t *persistent_objects = apr_hash_make(pool); | 
 |       apr_pool_t *subpool = svn_pool_create(pool); | 
 |  | 
 |       for (i = 0; i < n; ++i) | 
 |       { | 
 |         const char *intermediate_result; | 
 |         const char *key, *val; | 
 |          | 
 |         svn_pool_clear(subpool); | 
 |         SVN_ERR(do_something(&intermediate_result, ..., subpool)); | 
 |         SVN_ERR(get_result(intermediate_result, &key, &val, ..., pool)); | 
 |         apr_hash_set(persistent_objects, key, APR_HASH_KEY_STRING, val); | 
 |       } | 
 |       svn_pool_destroy(subpool); | 
 |  | 
 |       return persistent_objects; | 
 | </pre> | 
 |  | 
 | <p>Except for some legacy code, which was written before these | 
 | principles were fully understood, virtually all pool usage in | 
 | Subversion follows the above guidelines.</p> | 
 |  | 
 | <p>One such legacy pattern is a tendency to allocate an object inside | 
 | a pool, store the pool in the object, and then free that pool (either | 
 | directly or through a close_foo() function) to destroy the object.</p> | 
 |  | 
 | <p>For example:</p> | 
 |  | 
 | <pre> | 
 |    <span style="color: red;">/*** Example of how NOT to use pools.  Don't be like this. ***/</span> | 
 |  | 
 |    static foo_t * | 
 |    make_foo_object(arg1, arg2, apr_pool_t *pool) | 
 |    { | 
 |       apr_pool_t *subpool = svn_pool_create(pool); | 
 |       foo_t *foo = apr_palloc(subpool, sizeof(*foo)); | 
 |  | 
 |       foo->field1 = arg1; | 
 |       foo->field2 = arg2; | 
 |       foo->pool   = subpool; | 
 |    } | 
 |  | 
 |    [...] | 
 |  | 
 |    [Now some function calls make_foo_object() and returns, passing | 
 |    back a new foo object.] | 
 |  | 
 |    [...] | 
 |  | 
 |    [Now someone, at some random call level, decides that the foo's | 
 |    lifetime is over, and calls svn_pool_destroy(foo->pool).] | 
 | </pre> | 
 |  | 
 | <p>This is tempting, but it defeats the point of using pools, which is | 
 | to not worry so much about individual allocations, but rather about | 
 | overall performance and lifetime groups.  Instead, foo_t generally | 
 | should not have a `pool' field.  Just allocate as many foo objects as | 
 | you need in the current pool — when that pool gets | 
 | cleared or destroyed, they will all go away simultaneously.</p> | 
 |  | 
 | <p>See also the <a href="#exception-handling">Exception handling</a> | 
 | section, for details of how resources associated with a pool are | 
 | cleaned up when that pool is destroyed.</p> | 
 |  | 
 | <p>In summary:</p> | 
 |  | 
 | <ul> | 
 |  | 
 | <li><p>Objects should not have their own pools.  An object is | 
 |        allocated into a pool defined by the constructor's caller.  The | 
 |        caller knows the lifetime of the object and will manage it via | 
 |        the pool.</p> | 
 | </li> | 
 |  | 
 | <li><p>Functions should not create/destroy pools for their operation; | 
 |        they should use a pool provided by the caller.  Again, the | 
 |        caller knows more about how the function will be used, how | 
 |        often, how many times, etc. thus, it should be in charge of the | 
 |        function's memory usage.</p> | 
 |  | 
 |     <p>For example, the caller might know that the app will exit upon | 
 |        the function's return. Thus, the function would create extra | 
 |        work if it built/destroyed a pool. Instead, it should use the | 
 |        passed-in pool, which the caller is going to be tossing as part | 
 |        of app-exit anyway.</p> | 
 | </li> | 
 |  | 
 | <li><p>Whenever an unbounded iteration occurs, an iteration subpool | 
 |        should be used.</p> | 
 | </li> | 
 |  | 
 | <li><p>Given all of the above, it is pretty well mandatory to pass a | 
 |        pool to every function.  Since objects are not recording pools | 
 |        for themselves, and the caller is always supposed to be | 
 |        managing memory, then each function needs a pool, rather than | 
 |        relying on some hidden magic pool.  In limited cases, objects | 
 |        may record the pool used for their construction so that they | 
 |        can construct sub-parts, but these cases should be examined | 
 |        carefully.</p> | 
 | </li> | 
 | </ul> | 
 |  | 
 |  | 
 | <p>See also <a href="#tracing-memory-leaks">Tracking down memory | 
 | leaks</a> for tips on diagnosing pool usage problems.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="apr-status-codes" title="apr-status-codes"> | 
 | <h2>APR status codes</h2> | 
 |  | 
 | <p>Always check for APR status codes (except APR_SUCCESS) with the | 
 | APR_STATUS_IS_...() macros, not by direct comparison. This is required | 
 | for portability to non-Unix platforms.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="exception-handling" title="exception-handling"> | 
 | <h2>Exception handling</h2> | 
 |  | 
 | <p>OK, here's how to use exceptions in Subversion.</p> | 
 |  | 
 | <ol> | 
 |  | 
 | <li><p>Exceptions are stored in svn_error_t structures:</p> | 
 |  | 
 | <pre> | 
 | typedef struct svn_error_t | 
 | { | 
 |   apr_status_t apr_err;      /* APR error value, possibly SVN_ custom err */ | 
 |   const char *message;       /* details from producer of error */ | 
 |   struct svn_error_t *child; /* ptr to the error we "wrap" */ | 
 |   apr_pool_t *pool;          /* place to generate message strings from */ | 
 |   const char *file;          /* Only used iff SVN_DEBUG */ | 
 |   long line;                 /* Only used iff SVN_DEBUG */ | 
 | } svn_error_t; | 
 | </pre> | 
 |  | 
 | </li> | 
 |  | 
 | <li><p>If you are the <em>original</em> creator of an error, you would do | 
 |        something like this:</p> | 
 |  | 
 |     <pre> | 
 | return svn_error_create(SVN_ERR_FOO, NULL,  | 
 |                         "User not permitted to write file"); | 
 |     </pre> | 
 |  | 
 |     <p>NOTICE the NULL field... indicating that this error has no | 
 |     child, i.e. it is the bottom-most error.</p> | 
 |  | 
 |     <p>See also the <a href="#error-messages"> section on writing | 
 |     error messages</a>.</p> | 
 |  | 
 |     <p>Subversion internally uses UTF-8 to store its data. This also | 
 |     applies to the 'message' string. APR is assumed to return its data | 
 |     in the current locale, so any text returned by APR needs | 
 |     conversion to UTF-8 before inclusion in the message string.</p> | 
 | </li> | 
 |  | 
 | <li><p>If you <em>receive</em> an error, you have three choices:</p> | 
 |  | 
 |     <ol> | 
 |     <li><p>Handle the error yourself.  Use either your own code, or | 
 |            just call the primitive svn_handle_error(err).  (This | 
 |            routine unwinds the error stack and prints out messages | 
 |            converting them from UTF-8 to the current locale.)</p> | 
 |  | 
 |         <p>When your routine receives an error which it intends to | 
 |            ignore or handle itself, be sure to clean it up using | 
 |            svn_error_clear(). Any time such an error is not cleared | 
 |            constitutes a <em>memory leak</em>.</p> | 
 |     </li> | 
 |  | 
 |     <li><p>Throw the error upwards, unmodified:</p> | 
 |  | 
 |         <pre> | 
 |         error = some_routine(foo); | 
 |         if (error) | 
 |           return (error); | 
 |         </pre> | 
 |  | 
 |         <p>Actually, a better way to do this would be with the | 
 |         SVN_ERR() macro, which does the same thing:</p> | 
 |         <pre> | 
 |         SVN_ERR(some_routine(foo)); | 
 |         </pre> | 
 |      </li> | 
 |  | 
 |     <li><p>Throw the error upwards, wrapping it in a new error | 
 |            structure by including it as the "child" argument:</p> | 
 |  | 
 |         <pre> | 
 |         error = some_routine(foo); | 
 |         if (error) | 
 |           { | 
 |            svn_error_t *wrapper = svn_error_create(SVN_ERR_FOO, error, | 
 |                                                    "Authorization failed"); | 
 |            return wrapper; | 
 |           } | 
 |         </pre> | 
 |  | 
 |         <p>Of course, there's a convenience routine which creates a | 
 |            wrapper error with the same fields as the child, except for | 
 |            your custom message:</p> | 
 |  | 
 |         <pre> | 
 |         error = some_routine(foo); | 
 |         if (error) | 
 |           { | 
 |            return svn_error_quick_wrap(error,  | 
 |                                        "Authorization failed"); | 
 |           } | 
 |         </pre> | 
 |  | 
 |         <p>The same can (and should) be done by using the SVN_ERR_W() | 
 |            macro:</p> | 
 |  | 
 |         <pre> | 
 |           SVN_ERR_W(some_routine(foo), "Authorization failed"); | 
 |         </pre> | 
 |     </li> | 
 |     </ol> | 
 |  | 
 |     <p>In cases (b) and (c) it is important to know that resources | 
 |     allocated by your routine which are associated with a pool, are | 
 |     automatically cleaned up when the pool is destroyed. This means | 
 |     that there is no need to cleanup these resources before passing | 
 |     the error. There is therefore no reason not to use the SVN_ERR() | 
 |     and SVN_ERR_W() macros.  Resources associated with pools are:</p> | 
 |  | 
 |     <ul> | 
 |  | 
 |     <li><p>Memory</p></li> | 
 |  | 
 |     <li><p>Files</p> | 
 |  | 
 |         <p>All files opened with apr_file_open are closed at pool | 
 |         cleanup.  Subversion uses this function in its svn_io_file_* | 
 |         api, which means that files opened with svn_io_file_* or | 
 |         apr_file_open will be closed at pool cleanup.</p> | 
 |  | 
 |         <p>Some files (lock files for example) need to be removed when | 
 |         an operation is finished. APR has the APR_DELONCLOSE flag for | 
 |         this purpose.  The following functions create files which are | 
 |         removed on pool cleanup:</p> | 
 |  | 
 |         <ul> | 
 |         <li><p>apr_file_open and svn_io_file_open (when passed the  | 
 |                APR_DELONCLOSE flag)</p></li> | 
 |         <li><p>svn_io_open_unique_file (when passed TRUE in its | 
 |                delete_on_close)</p></li> | 
 |         </ul> | 
 |     | 
 |         <p>Locked files are unlocked if they were locked using | 
 |         svn_io_file_lock.</p> | 
 |     </li> | 
 |     </ul> | 
 |  | 
 | </li> | 
 | </ol> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="automated-tests" title="automated-tests"> | 
 | <h2>Automated tests</h2> | 
 |  | 
 | <p>For a description of how to use and add tests to Subversion's | 
 | automated test framework, please read <a | 
 | href="http://svn.collab.net/repos/svn/trunk/subversion/tests/README" | 
 | >subversion/tests/README</a> and <a | 
 | href="http://svn.collab.net/repos/svn/trunk/subversion/tests/cmdline/README" | 
 | >subversion/tests/cmdline/README</a>.</p> | 
 |  | 
 | <p>Various people have arranged for the automated test framework to | 
 | run at regular intervals on their own machines, sending the results to | 
 | the svn-breakage@subversion.tigris.org mailing list.  The more | 
 | different platforms the tests run on, the more quickly we can detect | 
 | portability bugs in Subversion.  If you'd like to send svn-breakage | 
 | messages too, use the <a | 
 | href="http://svn.collab.net/repos/svn/trunk/tools/test-scripts/svntest/"  | 
 | >svntest</a> framework (start at the <a | 
 | href="http://svn.collab.net/repos/svn/trunk/tools/test-scripts/svntest/README"  | 
 | >README</a>).</p> | 
 |  | 
 | <p>Lieven Govaerts has set up a | 
 | <a href="http://buildbot.sourceforge.net/" >BuildBot</a> build/test | 
 | farm at <a href="http://www.mobsol.be/buildbot/" | 
 | >http://www.mobsol.be/buildbot/</a>, see his message</p> | 
 |  | 
 | <pre> | 
 |    <a href="http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=114212">http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=114212</a> | 
 |    (Thread URL: <a href="http://subversion.tigris.org/servlets/BrowseList?list=dev&by=thread&from=450110">http://subversion.tigris.org/servlets/BrowseList?list=dev&by=thread&from=450110</a>) | 
 |    Message-ID: 20060326205918.F3C50708B0@adicia.telenet-ops.be | 
 |    From: "Lieven Govaerts" <lgo@mobsol.be> | 
 |    To: <dev@subversion.tigris.org> | 
 |    Subject: Update: Subversion build and test farm with Buildbot. | 
 |    Date: Sun, 26 Mar 2006 22:56:11 +0200 | 
 | </pre> | 
 |  | 
 | <p>for more details.  (<a href="http://buildbot.sourceforge.net/" | 
 | >BuildBot</a> is a system for centrally managing multiple automated | 
 | testing environments; it's especially useful for portability testing, | 
 | including of uncommitted changes.)</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="write-test-cases-first" title="write-test-cases-first"> | 
 | <h2>Writing test cases before code</h2> | 
 |  | 
 | <pre> | 
 | From: Karl Fogel <kfogel@collab.net> | 
 | Subject: writing test cases | 
 | To: dev@subversion.tigris.org | 
 | Date: Mon, 5 Mar 2001 15:58:46 -0600 | 
 |  | 
 | Many of us implementing the filesystem interface have now gotten into | 
 | the habit of writing the test cases (see fs-test.c) *before* writing | 
 | the actual code.  It's really helping us out a lot -- for one thing, | 
 | it forces one to define the task precisely in advance, and also it | 
 | speedily reveals the bugs in one's first try (and second, and | 
 | third...). | 
 |  | 
 | I'd like to recommend this practice to everyone.  If you're | 
 | implementing an interface, or adding an entirely new feature, or even | 
 | just fixing a bug, a test for it is a good idea.  And if you're going | 
 | to write the test anyway, you might as well write it first. :-) | 
 |  | 
 | Yoshiki Hayashi's been sending test cases with all his patches lately, | 
 | which is what inspired me to write this mail to encourage everyone to | 
 | do the same.  Having those test cases makes patches easier to examine, | 
 | because they show the patch's purpose very clearly.  It's like having | 
 | a second log message, one whose accuracy is verified at run-time. | 
 |  | 
 | That said, I don't think we want a rigid policy about this, at least | 
 | not yet.  If you encounter a bug somewhere in the code, but you only | 
 | have time to write a patch with no test case, that's okay -- having | 
 | the patch is still useful; someone else can write the test case. | 
 |  | 
 | As Subversion gets more complex, though, the automated test suite gets | 
 | more crucial, so let's all get in the habit of using it early. | 
 |  | 
 | -K | 
 | </pre> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="server-debugging" title="server-debugging"> | 
 | <h2>Debugging the server</h2> | 
 |  | 
 | <div class="h3" id="debugging-ra-dav" title="debugging-ra-dav"> | 
 | <h3>Debugging the DAV server</h3> | 
 |  | 
 | <p>'mod_dav_svn.so' contains the main Subversion server logic; it runs | 
 | as a module within mod_dav, which runs as a module within httpd. | 
 | Since httpd is probably using dynamic shared modules, you normally | 
 | won't be able to set breakpoints in advance when you start Apache in a | 
 | debugger such as GDB.  Instead, you'll need to start up, then | 
 | interrupt httpd, set your breakpoint, and continue:</p> | 
 |  | 
 | <pre> | 
 |    % gdb httpd | 
 |    (gdb) run -X | 
 |    ^C | 
 |    (gdb) break some_func_in_mod_dav_svn | 
 |    (gdb) continue | 
 | </pre> | 
 |  | 
 | <p>The -X switch is equivalent to -DONE_PROCESS and -DNO_DETACH, which | 
 | ensure that httpd runs as a single thread and remains attached to the | 
 | tty, respectively.  As soon as it starts, it sits and waits for | 
 | requests; that's when you hit control-C and set your breakpoint.</p> | 
 |  | 
 | <p>You'll probably want to watch Apache's run-time logs</p> | 
 |  | 
 | <pre> | 
 |    /usr/local/apache2/logs/error_log | 
 |    /usr/local/apache2/logs/access_log | 
 | </pre> | 
 |  | 
 | <p>to help determine what might be going wrong and where to set | 
 | breakpoints.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="debugging-ra-svn" title="debugging-ra-svn"> | 
 | <h3>Debugging the ra_svn client and server, on Unix</h3> | 
 |  | 
 | <p>Bugs in ra_svn usually manifest themselves with one of the | 
 | following cryptic error messages:</p> | 
 |  | 
 | <pre> | 
 |   svn: Malformed network data | 
 |   svn: Connection closed unexpectedly | 
 | </pre> | 
 |  | 
 | <p>(The first message can also mean the data stream was corrupted in | 
 | tunnel mode by user dotfiles or hook scripts; see  | 
 | <a href="http://subversion.tigris.org/issues/show_bug.cgi?id=1145" | 
 | >issue #1145</a>.)  The first message generally means you to have | 
 | to debug the client; the second message generally means you have to | 
 | debug the server.</p> | 
 |  | 
 | <p>It is easiest to debug ra_svn using a build with --disable-shared | 
 | --enable-maintainer-mode.  With the latter option, the error message | 
 | will tell you exactly what line to set a breakpoint at; otherwise, | 
 | look up the line number at the end of marshal.c:vparse_tuple() where | 
 | it returns the "Malformed network data" error.</p> | 
 |  | 
 | <p>To debug the client, simply pull it up in gdb, set a breakpoint, | 
 | and run the offending command:</p> | 
 |  | 
 | <pre> | 
 |   % gdb svn | 
 |   (gdb) break marshal.c:NNN | 
 |   (gdb) run ARGS | 
 |   Breakpoint 1, vparse_tuple (list=___, pool=___, fmt=___,  | 
 |     ap=___) at subversion/libsvn_ra_svn/marshal.c:NNN | 
 |   NNN                                 "Malformed network data"); | 
 | </pre> | 
 |  | 
 | <p>There are several bits of useful information:</p> | 
 |  | 
 | <ul> | 
 | <li><p>A backtrace will tell you exactly what protocol exchange is | 
 |     failing.</p> | 
 | </li> | 
 |  | 
 | <li><p>"print *conn" will show you the connection buffer.  read_buf, | 
 |     read_ptr, and read_end represent the read buffer, which can | 
 |     show | 
 |     you the data the marshaller is looking at.  (Since read_buf isn't | 
 |     generally 0-terminated at read_end, be careful of falsely assuming | 
 |     that there's garbage data in the buffer.)</p> | 
 | </li> | 
 |  | 
 | <li><p>The format string determines what the marshaller was expecting to | 
 |     see.</p> | 
 | </li> | 
 | </ul> | 
 |  | 
 | <p>To debug the server in daemon mode, pull it up in gdb, set a | 
 | breakpoint (usually a "Connection closed unexpectedly" error on the | 
 | client indicates a "Malformed network data" error on the server, | 
 | although it can also indicate a core dump), and run it with the "-X" | 
 | option to serve a single connection:</p> | 
 |  | 
 | <pre> | 
 |   % gdb svnserve | 
 |   (gdb) break marshal.c:NNN | 
 |   (gdb) run -X | 
 | </pre> | 
 |  | 
 | <p>Then run the offending client command.  From there, it's just like | 
 | debugging the client.</p> | 
 |  | 
 | <p>Debugging the server in tunnel mode is more of a pain.  You'll need | 
 | to stick something like "{ int x = 1; while (x); }" near the top of | 
 | svnserve's main() and put the resulting svnserve in the user path on | 
 | the server.  Then start an operation, gdb attach the process on the | 
 | server, "set x = 0", and step through the code as desired.</p> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="net-trace" title="net-trace"> | 
 | <h2>Tracing network traffic</h2> | 
 |  | 
 | <p>Use <a href="http://www.wireshark.org/">Wireshark</a> (formerly | 
 | known as "Ethereal") to eavesdrop on the conversation.</p> | 
 |  | 
 | <p>First, make sure that between captures within the same wireshark | 
 | session, you hit <em>Clear</em>, otherwise filters from one capture | 
 | (say, an HTTP capture) might interfere with others (say, an ra_svn | 
 | capture). </p> | 
 |  | 
 | <p>Assuming you're cleared, then:</p> | 
 |  | 
 | <ol> | 
 | <li><p>Pull down the <i>Capture</i> menu, and choose | 
 |     <i>Capture Filters</i>.</p></li> | 
 | <li><p>If debugging the http:// (WebDAV) protocol, then in the window | 
 |     that pops up, choose "<code>HTTP TCP port (80)</code>" | 
 |     (which should result in the filter string | 
 |     "<code><i>tcp port http</i></code>").</p> | 
 |     <p>If debugging the svn:// (ra_svn) protocol, then choose <i>New</i>, | 
 |     give the new filter a name (say, "ra_svn"), and type | 
 |     "<code>tcp port 3690</code>" into the filter string box.</p> | 
 |     <p>When done, click OK.</p></li>  | 
 | <li><p>Again go to the <i>Capture</i> menu, this time choose | 
 |     <i>Interfaces</i>, and click <i>Options</i> next to the | 
 |     appropriate interface (probably you want interface "lo", for | 
 |     "loopback", assuming the server will run on the same machine as | 
 |     the client).</p></li> | 
 | <li><p>Turn off promiscuous mode by unchecking the appropriate | 
 |     checkbox.</p></li> | 
 | <li><p>Click the <i>Start</i> button in the lower right to start the | 
 |     capture.</p></li> | 
 | <li><p>Run your Subversion client.</p></li> | 
 | <li><p>Click the Stop icon (a red X over an ethernet interface card) when | 
 |     the operation is finished (or <i>Capture->Stop</i> should | 
 |     work).  Now you have a capture.  It looks like a huge list of | 
 |     lines.</p></li> | 
 | <li><p>Click on the <i>Protocol</i> column to sort.</p></li> | 
 | <li><p>Then, click on the first relevant line to select it; usually this | 
 |     is just the first line.</p></li> | 
 | <li><p>Right click, and choose <i>Follow TCP Stream</i>.  You'll be | 
 |     presented with the request/response pairs of the Subversion | 
 |     client's HTTP conversion.</p></li> | 
 | </ol> | 
 |  | 
 | <p>The above instructions are specific to the graphical version of | 
 | Wireshark (version 0.99.6), and don't apply to the command-line | 
 | version known as "tshark" (which corresponds to "tethereal", from back | 
 | when Wireshark was called Ethereal).</p> | 
 |  | 
 | <p>Alternatively, you may set the <tt>neon-debug-mask</tt> parameter in your | 
 | <tt>servers</tt> configuration file to cause neon's debugging output | 
 | to appear when you run the <tt>svn</tt> client.  The numeric value of | 
 | <tt>neon-debug-mask</tt> is a combination of the <tt>NE_DBG_...</tt> values | 
 | in the header file <tt>ne_utils.h</tt>.  For current versions of neon, setting | 
 | <tt>neon-debug-mask</tt> to 130 (i.e. <tt>NE_DBG_HTTP+NE_DBG_HTTPBODY)</tt> | 
 | will cause the HTTP data to be shown.</p> | 
 |  | 
 | <p>You may well want to disable compression when doing a network | 
 | trace—see the <tt>http-compression</tt> parameter in the <tt>servers</tt> | 
 | configuration file.</p> | 
 |  | 
 | <p>Another alternative is to set up a logging proxy between the | 
 | Subversion client and server.  A simple way to do this is to use the | 
 | <tt>socat</tt> program.  For example, to log communication with an | 
 | svnserve instance, run the following command:</p> | 
 |  | 
 | <p><tt>socat -v  TCP4-LISTEN:9630,reuseaddr,fork | 
 |     TCP4:localhost:svn</tt></p> | 
 |  | 
 | <p>Then run your svn commands using an URL base of | 
 | <tt>svn://127.0.0.1:9630/</tt>; <tt>socat</tt> will forward the | 
 | traffic from port 9630 to the normal svnserve port (3690), and will | 
 | print all traffic in both directions to standard error, prefixing it | 
 | with < and > signs to show the direction of the traffic.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="tracing-memory-leaks" title="tracing-memory-leaks"> | 
 | <h2>Tracking down memory leaks</h2> | 
 |  | 
 | <p>Our use of APR pools makes it unusual for us to have memory leaks | 
 | in the strictest sense; all the memory we allocate will be cleaned up | 
 | eventually.  But sometimes an operation takes more memory than it | 
 | should; for instance, a checkout of a large source tree should not use | 
 | much more memory than a checkout of a small source tree.  When that | 
 | happens, it generally means we're allocating memory from a pool whose | 
 | lifetime is too long.</p> | 
 |  | 
 | <p>If you have a favorite memory leak tracking tool, you can configure | 
 | with --enable-pool-debug (which will make every pool allocation use | 
 | its own malloc()), arrange to exit in the middle of the operation, and | 
 | go to it.  If not, here's another way:</p> | 
 |  | 
 | <ul> | 
 |  | 
 | <li><p>Configure with --enable-pool-debug=verbose-alloc.  Make sure to | 
 |        rebuild all of APR and Subversion so that every allocation gets | 
 |        file-and-line information.</p> | 
 | </li> | 
 |  | 
 | <li><p>Run the operation, piping stderr to a file.  Hopefully you have | 
 |       lots of disk space.</p> | 
 | </li> | 
 |  | 
 | <li><p>In the file, you'll see lots of lines which look like:</p> | 
 |  | 
 |    <pre> | 
 |     POOL DEBUG: [5383/1024] PCALLOC (      2763/      2763/      5419) \ | 
 |     0x08102D48 "subversion/svn/main.c:612"                             \ | 
 |     <subversion/libsvn_subr/auth.c:122> (118/118/0) | 
 |    </pre> | 
 |  | 
 |     <p>What you care about most is the tenth field (the one in | 
 |        quotes), which gives you the file and line number where the | 
 |        pool for this allocation was created.  Go to that file and line | 
 |        and determine the lifetime of the pool.  In the example above, | 
 |        main.c:612 indicates that this allocation was made in the | 
 |        top-level pool of the svn client.  If this were an allocation | 
 |        which was repeated many times during the course of an | 
 |        operation, that would indicate a source of a memory leak.  The | 
 |        eleventh field (the one in brackets) gives the file and line | 
 |        number of the allocation itself.</p> | 
 | </li> | 
 |  | 
 | </ul> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="log-messages" title="log-messages"> | 
 | <h2>Writing log messages</h2> | 
 |  | 
 | <p>Every commit needs a log message.  </p> | 
 |  | 
 | <p>The intended audience for a log message is a developer who is | 
 | already familiar with Subversion, but not necessarily familiar with | 
 | this particular commit.  Usually when someone goes back and reads a | 
 | change, he no longer has in his head all the context around that | 
 | change.  This is true even if he is the author of the change!  All the | 
 | discussions and mailing list threads and everything else may be | 
 | forgotten; the only clue to what the change is about comes from the | 
 | log message and the diff itself.  People revisit changes with | 
 | surprising frequency, too: for example, it might be months after the | 
 | original commit and now the change is being ported to a maintenance | 
 | branch.</p> | 
 |  | 
 | <p>The log message is the introduction to the change.  Start it off | 
 | with one line indicating the general nature of the change, and follow | 
 | that with a descriptive paragraph if necessary.  This not only helps | 
 | put developers in the right frame of mind for reading the rest of the | 
 | log message, but also plays well with the "CIA" bot that echoes the | 
 | first line of each commit to realtime forums like IRC.  (For details, | 
 | see <a href="http://cia.vc/">http://cia.vc/</a>.)  However, if the  | 
 | commit is just one simple change to one file, then you can dispense | 
 | with the general description and simply go straight to the detailed | 
 | description, in the standard filename-then-symbol format shown | 
 | below.</p> | 
 |  | 
 | <p>Throughout the log message, use full sentences, not sentence | 
 | fragments.  Fragments are more often ambiguous, and it takes only a | 
 | few more seconds to write out what you mean.  Certain fragments like | 
 | "Doc fix", "New file", or "New function" are acceptable because they | 
 | are standard idioms, and all further details should appear in the | 
 | source code.</p> | 
 |  | 
 | <p>The log message should name every affected function, variable, | 
 | macro, makefile target, grammar rule, etc, including the names of | 
 | symbols that are being removed in this commit.  This helps people | 
 | searching through the logs later.  Don't hide names in wildcards, | 
 | because the globbed portion may be what someone searches for later. | 
 | For example, this is bad:</p> | 
 |  | 
 | <pre> | 
 |    * subversion/libsvn_ra_pigeons/twirl.c | 
 |      (twirling_baton_*): Removed these obsolete structures. | 
 |      (handle_parser_warning): Pass data directly to callees, instead | 
 |       of storing in twirling_baton_*. | 
 |  | 
 |    * subversion/libsvn_ra_pigeons/twirl.h: Fix indentation. | 
 | </pre> | 
 |  | 
 | <p>Later on, when someone is trying to figure out what happened to | 
 | `twirling_baton_fast', they may not find it if they just search for | 
 | "_fast".  A better entry would be:</p> | 
 |  | 
 | <pre> | 
 |    * subversion/libsvn_ra_pigeons/twirl.c | 
 |      (twirling_baton_fast, twirling_baton_slow): Removed these | 
 |       obsolete structures.  | 
 |      (handle_parser_warning): Pass data directly to callees, instead | 
 |       of storing in twirling_baton_*.  | 
 |  | 
 |    * subversion/libsvn_ra_pigeons/twirl.h: Fix indentation. | 
 | </pre> | 
 |  | 
 | <p>The wildcard is okay in the description for | 
 | `handle_parser_warning', but only because the two structures were | 
 | mentioned by full name elsewhere in the log entry.</p> | 
 |  | 
 | <p>You should also include property changes in your log messages. | 
 | For example, if you were to modify the "svn:ignore" property on | 
 | the trunk, you might put something like this in your log:</p> | 
 |  | 
 | <pre> | 
 |    * trunk/ (svn:ignore): Ignore 'build'. | 
 | </pre> | 
 |  | 
 | <p>The above only applies to properties you maintain, not those | 
 | maintained by subversion like "svn:mergeinfo".</p> | 
 |  | 
 | <p>Note how each file gets its own entry prefixed with an "*", and the | 
 | changes within a file are grouped by symbol, with the symbols listed | 
 | in parentheses followed by a colon, followed by text describing the | 
 | change.  Please adhere to this format, even when only one file is | 
 | changed — not only does consistency aid readability, | 
 | it also allows software to colorize log entries automatically.</p> | 
 |  | 
 | <p>As an exception to the above, if you make exactly the same change | 
 | in several files, list all the changed files in one entry. For | 
 | example:</p> | 
 |  | 
 | <pre> | 
 |    * subversion/libsvn_ra_pigeons/twirl.c, | 
 |      subversion/libsvn_ra_pigeons/roost.c: | 
 |      Include svn_private_config.h. | 
 | </pre> | 
 |  | 
 | <p>If all the changed files are deep inside the source tree, you can | 
 | shorten the file name entries by noting the common prefix before the | 
 | change entries:</p> | 
 |  | 
 | <pre> | 
 |    [in subversion/bindings/swig/birdsong] | 
 |  | 
 |    * dialects/nightingale.c (get_base_pitch): Allow 3/4-tone | 
 |      pitch variation to account for trait variability amongst | 
 |      isolated populations Erithacus megarhynchos. | 
 |  | 
 |    * dialects/gallus_domesticus.c: Remove. Unreliable due to | 
 |      extremely low brain-to-body mass ratio. | 
 | </pre> | 
 |  | 
 | <p>If your change is related to a specific issue in the issue tracker, | 
 | then include a string like "issue #N" in the log message, but make | 
 | sure you still summarize what the change is about.  For example, if a | 
 | patch resolves issue #1729, then the log message might be:</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 | </pre> | 
 |  | 
 | <p>Try to put related changes together.  For example, if you create | 
 | svn_ra_get_ansible2(), deprecating svn_ra_get_ansible(), then those | 
 | two things should be near each other in the log message:</p> | 
 |  | 
 | <pre> | 
 |    * subversion/include/svn_ra.h | 
 |      (svn_ra_get_ansible2): New prototype, obsoletes svn_ra_get_ansible. | 
 |      (svn_ra_get_ansible): Deprecate. | 
 | </pre> | 
 |  | 
 | <p>For large changes or change groups, group the log entry into | 
 | paragraphs separated by blank lines.  Each paragraph should be a set | 
 | of changes that accomplishes a single goal, and each group should | 
 | start with a sentence or two summarizing the change.  Truly | 
 | independent changes should be made in separate commits, of course.</p> | 
 |  | 
 | <p>See <a href="#crediting">Crediting</a> for how to give credit to | 
 | someone else if you are committing their patch, or committing a change | 
 | they suggested.</p> | 
 |  | 
 | <p>One should never need the log entries to understand the current | 
 | code.  If you find yourself writing a significant explanation in the | 
 | log, you should consider carefully whether your text doesn't actually | 
 | belong in a comment, alongside the code it explains.  Here's an | 
 | example of doing it right:</p> | 
 |  | 
 | <pre> | 
 |    (consume_count): If `count' is unreasonable, return 0 and don't | 
 |     advance input pointer. | 
 | </pre> | 
 |  | 
 | <p>And then, in `consume_count' in `cplus-dem.c':</p> | 
 |  | 
 | <pre> | 
 |    while (isdigit((unsigned char)**type)) | 
 |      { | 
 |        count *= 10; | 
 |        count += **type - '0'; | 
 |        /* A sanity check.  Otherwise a symbol like | 
 |          `_Utf390_1__1_9223372036854775807__9223372036854775' | 
 |          can cause this function to return a negative value. | 
 |          In this case we just consume until the end of the string.  */ | 
 |       if (count > strlen(*type)) | 
 |         { | 
 |           *type = save; | 
 |           return 0; | 
 |         } | 
 | </pre> | 
 |  | 
 | <p>This is why a new function, for example, needs only a log entry | 
 | saying "New Function" --- all the details should be in the source.</p> | 
 |  | 
 | <p>You can make common-sense exceptions to the need to name everything | 
 | that was changed.  For example, if you have made a change which | 
 | requires trivial changes throughout the rest of the program (e.g., | 
 | renaming a variable), you needn't name all the functions affected, you | 
 | can just say "All callers changed".  When renaming any symbol, please | 
 | remember to mention both the old and new names, for traceability; see | 
 | r20946 for an example.</p> | 
 |  | 
 | <p>In general, there is a tension between making entries easy to find | 
 | by searching for identifiers, and wasting time or producing unreadable | 
 | entries by being exhaustive.  Use the above guidelines and your best | 
 | judgment, and be considerate of your fellow developers.  (Also, <a | 
 | href="http://subversion.tigris.org/servlets/BrowseList?listName=svn"> | 
 | run "svn log"</a> to see how others have been writing their log | 
 | entries.)</p> | 
 |  | 
 | <p>Log messages for documentation or translation have somewhat looser | 
 | guidelines.  The requirement to name every symbol obviously does not | 
 | apply, and if the change is just one more increment in a continuous | 
 | process such as translation, it's not even necessary to name every | 
 | file.  Just briefly summarize the change, for example: "More work on | 
 | Malagasy translation."  Please write your log messages in English, so | 
 | everybody involved in the project can understand the changes you | 
 | made.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="crediting" title="crediting"> | 
 | <h2>Crediting</h2> | 
 |  | 
 | <p>It is very important to record code contributions in a consistent | 
 | and parseable way.  This allows us to write scripts to figure out who | 
 | has been actively contributing — and what they have | 
 | contributed — so we can <a | 
 | href="http://www.red-bean.com/svnproject/contribulyzer/">spot | 
 | potential new committers quickly</a>.  The Subversion project uses | 
 | human-readable but machine-parseable fields in log messages to | 
 | accomplish this.</p> | 
 |  | 
 | <p>When committing a patch written by someone else, use | 
 | "Patch by: " at the beginning of a line to indicate the | 
 | author:</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Patch by: J. Random <jrandom@example.com> | 
 | </pre> | 
 |  | 
 | <p>If multiple individuals wrote the patch, list them each on a | 
 | separate line — making sure to start each continuation | 
 | line with whitespace.  Non-committers should be listed by name, if | 
 | known, and e-mail.  Full and partial committers should be listed by | 
 | their canonical usernames from <a | 
 | href="http://svn.collab.net/repos/svn/trunk/COMMITTERS" | 
 | >COMMITTERS</a> (the leftmost column in that file).  Additionally, | 
 | "me" is an acceptable shorthand for the person actually committing the | 
 | change.</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Patch by: J. Random <jrandom@example.com> | 
 |              Enrico Caruso <codingtenor@codingtenor.com> | 
 |              jcommitter | 
 |              me | 
 | </pre> | 
 |  | 
 | <p>If someone found the bug or pointed out the problem, but didn't | 
 | write the patch, indicate their contribution with | 
 | "Found by: ":</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Found by: J. Random <jrandom@example.com> | 
 | </pre> | 
 |  | 
 | <p>If someone suggested something useful, but didn't write the patch, | 
 | indicate their contribution with "Suggested by: ":</p> | 
 |  | 
 | <pre> | 
 |    Extend the Contribulyzer syntax to distinguish finds from ideas. | 
 |  | 
 |    * www/hacking.html (crediting): Adjust accordingly. | 
 |  | 
 |    Suggested by: dlr | 
 | </pre> | 
 |  | 
 | <p>If someone reviewed the change, use "Review by: " | 
 | (or "Reviewed by: " if you prefer):</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Review by: Eagle Eyes <eeyes@example.com> | 
 | </pre> | 
 |  | 
 | <p>A field may have multiple lines, and a log message may contain any | 
 | combination of fields:</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Patch by: J. Random <jrandom@example.com> | 
 |              Enrico Caruso <codingtenor@codingtenor.com> | 
 |              me | 
 |    Found by: J. Random <jrandom@example.com> | 
 |    Review by: Eagle Eyes <eeyes@example.com> | 
 |               jcommitter | 
 | </pre> | 
 |  | 
 | <p>Further details about a contribution should be listed in a | 
 | parenthetical aside immediately after the corresponding field.  Such | 
 | an aside always applies to the field right above it; in the following | 
 | example, the fields have been spaced out for readability, but note | 
 | that the spacing is optional and not necessary for parseability:</p> | 
 |  | 
 | <pre> | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |  | 
 |    Patch by: J. Random <jrandom@example.com> | 
 |    (Tweaked by me.) | 
 |  | 
 |    Review by: Eagle Eyes <eeyes@example.com> | 
 |               jcommitter | 
 |    (Eagle Eyes caught an off-by-one-error in the basename extraction.) | 
 | </pre> | 
 |  | 
 | <p>Currently, these fields</p> | 
 |  | 
 | <pre> | 
 |    Patch by: | 
 |    Suggested by: | 
 |    Found by: | 
 |    Review by: | 
 | </pre> | 
 |  | 
 | <p>are the only officially-supported crediting fields (where | 
 | "supported" means scripts know to look for them), and they are widely | 
 | used in Subversion log messages.  Future fields will probably be of | 
 | the form "VERB by: ", and from time to time someone may use | 
 | a field that sounds official but really is not — for | 
 | example, there are a few instances of "Reported by: ". | 
 | These are okay, but try to use an official field, or a parenthetical | 
 | aside, in preference to creating your own.  Also, don't use | 
 | "Reported by: " when the reporter is already recorded in an | 
 | issue; instead, simply refer to the issue.</p> | 
 |  | 
 | <p>Look over Subversion's existing log messages to see how to use | 
 | these fields in practice.  This command from the top of your trunk | 
 | working copy will help:</p> | 
 |  | 
 | <pre> | 
 | svn log | contrib/client-side/search-svnlog.pl "(Patch|Review|Suggested) by: " | 
 | </pre> | 
 |  | 
 | <p><b>Note:</b> The "Approved by: " field seen in some | 
 | commit messages is totally unrelated to these crediting fields, and is | 
 | generally not parsed by scripts.  It is simply the standard syntax for | 
 | indicating either who approved a partial committer's commit outside | 
 | their usual area, or (in the case of merges to release branches) who | 
 | voted for the change to be merged.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="patches" title="patches"> | 
 | <h2>Patch submission guidelines</h2> | 
 |  | 
 | <p>Mail patches to dev@subversion.tigris.org, starting the subject | 
 | line with <tt>[PATCH]</tt>.  This helps our patch manager spot patches | 
 | right away.  For example:</p> | 
 |  | 
 | <pre> | 
 |    Subject: [PATCH] fix for rev printing bug in svn status | 
 | </pre> | 
 |  | 
 | <p>If the patch addresses a particular issue, include the issue number | 
 | as well: "<tt>[PATCH] issue #1729: ...</tt>".  Developers | 
 | who are interested in that particular issue will know to read the | 
 | mail.</p> | 
 |  | 
 | <p>A patch submission should contain one logical change; please don't | 
 | mix N unrelated changes in one submission — send N | 
 | separate emails instead.</p> | 
 |  | 
 | <p>Generate the patch using <tt>svn diff</tt> from the top of a | 
 | Subversion trunk working copy.  If the file you're diffing is not | 
 | under revision control, you can achieve the same effect by using | 
 | <tt>diff -u</tt>.</p> | 
 |  | 
 | <p>Please include a log message with your patch.  A good log message | 
 | helps potential reviewers understand the changes in your patch, and | 
 | increases the likelihood that it will be applied.  You can put the log | 
 | message in the body of the email, or at the top of the patch | 
 | attachment (see below).  Either way, it should follow the guidelines | 
 | given in <a href="#log-messages">Writing log messages</a>, and be | 
 | enclosed in triple square brackets, like so:</p> | 
 |  | 
 | <pre> | 
 |    [[[ | 
 |    Fix issue #1729: Don't crash because of a missing file. | 
 |  | 
 |    * subversion/libsvn_ra_ansible/get_editor.c | 
 |      (frobnicate_file): Check that file exists before frobnicating. | 
 |    ]]] | 
 | </pre> | 
 |  | 
 | <p>(The brackets are not actually part of the log message, they're | 
 | just a way to clearly mark off the log message from its surrounding | 
 | context.)</p> | 
 |  | 
 | <p>If possible, send the patch as an attachment with a mime-type of | 
 | <code>text/x-diff</code>, <code>text/x-patch</code>, or <code>text/plain</code>. | 
 | Most people's mailreaders can display those inline, and having the patch as an | 
 | attachment allows them to extract the patch from the message conveniently. | 
 | Never send patches in archived or compressed form (e.g., tar, gzip, zip, bzip2), | 
 | because that prevents people from reviewing the patch directly in | 
 | their mailreaders.</p> | 
 |  | 
 | <p>If you can't attach the patch with one of these mime-types, or if | 
 | the patch is very short, then it's okay to include it directly in the | 
 | body of your message.  But watch out: some mail editors munge inline | 
 | patches by inserting unasked-for line breaks in the middle of long | 
 | lines.  If you think your mail software might do this, then please use | 
 | an attachment instead.</p> | 
 |  | 
 | <p>If the patch implements a new feature, make sure to describe the | 
 | feature completely in your mail; if the patch fixes a bug, describe | 
 | the bug in detail and give a reproduction recipe.  An exception to | 
 | these guidelines is when the patch addresses a specific issue in the | 
 | issues database — in that case, just refer to the | 
 | issue number in your log message, as described | 
 | in <a href="#log-messages">Writing log messages</a>.</p> | 
 |  | 
 | <p>It is normal for patches to undergo several rounds of feedback and | 
 | change before being applied.  Don't be discouraged if your patch is | 
 | not accepted immediately — it doesn't mean you goofed, | 
 | it just means that there are a <em>lot</em> of eyes looking at every | 
 | code submission, and it's a rare patch that doesn't have at least a | 
 | little room for improvement.  After reading people's responses to your | 
 | patch, make the appropriate changes and resubmit, wait for the next | 
 | round of feedback, and lather, rinse, repeat, until some committer | 
 | applies it.</p> | 
 |  | 
 | <p>If you don't get a response for a while, and don't see the patch | 
 | applied, it may just mean that people are really busy.  Go ahead and | 
 | repost, and don't hesitate to point out that you're still waiting for | 
 | a response.  One way to think of it is that patch management is highly | 
 | parallizable, and we need you to shoulder your share of the management | 
 | as well as the coding.  Every patch needs someone to shepherd it | 
 | through the process, and the person best qualified to do that is the | 
 | original submitter.</p> | 
 |  | 
 | <div class="h3" id="patch-manager" title="patch-manager"> | 
 | <h3>The "Patch Manager" Role</h3> | 
 |  | 
 | <p>Subversion usually has a Patch Manager, whose job is to watch the | 
 | dev@ mailing list and make sure that no patches "slip through the | 
 | cracks".</p> | 
 |  | 
 | <p>This means watching every thread containing "[PATCH]" mails, and | 
 | taking appropriate action based on the progress of the thread.  If the | 
 | thread resolves on its own (because the patch gets committed, or | 
 | because there is consensus that the patch doesn't need to be applied, | 
 | or whatever) then no further action need be taken.  But if the thread | 
 | fades out without any clear decision, then the patch needs to be saved | 
 | in the issue tracker.  This means that a summary of any discussion | 
 | threads around that patch, and links to relevant mailing list | 
 | archives, will be added to some issue in the tracker.  For a patch | 
 | which addresses an existing issue tracker item, the patch is saved to | 
 | that item.  Otherwise, a new issue of type 'PATCH' is filed, and the | 
 | patch is saved to that new issue.</p> | 
 |  | 
 | <p>The Patch Manager needs a basic technical understanding of | 
 | Subversion, and the ability to skim a thread and get a rough | 
 | understanding of whether consensus has been reached, and if so, of | 
 | what kind.  It does <em>not</em> require actual Subversion development | 
 | experience or commit access.  Expertise in using one's mail reading | 
 | software is optional, but recommended :-).</p> | 
 |  | 
 | <p>The current patch manager is Daniel Shahaf  | 
 | <danielsh@tigris.org>.</p> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="filing-issues" title="filing-issues"> | 
 | <h2>Filing bugs / issues</h2> | 
 |  | 
 | <p>This pretty much says it all:</p> | 
 |  | 
 | <pre> | 
 |    From: Karl Fogel <kfogel@collab.net> | 
 |    Subject: Please ask on the list before filing a new issue. | 
 |    To: dev@subversion.tigris.org | 
 |    Date: Tue, 30 Jul 2002 10:51:24 (CDT) | 
 |     | 
 |    Folks, we're getting tons of new issues, which is a Good Thing in | 
 |    general, but some of them don't really belong in the issue tracker. | 
 |    They're things that would be better solved by a quick conversation | 
 |    here on the dev list.  Compilation problems, behavior questions, | 
 |    feature ideas that have been discussed before, that sort of thing. | 
 |     | 
 |    *Please* be more conservative about filing issues.  The issues | 
 |    database is physically much more cumbersome than email.  It wastes | 
 |    people's time to have conversations in the issues database that should | 
 |    be had in email.  (This is not a libel against the issue tracker, it's | 
 |    just a result of the fact that the issues database is for permanent | 
 |    storage and flow annotation, not for real-time conversation.) | 
 |     | 
 |    If you encounter a situation where Subversion is clearly behaving | 
 |    wrongly, or behaving opposite to what the documentation says, then | 
 |    it's okay to file the issue right away (after searching to make sure | 
 |    it isn't already filed, of course!).  But if you're | 
 |     | 
 |       a) Requesting a new feature, or | 
 |       b) Having build problems, or | 
 |       c) Not sure what the behavior should be, or | 
 |       d) Disagreeing with current intended behavior, or | 
 |       e) Not TOTALLY sure that others would agree this is a bug, or | 
 |       f) For any reason at all not sure this should be filed, | 
 |     | 
 |    ...then please post to the dev list first.  You'll get a faster | 
 |    response, and others won't be forced to use the issues database to | 
 |    have the initial real-time conversations. | 
 |     | 
 |    Nothing is lost this way.  If we eventually conclude that it should be | 
 |    in the issue tracker, then we can still file it later, after the | 
 |    description and reproduction recipe have been honed on the dev list. | 
 |     | 
 |    Thank you, | 
 |    -Karl | 
 | </pre> | 
 |     | 
 | </div> | 
 |  | 
 | <div class="h2" id="issue-triage" title="issue-triage"> | 
 | <h2>Issue triage</h2> | 
 |  | 
 | <p>When an issue is filed, it goes into the special milestone "---", | 
 | meaning <em>unmilestoned</em>.  This is a holding area that issues | 
 | live in until someone gets a chance to look at them and decide what to | 
 | do.</p> | 
 |  | 
 | <p>The unmilestoned issues are listed first when you sort by | 
 | milestone, and <em>issue triage</em> is the process of trawling | 
 | through all the <a | 
 | href="http://subversion.tigris.org/issues/buglist.cgi?component=subversion&issue_status=UNCONFIRMED&issue_status=NEW&issue_status=STARTED&issue_status=REOPENED&order=issues.target_milestone%2C%20issues.priority%2C%20issues.issue_type" | 
 | >open issues</a> (starting with the unmilestoned ones), determining | 
 | which are important enough to be fixed now, which can wait until | 
 | another release, which are duplicates of existing issues, which have | 
 | been resolved already, etc.  For each issue that will remain open, it | 
 | also means making sure that the various fields are set appropriately: | 
 | type, subcomponent, platform, OS, version, keywords (if any), and so | 
 | on.</p> | 
 |  | 
 | <p>Here's an overview of the process (in this example, 1.5 is the next | 
 | release, so urgent issues would go there):</p> | 
 |  | 
 | <pre> | 
 |     for i in issues_marked_as("---"): | 
 |       if issue_is_a_dup_of_some_other_issue(i): | 
 |         close_as_dup(i) | 
 |       elif issue_is_invalid(i): | 
 |         # A frequent reason for invalidity is that the reporter | 
 |         # did not follow the <a href="http://subversion.tigris.org/issue-tracker.html#buddy-system">"buddy system"</a> for filing. | 
 |         close_as_invalid(i) | 
 |       elif issue_already_fixed(i): | 
 |         close_as_fixed(i) | 
 |       elif issue_unreproducible(i): | 
 |         close_as_worksforme(i) | 
 |       elif issue_is_real_but_we_won't_fix_it(i): | 
 |         close_as_wontfix(i) | 
 |       elif issue_is_closeable_for_some_other_reason(i): | 
 |         close_as_it_for_that_reason(i) | 
 |  | 
 |       # Else issue should remain open, so DTRT with it... | 
 |  | 
 |       # Set priority, platform, subcomponent, etc, as needed. | 
 |       adjust_all_fields_that_need_adjustment(i) | 
 |  | 
 |       # Figure out where to put it. | 
 |       if issue_is_a_lovely_fantasy(i): | 
 |         move_to_milestone(i, "blue-sky") | 
 |       if issue_is_not_important_enough_to_block_any_particular_release(i): | 
 |         move_to_milestone(i, "nonblocking") | 
 |       elif issue_resolution_would_require_incompatible_changes(i): | 
 |         move_to_milestone(i, "2.0") | 
 |       elif issue_hurts_people_somewhat(i): | 
 |         move_to_milestone(i, "1.6")  # or whatever | 
 |       elif issue_hurts_people_a_lot(i): | 
 |         move_to_milestone(i, "1.5-consider") | 
 |       elif issue_hurts_and_hurts_and_won't_stop_hurting(i): | 
 |         move_to_milestone(i, "1.5") | 
 | </pre> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="commit-access" title="commit-access"> | 
 | <h2>Commit access</h2> | 
 |  | 
 | <p>There are two types of commit access: full and partial.  Full means | 
 | anywhere in the tree, partial means only in that committer's specific | 
 | area(s) of expertise.  The <a | 
 | href="http://svn.collab.net/repos/svn/trunk/COMMITTERS" | 
 | >COMMITTERS</a> file lists all committers, both full and partial, and | 
 | says the domains for each partial committer.</p> | 
 |  | 
 | <div class="h3" id="full-commit-access" title="full-commit-access"> | 
 | <h3>How full commit access is granted</h3> | 
 |  | 
 | <p>After someone has successfully contributed a few non-trivial | 
 | patches, some full committer, usually whoever has reviewed and applied | 
 | the most patches from that contributor, proposes them for commit | 
 | access.  This proposal is sent only to the other full committers -- | 
 | the ensuing discussion is private, so that everyone can feel | 
 | comfortable speaking their minds.  Assuming there are no objections, | 
 | the contributor is granted commit access.  The decision is made by | 
 | consensus; there are no formal rules governing the procedure, though | 
 | generally if someone strongly objects the access is not offered, or is | 
 | offered on a provisional basis.</p> | 
 |  | 
 | <p><i>The primary criterion for full commit access is good | 
 | judgment.</i></p> | 
 |  | 
 | <p>You do not have to be a technical wizard, or demonstrate deep | 
 | knowledge of the entire codebase, to become a full committer.  You | 
 | just need to know what you don't know.  If your patches adhere to the | 
 | guidelines in this file, adhere to all the usual unquantifiable rules | 
 | of coding (code should be readable, robust, maintainable, etc.), and | 
 | respect the Hippocratic Principle of "first, do no harm", then you | 
 | will probably get commit access pretty quickly.  The size, complexity, | 
 | and quantity of your patches do not matter as much as the degree of | 
 | care you show in avoiding bugs and minimizing unnecessary impact on | 
 | the rest of the code.  Many full committers are people who have not | 
 | made major code contributions, but rather lots of small, clean fixes, | 
 | each of which was an unambiguous improvement to the code.  (Of course, | 
 | this does not mean the project needs a bunch of very trivial patches | 
 | whose only purpose is to gain commit access; knowing what's worth a | 
 | patch post and what's not is part of showing good judgement :-) .)</p> | 
 |  | 
 | <p>To assist developers in discovering new committers, we record | 
 | patches and other contributions in a <a href="#crediting">special | 
 | crediting format</a>, which is then parsed to produce a | 
 | browser-friendly <a | 
 | href="http://www.red-bean.com/svnproject/contribulyzer/">contribution | 
 | list</a>, updated nightly.  If you're thinking of proposing someone | 
 | for commit access and want to look over all their changes, that <a | 
 | href="http://www.red-bean.com/svnproject/contribulyzer/">contribution | 
 | list</a> might be the most convenient place to do it.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="partial-commit-access" title="partial-commit-access"> | 
 | <h3>How partial commit access is granted</h3> | 
 |  | 
 | <p>A full committer sponsors the partial committer.  Usually this | 
 | means the full committer has applied several patches to the same area | 
 | from the proposed partial committer, and realizes things would be | 
 | easier if the person were just committing directly.  Approval is not | 
 | required from the full committers; it is assumed that sponsors know | 
 | what they're doing and will watch the partial committer's first few | 
 | commits to make sure everything's going smoothly.</p> | 
 |  | 
 | <p>Patches submitted by a partial committer may be committed by that | 
 | committer even if they are outside that person's domain.  This | 
 | requires approval (often expressed as a +1 vote) from at least one | 
 | full committer.  In such a case, the approval should be noted in the | 
 | log message, like so:</p> | 
 |  | 
 | <pre> | 
 |    Approved by: lundblad | 
 | </pre> | 
 |  | 
 | <p>Any full committer may offer anyone commit access to an | 
 | experimental branch at any time.  It is not necessary that the | 
 | experimental branch have a high likelihood of being merged to trunk | 
 | (although that's always a good goal to aim for).  It's just as | 
 | important that the full committer — all the full | 
 | committers, actually — view such branches as training | 
 | grounds for new developers, by giving feedback on the commits.  The | 
 | goal of these branches is both to get new code into Subversion and to | 
 | get new developers into the project.  See also the <a | 
 | href="#lightweight-branches" >section on lightweight branches</a>, and | 
 | this mail:</p> | 
 |  | 
 | <pre> | 
 |    <a href="http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=132746" | 
 | >http://subversion.tigris.org/servlets/ReadMsg?list=dev&msgNo=132746 | 
 |    From: Karl Fogel <kfogel@red-bean.com> | 
 |    To: dev@subversion.tigris.org | 
 |    Subject: branch liberalization (was: Elego tree conflicts work) | 
 |    Date: Tue, 20 Nov 2007 10:49:38 -0800 | 
 |    Message-Id: <87y7cswy4d.fsf@red-bean.com></a> | 
 | </pre> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="contrib-area" title="contrib-area"> | 
 | <h3>The contrib/ area</h3> | 
 |  | 
 | <p>When a tool is accepted into the <i>contrib/</i> area, we | 
 | automatically offer its author partial commit access to maintain the | 
 | tool there.  Any full committer can sponsor this.  Usually no | 
 | discussion or vote is necessary, though if there are objections then | 
 | the usual decision-making procedures apply (attempt to reach consensus | 
 | first, then vote among the full committers if consensus cannot be | 
 | reached).</p> | 
 |  | 
 | <p>Code under contrib/ must be open source, but need not have the same | 
 | license or copyright holder as Subversion itself.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="obvious-fix" title="obvious-fix"> | 
 | <h3>The "obvious fix" rule</h3> | 
 |  | 
 | <p>Any committer, whether full or partial, may commit fixes for | 
 | obvious typos, grammar mistakes, and formatting problems wherever they | 
 | may be — in the web pages, API documentation, code | 
 | comments, commit messages, etc.  We rely on the committer's judgement | 
 | to determine what is "obvious"; if you're not sure, just ask.</p> | 
 |  | 
 | <p>Whenever you invoke the "obvious fix" rule, please say so in | 
 | the <a href="#log-messages">log message</a> of your commit. For example:</p> | 
 |  | 
 | <pre> | 
 | ------------------------------------------------------------------------ | 
 | r32135 | stylesen | 2008-07-16 10:04:25 +0200 (Wed, 16 Jul 2008) | 8 lines | 
 |  | 
 | Update "check-license.py" so that it can generate license text applicable | 
 | to this year. | 
 |  | 
 | Obvious fix. | 
 |  | 
 | * tools/dev/check-license.py | 
 |   (NEW_LICENSE): s/2005/2008/ | 
 |  | 
 | ------------------------------------------------------------------------ | 
 | </pre> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="lightweight-branches" title="lightweight-branches"> | 
 | <h2>Use lightweight branches</h2> | 
 |  | 
 | <p>If you're working on a feature or bugfix in stages involving | 
 | multiple commits, and some of the intermediate stages aren't stable | 
 | enough to go on trunk, then create a temporary branch in /branches. | 
 | There's no need to ask — just do it.  It's fine to try | 
 | out experimental ideas in a temporary branch, too.  And all the | 
 | preceding applies to partial as well as full committers.</p> | 
 |  | 
 | <p>If you're just using the branch to "checkpoint" your code, and | 
 | don't feel it's ready for review, please put some sort of notice at | 
 | the top of the log message, such as:</p> | 
 |  | 
 | <pre> | 
 |    *** checkpoint commit -- please don't waste your time reviewing it *** | 
 | </pre> | 
 |  | 
 | <p>And if a later commit on that branch <em>should</em> be reviewed, | 
 | then please supply, in the log message, the appropriate 'svn diff' | 
 | command, since the diff would likely involve two non-adjacent commits | 
 | on that branch, and reviewers shouldn't have to spend time figuring | 
 | out which ones they are.</p> | 
 |  | 
 | <p>When you're done with the branch — when you've | 
 | either merged it to trunk or given up on it — please | 
 | remember to remove it.</p> | 
 |  | 
 | <p>See also the <a href="#partial-commit-access" >section on partial | 
 | commit access</a> for our policy on offering commit access to | 
 | experimental branches.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="configury" title="configury"> | 
 | <h2>The configuration/build system under unix</h2> | 
 |  | 
 | <p>Greg Stein wrote a custom build system for Subversion, which had | 
 | been using `automake' and recursive Makefiles.  Now it uses a single, | 
 | top-level Makefile, generated from Makefile.in (which is kept under | 
 | revision control).  `Makefile.in' in turn includes `build-outputs.mk', | 
 | which is automatically generated from `build.conf' by the | 
 | `gen-make.py' script.  Thus, the latter two are under revision | 
 | control, but `build-outputs.mk' is not.</p> | 
 |  | 
 | <p>Here is Greg's original mail describing the system, followed by | 
 | some advice about hacking it:</p> | 
 |  | 
 | <pre> | 
 |    From: Greg Stein <gstein@lyra.org> | 
 |    Subject:  new build system (was: Re: CVS update: MODIFIED: ac-helpers ...) | 
 |    To: dev@subversion.tigris.org | 
 |    Date: Thu, 24 May 2001 07:20:55 -0700 | 
 |    Message-ID: <20010524072055.F5402@lyra.org> | 
 |  | 
 |    On Thu, May 24, 2001 at 01:40:17PM -0000, gstein@tigris.org wrote: | 
 |    >   User: gstein | 
 |    >   Date: 01/05/24 06:40:17 | 
 |    > | 
 |    >   Modified:    ac-helpers .cvsignore svn-apache.m4 | 
 |    >   Added:       .        Makefile.in | 
 |    >   Log: | 
 |    >   Switch over to the new non-recursive build system. | 
 |    >... | 
 |  | 
 |    Okay... this is it. We're now on the build system. | 
 |  | 
 |        "It works on my machine." | 
 |  | 
 |    I suspect there may be some tweaks to make on different OSs. I'd be | 
 |    interested to hear if Ben can really build with normal BSD make. It | 
 |    should be possible. | 
 |  | 
 |    The code supports building, installation, checking, and | 
 |    dependencies. It does *NOT* yet deal with the doc/ subdirectory. That | 
 |    is next; I figured this could be rolled out and get the kinks worked | 
 |    out while I do the doc/ stuff.  Oh, it doesn't build Neon or APR yet | 
 |    either. I also saw a problem where libsvn_fs wasn't getting built | 
 |    before linking one of the test proggies (see below). | 
 |  | 
 |    Basic operation: same as before. | 
 |  | 
 |    $ ./autogen.sh | 
 |    $ ./configure OPTIONS | 
 |    $ make | 
 |    $ make check | 
 |    $ make install | 
 |  | 
 |    There are some "make check" scripts that need to be fixed up. That'll | 
 |    happen RSN. Some of them create their own log, rather than spewing to | 
 |    stdout (where the top-level make will place the output into | 
 |    [TOP]/tests.log). | 
 |  | 
 |    The old Makefile.am files are still around, but I'll be tossing those | 
 |    along with a bunch of tweaks to all the .cvsignore files. There are a | 
 |    few other cleanups, too. But that can happen as a step two. | 
 |  | 
 |    [ $ cvs rm -f `find . -name Makefile.rm` | 
 |  | 
 |      See the mistake in that line? I didn't when I typed it. The find | 
 |      returned nothing, so cvs rm -f proceeded to delete my entire | 
 |      tree. And the -f made sure to delete all my source files, too. Good | 
 |      fugging thing that I had my mods in some Emacs buffers, or I'd be | 
 |      bitching. | 
 |  | 
 |      I am *so* glad that Ben coded SVN to *not* delete locally modified | 
 |      files *and* that we have an "undel" command. I had to go and tweak a | 
 |      bazillion Entries files to undo the delete... | 
 |    ] | 
 |  | 
 |    The top-level make has a number of shortcuts in it (well, actually in | 
 |    build-outputs.mk): | 
 |  | 
 |    $ make subversion/libsvn_fs/libsvn_fs.la | 
 |  | 
 |    or | 
 |  | 
 |    $ make libsvn_fs | 
 |  | 
 |    The two are the same. So... when your test proggie fails to link | 
 |    because libsvn_fs isn't around, just run "make libsvn_fs" to build it | 
 |    immediately, then go back to the regular "make". | 
 |  | 
 |    Note that the system still conditionally builds the FS stuff based | 
 |    on whether DB (See 'Building on Unix' below) is available, and | 
 |    mod_dav_svn if Apache is available. | 
 |  | 
 |    Handy hint: if you don't like dependencies, then you can do: | 
 |  | 
 |    $ ./autogen.sh -s | 
 |  | 
 |    That will skip the dependency generation that goes into | 
 |    build-outputs.mk. It makes the script run quite a bit faster (48 secs | 
 |    vs 2 secs on my poor little Pentium 120). | 
 |  | 
 |    Note that if you change build.conf, you can simply run: | 
 |  | 
 |    $ ./gen-make.py build.conf | 
 |  | 
 |    to regen build-outputs.mk. You don't have to go back through the whole | 
 |    autogen.sh / configure process. | 
 |  | 
 |    You should also note that autogen.sh and configure run much faster now | 
 |    that we don't have the automake crap. Oh, and our makefiles never | 
 |    re-run configure on you out of the blue (gawd, I hated when automake | 
 |    did that to me). | 
 |  | 
 |    Obviously, there are going to be some tweaky things going on. I also | 
 |    think that the "shadow" builds or whatever they're called (different | 
 |    source and build dirs) are totally broken. Something tweaky will have | 
 |    to happen there.  But, thankfully, we only have one Makefile to deal | 
 |    with. | 
 |  | 
 |    Note that I arrange things so that we have one generated file | 
 |    (build-outputs.mk), and one autoconf-generated file (Makefile from | 
 |    .in).  I also tried to shove as much logic/rules into | 
 |    Makefile.in. Keeping build-outputs.mk devoid of rules (thus, implying | 
 |    gen-make.py devoid of rules in its output generation) manes that | 
 |    tweaking rules in Makefile.in is much more approachable to people. | 
 |  | 
 |    I think that is about it. Send problems to the dev@ list and/or feel | 
 |    free to dig in and fix them yourself. My next steps are mostly | 
 |    cleanup. After that, I'm going to toss out our use of libtool and rely | 
 |    on APR's libtool setup (no need for us to replicate what APR already | 
 |    did). | 
 |  | 
 |    Cheers, | 
 |    -g | 
 |  | 
 |    -- | 
 |    Greg Stein, http://www.lyra.org/ | 
 | </pre> | 
 |  | 
 | <p>And here is some advice for those changing or testing the | 
 | configuration/build system:</p> | 
 |  | 
 | <pre> | 
 |    From: Karl Fogel <kfogel@collab.net> | 
 |    To: dev@subversion.tigris.org | 
 |    Subject: when changing build/config stuff, always do this first | 
 |    Date: Wed 28 Nov 2001 | 
 |  | 
 |    Yo everyone: if you change part of the configuration/build system, | 
 |    please make sure to clean out any old installed Subversion libs | 
 |    *before* you try building with your changes.  If you don't do this, | 
 |    your changes may appear to work fine, when in fact they would fail if | 
 |    run on a truly pristine system. | 
 |  | 
 |    This script demonstrates what I mean by "clean out".  This is | 
 |    `/usr/local/cleanup.sh' on my system.  It cleans out the Subversion | 
 |    libs (and the installed httpd-2.0 libs, since I'm often reinstalling | 
 |    that too): | 
 |  | 
 |       #!/bin/sh | 
 |  | 
 |       # Take care of libs | 
 |       cd /usr/local/lib | 
 |       rm -f APRVARS | 
 |       rm -f libapr* | 
 |       rm -f libexpat* | 
 |       rm -f libneon* | 
 |       rm -f libsvn* | 
 |  | 
 |       # Take care of headers | 
 |       cd /usr/local/include | 
 |       rm -f apr* | 
 |       rm -f svn* | 
 |       rm -f neon/* | 
 |  | 
 |       # Take care of headers | 
 |       cd /usr/local/apache2/lib | 
 |       rm -f * | 
 |  | 
 |    When someone reports a configuration bug and you're trying to | 
 |    reproduce it, run this first. :-) | 
 |  | 
 |    The voice of experience, | 
 |    -Karl | 
 | </pre> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="releasing" title="releasing"> | 
 | <h2>How to release a distribution tarball</h2> | 
 |  | 
 | <p>See <a href="release-process.html">The Subversion Release Procedure</a>.</p> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="release-numbering" title="release-numbering"> | 
 | <h2>Release numbering, compatibility, and deprecation</h2> | 
 |  | 
 | <p>Subversion uses "MAJOR.MINOR.PATCH" release numbers, with the same | 
 | guidelines as APR (see <a href="http://apr.apache.org/versioning.html" | 
 | >http://apr.apache.org/versioning.html</a>), plus a few extensions, | 
 | described later.  The general idea is:</p> | 
 |  | 
 | <ol> | 
 |  | 
 | <li><p>Upgrading/downgrading between different patch releases in the | 
 |        same MAJOR.MINOR line never breaks code.  It may cause bugfixes | 
 |        to disappear/reappear, but API signatures and semantics remain | 
 |        the same.  (Of course, the semantics may change in the trivial | 
 |        ways appropriate for bugfixes, just not in ways that would | 
 |        force adjustments in calling code.)</p> | 
 | </li> | 
 |  | 
 | <li><p>Upgrading to a new minor release in the same major line may | 
 |        cause new APIs to appear, but not remove any APIs.  Any code | 
 |        written to the old minor number will work with any later minor | 
 |        number in that line.  However, downgrading afterwards may not | 
 |        work, if new code has been written that takes advantage of the | 
 |        new APIs.</p> | 
 | </li> | 
 |  | 
 | <li><p>When the major number changes, all bets are off.  This is the | 
 |        only opportunity for a full reset of the APIs, and while we try | 
 |        not to gratuitously remove interfaces, we will use it to clean | 
 |        house a bit.</p> | 
 | </li> | 
 |  | 
 | </ol> | 
 |  | 
 | <p>Subversion extends the APR guidelines to cover client/server | 
 | compatibility questions:</p> | 
 |  | 
 | <ol> | 
 |  | 
 | <li><p>A patch or minor number release of a server (or client) never | 
 |        breaks compatibility with a client (or server) in the same | 
 |        major line.  However, new features offered by the release might | 
 |        be unsupported without a corresponding upgrade to the other | 
 |        side of the connection.  For updating ra_svn code specifically, | 
 |        please observe these principles:</p> | 
 |  | 
 |     <ol> | 
 |  | 
 |     <li><p>Fields can be added to any tuple; old clients will simply | 
 |            ignore them.  (Right now, the marshalling implementation | 
 |            does not let you put number or boolean values in the | 
 |            optional part of a tuple, but changing that will not affect | 
 |            the protocol.)</p> | 
 |     | 
 |         <p>We can use this mechanism when information is added to an | 
 |            API call.</p> | 
 |     </li> | 
 |     | 
 |     <li><p>At connection establishment time, clients and servers exchange | 
 |            a list of capability keywords.</p> | 
 |     | 
 |          <p>We can use this mechanism for more complicated changes, | 
 |            like introducing pipelining or removing information from | 
 |            API calls.</p> | 
 |     </li> | 
 |     | 
 |     <li><p>New commands can be added; trying to use an unsupported | 
 |            command will result in an error which can be checked and dealt | 
 |            with.</p> | 
 |     </li> | 
 |     | 
 |     <li><p>The protocol version number can be bumped to allow graceful | 
 |            refusal of old clients or servers, or to allow a client or | 
 |            server to detect when it has to do things the old way.</p> | 
 |   | 
 |         <p>This mechanism is a last resort, to be used when capability | 
 |            keywords would be too hard to manage.</p> | 
 |     </li> | 
 |  | 
 |     </ol> | 
 | </li> | 
 |  | 
 | <li><p>Working copy and repository formats are backward- and | 
 |        forward-compatible for all patch releases in the same minor | 
 |        series.  They are forward-compatible for all minor releases in | 
 |        the same major series; however, a minor release is allowed to | 
 |        make a working copy or repository that doesn't work with | 
 |        previous minor releases, where "make" could mean "upgrade" as | 
 |        well as "create".</p> | 
 | </li> | 
 |  | 
 | </ol> | 
 |  | 
 | <p>Subversion does not use the "even==stable, odd==unstable" | 
 | convention; any unqualified triplet indicates a stable release:</p> | 
 |  | 
 | <pre> | 
 |    1.0.1  -->  first stable patch release of 1.0 | 
 |    1.1.0  -->  next stable minor release of 1.x after 1.0.x | 
 |    1.1.1  -->  first stable patch release of 1.1.x | 
 |    1.1.2  -->  second stable patch release of 1.1.x | 
 |    1.2.0  -->  next stable minor release after that | 
 | </pre> | 
 |  | 
 | <p>The order of releases is semi-nonlinear — a 1.0.3 | 
 | <em>might</em> come out after a 1.1.0.  But it's only "semi"-nonlinear | 
 | because eventually we declare a patch line defunct and tell people to | 
 | upgrade to the next minor release, so over the long run the numbering | 
 | is basically linear.</p> | 
 |  | 
 | <p>Non-stable releases are qualified with "alphaN" or "betaN" | 
 | suffixes, and release candidates with "-rcN".  For example, the | 
 | prereleases leading to 1.3.7 might look like this:</p> | 
 |  | 
 | <pre> | 
 |    subversion-1.3.7-alpha1.tar.gz | 
 |    subversion-1.3.7-alpha2.tar.gz | 
 |    subversion-1.3.7-beta1.tar.gz | 
 |    subversion-1.3.7-rc1.tar.gz | 
 |    subversion-1.3.7-rc2.tar.gz | 
 |    subversion-1.3.7-rc3.tar.gz | 
 |    subversion-1.3.7.tar.gz | 
 | </pre> | 
 |  | 
 | <p>The output of 'svn --version' corresponds in the obvious way:</p> | 
 |  | 
 | <pre> | 
 |    version 1.3.7 (Alpha 1) | 
 |    version 1.3.7 (Alpha 2) | 
 |    version 1.3.7 (Beta 1) | 
 |    version 1.3.7 (Release Candidate 1) | 
 |    version 1.3.7 (Release Candidate 2) | 
 |    version 1.3.7 (Release Candidate 3) | 
 |    version 1.3.7 | 
 | </pre> | 
 |  | 
 | <p>(See <a href="#alphas-betas">this section</a> for more information | 
 | about when and how we do alpha and beta releases.)</p> | 
 |  | 
 | <p>When you 'make install' subversion-1.3.7-rc1, it still installs as | 
 | though it were "1.3.7", of course.  The qualifiers are metadata on the | 
 | release; we want each subsequent prerelease release to overwrite the | 
 | previous one, and the final release to overwrite the last | 
 | prerelease.</p> | 
 |  | 
 | <p>For working copy builds, there is no tarball name to worry about, | 
 | but 'svn --version' still produces special output:</p> | 
 |  | 
 | <pre> | 
 |    version 1.3.8 (dev build) | 
 | </pre> | 
 |  | 
 | <p>The version number is the next version that project is working | 
 | towards.  The important thing is to say "dev build".  This indicates | 
 | that the build came from a working copy, which is useful in bug | 
 | reports.</p> | 
 |  | 
 | <p>We have no mechanism for releasing dated snapshots.  If we want | 
 | code to get wider distribution than just those who build from working | 
 | copies, we put out a prerelease.</p> | 
 |  | 
 | <div class="h3" id="name-reuse" title="name-reuse"> | 
 | <h3>Reuse of release names</h3> | 
 |  | 
 | <p>If a release or candidate release needs to be quickly re-issued due | 
 | to some non-code problem (say, a packaging glitch), it's okay to reuse | 
 | the same name, as long as the tarball hasn't been | 
 | <a href="#tarball-signing">blessed by signing</a> yet.  But if it has | 
 | been uploaded to the standard distribution area with signatures, or if | 
 | the re-issue was due to a change in code a user might run, then the | 
 | old name must be tossed and the next name used.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h3" id="deprecation" title="deprecation"> | 
 | <h3>Deprecation</h3> | 
 |  | 
 | <p>When a new, improved version of an API is introduced, the old one | 
 | remains for compatibility, at least until the next major release. | 
 | However, we mark the old one as deprecated and point to the new one, | 
 | so people know to write to the new API if at all possible.  When | 
 | deprecating, mention the release after which the deprecation was | 
 | introduced, and point to the new API.  If possible, replace the old | 
 | API documentation with a diff to the new one.  For example:</p> | 
 |  | 
 | <pre> | 
 |    /** | 
 |     * @deprecated Provided for backward compatibility with the 1.0.0 API. | 
 |     * | 
 |     * Similar to svn_repos_dump_fs2(), but with the @a use_deltas | 
 |     * parameter always set to @c FALSE. | 
 |     */ | 
 |    SVN_DEPRECATED | 
 |    svn_error_t * | 
 |    svn_repos_dump_fs(svn_repos_t *repos, | 
 |                      svn_stream_t *dumpstream, | 
 |                      svn_stream_t *feedback_stream, | 
 |                      svn_revnum_t start_rev, | 
 |                      svn_revnum_t end_rev, | 
 |                      svn_boolean_t incremental, | 
 |                      svn_cancel_func_t cancel_func, | 
 |                      void *cancel_baton, | 
 |                      apr_pool_t *pool); | 
 | </pre> | 
 |  | 
 | <p>When the major release number changes, the "best" new API in a | 
 | series generally replaces all the previous ones (assuming it subsumes | 
 | their functionality), and it will take the name of the original API. | 
 | Thus, marking 'svn_repos_dump_fs' as deprecated in 1.1.x doesn't mean | 
 | that 2.0.0 doesn't have 'svn_repos_dump_fs', it just means the | 
 | function's signature will be different: it will have the signature | 
 | held by svn_repos_dump_fs2 (or svn_repos_dump_fs3, or whatever) in | 
 | 1.1.x.  The numbered-suffix names disappear, and there is a single | 
 | (shiny, new) svn_repos_dump_fs again.</p> | 
 |  | 
 | <p>One exception to this replacement strategy is when the old function | 
 | has a totally unsatisfying name anyway.  Deprecation is a chance to | 
 | fix that: we give the new API a totally new name, mark the old API as | 
 | deprecated, point to the new API; then at the major version change, we | 
 | remove the old API, but don't rename the new one to the old name, | 
 | because its new name is fine.</p> | 
 |     | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 |  | 
 | <div class="h2" id="release-stabilization" title="release-stabilization"> | 
 | <h2>Stabilizing and maintaining releases</h2> | 
 |  | 
 | <p>Minor and major number releases go through a stabilization period | 
 | before release, and remain in maintenance (bugfix) mode after release. | 
 | To start the release process, we create an "A.B.x" branch based on the | 
 | latest trunk, for example:</p> | 
 |  | 
 | <pre> | 
 |    $ svn cp http://svn.collab.net/repos/svn/trunk \ | 
 |             http://svn.collab.net/repos/svn/branches/A.B.x | 
 | </pre> | 
 |  | 
 | <p>The stabilization period for a new A.B.0 release normally lasts | 
 | four weeks, and allows us to make conservative bugfixes and discover | 
 | showstopper issues.  The stabilization period begins with a release | 
 | candidate tarball with the version A.B.0-rc1.  Further release | 
 | candidate tarballs may be made as blocking bugs are fixed; for | 
 | example, if a set of language bindings is found to be broken, it is | 
 | prudent to make a new release candidate when they are fixed so that | 
 | those language bindings may be tested.</p> | 
 |  | 
 | <p>At the beginning of the final week of the stabilization period, a | 
 | new release candidate tarball should be made if there are any changes | 
 | pending since the last one.  The final week of the stabilization | 
 | period is reserved for critical bugfixes; fixes for minor bugs should | 
 | be deferred to the A.B.1 release.  A critical bug is a non-edge-case | 
 | crash, a data corruption problem, a major security hole, or something | 
 | equally serious.</p> | 
 |  | 
 | <p>Under some circumstances, the stabilization period will be | 
 | extended:</p> | 
 |  | 
 | <ul> | 
 | <li><p>If a potentially destabilizing change must be made in order to | 
 |        fix a bug, the entire four-week stabilization period is | 
 |        restarted.  A potentially destabilizing change is one which | 
 |        could affect many parts of Subversion in unpredictable ways, or | 
 |        which involves adding a substantial amount of new code.  Any | 
 |        incompatible API change (only allowable in the first place if | 
 |        the new release is an A.0.0 release) should be considered a | 
 |        potentially destabilizing change.</p> | 
 | </li> | 
 |  | 
 | <li><p>If a critical bugfix is made during the final week of the | 
 |        stabilization period, the final week is restarted.  The final | 
 |        A.B.0 release is always identical to the release candidate made | 
 |        one week before (with the exceptions discussed below).</p> | 
 | </li> | 
 |  | 
 | </ul> | 
 |  | 
 | <p>If there are disagreements over whether a change is potentially | 
 | destabilizing or over whether a bug is critical, they may be settled | 
 | with a committer vote.</p> | 
 |  | 
 | <p>After the A.B.0 release is out, patch releases (A.B.1, A.B.2, etc.) | 
 | follow when bugfixes warrant them.  Patch releases do not require a | 
 | four week soak, because only conservative changes go into the | 
 | line.</p> | 
 |  | 
 | <p>Certain kinds of commits can go into A.B.0 without restarting the | 
 | soak period, or into a later release without affecting the testing | 
 | schedule or release date:</p> | 
 |  | 
 | <ul> | 
 | <li><p>Without voting:</p> | 
 |     <ul> | 
 |     <li><p>Changes to the STATUS file.</p></li> | 
 |     <li><p>Documentation fixes.</p></li> | 
 |     <li><p>Changes that are a normal part of release bookkeeping, for | 
 |            example, the steps listed in notes/releases.txt.</p></li> | 
 |     <li><p>Changes to dist.sh by, or approved by, the release manager.</p></li> | 
 |     <li><p>Changes to message translations in .po files or additions of | 
 |            new .po files.</p></li> | 
 |     </ul> | 
 | </li> | 
 |  | 
 | <li><p>With voting:</p> | 
 |     <ul> | 
 |     <li><p>Anything affecting only tools/, packages/, or bindings/.</p></li> | 
 |     <li><p>Changes to printed output, such as error and usage messages, as | 
 |            long as format string "%" codes and their args are not | 
 |            touched.</p></li> | 
 |     </ul> | 
 | </li> | 
 |  | 
 | </ul> | 
 |  | 
 | <p>NOTE: The requirements on message translation changes are looser | 
 | than for text messages in C code.  Changing format specifiers in .po | 
 | files is allowed because their validity can be checked mechanically | 
 | (with the -c flag on msgfmt of GNU gettext).  This is done at build | 
 | time if GNU gettext is in use.</p> | 
 |  | 
 | <p>Core code changes, of course, require voting, and restart the soak | 
 | or test period, since otherwise the change could be undertested.</p> | 
 |  | 
 | <p>The voting system works like this:</p> | 
 |  | 
 | <p>A change to the A.B.x line must be first proposed in the | 
 | A.B.x/STATUS file.  Each proposal consists of a short identifying | 
 | block (e.g., the revision number of a trunk or related-line commit, or | 
 | perhaps an issue number), a brief description of the change, an | 
 | at-most-one-line justification of why it should be in A.B.x, perhaps | 
 | some notes/concerns, and finally the votes.  The notes and concerns | 
 | are meant to be brief summaries to help a reader get oriented; please | 
 | don't use the STATUS file for actual discussion, use dev@ instead.</p> | 
 |  | 
 | <p>Here's an example, probably as complex as an entry would ever | 
 | get:</p> | 
 |  | 
 | <pre> | 
 |    * r98765 (issue #56789) | 
 |      Make commit editor take a closure object for future mindreading. | 
 |      Justification: API stability, as prep for future enhancement. | 
 |      Notes: There was consensus on the desirability of this feature in | 
 |        the near future; see thread at http://... (Message-Id: blahblah). | 
 |      Concerns: Vetoed by jerenkrantz due to privacy concerns with the | 
 |        implementation; see thread at http://... (Message-Id: blahblah) | 
 |      Votes: | 
 |        +1: ghudson, bliss | 
 |        +0: cmpilato | 
 |        -0: gstein | 
 |        -1: jerenkrantz | 
 | </pre> | 
 |  | 
 | <p>A change needs three +1 votes from full committers (or partial | 
 | committers for the involved areas), and no vetoes, to go into | 
 | A.B.x. If partial committers would like to vote for a different area, | 
 | which does not fall within their privilege, it must be made clear in | 
 | the STATUS file that their vote is 'non-binding' as follows:</p> | 
 |  | 
 | <pre> | 
 |  * r31833 | 
 |    svndumpfilter: Don't match prefixes to partial path components. | 
 |    Fixes #desc4 of issue #1853. | 
 |    Votes: | 
 |      +1: danielsh, hwright | 
 |      +1 (non-binding): stylesen | 
 | </pre> | 
 |  | 
 | <p>If you cast a veto (i.e. -1), please state the reason in the | 
 | concerns field, and include a url / message-id for the list discussion | 
 | if any.  You can go back and add the link later if the thread isn't | 
 | available at the time you commit the veto.</p> | 
 |  | 
 | <p>If you add revisions to a group, note that the previous voters have | 
 | not voted for those revisions, as follows:</p> | 
 |  | 
 | <pre> | 
 |    * r30643, r30653, r30785 | 
 |      Update bash completion script. | 
 |      Votes: | 
 |        +1: arfrever (r30785 only), stylesen | 
 | </pre> | 
 |  | 
 | <p>If in case votes have been communicated via IRC or other means, | 
 | note that in the log message. <a href="#obvious-fix">Obvious fixes</a> | 
 | do not require '(rX only)' to be mentioned.</p> | 
 |  | 
 | <p>Voting +1 on a change doesn't just mean you approve of it in | 
 | principle.  It means you have thoroughly reviewed the change, and find | 
 | it correct and as nondisruptive as possible.  When it is committed to | 
 | the release branch, the log message will include the names of all who | 
 | voted for it, as well as the original author and the person making the | 
 | commit.  All of these people are considered equally answerable for | 
 | bugs.</p> | 
 |  | 
 | <p>If you've reviewed a patch, and like it but have some reservations, | 
 | you can write "+1 (concept)" and then ask questions on the list about | 
 | your concerns.  You can write "+0" if you like the general idea but | 
 | haven't reviewed the patch carefully.  Neither of these votes counts | 
 | toward the total, but they can be useful for tracking down people who | 
 | are following the change and might be willing to spend more time on | 
 | it.</p> | 
 |  | 
 | <p>There is a somewhat looser voting system for areas that are not | 
 | core code, and that may have fewer experts available to review changes | 
 | (for example, tools/, packages/, bindings/, test scripts, etc.).  A | 
 | change in these areas can go in with a +1 from a full committer or a | 
 | partial committer for that area, at least one +0 or "concept +1" from | 
 | any other committer, and no vetoes.  (If a change affects the build | 
 | system, however, it is considered a core change, and needs three | 
 | +1's.)  Use your judgment and don't review changes unless you have | 
 | some competence to do so, of course.  The goal is to get at least two | 
 | pairs of eyes on the change, without demanding that every reviewer | 
 | have the same amount of expertise as the area maintainer.  This way | 
 | one can review for general sanity, accurate comments, obvious | 
 | mistakes, etc, without being forced to assert "Yes, I understand these | 
 | changes in every detail and have tested them."</p> | 
 |  | 
 | <p>Before proposing a change in STATUS, you should try merging it onto | 
 | the branch to ensure that it doesn't produce merge conflicts.  If | 
 | conflicts occur, please create a new temporary branch from the release | 
 | branch with your changes merged and the conflicts resolved.  The | 
 | branch should be named A.B.x-rYYYY, where YYYY is the first revision | 
 | of your change in the STATUS file.  Add a note in the STATUS file | 
 | about the existence of the temporary branch.  If the change involves | 
 | further work, you can merge those revisions to the branch.  When the | 
 | entry for this change is removed from STATUS, this temporary branch | 
 | should also be removed to avoid cluttering the /branches | 
 | directory.</p> | 
 |  | 
 | <p>NOTE: Changes to STATUS regarding the temporary branch, including | 
 | voting, are always kept on the main release branch.</p> | 
 |  | 
 | <div class="h3" id="alphas-betas" title="alphas-betas"> | 
 | <h2>Alpha and beta releases</h2> | 
 |  | 
 | <p>When we want new features to get wide testing before we enter the | 
 | formal stabilization period described above, we'll sometimes release | 
 | alpha and beta tarballs (as <a href="#release-numbering" >shown | 
 | earlier</a>).  The line between alpha and beta is fuzzy, but | 
 | basically, "alpha" means "we know or expect there are problems", and | 
 | "beta" means "we don't expect problems".  There is no requirement to | 
 | do any beta releases even if there were "alpha1", "alpha2", etc | 
 | releases; we could just jump straight to "rc1".  However, there are | 
 | circumstances where a beta can be useful: for example, if we're unsure | 
 | of a UI decision and want to get wider user feedback before | 
 | solidifying it into a formal release candidate.</p> | 
 |  | 
 | <p>Alphas and betas are only for people who want to help test, and who | 
 | understand that there may be UI- or API-incompatible changes before | 
 | the final release.  The signature requirements are at the release | 
 | manager's discretion.  Typically, the RM will require only 1 or 2 | 
 | signatures for each platform, and to tell signers that they can still | 
 | sign even if their testing reveals minor failures, as long as they | 
 | think the code is solid enough to make testing by others worthwhile. | 
 | The RM should request that signers include a description of any errors | 
 | along with their signatures, so the problems can be published when the | 
 | alpha or beta release is announced.</p> | 
 |  | 
 | <p>When the alpha or beta is publicly announced, distribution packagers | 
 | should be firmly warned off packaging it.  See <a | 
 | href="http://subversion.tigris.org/servlets/ReadMsg?list=announce&msgNo=264" | 
 | >this mail from Hyrum K. Wright</a> for a good model.</p> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="tarball-signing"> | 
 | <h2>Signing source distribution packages (a.k.a tarballs)</h2> | 
 |  | 
 | <p>Before a release or release candidate is officially made public, it is | 
 | made available in a temporary location for committers to test and sign. | 
 | The point is to have the tarballs tested on more systems than just that of the | 
 | person who rolled the release.  When there are three signatures from full | 
 | committers for each of the <tt>.tar.bz2</tt>, <tt>.tar.gz</tt> and | 
 | <tt>.zip</tt> files, the release (candidate) can go public.</p> | 
 |  | 
 | <p>Signing a tarball means that you assert certain things about it.  When | 
 | sending your signature (see below), indicate in the mail what steps | 
 | you've taken to verify that the tarball is correct.  Running | 
 | <tt>make check</tt> over all RA layers and FS backends is a good idea, | 
 | as well as building and testing the bindings.</p> | 
 |  | 
 | <p>After having extracted and tested the tarball, you should sign it using | 
 | <a href="http://www.gnupg.org">gpg</a>.  To do so, use a command like:</p> | 
 |  | 
 | <pre> | 
 |     gpg -ba subversion-1.3.0-rc4.tar.bz2 | 
 | </pre> | 
 |  | 
 | <p>This will result in a file with the same name as the signed file, but with | 
 | a <tt>.asc</tt> extension in the appropriate format for inclusion in the | 
 | release announcement.  Include this file in a mail, typically in reply | 
 | to the announcement of the unofficial tarball.</p> | 
 |  | 
 | <p>If you've downloaded and tested a <tt>.tar.bz2</tt> file, it is possible to | 
 | sign a <tt>.tar.gz</tt> file with the same contents without having | 
 | to download and test it separately.  The trick is to extract the | 
 | <tt>.bz2</tt> file, and pack it using <tt>gzip</tt> like this:</p> | 
 |  | 
 | <pre> | 
 |     bzip2 -cd subversion-1.3.0-rc4.tar.bz2 \ | 
 |     | gzip -9n > subversion-1.3.0-rc4.tar.gz | 
 | </pre> | 
 |  | 
 | <p>The resulting file should be identical to the file generated by the | 
 | release manager, and thus can be signed as described above. | 
 | To verify that the files are identical, you may use either the MD5 checksums | 
 | or the release manager's signature, both of which should be provided with the | 
 | tarballs. | 
 | </p> | 
 | </div> | 
 |  | 
 | <div class="h2" id="custom-releases" title="custom-releases"> | 
 | <h2>Custom releases</h2> | 
 |  | 
 | <p>It is preferred to use the patch process and have your changes | 
 | accepted and applied to trunk to be released on the normal Subversion | 
 | release schedule.  However, if you feel that you need to make changes | 
 | that would not be widely accepted by the Subversion developer | 
 | community, or need to provide early access to unreleased features, you | 
 | should follow the guidelines below.</p> | 
 |  | 
 | <p>First, make sure you follow the <a | 
 | href="http://subversion.org/legal/trademark-policy.html">Subversion | 
 | trademark policy</a>.  You will need to differentiate your release | 
 | from the standard Subversion releases to reduce any potential | 
 | confusion caused by your custom release.</p> | 
 |  | 
 | <p>Second, consider creating a branch in the public Subversion | 
 | repository to track your changes and to potentially allow your custom | 
 | changes to be merged into mainline Subversion.</p> | 
 |  | 
 | <p>Third, if your custom release is likely to generate bug reports | 
 | that would not be relevant to mainline Subversion, please stay in | 
 | touch with the users of the custom release so you can intercept and | 
 | filter those reports.  But of course, the best option would be not to | 
 | be in that situation in the first place — the more | 
 | your custom release diverges from mainline Subversion, the more | 
 | confusion it invites.  If you must make custom releases, please try to | 
 | keep them as temporary and as non-divergent as possible.</p> | 
 |  | 
 | </div> | 
 |  | 
 | <div class="h2" id="l10n" title="l10n"> | 
 | <h2>Localization (l10n)</h2> | 
 |  | 
 | <p>Translation has been divided into two domains.  First, there is the | 
 | translation of server messages sent to connecting clients.  This issue | 
 | has been <a | 
 | href="http://svn.collab.net/repos/svn/trunk/notes/l10n-problems">punted | 
 | for now</a>.  Second there is the translation of the client and its | 
 | libraries.</p> | 
 |  | 
 | <p>The gettext package provides services for translating messages.  It | 
 | uses the xgettext tool to extract strings from the sources for | 
 | translation.  This works by extracting the arguments of the _(), N_() and | 
 | Q_() macros.  _() is used in context where function calls are allowed | 
 | (typically anything except static initializers).  N_() is used whenever | 
 | _() isn't.  Strings marked with N_() need to be passed to gettext | 
 | translation routines whenever referenced in the code.  For an example, | 
 | look at how the header and footer are handled in subversion/svn/help-cmd.c. | 
 | Q_() is used for messages which have singular and plural version.</p> | 
 |  | 
 | <p>Beside _(), N_() and Q_() macros also U_() is used to mark strings which | 
 | will not be translated because it's in general not useful to translate | 
 | internal error messages. This should affect only obscure error messages | 
 | most users should never ever see (caused by bugs in Subversion or | 
 | very special repository corruptions). The reason for using U_() is to | 
 | explicitly note that a gettext call was not just forgotten.</p> | 
 |  | 
 | <p>When using direct calls to gettext routines (*gettext or | 
 | *dgettext), keep in mind that most of Subversion code is library code. | 
 | Therefore the default domain is not necessarily Subversion's own | 
 | domain.  In library code you should use the dgettext versions of the | 
 | gettext functions.  The domain name is defined in the PACKAGE_NAME | 
 | define.</p> | 
 |  | 
 | <p>All required setup for localization is controlled by the ENABLE_NLS | 
 | conditional in svn_private_config.h (for *nix) and | 
 | svn_private_config.hw (for Windows).  Be sure to put</p> | 
 |  | 
 | <pre> | 
 |    #include "svn_private_config.h" | 
 | </pre> | 
 |  | 
 | <p>as the last include in any file which requires localization.</p> | 
 |  | 
 | <p>Also note that return values of _(), Q_() and *gettext() calls are UTF-8 | 
 | encoded; this means that they should be translated to the current | 
 | locale being written as any form of program output.</p> | 
 |  | 
 | <p>The GNU gettext manual | 
 | (<a | 
 | href="http://www.gnu.org/software/gettext/manual/html_node/gettext_toc.html" | 
 | >http://www.gnu.org/software/gettext/manual/html_node/gettext_toc.html</a>) | 
 | provides additional information on writing translatable programs in | 
 | its section "Preparing Program Sources".  Its hints mainly apply to | 
 | string composition.</p> | 
 |  | 
 | <p>Currently available translations can be found in <a | 
 | href="http://svn.collab.net/repos/svn/trunk/subversion/po/" >the po | 
 | section of the repository</a>.  Please contact | 
 | dev@subversion.tigris.org when you want to start a translation not | 
 | available yet.  Translation discussion takes place both on that list | 
 | and on dedicated native language mailing lists (<a | 
 | href="http://subversion.tigris.org/servlets/ProjectMailingListList" | 
 | ><em>l10n-??@subversion.tigris.org</em></a>).</p> | 
 |  | 
 | <p>See <a href="http://svn.collab.net/repos/svn/trunk/TRANSLATING" | 
 | >http://svn.collab.net/repos/svn/trunk/TRANSLATING</a> for more | 
 | information about translating.</p> | 
 |  | 
 | </div> | 
 |  | 
 | </div> | 
 | </body> | 
 | </html> |