It is relatively simple to marry !-FitNesse-! to your source code control system.  It's all handled through a !-FitNesse-! variable named CM_SYSTEM.  As with all variables, if this variable is !-!define-!ed on a page, then it will apply to that page and all pages below it.  Otherwise if either the CM_SYSTEM environment variable or java system property is set, it will apply to all pages.

Let's say you want to marry !-FitNesse-! with git.  You could start !-FitNesse-! this way: {{{java -DCM_SYSTEM=fitnesse.wiki.cmSystems.GitCmSystem -jar fitnesse.jar}}}  Or, if you just wanted to put a sub-hierarchy of pages under git, then put {{{!define CM_SYSTEM {fitnesse.wiki.cmSystems.GitCmSystem} }}} in the top page of that hierarchy.  If you want turn the CM marriage off below some point in the hierarhcy, just put a !style_code(!-!-!define CM_SYSTEM {}) just above that level.

The value of this variable is the fully qualified name of a class that looks like !-GitCmSystem-! (see below).  Make sure that class in in your classpath when you start fitnesse.

Here's the plugin I use for git.  This ships with !-FitNesse-! so you can [[use it][>GitPlugin]] if it works for you.

{{{public class GitCmSystem {
  public static void cmUpdate(String file, String payload) throws IOException {
    Runtime.getRuntime().exec("/usr/local/bin/git add " + file);
  }

  public static void cmEdit(String file, String payload) {
   //git doesn't need this.
  }

  public static void cmPreDelete(String file, String payload) throws IOException {
    //git doesn't need this.
  }

  public static void cmDelete(String file, String payload) throws IOException {
    Runtime.getRuntime().exec("/usr/local/bin/git rm -rf --cached " + file);
  }
} }}}

The four functions: !style_code[cmUpdate], !style_code(cmEdit), !style_code(cmPreDelete), and !style_code(cmDelete) are called if:
 1 The name of the class is in the CM_SYSTEM variable, and
 2 that page is being created, modified, or deleted.

 * !style_code[cmEdit(file, payload)] is called just before file is about to be written
 * !style_code[cmUpdate(file, payload)] is called just after file has been written
 * !style_code[cmPreDelete(directory, payload)] is called just before the directory defining a page will be deleted.
 * !style_code[cmDelete(directory, payload)] is called just after the directory defining a page has been deleted.

Remember that each page is defined by a directory that bears it's name, and two files that contain it's content.
The first file is !style_code(content.txt) which holds the wiki text.  The second is !style_code(properties.xml) which holds all the metatdata
for the page.  The file operations !style_code(cmEdit) and !style_code(cmUpdate) are called for each file.  The file argument is the relative
path of the file.  The !style_code(cmDelete) function is called with the relative path of the directory that holds the content of
the deleted page.  These paths are relative to the -d argument of !-FitNesse-!

The 'payload' is there just in case you need it.  It contains the complete definition of the !style_code(CM_SYSTEM) variable.  You can
put whatever you like in this variable, so long as the fully qualified name of your plugin comes first.  Use a space to separate the classname from whatever else you want.

What would you put in this payload?  You might put your username and password for the CM system...  Or you might put the path
of the CM root.  Anything you need to make the CM system work...

So given: !style_code(!-!define CM_SYSTEM {fitnesse.wiki.cmSystems.MyCmSystem unclebob/password /cm/myResponsitory}-!)
Then the payload would be: !style_code(!-fitnesse.wiki.cmSystems.MyCmSystem unclebob/password /cm/myResponsitory-!)
