Contributing to OpenStructure
================================================================================

.. note::

  This document describes how to develop features to be included in OpenStructure. If you are mainly planning to use the framework from Python you probably shouldn't read this document and refer to the :doc:`API docs <index>` instead.

OpenStructure uses `git <http://git-scm.org>`_ as the revision control system. It allows for branch-and-merge driven workflows ideal for a scientific environment. 

The main repository can be browsed `here <https://git.scicore.unibas.ch/schwede/openstructure>`_. 


Even though, technically, there is no such a thing as a central repository in git, we use a central "repository of truth" where everyone is pulling from. You can get the source code with ``git clone``:

.. code-block:: bash

  git clone https://git.scicore.unibas.ch/schwede/openstructure.git


For information on how to install OpenStructure from source, refer to :doc:`install`. 

Leaving aside all the short-lived features branches, the OpenStructure repository has two long-lived branches, one called *master* and one called *develop*. *Master* contains the latest stable changes, *develop* contains features currently under development that are  potentially not working. Once stable, the changes in *develop* will be merged into *master* and together will form the next release. A very detailed description of the branching model used for OpenStructure is available at `this site <http://nvie.com/posts/a-successful-git-branching-model/>`_.



Making Changes
--------------------------------------------------------------------------------

The common workflow of making changes to OpenStructure is depicted in the following section.

Even though it is not neccessary, it is advised to carry out your changes in a separate branch. The new branch can be created with:

.. code-block:: bash
  
  # checkout branch my_branch and create it if it doesn't exist yet.
  # Of course you are free to name the branch whatever you want.
  git checkout -b my_branch

From now on, all your work will be carried out in my_branch. Make your changes and once you are happy, commit them to your repository.


Writing Good Commit Messages
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Your commit message should have a one-line description that summarizes the change and optionally a more detailed description of what the changes imply. An example from the commit history:

::

  improve warning when using generic property of string type in query
  
  Fixes BZDNG-204


The one-liner and the detailed description are separated by an empty line. The reason for this format is that the one-line description will be used as the subject line for the patches generated by format-patch and the ones sent to the commit mailing lists. People can quickly see if the change is of interest so that they can safely ignore the e-mail. 

Additionally, they also come in handy when using the --online option of ``git log``.

Writing Documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

OpenStructure uses `sphinx <http://sphinx.pocoo.org>`_ as the documentation generator. The main part of the documentation of each module resides in files with the ``.rst`` extension (a markup language called `reStructuredText  <http://docutils.sourceforge.net/docs/user/rst/quickref.html#literal-blocks>`_) in a sub-folder called doc.

From the top level directory of the git repository convert the .rst files to html by using the doc/make.py script :

.. code-block:: bash

  ost doc/make.py

The script first recursively searches for modified ``.rst`` files, starting at the modules directory and copies the files that have changed to ``doc/source``. It also copies images to the source directory. Then it runs sphinx to convert the documentation to html. If no further options are given to the script, the html documentation is generated. The HTML, CSS and static media files will be put into ``doc/build/html``.

For classes and functions written in Python, it is possible to tell sphinx to extract the documentation directly from the doc-string. For example, to get the documentation for :func:`~ost.io.LoadPDB`, you can use:

.. code-block:: rest

  .. autofunction:: ost.io.LoadPDB


Synchronizing with upstream changes
--------------------------------------------------------------------------------

In the meanwhile, someone else might have committed changes to the develop branch. The best and cleanest way to incorporate these changes is to rebase your changes onto the latest develop branch:

.. code-block:: bash

  git checkout develop
  # pull the latest changes to make sure we are up to date
  git pull
  git checkout my_branch
  # rebase the changes
  git rebase develop


Sending Patches
--------------------------------------------------------------------------------

Changes always go into develop first before being integrated into master. Unless, you have commit access, the easiest way to share your changes is to create a patch and send it by email to the mailing list or one of the developers. To create a suitable diff, rebase your changes onto the latest develop branch and use the ``format-patch`` command:

.. code-block:: bash

  # this takes all the changes you introduced and writes them to 
  # changeset.diff
  git format-patch --stdout develop > changeset.diff

Applying Patches
--------------------------------------------------------------------------------

If you got a patch from someone else and would like to use apply it to your repository, use ``git am``.

.. code-block:: bash

  git am < changeset.diff

Starting Your Own Action
--------------------------------------------------------------------------------
In OST we call scripts/ programs 'actions'. They are started by a
launcher found in your staging directory at :file:`stage/bin/ost`. This little
guy helps keeping the shell environment in the right mood to carry out your
job. So usually you will start an action by

.. code-block:: console

   $ stage/bin/ost --help

Starting new action **do** go for a dedicated branch for action-development.
There you can produce intermediate commits while other branches stay clean in
case you have to do some work there which needs to get public.

After preparing your repository its time to create a file for the action. That
is a bit different than for modules. Assuming we are sitting in the
repository's root:

.. code-block:: console

   $ touch action/ost-awesome-action
   $ chmod +x action/ost-awesome-action

Two things are important here: actions are prefixed with :file:`ost-`, so they
are recognised by the :file:`ost` launcher. Secondly, action files need to be
executable, which does not propagate if you do it **after** the first call to
``make``.

To get the new action recognised by ``make`` to be placed in
:file:`stage/libexec/openstructure`, it has to be registered with ``cmake`` in
:file:`actions/CMakeLists.txt`:

.. code-block:: cmake
  :linenos:

   add_custom_target(actions ALL)

   ost_action_init()
   ost_action(ost-awesome-action actions)

Just add your action with its full filename with a call to `ost_action` at
the end of the file.

Now its time to fill your action with code. Instead of reading a lot more of
explanations, it should be easy to go by examples from the :file:`actions`
directory. There are only two really important points:

* No shebang line (``#! /usr/bin/python``) in your action! Also no
  ``#! /usr/bin/env python`` or anything like this. This may lead to funny side
  effects, like calling a ``python`` interpreter from outside a virtual
  environment or calling a different version. Basically it may mess up the
  environment your action is running in. Actions are called by :file:`ost`,
  that's enough to get everything just right.

* The code of your action belongs in the :attr:`__main__` branch of the script.
  Your action will have own function definitions, variables and all the bells
  and whistles. Hiding behind :attr:`__main__` keeps everything separated and
  makes things easier when it gets to debugging. So just after

  .. code-block:: python

     import alot

     def functions_specific_to_your_action(...):

     if __name__ == "__main__":
         <put together what your action should do here>

  start putting your action together.
