
If you are contributing code to the RapidSVN project, please read
this first.

                     ==========================
                     HACKER'S GUIDE TO RAPIDSVN
                     ==========================

TABLE OF CONTENTS

   * Coding style
   * Documenting
   * Writing log messages
   * Other conventions
   * Maintainer's Corner



Coding style
============

To understand how things work, read the header and source files,
which tend to have thoroughly-commented data structures.

   char *                                     // func type on own line
   argblarg(char *arg1, int arg2)             // func name on own line, no
                                              // space between function name
                                              // and opening paren
   {                                          // first brace on own line
     if ((some_very_long_condition && arg2)   // indent 2 cols (no tabs!)
       || remaining_condition)                // new line before operator
     {                                        // brace on own line
       arg1 = some_func(arg1, arg2);          // no space before opening paren
     }                                        // close brace on own line
     else
     {
       do                                     // format do-while like this
       {
         arg1 = another_func(arg1);
       }
       while (*arg1);
     }
   }

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.



Naming conventions
==================

Do not use variable prefixes like used with the Hungarian Notation
naming style. Instead, try to give the variable a short but
appropriate name. Dont use variable names like "foo3" since people
always will have to lookup the meaning of the variable.

Class variables and module local variable get the prefix "m_".

Here is an example (with inline code).

*** foo.h ***

class Foo
{
  int m_myMember;

  Foo(int intitialFoo)
  {
    int bar = initialFoo * 2;

    m_myMember = bar;
  }
}



Documenting
===================

Every function and class, whether public or internal, must start
out with a documentation comment that describes what the function
does. The comments are placed in the headers. Comments in the
source files are only used for implementation details.

The documentation format that we choose is the Doxygen format:

http://www.stack.nl/~dimitri/doxygen/

Example:

/**
 * Multiplies 2 numbers together.
 * @param number1 first number
 * @param number2 second number
 * @return the multiplied number
 */
int
MultiplyMe(int number1, int number2);

Read over the RapidSVN code to get an overview of how this
documentation looks in practice.



Writing log messages
====================

Certain guidelines should be adhered to when writing log messages:

Make a log message for every change.  The value of the log becomes
much less if developers cannot rely on its completeness.  Even if
you've only changed comments, write a log that says "Doc fix." or
something.

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.  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.

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:

   * twirl.cpp
     (twirling_baton_*): Removed these obsolete structures.
     (handle_parser_warning): Pass data directly to callees, instead
     of storing in twirling_baton_*.

   * twirl.h: Fix indentation.

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:

   * twirl.cpp
     (twirling_baton_fast, twirling_baton_slow): Removed these
     obsolete structures.
     (handle_parser_warning): Pass data directly to callees, instead
     of storing in twirling_baton_*.

   * twirl.h: Fix indentation.

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.

Note how each file gets its own entry, and the changes within a file
are grouped by symbol, with the symbols are listed in parentheses
followed by a colon, followed by text describing the change.  Please
adhere to this format -- not only does consistency aid readability, it
also allows software to colorize log entries automatically.

If your change is related to a specific issue in the issue tracker,
then include a string like "Issue N" in the log message.  For
example, if a patch resolves issue 1729, then the log message might
be:

   Issue 1729: Program crashes if file doesnt exist

   * get_editor.cpp
     (frobnicate_file): Check that file exists first.

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.

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:

   (consume_count): If `count' is unreasonable, return 0 and don't
   advance input pointer.

And then, in `consume_count' in `cplus-dem.cpp':

   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;
     }

This is why a new function, for example, needs only a log entry saying
"New Function" --- all the details should be in the source.

There are some common-sense exceptions to the need to name everything
that was changed:

   *  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".

   *  If you have rewritten a file completely, the reader understands
      that everything in it has changed, so your log entry may simply
      give the file name, and say "Rewritten".

   *  If your change was only to one file, or was the same change to
      multiple files, then there's no need to list their paths in the
      log message (because "svn log" can show the changed paths for
      that revision anyway).  Only when you need to describe how the
      change affected different areas in different ways is it
      necessary to organize the log message by paths and symbols, as
      in the examples above.

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 your best judgment --- and be
considerate of your fellow developers.  (Also, run "svn log" to see
how others have been writing their log entries.)



Other conventions
=================

