Contributing to monotone
========================

This file gives a number of basic guidelines and tips for hacking on
monotone.  For more specific topics (for instance, documentation on
writing tests, or the release process), see also the files in the
notes/ directory.


Coding standards
----------------

Code is largely formatted according to the GNU coding standards, but there
are minor deviations.  Where the coding style differs from the standard
please follow the coding style of the particular file you're making changes
to so that formatting consistency is retained within that file.

All source indentation should use two space characters per indentation
level.

Never use tab characters to indent code.  Always use spaces.  Teach
your editor to do the same.

The appropriate Emacs modeline to use for editing source is:

-*- mode: C++; c-file-style: "gnu"; indent-tabs-mode: nil; c-basic-offset: 2 -*-

And something close (but not perfect) for VIM:

vim: et:sw=2:sts=2:ts=2:cino=>2s,{s,\:s,+s,t0,g0,^-2,e-2,n-2,p2s,(0,=s:

The appropriate astyle options are:

astyle --style=gnu -s2 -p 

monotone's source includes a number of third party libraries.  These have
been imported from upstream, and should retain the original coding style of
the particular library in all cases.  This makes life easier when a
developer needs to send our fixes upstream or wants to import new upstream
versions into monotone.


Dialect issues
--------------

C++ is a big language with a lot of dialects spoken in different
projects.  monotone is no exception; we would prefer submissions
continued to adhere to the dialect we write in. in particular:


  - try to stick to simple functions and data types; don't make big
    complicated class hierarchies with a lot of interdependencies.

  - avoid pointers whenever possible. if you need to use a handle to a
    heap allocated object, use a shared_ptr, scoped_ptr, weak_ptr, or
    the like.

  - if a value has a clearly defined well-formedness condition,
    encapsulate the value in an object and make the constructors
    and mutators check the condition. see vocab.hh for string-valued
    examples.

  - in general, try to express both issues and semantically rich
    names in the type system. use typedefs to make names more
    meaningful.

  - avoid returning values, especially large ones. instead, pass a
    value as a parameter, by reference, clear it and assign into
    it. this style generally produces fewer invocations of copy
    constructors, and makes it natural to add multiple, named output
    parameters from a function.

  - use invariants and logging liberally.

  - make everything as const-correct as possible. make query methods
    on objects const. make the input parameters to a function const.
    the word "const" comes after the thing which is constant; for
    example write "int const" rather than "const int".

  - separate pointer and reference types with space. write "int * foo"
    rather than "int *foo" or "int* foo".

  - if you have a const, put that _after_ the main type, but before
    any * or &.  Example: "set<revision_id> const & foo".

  - put the name of a function in the first column of the line it
    occurs on. the visibility and return type go on the preceeding
    line.

  - use enums rather than magic constants, if you can.

  - magic constants, when needed, go in constants.{cc,hh}.

  - generally avoid the preprocessor unless you have a matter which is
    very difficult to express using inlines, reference args,
    templates, etc.

  - avoid indexing into an array or vector with []. use idx(vec,i),
    and you will get a nicely informative runtime error when you
    overflow rather than a crash.

  - avoid recursion, so that you will not overflow the stack on large
    work sets. use a heap-allocated std::deque<> for breadth-first
    recursion, std::stack<> for depth-first.

  - generally avoid anything which can generate a SEGV, as it's an
    uninformative error. prefer errors which say what went wrong.

  - do not use "using namespace <foo>" anywhere.  especially do not
    use "using namespace std".

  - in .cc files, it is preferred to put "using std::foo" at the top
    for each foo used in the file rather than put "std::" in front of
    all the uses.  this is also the preferred style for symbols from
    other namespaces when they are used frequently.

  - do not put any "using" declarations in .hh files; use the fully
    qualified name everywhere necessary.

  - .hh files should include everything that is necessary to parse all
    of their declarations, but strenuous efforts should be made to
    keep the number of nested includes to a minimum.  wherever
    possible, use forward declarations (struct foo;) and similar
    techniques.

  - <iostream> deserves special mention.  including this file causes
    the compiler to emit static constructors to ensure that the
    standard streams are initialized before their first use.
    therefore, do not include <iostream> unless you actually refer to
    one of the standard streams (cin, cout, cerr, clog).  use <iosfwd>,
    <istream>, <ostream>, <fstream>, etc instead, as appropriate.  do not,
    under any circumstances, refer to the standard streams in a header file.

  - it is almost always a mistake to use std::endl instead of '\n'.
    std::endl writes a newline to the stream *and flushes it*.
    in monotone this is basically only appropriate when one needs to
    resynchronize clog and cout (ui.cc:clear_line()), or recover from
    disabling terminal echo (read_password()).  note that it is never
    necessary to use endl with cerr, as cerr is unbuffered.

  - prefer character constants ('x') to single-character strings ("x") in
    formatted output sequences.

  - return type and function qualifiers should be placed on the line above
    the function name, so that the function name sits flush with the first
    column.  this makes grepping for function definitions easier.

Interfacing with Lua
--------------------

monotone is extended with hooks written in the Lua language. Code that
interfaces with Lua must obey the following rules:

  - Lua arrays (tables with numeric indices) are 1-indexed. This is not
    mandated by the language per se, but the standard libraries assume that
    and using the arrays otherwise may break hooks that use standard
    functions.

Test suites, and writing test cases
----------------------------------

monotone includes a number of unit and integration tests.  These can be run
easily by initiating a 'make check'.  The test suite (or, at least, any
tests potentially affected by your change) should be run before you
distribute your changes.

Automated build bots run the complete test suite on a regular basis, so
any problems will be noticed quickly, but it is still faster to find and fix
any problems locally rather than waiting for the build bots to alert the
development team of a problem.

All changes to monotone that alter monotone's behaviour should include a new
test.  This includes most changes, but use your judgment about adding tests
for very small changes..  The tests are located in the source tree in the
tests/ directory, documentation on writing tests is available in
tests/README.

When fixing a bug, check for an existing test case for that bug and
carefully observe the test case's behaviour before and after your fix. If no
test case exists, it is strongly recommended to write a test case before
attempting to fix the bug.

Tip: if the unit tests are failing, the quickest way to find the
problem is to search the output for the regexp \([0-9]+\) -- i.e., a
number in parentheses.  Or, if using gdb, try setting a breakpoint on
theboost::unit_test::first_failed_assertion function (see
results_collector.hpp).


Single-character macros
-----------------------

These are very convenient once you get used to them, but when you
first look at the code, it can be a bit of a shock to see all these
bare capital letters scattered around.  Here's a quick guide.

   Formatting macros:
      F("foo %s"): create a formatting object, for display to the user.
         Translators will translate this string, and F() runs
         gettext() on its argument.  NB: this string should usually
         _not_ end in a newline.
      FP("%d foo", "%d foos", n) % n: create a formatting object, with
         plural handling.  Same comments apply as to F().
      FL("foo %s"): create a raw ("literal") formatting object, mostly for
         use in logging.  This string will _not_ be translated, and
         gettext() is _not_ called.  This is almost always an argument
         to the L() macro:

   Informational macros:
      L(FL("foo")): log "foo".  Log messages are generally not seen by the
         user, and are used to debug problems with monotone.
      P(F("foo")): print "foo".  For generic informative messages to the
         user.
      W(F("foo")): warn "foo".  For warnings to the user.

   Assertion macros (see also the next section).  These all cause
   monotone to exit if their condition is false:
      I(x != y): "invariant" -- if the condition is not true, then there
         is a bug in monotone.
      N(x != y, F("make x and y equal")): "naughty" -- the user
         requested something that doesn't make sense, they should fix
         that.
      E(x != y, F("x and y are not equal")): "error" -- not a bug in
         monotone, not necessarily the users fault... dunno boss, it
         just isn't working!

   Tracing macros:
      MM(x): Mark the given variable as one of the things we are looking
         at right now.  On its own, this statement has no visible
         effect; but if monotone crashes (that is, an I() check fails)
         while MM(x) is in scope, then the value of x will be printed
         to the debug log.  This is quite cheap, so feel free to
         scatter them through your code; this information is _very_
         useful when trying to understand crashes, especially ones
         reported by users, that cannot necessarily be reproduced.
         There are some limitations:
          -- the object passed to MM must remain in scope as long as the
             MM does.  Code like
                MM(get_cool_value())
             will probably crash!  Instead say
                cool_t my_cool_value = get_cool_value();
                MM(my_cool_value);"
          -- You can only use MM() once per line.  If you say
                MM(x); MM(y);
             you will get a compile error.  Instead say
                MM(x);
                MM(y);
          -- The object passed to MM() must have a defined "dump"
             function.  You can easily add an overload to "dump" to
             support new types.


Reporting errors to the user
----------------------------

monotone has a number of assertion macros available for different
situations.  These assertion macros are divided into three categories:
invariants, user naughtiness, and general errors.

Invariants assert that monotone's internal state is in the expected state.
An invariant failure indicates that there is a bug in monotone.  e.g.

    I(r_working.edges.size() == 1);

User naughtiness handles error conditions where the user has asked monotone
to do something it is unable to.  e.g.

    N(completions.size() != 0,
        F("no match for selection '%s'") % str);

Error conditions handle most other error cases, where monotone is unable to
complete an operation due to an error, but that error is not caused by a bug
in monotone or explicit user error.  e.g.

    E(converted != NULL,
        F("failed to convert string from %s to %s: '%s'")
            % src_charset % dst_charset % src);

Each of these assertion macros are fatal and will cause an exception to be
thrown that will ultimately cause the monotone process to exit.  Exceptions
are used (rather than C-style abort() based assertions) so that the stack
will unwind and cause the destructors for objects allocated on the stack to
run.  This allows monotone to leave the user's database and workspace in
as logical a state as possible.  Any in-flight uncommitted database
transactions will be aborted.  Operations occurring on a workspace may
leave the workspace in an inconsistent state, as we do not have a way to
atomically update the workspace.


Patch submission guidelines
---------------------------

Mail patches to 'monotone-devel@nongnu.org' with a subject beginning with
'[PATCH]' and followed by a brief description of the patch.  The body of the
message should contain a description of the patch with reasoning for why the
changes are required, followed by a prepared commit message.  Patches may
be included inline in a message, or attached as a text/plain, text/x-diff,
or text/x-patch attachment.  Make sure your mailer does not mangle the
patch (e.g. by wrapping lines in the patch) before sending your patch to the
list.

All changes to the monotone source require an accompanying commit message.
Any changes that affect the user interface (e.g. adding command-line
options, changing the output format) or affect the documented behaviour of
monotone must include appropriate changes to the documentation.

Please review your patch prior to submission, to not include
accidental white-space-only changes or changes to the language
files. Usually you should revert po/*.po files before generating a
patch - unfortunately these are often changed when you build but do
not contain any reasonable changes. Alternatively restrict mtn diff to
the files you've actually changed.

The monotone development team review and comment on all patches on a
best-efforts basis.  Patches are never ignored, but a patch may not be
discussed or applied immediately according to the amount of spare time the
developers have.  Don't be discouraged if you don't receive an immediate
response, and if you feel that your patch has slipped through the cracks,
post a follow up reminder message with a pointer to the original message in
the mailing list archives.


Third-party code
----------------

monotone contains parts of a number of third-party libraries, including but
not limited to: Lua, Popt, Botan, SQLite, Netxx, and libidn.  See AUTHORS
for complete details on the included third-party code and the copyrights and
licenses of each portion.

From time to time, bug fixes to this third-party code are required.  These
fixes should be made in the monotone versions of the code first to solve the
immediate problem.  In all cases that make sense (i.e. for general bug
fixes), the change should also be sent to the upstream developers for
inclusion in the next release.

In a small number of cases, a change made to our local version of the
third-party code may not make sense to send upstream.  In this case,
make a note of this in the file you're changing and in your commit
message so that this permanent deviation is documented.


Compiling Hints
---------------

  - monotone's compilation time can be improved significantly by compiling
  with 'CXXFLAGS=-O0'. Note that disabling optimisation makes the resultant
  binary significantly slower - don't bother using it for performance
  profiling.

  - precompiled headers can be enabled by running 'configure' with --enable-pch
  This should give shorter compile times, given boost's extensive use of
  templates.  Some versions of gcc have issues with precompiled headers, so if
  you get strange compilation errors, try disabling them.

  - ccache (http://ccache.samba.org/) is quite effective for speeding up
  repeated compiles of the same source
