Convert developer manual to rst
[alexxy/gromacs.git] / docs / dev-manual / uncrustify.rst
1 Automatic source code formatting
2 ================================
3
4 .. highlight:: bash
5
6 The source code can be automatically formatted using uncrustify, an automatic
7 source code formatting tool, to follow the guidelines in
8 :doc:`formatting`.
9 Additionally, Python scripts are used for a few other automatic
10 formatting/checking tasks.  The overview tools page contains a list of these
11 tools: :ref:`dev-formatting-tools`.
12 This page provides more details for uncrustify and copyright scripts.
13
14 Jenkins uses these same scripts (in particular, ``uncrustify.sh`` and the
15 ``check-source`` target) to enforce that the code stays invariant under such
16 formatting.
17
18 Setting up uncrustify
19 ---------------------
20
21 A patched version of uncrustify is used for |Gromacs|.  To set this up, you need
22 to do these (once):
23
24 1. Change to a directory under which you want to build uncrustify and run::
25
26      git clone -b gromacs git://github.com/rolandschulz/uncrustify.git
27      cd uncrustify
28      ./configure
29      make
30
31 2. Copy the binary ``src/uncrustify`` into a directory of your choice
32    (``/path/to/uncrustify`` below).
33
34 Alternatively, if you are running Linux, you can try whether the binary from
35 http://redmine.gromacs.org/issues/845 works for you.
36
37 In order to use the binary for ``uncrustify.sh`` and for the pre-commit hook, you
38 also need to run this in each of your |Gromacs| repositories::
39
40   git config hooks.uncrustifypath /path/to/uncrustify
41
42 Alternatively, if you just want to use ``uncrustify.sh``, you can set the
43 ``UNCRUSTIFY`` environment variable to ``/path/to/uncrustify``.
44
45 Using the pre-commit hook or git filters needs additional setup; see the
46 respective sections below.
47
48 What is automatically formatted?
49 --------------------------------
50
51 To identify which files are subject to automatic formatting, the scripts use
52 git filters, specified in ``.gitattributes`` files.  Only files that have the
53 attribute ``filter`` set to one of the below values are processed:
54
55 - ``filter=uncrustify``: uncrustify is run, copyright headers are checked, and
56   include order is enforced
57 - ``filter=uncrustify_only``: only uncrustify is run
58 - ``filter=includesort``: include order is enforced and copyright headers are
59   checked
60 - ``filter=copyright``: only copyright headers are checked
61
62 Other files are ignored by ``uncrustify.sh`` and ``reformat_all.sh`` scripts (see
63 below).
64
65
66 Scripts
67 -------
68
69 ``copyright.py``
70 ^^^^^^^^^^^^^^^^
71
72 This script provides low-level functionality to check and update copyright
73 headers in C/C++ source files, as well as in several other types of files like
74 CMake and Python scripts.
75
76 This file is also used as a loadable Python module for kernel generators, and
77 provides the functionality to generate conformant copyright headers for such
78 scripts.
79
80 The script is similar to uncrustify in that there is rarely need to run it
81 directly, but instead the bash scripts below use it internally.  You can run
82 the script with ``--help`` option if you want to see what all options it provides
83 if you need to do some maintenance on the copyright headers themselves.
84
85 ``uncrustify.sh``
86 ^^^^^^^^^^^^^^^^^
87
88 This script runs uncrustify and ``copyright.py`` on modified files and
89 reports/applies the results.
90 By default, the current HEAD commit is compared to the work tree,
91 and files that
92
93 1. are different between these two trees and
94 2. change under uncrustify and/or have outdated copyright header
95
96 are reported.  This behavior can be changed by
97
98 1. Specifying an ``--rev=REV`` argument, which uses ``REV`` instead of HEAD as
99    the base of the comparison.  A typical use case is to specify ``--rev=HEAD^``
100    to check the HEAD commit.
101 2. Specifying an action:
102
103    - ``check-*``:   reports the files that uncrustify changes
104    - ``diff-*``:    prints the actual diff of what would change
105    - ``update-*``:  applies the changes to the repository
106    - ``*-workdir``: operates on the working directory (files on disk)
107    - ``*-index``:   operates on the index of the repository
108
109    For convenience, if you omit the workdir/index suffix, workdir is assumed
110    (i.e., ``diff`` equals ``diff-workdir``).
111 3. Specifying ``--uncrustify=off``, which does not run uncrustify.
112 4. Specifying ``--copyright=<mode>``, which alters the level of copyright
113    checking is done:
114
115    ``off``
116      does not check copyright headers at all
117    ``year``
118      only update copyright year in new-format copyright headers
119    ``add``
120      in addition to ``year``, add copyright headers to files that do not
121      have any
122    ``update``
123      in addition to ``year`` and ``add``, also update new-format copyright
124      headers if they are broken or outdated
125    ``replace``
126      replace any copyright header with a new-format copyright header
127    ``full``
128      do all of the above
129
130 By default, ``update-*`` refuses to update dirty files (i.e., that differ
131 between the disk and the index) to make it easy to revert the changes.
132 This can be overridden by adding a ``-f``/``--force`` option.
133
134 git pre-commit hook
135 ^^^^^^^^^^^^^^^^^^^
136
137 If you want to run ``uncrustify.sh`` automatically for changes you make, you can
138 configure a pre-commit hook using ``admin/git-pre-commit``:
139
140 1. Copy the ``git-pre-commit`` script to .git/hooks/pre-commit.
141 2. Specify the path to uncrustify for the hook if you have not already done
142    so::
143
144      git config hooks.uncrustifypath /path/to/uncrustify
145
146 3. Set the operation mode for the hook::
147
148      git config hooks.uncrustifymode check
149      git config hooks.copyrightmode  update
150
151 With this configuration, all source files modified in the commit are run
152 through uncrustify and checked for correct copyright headers.
153 If any file would be changed by ``uncrustify.sh``, the names of those files are
154 reported and the commit is prevented.  The issues can be fixed by running
155 ``uncrustify.sh`` manually.
156
157 To disable the hook without removing the ``pre-commit`` file, you can set ::
158
159   git config hooks.uncrustifymode off
160   git config hooks.copyrightmode off
161
162 To disable it temporarily for a commit, set NO_FORMAT_CHECK environment
163 variable.  For example, ::
164
165     NO_FORMAT_CHECK=1 git commit -a
166
167 You can also run ``git commit --no-verify``, but that also disables other hooks,
168 such as the Change-Id ``commit-msg`` hook used by Gerrit.
169
170 Note that when you run ``git commit --amend``, the hook is only run for the
171 changes that are getting amended, not for the whole commit.  During a rebase,
172 the hook is not run.
173
174 The actual work is done by the ``admin/uncrustify.sh`` script, which gets
175 run with the ``check-index`` action, and with ``--uncrustify`` and ``--copyright``
176 getting set according to the ``git config`` settings.
177
178 ``reformat_all.sh``
179 ^^^^^^^^^^^^^^^^^^^
180
181 This script runs uncrustify, ``copyright.py``, or the include sorter for all
182 applicable files in the source tree.  See ``reformat_all.sh -h`` for the
183 invocation.
184
185 The script can also produce the list of files for which these commands would be
186 run.  To do this, specify ``list-files`` on the command line and use
187 ``--filter=<type>`` to specify which command to get the file list for.  This can
188 be used together with, e.g., ``xargs`` to run other scripts on the same set of
189 files.
190
191 For all the operations, it is also possible to apply patters (of the same style
192 that various git commands accept, i.e., ``src/*.cpp`` matches all ``.cpp`` files
193 recursively under ``src/``).  The patterns can be specified with
194 ``--pattern=<pattern>``, and multiple ``--pattern`` arguments can be given.
195
196 As with ``uncrustify.sh``, ``-f``/``--force`` is necessary if the working tree and
197 the git index do not match.
198
199
200 Using git filters
201 -----------------
202
203 An alternative to using a pre-commit hook to automatically apply uncrustify on
204 changes is to use a git filter (does not require ``uncrustify.sh``, only the
205 ``.gitattributes`` file).  You can run ::
206
207   git config filter.uncrustify.clean \
208       "/path/to/uncrustify -c admin/uncrustify.cfg -q -l cpp"
209
210 To configure a filter for all files that specify ``filter=uncrustify`` attribute.
211
212 The pre-commit hook + manually running ``uncrustify.sh`` gives better/more
213 intuitive control (with the filter, it is possible to have a work tree that is
214 different from HEAD and still have an empty ``git diff``) and provides better
215 performance for changes that modify many files.  It is the only way that
216 currently also checks the copyright headers.
217
218 The filter allows one to transparently merge branches that have not been run
219 through uncrustify, and is applied more consistently (the pre-commit hook is
220 not run for every commit, e.g., during a rebase).