In addition to the standards above, RapidSVN uses these conventions:

   *  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.

   *  Stay within 80 columns, the width of a minimal standard display
      window.

   *  If you add any files to the project that might be opened on more
      than one operating system then give the file the native eol-style
      property.  This ensures that all files downloaded via svn
      arrive with the line endings native to that OS.  Here is how you
      add the property:
      % svn propset eol-style native new_file.cpp

   *  If you add images to the project make sure you apply the correct
      mime-type property.
      Example for a XPM:
      % svn propset svn:mime-type image/x-xpm



Maintainer's Corner
===================

For the RapidSVN website we are producing two types of packages:

   *  Source tarball rapidsvn-???.tar.gz

   *  Windows Installer RapidSVN-???.exe


These are the steps to follow when creating a new release of RapidSVN:

0. Before Release:

   *  Check the translations (in src/locale).
   *  Make sure all the strings for all the translations are
      up to date (contact translators)

1. Release preparations:

   *  Edit the version numbers in the file "version.xml" and run
      the Python script check-version.py (from the directory "tools")

   *  Create the the change description in the "CHANGES" file

   *  Commit "version.xml" and "CHANGES"

   *  Create the version tag by copying (either using svn or RapidSVN):
      "svn cp -m "Version XYZ tag" . http://rapidsvn.tigris.org/svn/rapidsvn/tags/XYZ

2. Create source tarball (on Linux):

   *  Checkout a fresh working copy of RapidSVN (using
      http://rapidsvn.tigris.org/svn/rapidsvn/tags/XYZ) from the repository
      to make sure everything is built and no old stuff is lying around

   *  Make sure all the tools required are there (autoconf, automake,
      doxygen, xsltproc, docbook)

   *  Run "autogen.sh", "configure", "make" "make dist"
      (no errors allowed!)

   *  Uninstall older rapidsvn/libsvncpp version (if there)

   *  Extract the source tarball to a temporary directory, check if everything
      is there and call "configure", "make", "make install"

   *  Run RapidSVN

   *  Send the tarball to xelarellum@tigris.org, so he can upload it
      to http://www.rapidsvn.org/download and create the necessary links in
      the files/documents section of http://rapidsvn.tigris.org

3. Create Windows installer (on Windows using MSVC 6):

   *  Checkout a fresh working copy of RapidSVN (using
      http://rapidsvn.tigris.org/svn/rapidsvn/tags/XYZ) from the repository
      to make sure everything is built and no old stuff is lying around

   *  Make sure you are using the latest stable release of
      Innosetup, Subversion, wxWidgets, Openssl, BerkeyleyDB. Build all these tools
      and libraries. Some minor changes in apr_config.h or apu_config.h may
      be necessary so subversion compiles. Follow the build instructions
      for the subversion distribution

   *  Because of incompatibilities of the shfolder dll between
      different Internet Explorer/Windows versions make sure the settings
      for Visual C (in the menu "Extras->Options->Directories") are:
      -  Platform SDK library files first in list
      -  Platform SDK header files last in files

   *  Open the workspace rapidsvn.dsw in Visual C and build the projects
      "rapidsvn.dsp" and "svncpp.dsp" in release mode.

   *  Uninstall older RapidSVN version (if there)

   *  Copy the Openssl and BerkeleyDB dlls to "packages/win32"

   *  Open "packages/win32/rapidsvn.iss" and build the installer executable

   *  Run the installer

   *  Run RapidSVN

   *  Send the installer executable to xelarellum@tigris.org, so he can
      upload it to http://www.rapidsvn.org/download and create
      the necessary links in the files/documents section of
      http://rapidsvn.tigris.org

3. Create a news entry on http://rapidsvn.tigris.org and send announcement emails
   (with same text) to announce@rapidsvn.tigris.org, dev@rapidsvn.tigris.org,
   users@rapidsvn.tigris.org including the MD5 checksums for both the
   source tarball and the win32 installer executable.

4. Update and commit (with CVS) the webpage http://rapidsvn.tigris.org.
   This includes changes to the roadmap items, archival of older roadmap items,
   updating of the svncpp doxygen documentation (you can use the output generated
   when building on Linux).

5. Update the issue tracker. This includes creation of new versions and milestones.

Voila. Another release of RapidSVN is done!
