********************************** Developer guide for SVN operations ********************************** .. contents:: :depth: 1 Source code organisation ======================== Building from several checkouts ------------------------------- | As of now, the NEMO code is build from different sources in the repository, via SVN external definitions which are special versioned properties specified on its sub-items (folders and file). | For more, read `the documentation on external definitions in ​the SVN book `_. The *core code*, which is actively developed from one release to another, is still present and unique for a branch. :./cfgs: Reference configurations :./doc: Reference manuals (LaTeX) and user guide (reStructuredText) :./src: Modelling routines :./tests: Test cases | On the other hand, the *complementary code*, defined by minor modifications between consecutive releases, is managed apart from the default development organisation (``branches``, ``releases``, `tags` and ``trunk``). | It has been extracted to another locations in the repository and can considered from now on as external sources. :./arch: Settings for computing architecture :./ext: External dependencies (AGRIF for nesting, FCM for compilation and IOIPSL for IO) :./makenemo: Script for building NEMO executable :./mk: Compilation sub-scripts :./tools: User tools Thanks to this, the *complementary code* can be shared between several branches. External sources in working copy -------------------------------- Here is the current list of these externals for the NEMO code: .. code:: sh # Relative URL Item # '^': alias for repository root ^/utils/build/arch@{HEAD,${REV}} arch ^/utils/build/makenemo@{HEAD,${REV}} makenemo ^/utils/build/mk@{HEAD,${REV}} mk ^/utils/tools@{HEAD,${REV}} tools ^/vendors/AGRIF/dev@{HEAD,${REV}} ext/AGRIF ^/vendors/FCM@{HEAD,${REV}} ext/FCM ^/vendors/IOIPSL@{HEAD,${REV}} ext/IOIPSL .. important:: | Regarding the main branches of NEMO development, the default configuration for official releases and tagged snapshots will have fixed externals. | However the trunk will always refer to the ``HEAD`` of the repository. Developer perspective --------------------- | The external definitions are retained by branching operations so a development branch created from the trunk will in the first place update its external sources to the latest. | From that the developer has two options per each external **Be isolated from unwanted commits** Replace ``HEAD`` revision by a reliable number to be safe but this external will be updated by hand. **Be able to commit directly to the external** Let ``HEAD`` revision setting, in return you will receive all its updates. .. hint:: You can change your mind at any time and update the externals on a case-by-case basis. The SVN commands for managing external definitions are below .. code:: sh ## Get the current definitions $ svn propget svn:externals ${PATH} ## Edit them in external editor (SVN_EDITOR env. variable) $ svn propedit svn:externals ${PATH} .. warning:: | Think about committing your new definitions to the repository. | Modified externals are reported in the 2 :sup:`nd` column of ``svn {st,status}`` output. Recommended development environment =================================== Lightweight repository copy --------------------------- .. |download| replace:: **download** .. _download: https://forge.ipsl.jussieu.fr/nemo/export/HEAD/utils/dev/install_dev_env.sh Although each developer can have its own approach for developing the NEMO source code, **we recommend to** |download|_ **and run** ``install_dev_env.sh`` **script to set up a clean and minimal environment**. From there, the developer would be able to start his developments but also to support the NEMO shared reference in the same working copy. | Actually the script will checkout the repository in a slightly different manner from the usual way, using the ``--depth`` and ``--set-depth`` SVN options in order to download the sub-paths of the default development organisation in various depths (``branches``, ``releases``, ``tags`` and ``trunk``). | In the end, the developer will have a versioned copy of the repository first levels with empty folders, except for the `trunk` (``/NEMO/trunk``) and the last official release (``/NEMO/releases/release-X.X``) which have been fully downloaded. The benefits of this new approach are numerous: - **Possibility to work offline like git**: create a development branch by copying the `trunk` locally and start coding without a first commit to the remote repository, instead of creating the development branch remotely on the repository, then downloading it to begin to work. - **Simple UNIX-like syntax for SVN commands** (``svn {add,cat,cp,ls,mv,rm} ...``) and no more tedious URL scheme to use ( ``svn+ssh://...``). - **All developments handled in one common location** by putting an end at the branches scattering with several isolated working copies (usually one single checkout per branch). Examples -------- Usage of ``install_dev_env.sh`` ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: console $ ./install_dev_env.sh [${DEVELOPER_ID} [repo]] Positional arguments in option 1. ``DEVELOPER_ID``: configure the working copy in developer mode, i.e. URL in ``svn info`` begins with |DEV_URL| ... instead of |URL|, so the developer can commit to the repository right away (switching can be made later). 2. ``repo``: download the whole layout of the repository instead of the default development organisation. By default, the checkout is from root directory ``/NEMO`` with ``branches``, ``releases``, ``tags`` and ``trunk``. With ``repo`` argument, it does from the root of repository with ``/NEMO``, ``/utils``, ``/vendors``. Create a branch ^^^^^^^^^^^^^^^ .. code:: console $ svn copy {${URL_SRC},${PATH_SRC}}[@${REV}] {${URL_DST},${PATH_DST}} +------------------+--------------------------------------------------------------------+-----------------------------------------------+ | local -> local | ``PATH_SRC`` = ``trunk`` | *Copy unversioned items to the new branch* | | | | | | | ``PATH_DST`` = ``branches/${YEAR}/${BRANCH_NAME}`` | | +------------------+--------------------------------------------------------------------+-----------------------------------------------+ | local -> remote | ``PATH_SRC`` = ``trunk`` | *New branch created only in the repository* | | | | | | | ``URL_DST`` = ``${DEV_URL}/NEMO/branches/${YEAR}/${BRANCH_NAME}`` | | +------------------+--------------------------------------------------------------------+-----------------------------------------------+ | remote -> local | ``URL_SRC`` = ``${URL}/NEMO/trunk`` | *Clean copy of the trunk from the repository* | | | | | | | ``PATH_DST`` = ``branches/${YEAR}/${BRANCH_NAME}`` | | +------------------+--------------------------------------------------------------------+-----------------------------------------------+ | remote -> remote | ``URL_SRC`` = ``${URL}/NEMO/trunk`` | *All done on server side* | | | | | | | ``URL_DST`` = ``${DEV_URL}/NEMO/branches/${YEAR}/${BRANCH_NAME}`` | | +------------------+--------------------------------------------------------------------+-----------------------------------------------+ .. |URL| replace:: ``http://forge.ipsl.jussieu.fr/nemo/svn`` .. |DEV_URL| replace:: ``svn+ssh://${DEVELOPER_ID}@forge.ipsl.jussieu.fr/ipsl/forge/projets/nemo/svn`` .. note:: | ``URL`` = |URL| | ``DEV_URL`` = |DEV_URL| | Usual convention for the naming of the development branches: | ``BRANCH_NAME`` = ``dev_r${TRUNK_REVISION_ON_FORK}_${ACTION_NAME_IN_WORKPLAN}`` Download a branch from the repository ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: console List the remote branches in the repository $ svn ls branches/${YEAR} Download the one chosen $ svn update branches/${YEAR}/${BRANCH_NAME} Delete the local copy of a branch ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ .. code:: console Set branch depth to 'exclude' => Tag the branch as to be deleted $ svn update --set-depth exclude branches/${YEAR}/${BRANCH_NAME} D dev_r.... Effective removal $ svn update branches/${YEAR} Working smart with available resources ====================================== Make link between commit and ticket(s) -------------------------------------- If a commit is related to ticket(s), we highly suggest to mention it in the commit log message: - the commit will be converted into a comment in the ticket thread(s) - URL link(s) to selected ticket(s) will be provided in the email notification and the changeset page. | To do so, you can use a word from this list ``addresses re references refs see`` followed by usual ticket link(s). | For instance .. code:: console $ svn commit -m '[...] see #${TICKET_ID} [...]' Close ticket(s) when committing ------------------------------- | If a commit is a fix, you can close targeted ticket(s) with the commit operation without the need of a browser. | For this, you can use a word from the list ``close closed closes fix fixed fixes`` followed by usual ticket link(s). | For instance .. code:: console $ svn commit -m '[...] fix #${TICKET_ID} [...]'