4 Basic workflow
Update the 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 base
), use:
(cd src/library/base/ && make && cd .. && make install)
4.2 Testing your changes
4.2.1 Running tests
Go to the tests
folder inside your build directory. There are many make
targets for running tests. See the README file in the tests folder. The three main targets to know about are:
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 includingR CMD check
on the recommended packages. You normally don’t need to run this until you’re ready to finalise a patch.
Other useful targets are test-Specific
, test-Sloppy
, and 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.
Running the check-devel
and 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):
TEST_MC_CORES=4
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:
Strict, like
method-dispatch.Rout.save
. The saved and actual outputs must match exactly or the tests fail.Sloppy, like
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
srcref
attributes might change how functions are printed. This could happen if you have setR_KEEP_PKG_SOURCE
.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.save
output file checked in, you need to update that file as well. To do this, run the tests as usual. You will find a.Rout
file insidebuild/tests
. Go toroot/tests
and copy paste the new contents in the corresponding.Rout.save
file.
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:
https://github.com/lionel-/r-source/commit/7b7ce5be72cab4c6ad41f0d8eb01591a4c01a882.patch
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.
4.4 Submitting
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.