4 Basic workflow
trunk branch to the latest sources with
git pull --rebase. Create a new branch for your changes off of
trunk and develop as you would normally with git commits.
4.1 Rebuilding R
Compiling R takes some time. Building it from scratch every time you’d like to test a change would slow down your workflow considerably. Fortunately, it is easy to rebuild only parts of it.
If you have changed a source file inside
src/main run this from the build directory:
(cd src/main/ && make) && make install
If you have changed a package (say
(cd src/library/base/ && make && cd .. && make install)
4.2 Testing your changes
4.2.1 Running tests
make check: Runs the main unit test files. This includes running examples of the base packages and checking the outputs conform and no unexpected errors arise.
make check-devel: Runs all tests minus those of the recommended package. This includes running R CMD check on the base packages.
make check-all: Runs all tests including
R CMD checkon the recommended packages. You normally don’t need to run this until you’re ready to finalise a patch.
Other useful targets are
test-Reg as their running time is much faster. If you’re having trouble with a particular test domain and would like to find a smaller target to run these tests, check Makefile.common to find out which target invokes these tests.
check-all suites can take quite some time. Set this environment variable (maybe in your shell profile) to run the tests in parallel (in this case on 4 cores):
4.2.2 Output comparison
Many test files have a
.Rout.save file checked in the repository. These files are meant to monitor changes to the output of tested functions. There are two kinds of comparisons:
method-dispatch.Rout.save. The saved and actual outputs must match exactly or the tests fail.
print-tests.Rout.save. The diff of the changes are printed at the console, but they don’t make the tests fail.
In doubt, check
tests/Makefile.common and search for
RVAL_IF_DIFF. If set to 1, the comparison is strict, otherwise it is sloppy.
Some tests are compared sloppily because they are sensitive to benign changes, for instance:
The presence of
srcrefattributes might change how functions are printed. This could happen if you have set
The memory addresses of environments or bytecode will change each time the file is run.
It is your responsibility to inspect all output changes in the test results and determine whether they actually are failures.
4.2.3 Debugging failures
When an unexpected error occurs, you will find a
.Rout.fail file in the
tests directory (the one inside your build directory). If the error was from a base package example, the failure file will be in
tests/Example. From this file you should be able to find the source of the failure.
4.2.4 Adding new unit tests
The go-to file for new unit tests is currently
tests/reg-tests-1d.R (choose the
reg-tests-1 file with the highest letter suffix).
Insert your tests as a single block without whitespace. The tests should be navigable by contiguous paragraph. You can use
##to create empty lines inside your block.
If you are fixing a bug, insert comments describing the old behaviour.
If you have added code to a file that has a
.Rout.saveoutput file checked in, you need to update that file as well. To do this, run the tests as usual. You will find a
build/tests. Go to
root/testsand copy paste the new contents in the corresponding
4.3 Making a patch
In a git-based workflow, you submit contributions via pull requests. Since R core doesn’t use git, we’re going to submit our changes the old fashioned way, by creating a patch file.
4.3.1 With github
Fortunately it is very easy to create patches from git branches and git commits. The simplest way is to send a pull request or branch to your github’s mirror repo and append
.patch to a PR or commit URL. If you do that on a PR, all the commits are folded in a single patch. For instance, given this dummy PR that I made to my own clone of the R sources on github:
Get the corresponding patch via this URL:
It also works with individual commits:
4.3.2 At the command line
To manually create a patch, use
git format-patch. When given one argument (a revision), it creates patches for each commit from that revision to the current head:
git checkout mypatch git format-patch trunk
Squash the commits together beforehand if you’d like to create a single patch.
If the patch is trivial (e.g. it fixes a bug, implements a small feature that was already discussed), create a bugzilla report with a reprex if there isn’t one already. Attach the patch, click on “Show Advanced Fields” to reveal the “Content Type” checkbox and declare the attachment is a patch. This way the patch is properly formatted in the bug report.
If the patch introduces a new feature or change the API, it’s probably better to discuss it first on r-devel or with the relevant R core member.